CrazyIter_Bin 2 jaren geleden
bovenliggende
commit
43bea77f5c
100 gewijzigde bestanden met toevoegingen van 6128 en 2308 verwijderingen
  1. 1 1
      TEAMModelBI/ClientApp/public/index.html
  2. 4 1
      TEAMModelBI/ClientApp/src/api/index.js
  3. BIN
      TEAMModelBI/ClientApp/src/assets/img/notdata.png
  4. 10 8
      TEAMModelBI/ClientApp/src/until/common.js
  5. 49 15
      TEAMModelBI/ClientApp/src/view/areaServe/areamanage.vue
  6. 13 7
      TEAMModelBI/ClientApp/src/view/areamanage/statistics.vue
  7. 13 2
      TEAMModelBI/ClientApp/src/view/common/aside.vue
  8. 13 10
      TEAMModelBI/ClientApp/src/view/created/created.vue
  9. 29 23
      TEAMModelBI/ClientApp/src/view/index/index.vue
  10. 557 0
      TEAMModelBI/ClientApp/src/view/participation/examination.vue
  11. 243 104
      TEAMModelBI/ClientApp/src/view/participation/index.vue
  12. 118 94
      TEAMModelBI/ClientApp/src/view/participation/setPhase.vue
  13. 7 3
      TEAMModelBI/ClientApp/src/view/schoolServe/analyseSchool.vue
  14. 4 4
      TEAMModelBI/ClientApp/src/view/schoolServe/school.vue
  15. 18 19
      TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue
  16. 19 9
      TEAMModelBI/ClientApp/src/view/schoolmanage/schoolAnalyse.vue
  17. 142 17
      TEAMModelBI/ClientApp/src/view/systemConfig/correlation.vue
  18. 568 377
      TEAMModelBI/ClientApp/src/view/systemConfig/manageschool.vue
  19. 16 5
      TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue
  20. 27 14
      TEAMModelBI/ClientApp/src/view/teachermanage/traitmanage.vue
  21. 5 6
      TEAMModelBI/Controllers/BINormal/AreaRelevantController.cs
  22. 233 212
      TEAMModelBI/Controllers/BINormal/BatchAreaController.cs
  23. 26 24
      TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs
  24. 36 31
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  25. 38 4
      TEAMModelBI/Controllers/BITable/IES5OAuthController.cs
  26. 52 20
      TEAMModelBI/Controllers/BITest/TestController.cs
  27. 115 0
      TEAMModelBI/Controllers/Census/ItemSticsController.cs
  28. 191 1
      TEAMModelBI/Controllers/Census/PaperController.cs
  29. 49 0
      TEAMModelBI/Models/ItemInfo.cs
  30. 3 3
      TEAMModelBI/TEAMModelBI.csproj
  31. 6 2
      TEAMModelBI/Tool/CommonFind.cs
  32. 1 1
      TEAMModelBI/Tool/CosmosBank/SchoolWay.cs
  33. 1 1
      TEAMModelOS.FunctionV4/CosmosDB/TriggerExam.cs
  34. 98 5
      TEAMModelOS.FunctionV4/HttpTrigger/IESHttpTrigger.cs
  35. 6 2
      TEAMModelOS.FunctionV4/Lang/en-us.json
  36. 6 2
      TEAMModelOS.FunctionV4/Lang/zh-cn.json
  37. 6 2
      TEAMModelOS.FunctionV4/Lang/zh-tw.json
  38. 1 1
      TEAMModelOS.SDK/Models/Cosmos/BI/AreaQuoteRecord.cs
  39. 1 0
      TEAMModelOS.SDK/Models/Cosmos/BI/BICommon/MonthStartEnd.cs
  40. 3 0
      TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs
  41. 4 1
      TEAMModelOS.SDK/Models/Cosmos/Normal/Area.cs
  42. 209 0
      TEAMModelOS.SDK/Models/Cosmos/Student/OverallEducation.cs
  43. 125 0
      TEAMModelOS.SDK/Models/Cosmos/Student/StudentArtResult.cs
  44. 30 0
      TEAMModelOS.SDK/Models/Service/BatchCopyFileService.cs
  45. 61 6
      TEAMModelOS.SDK/Models/Service/Common/ActivityStudentService.cs
  46. 1 0
      TEAMModelOS/ClientApp/package.json
  47. 21 5
      TEAMModelOS/ClientApp/public/lang/en-US.js
  48. 75 59
      TEAMModelOS/ClientApp/public/lang/zh-CN.js
  49. 69 53
      TEAMModelOS/ClientApp/public/lang/zh-TW.js
  50. 11 0
      TEAMModelOS/ClientApp/src/api/areaArt.js
  51. BIN
      TEAMModelOS/ClientApp/src/assets/dashboard/student/icon-crown.png
  52. BIN
      TEAMModelOS/ClientApp/src/assets/dashboard/student/icon_crown.png
  53. BIN
      TEAMModelOS/ClientApp/src/assets/dashboard/student/icon_crown2.png
  54. BIN
      TEAMModelOS/ClientApp/src/assets/dashboard/student/icon_crown3.png
  55. BIN
      TEAMModelOS/ClientApp/src/assets/image/c-import-stu-cn.png
  56. 9 9
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  57. 1 1
      TEAMModelOS/ClientApp/src/components/dashboard/art/RightBotR.vue
  58. 147 0
      TEAMModelOS/ClientApp/src/components/dashboard/student/BaseCircle.vue
  59. 2 2
      TEAMModelOS/ClientApp/src/components/dashboard/student/BaseProgressBar.vue
  60. 1 1
      TEAMModelOS/ClientApp/src/components/dashboard/studentAll/BaseScoreBar.vue
  61. 128 126
      TEAMModelOS/ClientApp/src/components/echart/acPie/chart.vue
  62. 132 133
      TEAMModelOS/ClientApp/src/components/echart/techBar/chart.vue
  63. 156 0
      TEAMModelOS/ClientApp/src/components/research-dashboard/BaseTechBar.vue
  64. 112 119
      TEAMModelOS/ClientApp/src/components/research-dashboard/LeftBottom.vue
  65. 144 145
      TEAMModelOS/ClientApp/src/components/research-dashboard/LeftTop.vue
  66. 49 53
      TEAMModelOS/ClientApp/src/components/research-dashboard/RightBotR.vue
  67. 6 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/VoteResultChart.vue
  68. 11 11
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue
  69. 208 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewMobile.less
  70. 436 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewMobile.vue
  71. BIN
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-en-us.png
  72. BIN
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-zh-cn.png
  73. BIN
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-zh-tw.png
  74. 7 7
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/newHomeView.vue
  75. BIN
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-en-us.png
  76. BIN
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-zh-cn.png
  77. BIN
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-zh-tw.png
  78. 48 28
      TEAMModelOS/ClientApp/src/router/routes.js
  79. 33 8
      TEAMModelOS/ClientApp/src/view/areaArtExam/DataView.vue
  80. 75 39
      TEAMModelOS/ClientApp/src/view/areaArtExam/Mgt.vue
  81. 3 3
      TEAMModelOS/ClientApp/src/view/areaMgmt/AreaLayout.vue
  82. 146 38
      TEAMModelOS/ClientApp/src/view/art/AreaArt.vue
  83. 22 7
      TEAMModelOS/ClientApp/src/view/art/SchoolArt.less
  84. 170 39
      TEAMModelOS/ClientApp/src/view/art/SchoolArt.vue
  85. 1 1
      TEAMModelOS/ClientApp/src/view/art/echart/KngLevel.vue
  86. 19 5
      TEAMModelOS/ClientApp/src/view/art/echart/KngPoint.vue
  87. 36 34
      TEAMModelOS/ClientApp/src/view/art/echart/Overall.vue
  88. 3 3
      TEAMModelOS/ClientApp/src/view/art/echart/SchoolComp.vue
  89. 36 9
      TEAMModelOS/ClientApp/src/view/artexam/Create.vue
  90. 2 1
      TEAMModelOS/ClientApp/src/view/artexam/ExamSetting.vue
  91. 10 5
      TEAMModelOS/ClientApp/src/view/artexam/Mgt.vue
  92. 113 112
      TEAMModelOS/ClientApp/src/view/artexam/QuoTree.vue
  93. 10 3
      TEAMModelOS/ClientApp/src/view/assessment/ArtAssessment.vue
  94. 10 3
      TEAMModelOS/ClientApp/src/view/auth/Product.vue
  95. 90 13
      TEAMModelOS/ClientApp/src/view/dashboard/Art.vue
  96. 60 43
      TEAMModelOS/ClientApp/src/view/dashboard/Index.vue
  97. 7 3
      TEAMModelOS/ClientApp/src/view/dashboard/Research.less
  98. 150 150
      TEAMModelOS/ClientApp/src/view/dashboard/Research.vue
  99. 201 0
      TEAMModelOS/ClientApp/src/view/dashboard/Student.less
  100. 0 0
      TEAMModelOS/ClientApp/src/view/dashboard/Student.vue

+ 1 - 1
TEAMModelBI/ClientApp/public/index.html

@@ -12,7 +12,7 @@
     </title>
 </head>
 <script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
-<script src="https://at.alicdn.com/t/c/font_2934132_1kz9lc35x9r.js"></script>
+<script src="https://at.alicdn.com/t/c/font_2934132_jpe031zj2cg.js"></script>
 <script src="../src/access/iconfont.js"></script>
 
 <body>

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

@@ -401,7 +401,10 @@ export default {
     proportionData(data) {
         return post('schoolcheck/get-schooldate', data)
     },
-
+    //获取试卷资源
+    getExaminations(data) {
+        return post('/paper/get-list', data)
+    },
 
     //第三方相关API(BI)
     //创建or保存 第三方信息

BIN
TEAMModelBI/ClientApp/src/assets/img/notdata.png


+ 10 - 8
TEAMModelBI/ClientApp/src/until/common.js

@@ -74,17 +74,19 @@ export default {
         });
         return totaldays
     },
-    timestampToTime(timestamp) {
+    timestampToTime(timestamp, state) {
         if (timestamp === 0) { return 0 }
-        var date = new Date(Number(timestamp) * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+        let multiple = timestamp.toString().length === 13 ? 1 : 1000
+        var date = new Date(Number(timestamp) * multiple); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
         var Y = date.getFullYear() + '-';
         var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
-        var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
-        // var h = (date.getHours() < 10 ? '0'+date.getHours() : date.getHours()) + ':';
-        // var m = (date.getMinutes() < 10 ? '0'+date.getMinutes() : date.getMinutes()) + ':';
-        // var s = (date.getSeconds() < 10 ? '0'+date.getSeconds() : date.getSeconds());
-
-        var strDate = Y + M + D;
+        var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + '   ';
+        if (state === 'all') {
+            var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+            var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':';
+            var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+        }
+        var strDate = state !== 'all' ? Y + M + D : Y + M + D + h + m + s;
         return strDate; //2020-07-30 01:05:54
 
     },

+ 49 - 15
TEAMModelBI/ClientApp/src/view/areaServe/areamanage.vue

@@ -111,6 +111,15 @@
               <div class="schoolLeft" v-loading="loadingSchoolList" element-loading-text="数据加载中..." v-if="PowerShow">
                 <div class="haveSchool-title">
                   <div>{{ $t(`areaManages.operational.areaAddSchool.schooltitle`) }}</div>
+                  <div class="search-school">
+                    <el-input v-model="schoolSeach" placeholder="输入学校名称搜索" size="small" clearable>
+                      <!-- <template #prepend>
+                        <svg class="addrelevancy-icon" aria-hidden="true">
+                          <use xlink:href="#icon-sousuo3-copy"></use>
+                        </svg>
+                      </template> -->
+                    </el-input>
+                  </div>
                   <div class="synchronization-title" v-show="currentlySelect.cutArea"><span>已同步省平台</span></div>
                 </div>
                 <ul>
@@ -122,9 +131,9 @@
                       <div>
                         {{$t(`areaManages.operational.areaAddSchool.schoolList.name`)}}:<span>{{ item.name }}</span>
                       </div>
-                      <div>
+                      <!-- <div>
                         {{$t(`areaManages.operational.areaAddSchool.schoolList.grading`)}}:<span>{{ item.period[0] }}</span>
-                      </div>
+                      </div> -->
                       <div>
                         {{$t(`areaManages.operational.areaAddSchool.schoolList.code`)}}:<span>{{ item.id }}</span>
                       </div>
@@ -330,11 +339,6 @@
                       <div class="table-not-title">未管理学校列表</div>
                       <div class="searchSc-box">
                         <el-input v-model="manaNotValue" placeholder="搜索 学校名称/简码" class="input-with-select" size="small" clearable>
-                          <template #prepend>
-                            <svg class="addrelevancy-icon" aria-hidden="true">
-                              <use xlink:href="#icon-sousuo3-copy"></use>
-                            </svg>
-                          </template>
                         </el-input>
                       </div>
                       <el-table :data="adminSchoold.not" style="width: 100%" max-height="55vh" height="55vh" v-loading="adminSchoold.loading" element-loading-text="数据加载中..." empty-text="暂无数据" size="small" @selection-change="addSelectSchool">
@@ -593,7 +597,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 } from '@element-plus/icons-vue'
+import { CopyDocument, ArrowRight, ArrowLeft, Search } from '@element-plus/icons-vue'
 import useClipboard from 'vue-clipboard3'
 import jwt_decode from 'jwt-decode'
 const optionsData = option
@@ -603,7 +607,8 @@ export default {
     loadingsz,
     CopyDocument,
     ArrowRight,
-    ArrowLeft
+    ArrowLeft,
+    Search
   },
   setup () {
     let { proxy } = getCurrentInstance()
@@ -630,6 +635,7 @@ export default {
     let adjustmentbox = ref(false)
     let activeName = ref('add')
     let notjoinSchool = ref([])
+    let notjoinPrimitive = ref([])
     let position = ref()
     let cutbtnTitle = ref({
       name: '切换微能力方案',
@@ -706,6 +712,8 @@ export default {
     //学校搜索(左右框内)
     let manaNotValue = ref('')
     let manaJoinValue = ref('')
+    //未加入学区学校搜索
+    let schoolSeach = ref('')
     onMounted(() => {
       provinceOptions.value.optionInfo = optionsData
     })
@@ -770,13 +778,13 @@ export default {
       loadingSchoolList.value = true
       console.log(currentlySelect.value.id)
       proxy.$api
-        .getNotjoinSchool({})
+        .getNotjoinSchool({ areaId: '' })
         .then((res) => {
           console.log(res, '获取未加入区域的学校')
           res.state === 200
             ? ((notjoinSchool.value = []),
-              notjoinSchool.value.push(...res.notAreaSchools),
-              (loadingSchoolList.value = false))
+              notjoinSchool.value.push(...res.notAreaSchools), notjoinPrimitive.value.push(...res.notAreaSchools)
+                (loadingSchoolList.value = false))
             : ''
         })
     }
@@ -1252,6 +1260,12 @@ export default {
       })
       adminSchoold.value.data = newArr
     }
+    //学校列表 未加入学区
+    function notjoinSchoolarea () {
+      let values = schoolSeach.value
+      let newdata = notjoinPrimitive.value.filter((item) => { return item.name.includes(values) })
+      notjoinSchool.value = newdata
+    }
     watch(abilityModel, (newdata) => {
       console.log(newdata)
       newdata
@@ -1276,6 +1290,14 @@ export default {
         optionData.value = originalDatas.value
       }
     })
+    watch(schoolSeach, (newdata) => {
+      // console.log(newdata, '触发搜索内容')
+      if (newdata.trim().length !== 0) {
+        debounce(notjoinSchoolarea, 500)
+      } else {
+        notjoinSchool.value = notjoinPrimitive.value
+      }
+    })
     watch(manaNotValue, (newvalue) => {
       if (newvalue.trim().length !== 0) {
         debounce(searchSchools, 500)
@@ -1365,7 +1387,10 @@ export default {
       manaJoinValue,
       userRoles,
       removeList,
-      removeSelect
+      removeSelect,
+      schoolSeach,
+      notjoinSchoolarea,
+      notjoinPrimitive
     }
   },
 }
@@ -1447,6 +1472,7 @@ export default {
 .list-school-name {
   width: 65%;
   padding-left: 1%;
+  margin-top: 1.5%;
 }
 
 .list-school-name div {
@@ -1736,11 +1762,19 @@ export default {
 }
 .haveSchool-title {
   width: 100%;
-  line-height: 20px;
+  line-height: 40px;
 }
 .haveSchool-title div {
   display: inline-block;
-  vertical-align: top;
+  /* vertical-align: top; */
+  width: 20%;
+}
+.search-school {
+  width: 50% !important;
+  vertical-align: center;
+}
+.search-school div {
+  width: 100%;
 }
 .synchronization-title {
   float: right;

+ 13 - 7
TEAMModelBI/ClientApp/src/view/areamanage/statistics.vue

@@ -117,9 +117,9 @@
       <div class="headerbox" v-loading="aspectsLoading.counselorData" element-loading-background="rgba(0, 0, 0, 0.3)">
         <div class="header-title">
           <p class="header-item-name">{{nowArea.name}}</p>
-          <p class="header-item-school"><span class="header-item-school-title">学区学校数:</span><span class="header-item-school-content">{{nowArea.schoolCount}}</span></p>
+          <!-- <p class="header-item-school"><span class="header-item-school-title">学区学校数:</span><span class="header-item-school-content">{{nowArea.schoolCount}}</span></p>
           <p class="header-item-school"><span class="header-item-school-title">学区教师数:</span><span class="header-item-school-content">{{nowArea.teacherCount}}</span></p>
-          <p class="header-item-school"><span class="header-item-school-title">学区学生数:</span><span class="header-item-school-content">{{nowArea.studentCount}}</span></p>
+          <p class="header-item-school"><span class="header-item-school-title">学区学生数:</span><span class="header-item-school-content">{{nowArea.studentCount}}</span></p> -->
           <p class="header-item-school">
           <div class="header-item-school-title-counselor">学区内顾问:</div>
           <div class="counselor-item" @click="leaves(item)" v-for="item in CounselorList">
@@ -153,7 +153,7 @@
             <p class="right-top-num">{{item.num}}<span v-if="item.classname ==='size'">{{unit.oneself}}</span></p>
             <!-- <p class="right-top-title">{{item.title}}</p> -->
             <div class="right-top-bottombox" :class="[item.classname ==='school' || item.classname ==='teach' || item.classname ==='datas' || item.classname ==='student'? 'area-top-box':'right-all','right-top-bottombox-title']">
-              <div class="right-top-bottombox-title" :class="[item.classname ==='school' || item.classname ==='teach' || item.classname ==='datas'? 'all-top-box':'' ]">
+              <div class="right-top-bottombox-title" :class="[item.classname ==='school' || item.classname ==='teach' || item.classname ==='datas'? 'all-top-box':item.classname ==='size' ? 'sizeclass':'' ]">
                 <p class="right-top-title">{{item.title}}</p>
               </div>
               <div class="right-top-bottombox-comparison" v-if="item.classname ==='school' || item.classname ==='teach' || item.classname ==='datas' || item.classname ==='student'">
@@ -350,7 +350,7 @@ export default {
       { id: 1, title: '学区总数', num: 0, icon: '#icon-quyugongsi', classname: 'school' },
       { id: 2, title: '学区总校数', num: 0, icon: '#icon-all-school', classname: 'months', addweek: 0, addmonth: 0, },
       { id: 3, title: '学区老师数', num: 0, icon: '#icon-laoshi1', classname: 'teach', addweek: 0, addmonth: 0, },
-      { id: 4, title: '产出总数据', num: 0, icon: '#icon-shujutongji', classname: 'datas', addweek: 0, addmonth: 0, },
+      { id: 4, title: '总数据', num: 0, icon: '#icon-shujutongji', classname: 'datas', addweek: 0, addmonth: 0, },
       { id: 5, title: '空间总容量', num: 0, icon: '#icon-kongjian', classname: 'size' },
     ])
     let areaLists = ref([
@@ -2003,10 +2003,10 @@ export default {
   font-size: 16px;
 }
 .right-top-bottombox-title {
-  width: 100%;
+  width: 50%;
 }
 .all-top-box {
-  width: 45% !important;
+  width: 40% !important;
 }
 .area-top-box {
   width: 100%;
@@ -2033,7 +2033,7 @@ export default {
     transform: translate(-50%, 0%);
     color: #2c3e50; */
   margin-top: 5px;
-  font-size: 16px;
+  font-size: 15px;
 }
 .leftbox {
   width: 48%;
@@ -2210,6 +2210,8 @@ export default {
   font-size: 28px;
   font-weight: 600;
   color: #fff;
+  line-height: 28px;
+  margin-top: 2%;
 }
 .headerbox-detailsbtn {
   width: 40%;
@@ -2220,6 +2222,7 @@ export default {
 .header-item-school {
   font-size: 14px;
   color: #fff;
+  margin-top: 5%;
 }
 .header-back {
   width: 22px;
@@ -2469,6 +2472,9 @@ export default {
   width: 100%;
   height: 35vh;
 }
+.sizeclass {
+  width: 100% !important;
+}
 </style>
 <style>
 .statisticsbox-all .el-loading-spinner .circular,

+ 13 - 2
TEAMModelBI/ClientApp/src/view/common/aside.vue

@@ -226,7 +226,7 @@ export default {
         name: '区校掌握',
         icon: '#icon-jichuguanli',
         router: '',
-        role: ['admin', 'assist', 'leader'],
+        role: ['admin', 'assist', 'leader', 'sales'],
         isShow: true,
         permission: '',
         sort: 12,
@@ -253,7 +253,7 @@ export default {
         name: '我参与的',
         icon: '#icon-canyu',
         router: '',
-        role: ['admin', 'assist', 'leader'],
+        role: ['admin', 'assist', 'leader', 'sales'],
         isShow: true,
         permission: '',
         sort: 15,
@@ -349,6 +349,17 @@ export default {
         if (a > b) return 1
         return 0
       })
+      //处理顾问和销售  没有学区情况的路由
+      let userIsstate = userRoles.includes('admin') || userRoles.includes('leader') ? true : false
+      if ((userRoles.includes('sales') || userRoles.includes('assist')) && userIsstate === false) {
+        for (let i in menuList.value) {
+          let menuChild = menuList.value[i]
+          for (let y in menuChild.child) {
+            console.log(menuChild.child[y], 'Menu内容')
+            menuChild.child[y].router === '/home/district' ? menuChild.child.splice(y, 1) : ''
+          }
+        }
+      }
       console.log(menuList.value, result, '菜单')
       //router内容
       let nowUrl = routers.currentRoute.value.path

+ 13 - 10
TEAMModelBI/ClientApp/src/view/created/created.vue

@@ -768,15 +768,18 @@ export default {
       loadingCreatedArea.value = true;
       //获取最后一位的名字,生成名字
       let newstandard = formArea.value.options[formArea.value.options.length - 1].standard.substring(formArea.value.options[formArea.value.options.length - 1].standard.indexOf('standard') + 8)
-      let newname = 'standard' + (Number(newstandard) + 1)
+      let newname = 'standard' + (Number(newstandard) + 2)
+      console.log(newstandard, newname, '学区标准名')
       //查找选中的名字
-      let selectName = formArea.value.options.filter((item) => {
-        return item.id === formArea.value.capacityvalue
-      })
-      let users = JSON.parse(localStorage.getItem('userData'))
-      console.log(formArea.value.options)
+      console.log(formArea.value.capacityvalue, '选择名字')
       let names = ''
-      formArea.value.options.forEach((item) => { item.standard === selectName[0].standard ? names = item.name : '' })
+      let users = JSON.parse(localStorage.getItem('userData'))
+      if (formArea.value.capacityvalue) {
+        let selectName = formArea.value.options.filter((item) => {
+          return item.id === formArea.value.capacityvalue
+        })
+        formArea.value.options.forEach((item) => { item.standard === selectName[0].standard ? names = item.name : '' })
+      }
       let createdParame = {
         name: formArea.value.areaname.value,
         provCode: !formArea.value.areaselect.state ? formArea.value.areaselect.provincevalue : '',
@@ -788,9 +791,9 @@ export default {
         standard: newname,
         standardName: formArea.value.areaname.value,
         institution: formArea.value.institution,
-        oldId: formArea.value.capacityvalue,
-        oldStandard: selectName[0].standard,
-        oldName: names,
+        oldId: formArea.value.capacityvalue ? formArea.value.capacityvalue : '',
+        oldStandard: formArea.value.capacityvalue ? selectName[0].standard : '',
+        oldName: formArea.value.capacityvalue ? names : '',
         areaAdmin: formArea.value.areaAdmin,
         tmdId: users.tmdId,
         tmdName: users.tmdName,

+ 29 - 23
TEAMModelBI/ClientApp/src/view/index/index.vue

@@ -2255,21 +2255,27 @@ export default {
             })
           }
           console.log(replaceTime, '345345')
-          if (siteValue.value === 'china') {
-            replaceTime.forEach((q) => {
-              nowTimeQuantum.value.classTime.push(q.time)
-              nowTimeQuantum.value.classinToday.push(q.schoolClass)
-              nowTimeQuantum.value.todayUpload.push(q.teachClass)
-              nowTimeQuantum.value.totalattendClass.push(parseInt(q.schoolClass))
-            })
-          } else if (siteValue.value === 'international') {
-            replaceTime.forEach((q) => {
-              worldnowTimeQuantum.value.classTime.push(q.time)
-              worldnowTimeQuantum.value.classinToday.push(q.schoolClass)
-              worldnowTimeQuantum.value.todayUpload.push(q.teachClass)
-              worldnowTimeQuantum.value.totalattendClass.push(parseInt(q.schoolClass))
-            })
-          }
+          replaceTime.forEach((q) => {
+            nowTimeQuantum.value.classTime.push(q.time)
+            nowTimeQuantum.value.classinToday.push(q.schoolClass)
+            nowTimeQuantum.value.todayUpload.push(q.teachClass)
+            nowTimeQuantum.value.totalattendClass.push(parseInt(q.schoolClass))
+          })
+          // if (siteValue.value === 'china') {
+          //   replaceTime.forEach((q) => {
+          //     nowTimeQuantum.value.classTime.push(q.time)
+          //     nowTimeQuantum.value.classinToday.push(q.schoolClass)
+          //     nowTimeQuantum.value.todayUpload.push(q.teachClass)
+          //     nowTimeQuantum.value.totalattendClass.push(parseInt(q.schoolClass))
+          //   })
+          // } else if (siteValue.value === 'international') {
+          //   replaceTime.forEach((q) => {
+          //     worldnowTimeQuantum.value.classTime.push(q.time)
+          //     worldnowTimeQuantum.value.classinToday.push(q.schoolClass)
+          //     worldnowTimeQuantum.value.todayUpload.push(q.teachClass)
+          //     worldnowTimeQuantum.value.totalattendClass.push(parseInt(q.schoolClass))
+          //   })
+          // }
 
           console.log(nowTimeQuantum.value.todayUpload, '999999999999999999')
           //处理课例活跃数据(今日)
@@ -3122,7 +3128,7 @@ export default {
         totalArea.value.dynamic.series[1].data = nowTimeQuantum.value.classinToday
         totalArea.value.dynamic.series[2].data = nowTimeQuantum.value.yesterdayUpload
         totalArea.value.dynamic.series[3].data = nowTimeQuantum.value.classinYesterday
-        getClassLivelys()
+        // getClassLivelys()
       } else if (val === 'allmonth') {
         let month = date.getMonth() + 1
         console.log(month)
@@ -3244,13 +3250,13 @@ export default {
   background: url("../../assets/img/bg-index.jpg") no-repeat;
   background-size: 100% 100%;
   position: relative;
-  height: 100%;
+  /* height: 100%; */
 }
 .statisticsbox,
 .statisticsbox-all {
   width: 100%;
   height: 100%;
-  /* padding: 1% 1%; */
+  padding: 0% 0%;
   line-height: 20px;
   position: relative;
   /* margin-top: 35px; */
@@ -3272,7 +3278,7 @@ export default {
   position: relative;
   /* border-radius: 10px; */
   overflow: hidden;
-  padding-right: 2%;
+  padding-right: 1%;
   border-right: 1px solid #ccc;
   /* opacity: 0.2; */
 }
@@ -3292,12 +3298,12 @@ export default {
   display: table;
   text-align: center;
   /* background: rgba(223, 230, 233, 0.3); */
-  width: 30%;
+  width: 25%;
   position: relative;
 }
 
 .right-top-text {
-  width: 70%;
+  width: 75%;
   /* background: rgba(255, 255, 255, .9); */
   float: left;
   height: 100%;
@@ -3511,7 +3517,7 @@ export default {
 .bottom-leftbox {
   width: 56%;
   padding: 1%;
-  height: 350px;
+  height: 340px;
   /* background: #fff; */
   position: relative;
   margin-right: 1%;
@@ -3521,7 +3527,7 @@ export default {
 
 .bottom-rightbox {
   width: 43%;
-  height: 350px;
+  height: 340px;
   /* background-color: #fff; */
   display: flex;
   justify-content: center;

+ 557 - 0
TEAMModelBI/ClientApp/src/view/participation/examination.vue

@@ -0,0 +1,557 @@
+<template>
+  <div class="examinationbox">
+    <div class="header-filter">
+      <el-collapse v-model="activeNames" accordion>
+        <el-collapse-item title="数据筛选" name="1">
+          <div class="filtratebox">
+            <!--学段-->
+            <div class="filtratebox-phase">
+              <span class="filtratebox-phase-title">{{filters.pahse.name}}:</span>
+              <div class="filtratebox-phase-content">
+                <div class="phase-item" v-for="(items,index) in filters.pahse.option" :key="items.value" :class="[index ===clickNum.pahse ? 'filter-click':'' ]" @click="clickCut(items.id,index,'pahse')">{{items.name}}</div>
+              </div>
+            </div>
+            <!--学段end-->
+            <!--科目-->
+            <div class="filtratebox-phase">
+              <span class="filtratebox-phase-title">{{filters.subject.name}}:</span>
+              <div class="filtratebox-phase-content">
+                <div class="phase-item" v-for="(items,index) in filters.subject.option" :key="items.value" :class="[index ===clickNum.subject ? 'filter-click':'' ]" @click="clickCut(items.id,index,'subject')">{{items.name}}</div>
+              </div>
+            </div>
+            <!--科目end-->
+            <!--年级-->
+            <div class="filtratebox-phase">
+              <span class="filtratebox-phase-title">{{filters.grade.name}}:</span>
+              <div class="filtratebox-phase-content">
+                <div class="phase-item" v-for="(items,index) in filters.grade.option" :key="items.value" :class="[index ===clickNum.grade ? 'filter-click':'' ]" @click="clickCut(items,index,'grade')">{{items}}</div>
+              </div>
+            </div>
+            <!--年级end-->
+          </div>
+        </el-collapse-item>
+      </el-collapse>
+    </div>
+    <div class="middlebox">
+      <div class="middlebox-content">
+        <div class="middlebox-left">
+          <div class="middlebox-left-tag">
+            <span>标签:</span>
+            <el-select v-model="findbox.tagValue" class="m-2" placeholder="请选择" size="small" multiple @change="selectContent">
+              <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+          </div>
+          <div class="middlebox-left-serach">
+            <el-input v-model="findbox.searchValue" class="w-80 m-2" placeholder="输入试卷名进行搜索..." suffix-icon="el-icon-search" size="small" />
+          </div>
+        </div>
+        <div class="middlebox-right">
+          <div class="middlebox-right-title">共有<span class="middlebox-right-num">{{paperData.total}}</span>套</div>
+        </div>
+      </div>
+    </div>
+    <div class="bottombox">
+      <div class="bottombox-list" v-if="paperData.data.length !==0">
+        <div class="paperlist" v-for="item in paperData.data" :key="item.id">
+          <div class="paperlist-name">
+            <span class="paperlist-name-tag">{{item.subjectName}}</span>
+            <span class="paperlist-name-title">{{item.name}}</span>
+            <span class="paperlist-name-hint" v-for="itemg in item.tags">
+              <div :class="[itemg.indexOf('测试') !=-1|| itemg.indexOf('测试卷') !=-1? 'hint-tag':itemg.indexOf('A3') !=-1 || itemg.indexOf('A4') !=-1 ?'paper-green':'default-tag']">
+                <span :class="[itemg.indexOf('测试') !=-1|| itemg.indexOf('测试卷') !=-1 ? 'hint-tag-text':itemg.indexOf('A3') !=-1 || itemg.indexOf('A4') !=-1 ?'paper-green-text':'default-tag-text']">{{itemg}}</span>
+              </div>
+            </span>
+          </div>
+          <div class="paperlist-info">
+            <span class="paperlist-info-title">
+              适用学段:
+              <span class="paperlist-info-content">{{item.pahseText}}</span>
+            </span>
+            <span class="paperlist-info-title">
+              适用年级:
+              <span class="paperlist-info-content">{{item.gradeText}}</span>
+            </span>
+            <span class="paperlist-info-title">
+              题量:
+              <span class="paperlist-info-content">{{item.scoring.length}}</span>
+            </span>
+            <span class="paperlist-info-title">
+              排序方式:
+              <span class="paperlist-info-content">题型排序</span>
+            </span>
+            <span class="paperlist-info-title">
+              更新时间:
+              <span class="paperlist-info-content">{{item.timeText}}</span>
+            </span>
+          </div>
+          <div class="paperlist-tools">
+            <!-- <span class="paperlist-tools-download">
+              <svg class="icon" aria-hidden="true">
+                <use xlink:href="#icon-xiazai"></use>
+              </svg>
+              <span class="paperlist-tools-download-title">下载</span>
+            </span> -->
+            <span class="paperlist-tools-delete">
+              <svg class="icon" aria-hidden="true">
+                <use xlink:href="#icon-shanchutianchong"></use>
+              </svg>
+              <span class="paperlist-tools-download-title">删除</span>
+            </span>
+          </div>
+        </div>
+      </div>
+      <div class=notdatas v-else>
+        <div>
+          <el-image :src="notdataImg" fit="fill" />
+        </div>
+        <div class="notdata-text">暂无数据</div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import { ref, watch, getCurrentInstance } from 'vue'
+import { useStore } from 'vuex'
+import { ElMessage, ElLoading } from 'element-plus'
+export default {
+  props: {
+    detailsSchool: {
+      default: {}
+    },
+  },
+  setup (props) {
+    let { proxy } = getCurrentInstance()
+    const store = useStore()
+    let activeNames = ref(['1'])
+    const notdataImg = require('@/assets/img/notdata.png')
+    let findbox = ref({
+      tagValue: '',
+      searchValue: ''
+    })
+    const options = [
+      {
+        value: '测试',
+        label: '测试',
+      },
+      {
+        value: '测试卷',
+        label: '测试卷',
+      },
+      {
+        value: 'A3答题卡',
+        label: 'A3答题卡',
+      },
+      {
+        value: 'A4答题卡',
+        label: 'A4答题卡',
+      },
+    ]
+    let filters = ref({
+      pahse: { name: '学段', option: [] },
+      subject: { name: '科目', option: [] },
+      grade: { name: '年级', option: [] },
+    }
+    )
+    let clickNum = ref({
+      pahse: 0,
+      subject: 0,
+      grade: 0,
+    })
+    let filterperiod = ref([])
+    let allperiod = ref()
+    let nowperiod = ref()
+    //试卷资源
+    let paperData = ref({
+      total: 0,
+      data: [],
+      nowselectData: []
+    })
+    //处理筛选
+    function filterInt (data) {
+      console.log(data, '试卷数据')
+      allperiod.value = data
+      nowperiod.value = data.period
+      let schoolPeriod = data.period
+      for (let i in schoolPeriod) {
+        filters.value.pahse.option.push({ name: schoolPeriod[i].name, id: schoolPeriod[i].id })
+      }
+      filters.value.subject.option = schoolPeriod[0].subjects
+      // schoolPeriod[0].grades.unshift('全部')
+      // filters.value.grade.option.push()
+      let allArr = ['全部']
+      filters.value.grade.option = ([...allArr, ...schoolPeriod[0].grades])
+      //filters.value.grade.option.unshift('全部')
+      console.log(filters.value, '结果!')
+      getExamination(filters.value.pahse.option[0].id, filters.value.subject.option[0].id, true)
+    }
+    //获取相应的试卷内容
+    function getExamination (pahseId, subjectId, sort) {
+      let data = {
+        code: allperiod.value.id,
+        periodId: pahseId,
+        subjectId: [subjectId],
+        scope: 'school',
+        gradeIds: clickNum.value.grade === 0 ? '' : (Number(clickNum.value.grade) - 1).toString(),
+        isSort: sort ? false : true
+      }
+      proxy.$api.getExaminations(data).then((res) => {
+        console.log(res, 'API试卷资源')
+        if (res.state === 200) {
+          let papers = res.papers
+          paperData.value.total = res.cnt
+          for (let item of papers) {
+            let pahseIds = item.periodId; let subjectIds = item.subjectId; let gradeIds = item.gradeIds
+            item.pahseText = ''; item.subjectText = ''; item.gradeText = ''; item.timeText = ''
+            //处理适用学段
+            for (let p of filters.value.pahse.option) {
+              p.id === pahseIds ? item.pahseText = p.name : ''
+            }
+            //处理适用年级
+            gradeIds.forEach((itema) => {
+              let gradeNum = Number(itema) + 1
+              for (let g in filters.value.grade.option) {
+                // console.log(g, gradeNum, filters.value.grade.option[g])
+                g == gradeNum ? item.gradeText = item.gradeText ? item.gradeText + '/' + filters.value.grade.option[g] : item.gradeText = filters.value.grade.option[g] : ''
+              }
+            })
+            item.timeText = proxy.$common.timestampToTime(item.createTime, 'all')
+          }
+          paperData.value.data = papers
+          paperData.value.nowselectData = papers
+          console.log(papers, '处理结果')
+        }
+      }).catch((error) => {
+        ElMessage.error('API异常获取试卷失败')
+      })
+    }
+    //切换学科、科目、年级
+    function clickCut (value, index, state) {
+      console.log(nowperiod.value, '现在的值')
+      let pahseids = ''; let subjects = ''
+      if (state === 'pahse') {
+        clickNum.value.pahse = index
+        filters.value.grade.option = []
+        for (let p of nowperiod.value) {
+          p.id === value ? (filters.value.subject.option = p.subjects, filters.value.grade.option = ([...['全部'], ...p.grades]), pahseids = value, subjects = p.subjects[0].id) : ''
+        }
+      } else if (state === 'subject') {
+        clickNum.value.subject = index
+        let data = nowperiod.value[clickNum.value.pahse]
+        filters.value.grade.option = []
+        filters.value.grade.option = ([...['全部'], ...data.grades])
+        subjects = value; pahseids = nowperiod.value[clickNum.value.pahse].id
+      } else if (state === 'grade') {
+        // clickNum.value.grade = value !== '全部' ? Number(index) + 1 : index
+        clickNum.value.grade = index
+        pahseids = nowperiod.value[clickNum.value.pahse].id;
+        subjects = nowperiod.value[clickNum.value.pahse].subjects[clickNum.value.subject].id
+      }
+      findbox.value.tagValue = ''
+      getExamination(pahseids, subjects)
+    }
+    //标签筛选
+    function selectContent (val) {
+      if (val.length === 0) {
+        let pahseids = ''; let subjectid = ''
+        let datas = allperiod.value
+        console.log(datas, '复原的总数据')
+        pahseids = datas.period[clickNum.value.pahse].id
+        subjectid = datas.period[clickNum.value.pahse].subjects[clickNum.value.subject].id
+        getExamination(pahseids, subjectid)
+      }
+      let data = val
+      let selectData = []
+      console.log(paperData.value.data)
+      data.forEach((item) => {
+        let name = item
+        console.log(name, 'name')
+        for (let i of paperData.value.nowselectData) {
+          console.log(i)
+          i.tags.includes(name) ? selectData.push(i) : ''
+        }
+      })
+      paperData.value.data = selectData
+    }
+    watch(
+      props,
+      (newdata, olddata) => {
+        console.log(newdata, '试卷数据')
+        newdata.detailsSchool !== undefined && newdata !== olddata ? filterInt(newdata.detailsSchool) : ''
+      },
+      { immediate: true, deep: true }
+    )
+    return { activeNames, findbox, options, filters, clickNum, filterInt, filterperiod, allperiod, getExamination, paperData, nowperiod, clickCut, notdataImg, selectContent }
+  },
+}
+</script>
+<style scoped>
+.examinationbox {
+  width: 100%;
+  height: 87vh;
+  line-height: 20px;
+}
+.header-filter,
+.middlebox {
+  /* width: 100%; */
+  /* background-color: #fff; */
+  margin: 10px 20px;
+}
+.middlebox {
+  background-color: #fff;
+}
+.middlebox-content {
+  display: flex;
+}
+.middlebox-left {
+  width: 50%;
+  text-align: left;
+  padding-left: 1%;
+  font-size: 14px;
+  display: flex;
+}
+.middlebox-left-tag {
+  width: 35%;
+}
+.middlebox-left-serach {
+  width: 65%;
+}
+.middlebox-right {
+  width: 50%;
+  text-align: right;
+  font-size: 16px;
+  line-height: 48px;
+  padding-right: 1%;
+}
+.middlebox-right-num {
+  font-size: 18px;
+  color: #eb4d4b;
+}
+.bottombox {
+  background-color: #e9eef3;
+  margin: 10px 20px;
+  height: 75vh;
+  overflow: auto;
+}
+.paperlist {
+  height: 90px;
+  background: #fff;
+  margin-bottom: 10px;
+  padding-left: 10px;
+  align-items: flex-start;
+  cursor: pointer;
+  width: 100%;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+.paperlist-name {
+  font-size: 20px;
+  font-weight: 700;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.paperlist-name-tag {
+  font-size: 12px;
+  padding: 1px 10px;
+  border-radius: 5px;
+  color: #fff;
+  background: #15a06c;
+  margin: 0 10px;
+}
+.paperlist-name-title {
+  margin-left: 8px;
+}
+.paperlist-info {
+  margin-top: 18px;
+}
+.paperlist-info-title {
+  border-right: 2px solid #f3f3f3;
+  font-size: 12px;
+  padding: 0 10px;
+}
+.paperlist-info-title:last-child {
+  border-right: 0px !important;
+}
+.paperlist-info-content {
+  font-weight: 700;
+  color: #70b1e7;
+}
+.bottombox-list {
+  width: 100%;
+}
+.paperlist-tools {
+  position: absolute;
+  height: 100%;
+  right: 0px;
+  top: 0;
+  font-size: 14px;
+  color: #767676;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.paperlist-tools-download,
+.paperlist-tools-delete {
+  margin-right: 30px;
+  /* position: absolute; */
+  height: 100%;
+  /* right: 50px; */
+  top: 0;
+  font-size: 14px;
+  color: #767676;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.paperlist-tools-delete {
+  margin-right: 30px;
+}
+.paperlist-tools-download-title {
+  width: 35px;
+}
+.icon {
+  width: 1.3em;
+  height: 1.3em;
+  vertical-align: -0.4em;
+  fill: currentColor;
+  overflow: hidden;
+  margin-right: 5px;
+  margin-left: 0px;
+}
+.filtratebox {
+  width: 100%;
+  padding: 10px 20px;
+  padding-bottom: 20px;
+  background: #fff;
+  border-top: 1px solid #ccc;
+}
+.filtratebox-phase {
+  width: 100%;
+  margin-top: 10px;
+  display: flex;
+}
+.filtratebox-phase-title {
+  width: 3%;
+  font-size: 16px;
+  font-weight: bold;
+  margin-right: 10px;
+  min-width: 45px;
+}
+.filtratebox-phase-content {
+  width: 97%;
+  display: flex;
+  flex-wrap: wrap;
+}
+.phase-item {
+  padding: 0 10px;
+  margin-left: 15px;
+  height: 28px;
+  line-height: 28px;
+  box-shadow: none !important;
+  border: none !important;
+  font-size: 14px;
+  cursor: pointer;
+}
+.phase-item:hover {
+  color: #409eff;
+}
+.filter-click {
+  background: #10abe7;
+  box-shadow: none;
+  color: #fff !important;
+  border-radius: 5px;
+}
+.paperlist-name-hint {
+  margin-left: 8px;
+  font-size: 12px;
+  font-weight: 700;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.hint-tag {
+  line-height: 20px;
+  background: #f0f5ff;
+  border-color: #adc6ff;
+  vertical-align: sub;
+  display: inline-block;
+  height: 22px;
+  margin: 2px 4px 2px 0;
+  padding: 0 8px;
+  border: 1px solid #e8eaec;
+  border-radius: 3px;
+}
+.hint-tag-text {
+  color: #2f54eb !important;
+}
+.paper-green {
+  line-height: 20px;
+  background: #f6ffed;
+  border-color: #b7eb8f;
+  vertical-align: sub;
+  display: inline-block;
+  height: 22px;
+  margin: 2px 4px 2px 0;
+  padding: 0 8px;
+  border: 1px solid #e8eaec;
+  border-radius: 3px;
+}
+.paper-green-text {
+  color: #52c41a !important;
+}
+.default-tag {
+  line-height: 20px;
+  background: #b2bec3;
+  border-color: #dfe6e9;
+  display: inline-block;
+  height: 22px;
+  margin: 2px 4px 2px 0;
+  padding: 0 8px;
+  border: 1px solid #e8eaec;
+  border-radius: 3px;
+}
+.default-tag-text {
+  color: #636e72;
+}
+.notdatas {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  width: 100%;
+  padding: 60px;
+  background: #fff;
+  /* margin-top: 10px; */
+  font-size: 16px;
+}
+.notdata-text {
+  margin-top: 10px;
+  font-size: 16px;
+  color: #8395a7;
+}
+@media screen and (max-width: 1920px) {
+}
+@media screen and (max-width: 1400px) {
+  .middlebox-left-tag {
+    width: 50% !important;
+  }
+  .filtratebox-phase-title {
+    width: 5% !important;
+  }
+  .examinationbox {
+    height: 84vh !important;
+  }
+}
+</style>
+<style>
+.header-filter .el-collapse-item__header {
+  padding-left: 1%;
+  font-size: 16px;
+  font-weight: bold;
+}
+.notdatas .el-image__inner {
+  width: 40%;
+}
+</style>

+ 243 - 104
TEAMModelBI/ClientApp/src/view/participation/index.vue

@@ -120,9 +120,11 @@
         <!-- <el-table-column prop="state" label="状态" width="110" align="center" /> -->
         <el-table-column :label="$t(`schoolManages.tables.operate`)" align="center">
           <template #default="scope">
-            <el-button type="primary" size="small" @click.prevent="deleteRow(scope.$index, scope.row)">
-              {{ $t(`schoolManages.tables.operatecontent`) }}</el-button>
+            <el-button type="primary" size="small" @click.prevent="deleteRow(scope.$index, scope.row)" v-if="userPower.roles.includes('sales')">
+              查看</el-button>
             <!-- <el-button type="danger" size="small" @click="removeSchool(scope.row,scope.$index)">删除</el-button> -->
+            <el-button type="primary" size="small" @click.prevent="deleteRow(scope.$index, scope.row)" v-else>
+              {{ $t(`schoolManages.tables.operatecontent`) }}</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -152,10 +154,14 @@
           <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">
-                <el-input v-model="nowPitchdata.name"></el-input>
+                <el-input v-model="nowPitchdata.name" v-if="userPower.roles.includes('sales')" disabled></el-input>
+                <el-input v-model="nowPitchdata.name" v-else></el-input>
               </el-form-item>
               <el-form-item :label="$t(`schoolManages.basicSet.badge`) + ':'" class="school-form-badge">
-                <el-upload class="upload-demo-redact" :headers="uploadHeader" action="/blob/upload-public" :before-upload="changeBadge" :on-success="success" :on-error="handleUpdErr">
+                <div class="upload-demo-redact" v-if="userPower.roles.includes('sales')">
+                  <el-image :src="nowPitchdata.picture" fit="contain"></el-image>
+                </div>
+                <el-upload class="upload-demo-redact" :headers="uploadHeader" action="/blob/upload-public" :before-upload="changeBadge" :on-success="success" :on-error="handleUpdErr" v-else>
                   <el-image :src="nowPitchdata.picture" fit="contain"></el-image>
                   <div class="changebadge">
                     <el-button>{{ $t(`schoolManages.basicSet.badgeChange`) }}</el-button>
@@ -170,10 +176,18 @@
                                 <el-checkbox v-model="nowPitchdata.period[4].value" label="大学"></el-checkbox>
                             </el-form-item> -->
               <el-form-item :label="$t(`schoolManages.basicSet.type`) + ':'" class="school-form-grading">
-                <el-radio v-model="nowPitchdata.type" label="1" size="large">
-                  {{ $t(`schoolManages.basicSet.ordinary`) }}</el-radio>
-                <el-radio v-model="nowPitchdata.type" label="2" size="large">
-                  {{ $t(`schoolManages.basicSet.higherEducation`) }}</el-radio>
+                <el-radio-group v-model="nowPitchdata.type" class="study-radio" disabled v-if="userPower.roles.includes('sales')">
+                  <el-radio label="1" size="large">
+                    {{ $t(`schoolManages.basicSet.ordinary`) }}</el-radio>
+                  <el-radio label="2" size="large">
+                    {{ $t(`schoolManages.basicSet.higherEducation`) }}</el-radio>
+                </el-radio-group>
+                <el-radio-group v-model="nowPitchdata.type" class="study-radio" v-else>
+                  <el-radio label="1" size="large">
+                    {{ $t(`schoolManages.basicSet.ordinary`) }}</el-radio>
+                  <el-radio label="2" size="large">
+                    {{ $t(`schoolManages.basicSet.higherEducation`) }}</el-radio>
+                </el-radio-group>
               </el-form-item>
               <!-- <el-form-item :label="$t(`schoolManages.basicSet.nowAssistant`)+':'" class="school-form-admin">
                                 <el-select v-model="adminvalue" multiple @change="assistChange" :placeholder="$t(`schoolManages.basicSet.nowAssistanthint`)">
@@ -186,7 +200,13 @@
                 <el-input disabled :placeholder="$t(`schoolManages.basicSet.notCode`)" v-else="nowPitchdata.id ==null" />
               </el-form-item>
               <el-form-item label="所属学区:" class="school-form-area">
-                <el-select v-model="areaSelect.Selectvalue" :placeholder="$t(`schoolManages.basicSet.region`)">
+                <el-select v-model="areaSelect.Selectvalue" :placeholder="$t(`schoolManages.basicSet.region`)" disabled v-if="userPower.roles.includes('sales')">
+                  <el-option v-for="item in areaSelect.data" :key="item.name" :label="item.name" :value="item.id" :disabled="item.cutArea">
+                    <div class="areaname">{{item.name}}</div>
+                    <div class="stepicon" v-show="item.cutArea"><span>已同步省平台</span></div>
+                  </el-option>
+                </el-select>
+                <el-select v-model="areaSelect.Selectvalue" :placeholder="$t(`schoolManages.basicSet.region`)" v-else>
                   <el-option v-for="item in areaSelect.data" :key="item.name" :label="item.name" :value="item.id" :disabled="item.cutArea">
                     <div class="areaname">{{item.name}}</div>
                     <div class="stepicon" v-show="item.cutArea"><span>已同步省平台</span></div>
@@ -200,14 +220,28 @@
                                 <el-input disabled :placeholder="nowPitchdata.address" />
                             </el-form-item> -->
               <el-form-item :label="$t(`schoolManages.basicSet.spacesize`) + ':'" class="school-form-size">
-                <el-slider v-model="nowPitchdata.size" :step="100" show-stops show-input :min='0' :max='1000' />
+                <div v-if="!userPower.roles.includes('sales')" class="sizebox">
+                  <el-slider v-model="nowPitchdata.size" :step="500" show-stops show-input :min='0' :max='10300' />
+                </div>
+                <div v-else class="sizebox">
+                  <el-slider v-model="nowPitchdata.size" :step="500" show-stops show-input :min='0' :max='10300' disabled />
+                </div>
+                <div class="siznum">GB</div>
+                <div class="selectsize">
+                  <span>快捷选定:</span>
+                  <el-button size="small" @click="nowPitchdata.size =100" disabled v-if="userPower.roles.includes('sales')">100</el-button>
+                  <el-button size="small" @click="nowPitchdata.size =100" v-else>100</el-button>
+                  <el-button size="small" @click="nowPitchdata.size =300" disabled v-if="userPower.roles.includes('sales')">300</el-button>
+                  <el-button size="small" @click="nowPitchdata.size =300" v-else>300</el-button>
+                  <el-button size="small" @click="nowPitchdata.size =500" disabled v-if="userPower.roles.includes('sales')">500</el-button>
+                  <el-button size="small" @click="nowPitchdata.size =500" v-else>500</el-button>
+                </div>
               </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> -->
-              <el-form-item>
-                <el-button type="primary" @click="updateSchoolinfo">
-                  {{ $t(`schoolManages.basicSet.submit`) }}</el-button>
+              <el-form-item v-show="!userPower.roles.includes('sales')">
+                <el-button type="primary" @click="updateSchoolinfo">{{ $t(`schoolManages.basicSet.submit`) }}</el-button>
                 <el-button @click="schoolClose">{{ $t(`commonMsg.closes`) }}</el-button>
               </el-form-item>
             </el-form>
@@ -215,30 +249,31 @@
         </div>
       </el-tab-pane>
       <el-tab-pane :label="$t(`schoolManages.redactGrading`)">
-        <SetSchool :schoolData="studyPhase" ref="setSchoolData"></SetSchool>
+        <SetSchool :detailsSchool="detailsSchool" ref="setSchoolData"></SetSchool>
+      </el-tab-pane>
+      <el-tab-pane label="试卷资源">
+        <Exammination :detailsSchool="detailsSchool"></Exammination>
       </el-tab-pane>
-      <!-- <el-tab-pane :label="$t(`schoolManages.redactServe`)">
-                <Impower :schoolCode="studyPhase"></Impower>
-            </el-tab-pane>
-            <el-tab-pane :label="$t(`schoolManages.redactSerial`)">
-                <Classpower :schoolCode="studyPhase"></Classpower>
-            </el-tab-pane> -->
     </el-tabs>
   </div>
   <!--编辑学校页面end-->
 </template>
 <script>
 import { reactive, ref, getCurrentInstance, toRef, onMounted, watch } from 'vue'
-import option from '@/static/region.json'
+import option_cn from '@/static/regions/region_cn.json'
+import option_gl from '@/static/regions/region_gl.json'
 import { useStore } from 'vuex'
 import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
 import { useRouter } from 'vue-router'
 import jwt_decode from 'jwt-decode'
 import SetSchool from './setPhase.vue'
-const optionsData = option
+import Exammination from './examination.vue'
+const siteValue = window.location.host === 'localhost:5001' ? 'cn' : window.location.host === 'bi.teammodel.cn' ? 'cn' : window.location.host === 'bitest.teammodel.cn' ? 'cn' : 'international'
+const optionsData = siteValue === 'cn' ? option_cn : option_gl
 export default {
   components: {
     SetSchool,
+    Exammination
   },
   setup () {
     let { proxy } = getCurrentInstance()
@@ -246,6 +281,7 @@ export default {
     let PowerShow = true
     const store = useStore()
     const routerInfo = useRouter()
+    let userPower = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
     //为了让表单呈现 暂时的数据,
     let tableData = ref([])
     const form = reactive({
@@ -284,7 +320,7 @@ export default {
       scale: 0,
     })
     let originalData = ref([])
-    const options = option
+    const options = optionsData
     const props = {
       value: 'name',
       label: 'name',
@@ -351,6 +387,8 @@ export default {
       distCode: '',
     })
     let timer = ref()
+    //学校详情 
+    let detailsSchool = ref()
     onMounted(() => {
       //监听表格滚动事件
       // let table = mutipleTable.value._value.layout.table.refs.bodyWrapper;
@@ -401,12 +439,13 @@ export default {
           }
         }
         console.log(res)
-        res.state == 200 ? (tableData.value.push(...res.schoolAssists), (originalData.value = res.schoolAssists), (loading.value = false)) : ''
+        res.state == 200 ? (tableData.value.push(...res.schoolAssists), (originalData.value = res.schoolAssists), (loading.value = false), tableNexttoken.value = res.continuationToken) : ''
       })
     }
     //点击学校列表,详情
     function deleteRow (index, data) {
       console.log(index, data, 'DATA')
+      let school = data
       //处理的基础设置
       areaSelect.value.data = []
       studyPhase.value = data.id
@@ -427,7 +466,13 @@ export default {
       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()
-      models.value = 'details'
+      proxy.$api.getNowscholl({ schoolId: school.id }).then((res) => {
+        res.state === 200 ? (detailsSchool.value = res.schoolAssists, models.value = 'details') : ElMessage.error('详情API异常,访问失败')
+      }).catch((error) => {
+        ElMessage.error('详情API异常,访问失败')
+        return
+      })
+      // models.value = 'details'
       console.log(nowPitchdata.value, '查看当前学校的值')
     }
     //更换校徽
@@ -441,42 +486,103 @@ export default {
       }
     }
     //地区选择
-    function areaSelctChange (value, model) {
+    async function areaSelctChange (value, model) {
       console.log(value, model, '触发')
-      // loading.value = true
-      // console.log(value)
-      // let data = option
-      // if (model === 'province') {
-      //   //传输下一级的数据给select
-      //   let cityData = data.filter((item) => {
-      //     return item.name === value
-      //   })
-      //   cityOptions.value.cityInfo = cityData[0].children
-      //   //遍历list
-      //   let schoolData = originalData.value.filter((items) => {
-      //     return items.province === value
-      //   })
-      //   tableData.value = schoolData
-      //   console.log(schoolData, tableData.value)
-      // } else if (model === 'city') {
-      //   let distData = cityOptions.value.cityInfo.filter((item) => {
-      //     return item.name === value
-      //   })
-      //   distOptions.value.distInfo = distData[0].children
-      //   let provinceData = provinceOptions.value.provinceValue
-      //   let schoolData = originalData.value.filter((items) => {
-      //     return items.city === value && items.province === provinceData
-      //   })
-      //   tableData.value = schoolData
-      // } else if (model === 'dist') {
-      //   let provinceData = provinceOptions.value.provinceValue
-      //   let cityData = cityOptions.value.cityValue
-      //   let schoolData = originalData.value.filter((items) => {
-      //     return items.city === cityData && items.province === provinceData && items.dist === value
-      //   })
-      //   tableData.value = schoolData
-      // }
-      // loading.value = false
+      loading.value = true
+      let user = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
+      console.log(user, '人员')
+      let roleA = ''
+      if (user.roles.length > 1) {
+        user.roles.includes('admin') ? roleA = 'admin' :
+          user.roles.includes('leader') ? roleA = 'leader' :
+            user.roles.includes('assist') ? roleA = 'assist' :
+              user.roles.includes('sales') ? roleA = 'sales' :
+                user.roles.includes('rdc') ? roleA = 'rdc' : ''
+      } else {
+        roleA = user.roles[0]
+      }
+      var schoolListDatas = []
+      var nextPageToken = ''
+      var regionsData = optionsData
+      if (model === 'province') {
+        //传输下一级的数据给select
+        let cityData = regionsData.filter((item) => {
+          return value.includes(item.name)
+        })
+        cityOptions.value.cityInfo = cityData[0].children
+        let textNums = value.indexOf('省') !== -1 ? value.indexOf('省') : value.indexOf('自治区') !== -1 ? value.indexOf('自治区') : value.indexOf('市') !== -1 ? value.indexOf('市') : value.indexOf('特别行政区') !== -1 ? value.indexOf('特别行政区') : ''
+        let disposeText = value.substr(0, textNums)
+        console.log(textNums, disposeText, '位置')
+        let data = roleA === 'admin' || roleA === 'leader' ? { province: disposeText } : { province: disposeText, tmdId: user.tmdId }
+        await proxy.$api.getSchooldata(data).then((res) => {
+          console.log(res, '筛选结果')
+          // res.state === 200 ? tableData.value=res.schoolAssists:''
+          res.state === 200 ? (schoolListDatas = res.schoolAssists, selectValue.value.province = disposeText, nextPageToken = res.continuationToken) : ''
+        }).catch((error) => {
+          ElMessage.error('API异常,数据 省 筛选失败')
+        })
+        // tableData.value = schoolData
+        // console.log(schoolData, tableData.value)
+      } else if (model === 'city') {
+        let distData = cityOptions.value.cityInfo.filter((item) => {
+          return value.includes(item.name)
+        })
+        distOptions.value.distInfo = distData[0].children
+        // let provinceData = provinceOptions.value.provinceValue
+        // let schoolData = originalData.value.filter((items) => {
+        //   return value.includes(items.city) && provinceData.includes(items.province)
+        //   // return items.city === value && items.province === provinceData
+        // })
+        // tableData.value = schoolData
+        let cityNums = value.indexOf('市') !== -1 && value !== '直辖市' ? value.indexOf('市') : value.indexOf('县') !== -1 ? value.indexOf('县') : value.indexOf('自治州') !== -1 ? value.indexOf('自治州') : value.indexOf('直辖市') !== -1 ? value.length : ''
+        let disposeText = value.substr(0, cityNums)
+        console.log(cityNums, disposeText, '位置')
+        // let data = { province: selectValue.value.province ? selectValue.value.province : '', city: disposeText }
+        let data = roleA === 'admin' || roleA === 'leader' ? { province: selectValue.value.province ? selectValue.value.province : '', city: disposeText } : { province: selectValue.value.province ? selectValue.value.province : '', city: disposeText, tmdId: user.tmdId }
+        await proxy.$api.getSchooldata(data).then((res) => {
+          res.state === 200 ? (schoolListDatas = res.schoolAssists, selectValue.value.city = disposeText, nextPageToken = res.continuationToken) : ''
+        }).catch((error) => {
+          ElMessage.error('API异常,数据 市/县 筛选失败')
+        })
+      } else if (model === 'dist') {
+        let provinceData = provinceOptions.value.provinceValue
+        let cityData = cityOptions.value.cityValue
+        console.log(cityData, provinceData, '进入到地区选择')
+        let distNums = value.indexOf('区') !== -1 && value.length > 2 ? value.indexOf('区') : value.indexOf('县') !== -1 ? value.indexOf('县') : value.indexOf('市') !== -1 ? value.indexOf('市') : value.indexOf('直辖市') !== -1 || value.indexOf('天府新区') !== -1 ? value.length : ''
+        let disposeText = value.substr(0, distNums)
+        console.log(distNums, disposeText, '位置')
+        // let data = { province: selectValue.value.province ? selectValue.value.province : '', city: selectValue.value.city ? selectValue.value.city : '', dist: disposeText }
+        let data = roleA === 'admin' || roleA === 'leader' ? { province: selectValue.value.province ? selectValue.value.province : '', city: selectValue.value.city ? selectValue.value.city : '', dist: disposeText } : { province: selectValue.value.province ? selectValue.value.province : '', city: selectValue.value.city ? selectValue.value.city : '', dist: disposeText, tmdId: user.tmdId }
+        await proxy.$api.getSchooldata(data).then((res) => {
+          res.state === 200 ? (schoolListDatas = res.schoolAssists, nextPageToken = res.continuationToken) : ''
+        }).catch((error) => {
+          ElMessage.error('API异常,数据 地区 筛选失败')
+        })
+      }
+      //统一处理
+      console.log(schoolListDatas, '处理前的')
+      for (let i in schoolListDatas) {
+        schoolListDatas[i].serviceData = []
+        if (schoolListDatas[i].assists) {
+          schoolListDatas[i].assisName = ''
+          schoolListDatas[i].location = schoolListDatas[i].dist !== null ? schoolListDatas[i].province + schoolListDatas[i].city + schoolListDatas[i].dist : schoolListDatas[i].province + schoolListDatas[i].city
+          let datas = schoolListDatas[i].assists
+          for (let y in datas) {
+            schoolListDatas[i].assisName = schoolListDatas[i].assisName + datas[y].tmdName + ','
+          }
+        }
+        if (schoolListDatas[i].service.length > 0) {
+          schoolListDatas[i].service.forEach((x) => {
+            for (let m in patternIcon.value) {
+              patternIcon.value[m].key === x ? schoolListDatas[i].serviceData.push(patternIcon.value[m]) : ''
+            }
+          })
+        }
+      }
+      tableData.value = schoolListDatas
+      tableData.value.forEach((item) => { item.areaName = ''; areaSelect.value.data.forEach((itema) => { item.areaId === itema.id ? item.areaName = itema.name : '' }) })
+      tableNexttoken.value = nextPageToken
+      loading.value = false
     }
     //学校详情 close
     function schoolClose () {
@@ -686,49 +792,49 @@ export default {
     }
     function datascroll () {
       console.log('触发了')
-      // loading.value = true
-      // let data = { contToken: tableNexttoken.value, province: selectValue.value.province, city: selectValue.value.city, dist: selectValue.value.dist }
-      // if (tableNexttoken.value === null) {
-      //   ElMessage.success('已经到最底了')
-      //   setTimeout(function () { loading.value = false }, 500);
-      //   return
-      // }
-      // proxy.$api.getSchooldata(data).then((res) => {
-      //   console.log(res, '查询到下一页数据了')
-      //   if (res.state === 200) {
-      //     for (let i in res.schoolAssists) {
-      //       res.schoolAssists[i].serviceData = []
-      //       if (res.schoolAssists[i].assists) {
-      //         res.schoolAssists[i].assisName = ''
-      //         res.schoolAssists[i].location = res.schoolAssists[i].dist !== null ? res.schoolAssists[i].province + res.schoolAssists[i].city + res.schoolAssists[i].dist : res.schoolAssists[i].province + res.schoolAssists[i].city
-      //         let datas = res.schoolAssists[i].assists
-      //         for (let y in datas) {
-      //           res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
-      //         }
-      //       }
-      //       if (res.schoolAssists[i].service.length > 0) {
-      //         res.schoolAssists[i].service.forEach((x) => {
-      //           for (let m in patternIcon.value) {
-      //             patternIcon.value[m].key === x ? res.schoolAssists[i].serviceData.push(patternIcon.value[m]) : ''
-      //           }
-      //         })
-      //       }
-      //     }
-      //   }
-      //   tableData.value.push(...res.schoolAssists)
-      //   tableData.value.forEach((item) => { item.areaName = ''; areaSelect.value.data.forEach((itema) => { item.areaId === itema.id ? item.areaName = itema.name : '' }) })
-      //   tablesccnt.value = res.scCnt
-      //   tableNexttoken.value = res.continuationToken
-      // }).catch((error) => {
-      //   ElMessage.error('API异常,获取更多学校数据失败')
-      // })
-      // setTimeout(function () { loading.value = false }, 800);
+      loading.value = true
+      let data = { contToken: tableNexttoken.value, province: selectValue.value.province, city: selectValue.value.city, dist: selectValue.value.dist }
+      if (tableNexttoken.value === null || tableNexttoken.value === '') {
+        ElMessage.success('已经到最底了')
+        setTimeout(function () { loading.value = false }, 500);
+        return
+      }
+      proxy.$api.getSchooldata(data).then((res) => {
+        console.log(res, '查询到下一页数据了')
+        if (res.state === 200) {
+          for (let i in res.schoolAssists) {
+            res.schoolAssists[i].serviceData = []
+            if (res.schoolAssists[i].assists) {
+              res.schoolAssists[i].assisName = ''
+              res.schoolAssists[i].location = res.schoolAssists[i].dist !== null ? res.schoolAssists[i].province + res.schoolAssists[i].city + res.schoolAssists[i].dist : res.schoolAssists[i].province + res.schoolAssists[i].city
+              let datas = res.schoolAssists[i].assists
+              for (let y in datas) {
+                res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+              }
+            }
+            if (res.schoolAssists[i].service.length > 0) {
+              res.schoolAssists[i].service.forEach((x) => {
+                for (let m in patternIcon.value) {
+                  patternIcon.value[m].key === x ? res.schoolAssists[i].serviceData.push(patternIcon.value[m]) : ''
+                }
+              })
+            }
+          }
+        }
+        tableData.value.push(...res.schoolAssists)
+        tableData.value.forEach((item) => { item.areaName = ''; areaSelect.value.data.forEach((itema) => { item.areaId === itema.id ? item.areaName = itema.name : '' }) })
+        tablesccnt.value = res.scCnt
+        tableNexttoken.value = res.continuationToken
+      }).catch((error) => {
+        ElMessage.error('API异常,获取更多学校数据失败')
+      })
+      setTimeout(function () { loading.value = false }, 800);
     }
-    // watch(scrollHeight, (newdata) => {
-    //   if (scrollHeight.value < 0) {
-    //     debounce(datascroll, 500)
-    //   }
-    // })
+    watch(scrollHeight, (newdata) => {
+      if (scrollHeight.value < 0) {
+        debounce(datascroll, 500)
+      }
+    })
     getAllschool()
     getAllassists()
     return {
@@ -779,7 +885,9 @@ export default {
       debounce,
       datascroll,
       tableNexttoken,
-      selectValue
+      selectValue,
+      userPower,
+      detailsSchool
     }
   },
 }
@@ -867,7 +975,7 @@ export default {
 }
 
 .school-form-size {
-  width: 21%;
+  width: 55% !important;
   color: #bdc3c7;
 }
 
@@ -1059,6 +1167,9 @@ export default {
   color: #ecf0f1;
   margin: 0 auto;
 }
+.study-radio {
+  text-align: left !important;
+}
 .basic {
   color: #409eff;
 }
@@ -1068,6 +1179,34 @@ export default {
 .majors {
   color: #e6a23c;
 }
+.siznum,
+.sizebox,
+.selectsize {
+  display: inline-block;
+  vertical-align: top;
+}
+.sizebox {
+  width: 50.5%;
+}
+.siznum {
+  width: 3%;
+  margin-left: 2%;
+}
+.selectsize {
+  width: 35%;
+  font-size: 12px;
+  margin-left: 1%;
+}
+@media screen and (max-width: 1920px) {
+  .school-form-size {
+    width: 65% !important;
+  }
+}
+@media screen and (max-width: 1400px) {
+  .school-form-size {
+    width: 80% !important;
+  }
+}
 </style>
 <style>
 .schoolboxtad .el-cascader {

+ 118 - 94
TEAMModelBI/ClientApp/src/view/participation/setPhase.vue

@@ -5,10 +5,11 @@
         <div class="pane-title-name">{{ $t(`schoolManages.gradSet.grad.title`) }}</div>
         <div class="pane-title-icon">
           <el-tooltip placement="bottom">
-            <template #content>{{ $t(`schoolManages.gradSet.grad.hint1`) }}<br />{{
-                                $t(`schoolManages.gradSet.grad.hint2`)
-                        }}<br />{{ $t(`schoolManages.gradSet.grad.hint3`)
-}}<br />{{ $t(`schoolManages.gradSet.grad.hint4`) }}
+            <template #content>
+              {{ $t(`schoolManages.gradSet.grad.hint1`) }}<br />
+              {{$t(`schoolManages.gradSet.grad.hint2`)}}<br />
+              {{ $t(`schoolManages.gradSet.grad.hint3`)}}<br />
+              {{ $t(`schoolManages.gradSet.grad.hint4`) }}
             </template>
             <div>
               <svg class="ordinary-hint" aria-hidden="true">
@@ -17,7 +18,7 @@
             </div>
           </el-tooltip>
         </div>
-        <div class="redactbox" @click="amendPhasename">
+        <div class="redactbox" @click="amendPhasename" v-show="!userPower.roles.includes('sales')">
           <svg class="redacticon" aria-hidden="true">
             <use xlink:href="#icon-bianji"></use>
           </svg>
@@ -51,11 +52,10 @@
           <div class="semesterbox-title-name">{{ $t(`schoolManages.gradSet.semester.title`) }}</div>
           <div class="semesterbox-title-icon">
             <el-tooltip placement="bottom">
-              <template #content>{{ $t(`schoolManages.gradSet.semester.hint1`) }}<br />{{
-                                    $t(`schoolManages.gradSet.semester.hint2`)
-                            }}<br />{{
-        $t(`schoolManages.gradSet.semester.hint3`)
-}}
+              <template #content>
+                {{ $t(`schoolManages.gradSet.semester.hint1`) }}<br />
+                {{$t(`schoolManages.gradSet.semester.hint2`)}}<br />
+                {{$t(`schoolManages.gradSet.semester.hint3`)}}
               </template>
               <div>
                 <svg class="ordinary-hint" aria-hidden="true">
@@ -64,19 +64,17 @@
               </div>
             </el-tooltip>
           </div>
-          <div class="semesterbox-title-add" @click="semesterCompile('', 'semesterAdd')">
+          <div class="semesterbox-title-add" @click="semesterCompile('', 'semesterAdd')" v-show="!userPower.roles.includes('sales')">
             <svg class="mini-hint" aria-hidden="true">
               <use xlink:href="#icon-jia-copy"></use>
             </svg>
           </div>
         </div>
-        <div class="setting-time">
+        <div class="setting-time" v-if="nowschoolData.period[pathNowphase].semesters.length >1">
           <div class="set-item" v-for="(items, index) in nowschoolData.period[pathNowphase].semesters" @mouseenter="semesterCut(items, index)">
             <div class="set-time-semester">{{ items.name }}</div>
             <div class="set-time-start">
-              {{ $t(`schoolManages.gradSet.semester.startTime`) }}<span>{{ items.month }}月</span>/<span>{{
-                                    items.day
-                            }}日</span>
+              {{ $t(`schoolManages.gradSet.semester.startTime`) }}<span>{{ items.month }}月</span>/<span>{{items.day}}日</span>
             </div>
             <div class="set-time-period">
               {{ $t(`schoolManages.gradSet.semester.duration`) }}:<span>{{ items.totaldays }}</span></div>
@@ -84,9 +82,9 @@
               <span>{{ $t(`schoolManages.gradSet.semester.entrance`) }}</span>
             </div>
             <div class="set-time-enrollment-star" v-else-if="items.start === 1" @click="enrollment(items.id)">
-              <span>{{ $t(`schoolManages.gradSet.semester.setEntrance`) }}</span>
+              <span v-show="!userPower.roles.includes('sales')">{{ $t(`schoolManages.gradSet.semester.setEntrance`) }}</span>
             </div>
-            <div class="set-time-redact">
+            <div class="set-time-redact" v-show="!userPower.roles.includes('sales')">
               <div @click="semesterCompile(items, 'updateSemester', index)">
                 <svg class="redact-icon" aria-hidden="true">
                   <use xlink:href="#icon-bianji1"></use>
@@ -140,10 +138,12 @@
             </ul>
           </div>
           <div class="time-now-state">
-            <span>{{ $t(`schoolManages.gradSet.semester.nowstate`) }}:</span><span>{{ timesteps.nowitem.name
-                        }}</span>
+            <span>{{ $t(`schoolManages.gradSet.semester.nowstate`) }}:</span><span>{{ timesteps.nowitem.name}}</span>
           </div>
         </div>
+        <div class="notdata settimg-notdata" v-else>
+          <div class="notdata-title"><span>暂无数据</span></div>
+        </div>
       </div>
       <!--学期设置end-->
       <!--年级设置-->
@@ -151,20 +151,20 @@
         <div class="semesterbox-title">
           <div class="semesterbox-title-name">{{ $t(`schoolManages.gradSet.gradeAndsubjects.gradeTitle`) }}
           </div>
-          <div class="semesterbox-title-add" @click="addsemester()">
+          <div class="semesterbox-title-add" @click="addsemester()" v-show="!userPower.roles.includes('sales')">
             <svg class="mini-hint" aria-hidden="true">
               <use xlink:href="#icon-jia-copy"></use>
             </svg>
           </div>
         </div>
-        <div class="class-item-frame">
+        <div class="class-item-frame" v-if="nowschoolData.period[pathNowphase].grades.length !==0">
           <div class="class-item" v-for="(item, index) in nowschoolData.period[pathNowphase].grades" :key="index">
             <span class="class-item-number">{{ index + 1 }}</span>
             <div class="class-item-name" v-if="inputgrade.index !== index">{{ item }}</div>
             <div class="class-item-name" v-else-if="inputgrade.index === index">
               <el-input v-model="inputgrade.name" @blur="updategrade(index)" :placeholder='$t(`schoolManages.gradSet.gradeAndsubjects.gradeHint`)' />
             </div>
-            <div class="class-item-icon">
+            <div class="class-item-icon" v-show="!userPower.roles.includes('sales')">
               <div @click="inputgrade.name = item, inputgrade.index = index">
                 <svg class="redact-icon" aria-hidden="true">
                   <use xlink:href="#icon-bianji1"></use>
@@ -178,6 +178,9 @@
             </div>
           </div>
         </div>
+        <div class="notdata settimg-notdata" v-else>
+          <div class="notdata-title"><span>暂无数据</span></div>
+        </div>
       </div>
       <!--年级设置end-->
       <!--学科设置-->
@@ -190,14 +193,14 @@
                         <span class="ordinary-subject">{{$t(`schoolManages.gradSet.gradeAndsubjects.subjectType.subject`)}}</span>
                         <span class="specialty-subject">{{$t(`schoolManages.gradSet.gradeAndsubjects.subjectType.major`)}}</span>
                     </div> -->
-          <div class="semesterbox-title-add" @click="semesterCompile('', 'gradeClass')">
+          <div class="semesterbox-title-add" @click="semesterCompile('', 'gradeClass')" v-show="!userPower.roles.includes('sales')">
             <svg class="mini-hint" aria-hidden="true">
               <use xlink:href="#icon-jia-copy"></use>
             </svg>
           </div>
         </div>
-        <div class="subject-group">
-          <div class="subject-group-item" v-for="item in nowschoolData.period[pathNowphase].subjects" :key="item.id">
+        <div class="subject-group" v-if="nowschoolData.period[pathNowphase].subjects.length !==0">
+          <div :class="[userPower.roles.includes('sales') ?'replenish':'','subject-group-item']" v-for="item in nowschoolData.period[pathNowphase].subjects" :key="item.id">
             <!-- <span class="subject-type" title="通用" v-show="item.type ===0"></span>
                         <span class="subject-type-ordinary" title="学科" v-show="item.type ===1"></span>
                         <span class="subject-type-specialty" title="专业" v-show="item.type ===2"></span> -->
@@ -205,7 +208,7 @@
               <!-- <input autocomplete="off" spellcheck="false" type="text" placeholder="设置学科..." disabled="disabled" class="ivu-input ivu-input-default ivu-input-disabled"> -->
               {{ item.name }}
             </div>
-            <div class="redactbox-icon">
+            <div class="redactbox-icon" v-show="!userPower.roles.includes('sales')">
               <div class="redacicon" @click="semesterCompile(item, 'updateSubjects')">
                 <svg class="subject-redact-icon" aria-hidden="true">
                   <use xlink:href="#icon-bianji1-copy"></use>
@@ -219,13 +222,16 @@
             </div>
           </div>
         </div>
+        <div class="notdata settimg-notdata" v-else>
+          <div class="notdata-title"><span>暂无数据</span></div>
+        </div>
       </div>
       <!--学科设置end-->
       <!--班级专业名称/班级类型名称-->
       <div class="subjectbox">
         <div class="semesterbox-title grade-class">
           <div class="semesterbox-title-name">班级专业名称/班级类型名称</div>
-          <div class="semesterbox-title-add" @click="addExamtype('gradeClass')">
+          <div class="semesterbox-title-add" @click="addExamtype('gradeClass')" v-show="!userPower.roles.includes('sales')">
             <svg class="mini-hint" aria-hidden="true">
               <use xlink:href="#icon-jia-copy"></use>
             </svg>
@@ -240,7 +246,7 @@
               <div class="exam-type-item-name" v-else-if="gradeClassdata.index === index">
                 <el-input v-model="gradeClassdata.name" @blur="updateExamupdate(item, 'gradeclass')" placeholder='设置专业...' class="exam-edit-input" />
               </div>
-              <div class="exam-type-item-icon">
+              <div class="exam-type-item-icon" v-show="!userPower.roles.includes('sales')">
                 <div class="exam-type-redacicon" @click="gradeClassdata.name = item.name, gradeClassdata.id = item.id, gradeClassdata.index = index">
                   <svg class="subject-redact-icon" aria-hidden="true">
                     <use xlink:href="#icon-bianji1-copy"></use>
@@ -264,7 +270,7 @@
       <div class="situationbox">
         <div class="semesterbox-title">
           <div class="semesterbox-title-name">{{ $t(`schoolManages.gradSet.condition.title`) }}</div>
-          <div class="semesterbox-title-add" @click="addExamtype()">
+          <div class="semesterbox-title-add" @click="addExamtype()" v-show="!userPower.roles.includes('sales')">
             <svg class="mini-hint" aria-hidden="true">
               <use xlink:href="#icon-jia-copy"></use>
             </svg>
@@ -274,13 +280,12 @@
           <div class="exam-type-title"><span>{{ $t(`schoolManages.gradSet.condition.type`) }}:</span></div>
           <div class="exam-type-content">
             <div class="exam-type-item" v-for="(item, index) in nowschoolData.period[pathNowphase].analysis.type" :key="index">
-              <div class="exam-type-item-name" v-if="examType.index !== index"><span>{{ item.name
-                            }}</span>
+              <div class="exam-type-item-name" v-if="examType.index !== index"><span>{{ item.name}}</span>
               </div>
               <div class="exam-type-item-name" v-else-if="examType.index === index">
                 <el-input v-model="examType.name" @blur="updateExamupdate(item)" :placeholder='$t(`schoolManages.gradSet.condition.typehint`)' class="exam-edit-input" />
               </div>
-              <div class="exam-type-item-icon">
+              <div class="exam-type-item-icon" v-show="!userPower.roles.includes('sales')">
                 <div class="exam-type-redacicon" @click="examType.name = item.name, examType.id = item.id, examType.index = index">
                   <svg class="subject-redact-icon" aria-hidden="true">
                     <use xlink:href="#icon-bianji1-copy"></use>
@@ -297,13 +302,11 @@
           <div class="satisfybox">
             <div class="satisfybox-icon">
               <el-tooltip placement="right">
-                <template #content>{{ $t(`schoolManages.gradSet.condition.enterHint.hint1`) }}<br />{{
-                                        $t(`schoolManages.gradSet.condition.enterHint.hint2`)
-                                }}<br />{{
-        $t(`schoolManages.gradSet.condition.enterHint.hint3`)
-}}<br />{{
-        $t(`schoolManages.gradSet.condition.enterHint.hint4`)
-}}
+                <template #content>
+                  {{ $t(`schoolManages.gradSet.condition.enterHint.hint1`) }}<br />
+                  {{$t(`schoolManages.gradSet.condition.enterHint.hint2`)}}<br />
+                  {{$t(`schoolManages.gradSet.condition.enterHint.hint3`)}}<br />
+                  {{$t(`schoolManages.gradSet.condition.enterHint.hint4`)}}
                 </template>
                 <div>
                   <svg class="satisfybox-hint" aria-hidden="true">
@@ -317,7 +320,7 @@
             <div class="satisfybox-content">
               <el-input-number v-model="justOrsatisfy[0].num" :label="justOrsatisfy[0].num + '%'" @blur="coilAndpass('income')" :min="0" :max="100" size="mini" :disabled="justOrsatisfy[0].disabled" />
             </div>
-            <div class="satisfybox-modify" @click="justOrsatisfy[0].disabled = false">
+            <div class="satisfybox-modify" @click="justOrsatisfy[0].disabled = false" v-show="!userPower.roles.includes('sales')">
               <svg class="subject-redact-icon" aria-hidden="true">
                 <use xlink:href="#icon-75bianji"></use>
               </svg>
@@ -326,11 +329,10 @@
           <div class="passbox">
             <div class="pass-icon">
               <el-tooltip placement="right">
-                <template #content>{{ $t(`schoolManages.gradSet.condition.treadHint.hint1`) }}<br />{{
-                                        $t(`schoolManages.gradSet.condition.treadHint.hint2`)
-                                }}<br />{{
-        $t(`schoolManages.gradSet.condition.treadHint.hint3`)
-}}
+                <template #content>
+                  {{ $t(`schoolManages.gradSet.condition.treadHint.hint1`) }}<br />
+                  {{$t(`schoolManages.gradSet.condition.treadHint.hint2`)}}<br />
+                  {{$t(`schoolManages.gradSet.condition.treadHint.hint3`)}}
                 </template>
                 <div>
                   <svg class="satisfybox-hint" aria-hidden="true">
@@ -343,7 +345,7 @@
             <div class="pass-content">
               <el-input-number v-model="justOrsatisfy[1].num" @blur="coilAndpass('touch')" :min="0" :max="100" size="mini" :disabled="justOrsatisfy[1].disabled" />
             </div>
-            <div class="pass-modify" @click="justOrsatisfy[1].disabled = false">
+            <div class="pass-modify" @click="justOrsatisfy[1].disabled = false" v-show="!userPower.roles.includes('sales')">
               <svg class="subject-redact-icon" aria-hidden="true">
                 <use xlink:href="#icon-75bianji"></use>
               </svg>
@@ -360,9 +362,7 @@
           <div class="semesterbox-title-name settime">{{ $t(`schoolManages.gradSet.timeFrame.title`) }}</div>
           <div class="semesterbox-title-icon">
             <el-tooltip placement="right">
-              <template #content>{{ $t(`schoolManages.gradSet.timeFrame.hint1`) }}<br />{{
-                                    $t(`schoolManages.gradSet.timeFrame.hint2`)
-                            }}
+              <template #content>{{ $t(`schoolManages.gradSet.timeFrame.hint1`) }}<br />{{$t(`schoolManages.gradSet.timeFrame.hint2`)}}
               </template>
               <div>
                 <svg class="ordinary-hint" aria-hidden="true">
@@ -371,7 +371,7 @@
               </div>
             </el-tooltip>
           </div>
-          <div class="semesterbox-title-add" @click="semesterCompile('', 'addTimebucket', '')">
+          <div class="semesterbox-title-add" @click="semesterCompile('', 'addTimebucket', '')" v-show="!userPower.roles.includes('sales')">
             <svg class="mini-hint" aria-hidden="true">
               <use xlink:href="#icon-jia-copy"></use>
             </svg>
@@ -379,7 +379,7 @@
         </div>
       </div>
       <!--时段设置-->
-      <div class="settimebox">
+      <div class="settimebox" v-if="nowschoolData.period[pathNowphase].timetable.length !==0">
         <el-timeline>
           <el-timeline-item center v-for="(item, index) in nowschoolData.period[pathNowphase].timetable" :key="index" :icon="item.type === '1' ? 'el-icon-reading' : 'el-icon-alarm-clock'" class="settime-item" :class="{ 'pitch': pathNow == index }" @click="pathNow = index">
             <el-card>
@@ -387,7 +387,7 @@
               <div class="settime-time">{{ item.time }}</div>
               <div class="settime-name">({{ item.label }})</div>
             </el-card>
-            <div class="settime-icon">
+            <div class="settime-icon" v-show="!userPower.roles.includes('sales')">
               <div @click="semesterCompile(item, 'updateTimebucket', index)">
                 <svg class="mini-hint" aria-hidden="true">
                   <use xlink:href="#icon-bianji1"></use>
@@ -402,6 +402,9 @@
           </el-timeline-item>
         </el-timeline>
       </div>
+      <div class="notdata" v-else>
+        <div class="notdata-title"><span>暂无数据</span></div>
+      </div>
       <!--时段设置end-->
     </div>
     <!--時段設置end-->
@@ -493,17 +496,18 @@
 import { reactive, ref, getCurrentInstance, toRef, watch, nextTick } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { useStore } from 'vuex'
+import jwt_decode from 'jwt-decode'
 export default {
   props: {
-    schoolData: {
-      type: String,
-      default: '',
+    detailsSchool: {
+      default: {}
     },
   },
   setup (props) {
     let { proxy } = getCurrentInstance()
     // let PowerShow = proxy.$access.inspectPower('batchschool-upd')
     const store = useStore()
+    let userPower = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
     // const routerInfo = useRouter()
     let timesteps = ref({
       times: [
@@ -708,16 +712,17 @@ export default {
     function getnowSchool (data) {
       console.log(data, '进入调用API方法')
       let schoolData = {}
+      conductData(data)
       //处理学段管理api
-      proxy.$api
-        .getNowscholl({ schoolId: data })
-        .then((res) => {
-          console.log(res, '返回的res内容')
-          res.state === 200 ? ((schoolData = res.schoolAssists), conductData(res.schoolAssists)) : ''
-        })
-        .catch((res) => {
-          ElMessage.error('获取学校数据异常')
-        })
+      // proxy.$api
+      //   .getNowscholl({ schoolId: data })
+      //   .then((res) => {
+      //     console.log(res, '返回的res内容')
+      //     res.state === 200 ? ((schoolData = res.schoolAssists), conductData(res.schoolAssists)) : ''
+      //   })
+      //   .catch((res) => {
+      //     ElMessage.error('获取学校数据异常')
+      //   })
     }
     //接收到学校信息处理数据
     function conductData (data) {
@@ -725,12 +730,15 @@ export default {
       if (!data) {
         return
       }
-      if (data.period[pathNowphase.value].semesters.length === 0 || data.period[pathNowphase.value].subjects.length === 0) {
-        ElMessage.error('学段管理内数据异常')
-        return
-      }
       let datas = data
       //显示学段名称和校区
+      for (let i in datas.period) {
+        let ids = datas.period[i].campusId
+        for (let y in datas.campuses) {
+          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
@@ -743,16 +751,18 @@ export default {
       console.log(phasetime, '当前的学期')
       let topStart = 0
       let downStart = 0
-      for (let i in phasetime) {
-        phasetime[i].start === 0 ? ((topStart = phasetime[i].month), (phasetime[i].totaldays = 0)) : ((downStart = phasetime[i].month), (phasetime[i].totaldays = 0))
-        for (let u in timesteps.value.times) {
-          timesteps.value.times[u].id >= topStart && timesteps.value.times[u].id < downStart ? (timesteps.value.times[u].state = true) : ''
-          timesteps.value.times[u].id === topStart ? (timesteps.value.times[u].label = true) : ''
-          timesteps.value.times[u].id === downStart ? (timesteps.value.times[u - 1].label = true) : ''
+      if (phasetime.length > 1) {
+        for (let i in phasetime) {
+          phasetime[i].start === 0 ? ((topStart = phasetime[i].month), (phasetime[i].totaldays = 0)) : ((downStart = phasetime[i].month), (phasetime[i].totaldays = 0))
+          for (let u in timesteps.value.times) {
+            timesteps.value.times[u].id >= topStart && timesteps.value.times[u].id < downStart ? (timesteps.value.times[u].state = true) : ''
+            timesteps.value.times[u].id === topStart ? (timesteps.value.times[u].label = true) : ''
+            timesteps.value.times[u].id === downStart ? (timesteps.value.times[u - 1].label = true) : ''
+          }
         }
+        timesteps.value.nowitem = data.period[pathNowphase.value].semesters[0]
       }
-      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))
       // }
@@ -1261,9 +1271,9 @@ export default {
     }
     watch(
       props,
-      (newdata) => {
+      (newdata, olddata) => {
         console.log(newdata, '数据')
-        newdata.schoolData !== undefined ? getnowSchool(newdata.schoolData) : ''
+        newdata.detailsSchool !== undefined && newdata !== olddata ? getnowSchool(newdata.detailsSchool) : ''
       },
       { immediate: true, deep: true }
     )
@@ -1317,6 +1327,7 @@ export default {
       timeZoneList,
       semesterSort,
       gradeClassdata,
+      userPower
     }
   },
 }
@@ -1325,7 +1336,7 @@ export default {
 .phasebox {
   width: 100%;
   line-height: 20px;
-  height: 87vh;
+  height: 89vh;
   background-color: #fff;
 }
 
@@ -1335,7 +1346,7 @@ export default {
   text-align: left;
   display: inline-block;
   line-height: 20px;
-  height: 87vh;
+  height: 89vh;
   vertical-align: top;
 }
 
@@ -1346,7 +1357,7 @@ export default {
 .center-pane {
   width: 50%;
   display: inline-block;
-  height: 87vh;
+  height: 89vh;
   border-right: 1px solid #ccc;
   text-align: left;
   overflow-y: auto;
@@ -2182,6 +2193,12 @@ export default {
 .settimebox:hover {
   overflow-y: auto;
 }
+.replenish {
+  padding-right: 25px;
+}
+.settimg-notdata {
+  padding-top: 5%;
+}
 </style>
 <style>
 .pitch .el-card__body {
@@ -2296,7 +2313,7 @@ export default {
 }
 
 .settimebox {
-  overflow: hidden;
+  overflow: auto;
   height: 72vh;
 }
 
@@ -2358,16 +2375,24 @@ export default {
   font-weight: 600;
   color: #bdc3c7;
 }
-
 @media screen and (max-width: 1367px) {
+  .settime-icon div {
+    margin-bottom: 50%;
+  }
   .settimebox .el-card__body {
     width: 200px;
   }
-}
-
-@media screen and (max-width: 1367px) {
-  .settime-icon div {
-    margin-bottom: 50%;
+  /* .redactbox {
+    height: 84vh;
+  } */
+  .school-form-name {
+    width: 45% !important;
+  }
+  .school-form-badge {
+    width: 23vw !important;
+  }
+  .school-form-size {
+    width: 55% !important;
   }
 }
 
@@ -2376,13 +2401,12 @@ export default {
   .subjectbox {
     width: 98% !important;
   }
-
-  .phasebox {
-    height: 78vh !important;
-  }
-
+  .phasebox,
   .center-pane {
-    height: 79vh !important;
+    height: 86vh !important;
+  }
+  .settimebox {
+    height: 77vh !important;
   }
 }
 </style>

+ 7 - 3
TEAMModelBI/ClientApp/src/view/schoolServe/analyseSchool.vue

@@ -18,7 +18,7 @@
     </div>
     <div class="topbox">
       <div class="topbox-list">
-        <div class="top-aspects" v-for="(item,index) in headerData" :key="index">
+        <div class="top-aspects" v-for="(item,index) in headerData" :key="index" v-loading="loadingSchool.headerData" element-loading-background="rgba(0, 0, 0, 0.2)">
           <div :class="[item.classname,'left-top-icon']">
             <svg class="top-header-icon" aria-hidden="true">
               <use :xlink:href="item.icon"></use>
@@ -1021,6 +1021,7 @@ export default {
       },
     ])
     let loadingSchool = ref({
+      headerData: true,
       basics: true,
       modules: true,
       course: true,
@@ -1043,6 +1044,7 @@ export default {
           headerData.value[2].num = res.stuCnt
           headerData.value[3].num = res.roomCnt
           headerData.value[4].num = res.lesCnt
+          loadingSchool.value.headerData = false
           //本学期 本周数据
           basicsData.value.totals.month[0].num = res.weekLesCnt
           basicsData.value.totals.month[1].num = res.weekACTCnt
@@ -1089,7 +1091,6 @@ export default {
 
           loadingSchool.value.basics = false
           //模组情况
-
           for (let s in modulesData.value) {
             let keys = modulesData.value[s].key
             console.log(keys)
@@ -1101,7 +1102,7 @@ export default {
             let keys = tableData.value[t].key
             for (let i in res.schoolInfo.service) {
               res.schoolInfo.service[i].prodCode === keys ? (tableData.value[t].date = res.schoolInfo.service[i].startDate === 0 ? res.schoolInfo.service[i].startDate : proxy.$common.getLocalTime(res.schoolInfo.service[i].startDate * 1000),
-                tableData.value[t].expire = res.schoolInfo.service[i].endDate === 0 ? res.schoolInfo.service[i].endDate : roxy.$common.getLocalTime(res.schoolInfo.service[i].endDate * 1000), tableData.value[t].state = true) : ''
+                tableData.value[t].expire = res.schoolInfo.service[i].endDate === 0 ? res.schoolInfo.service[i].endDate : proxy.$common.getLocalTime(res.schoolInfo.service[i].endDate * 1000), tableData.value[t].state = true) : ''
             }
           }
           console.log(basicsData.value)
@@ -1508,4 +1509,7 @@ export default {
 .centerbox-right-rightbox .el-table__header-wrapper {
   line-height: 20px;
 }
+.school-servebox .el-loading-spinner .circular {
+  display: inline !important;
+}
 </style>

+ 4 - 4
TEAMModelBI/ClientApp/src/view/schoolServe/school.vue

@@ -207,7 +207,7 @@
                   <el-image :src="nowPitchdata.picture" fit="contain"></el-image>
                 </div>
               </el-form-item>
-              <!-- <el-form-item label="学段:" class="school-form-grading">
+              <!-- <el-form-item label="学段:" class="school-form-grading"> 
                                 <el-checkbox v-model="nowPitchdata.period[0].value" label="小学"></el-checkbox>
                                 <el-checkbox v-model="nowPitchdata.period[1].value" label="初中"></el-checkbox>
                                 <el-checkbox v-model="nowPitchdata.period[2].value" label="高中"></el-checkbox>
@@ -1043,9 +1043,9 @@ export default {
       })
       // setTimeout(function () { loading.value = false }, 500);
     }
-    watch(scrollHeight, (newdata) => {
-      if (scrollHeight.value < 0) {
-        debounce(datascroll, 500)
+    watch(scrollHeight, (newdata, olddata) => {
+      if (newdata < olddata) {
+        scrollHeight.value < 0 ? debounce(datascroll, 500) : ''
       }
     })
     watch(searchValues, (newdata) => {

+ 18 - 19
TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue

@@ -67,7 +67,7 @@
             </svg>
           </div>
         </div>
-        <div class="setting-time" v-if="nowschoolData.period[pathNowphase].semesters.length !==0">
+        <div class="setting-time" v-if="nowschoolData.period[pathNowphase].semesters.length >1">
           <div class="set-item" v-for="(items, index) in nowschoolData.period[pathNowphase].semesters" :key="index" @mouseenter="semesterCut(items, index)">
             <div class="set-time-semester">{{ items.name }}</div>
             <div class="set-time-start">
@@ -781,16 +781,18 @@ export default {
       console.log(phasetime, '当前的学期')
       let topStart = 0
       let downStart = 0
-      for (let i in phasetime) {
-        phasetime[i].start === 0 ? ((topStart = phasetime[i].month), (phasetime[i].totaldays = 0)) : ((downStart = phasetime[i].month), (phasetime[i].totaldays = 0))
-        for (let u in timesteps.value.times) {
-          timesteps.value.times[u].id >= topStart && timesteps.value.times[u].id < downStart ? (timesteps.value.times[u].state = true) : ''
-          timesteps.value.times[u].id === topStart ? (timesteps.value.times[u].label = true) : ''
-          timesteps.value.times[u].id === downStart ? (timesteps.value.times[u - 1].label = true) : ''
+      if (phasetime.length > 1) {
+        for (let i in phasetime) {
+          phasetime[i].start === 0 ? ((topStart = phasetime[i].month), (phasetime[i].totaldays = 0)) : ((downStart = phasetime[i].month), (phasetime[i].totaldays = 0))
+          for (let u in timesteps.value.times) {
+            timesteps.value.times[u].id >= topStart && timesteps.value.times[u].id < downStart ? (timesteps.value.times[u].state = true) : ''
+            timesteps.value.times[u].id === topStart ? (timesteps.value.times[u].label = true) : ''
+            timesteps.value.times[u].id === downStart ? (timesteps.value.times[u - 1].label = true) : ''
+          }
         }
+        timesteps.value.nowitem = data.period[pathNowphase.value].semesters[0]
+        console.log(timesteps.value)
       }
-      timesteps.value.nowitem = data.period[pathNowphase.value].semesters[0]
-      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))
       // }
@@ -1391,7 +1393,7 @@ export default {
 .phasebox {
   width: 100%;
   line-height: 20px;
-  height: 87vh;
+  height: 89vh;
   background-color: #fff;
 }
 
@@ -1401,7 +1403,7 @@ export default {
   text-align: left;
   display: inline-block;
   line-height: 20px;
-  height: 87vh;
+  height: 89vh;
   vertical-align: top;
 }
 
@@ -1412,7 +1414,7 @@ export default {
 .center-pane {
   width: 50%;
   display: inline-block;
-  height: 87vh;
+  height: 89vh;
   border-right: 1px solid #ccc;
   text-align: left;
   overflow-y: auto;
@@ -2383,8 +2385,8 @@ export default {
 }
 
 .settimebox {
-  overflow: hidden;
-  height: 72vh;
+  overflow: atuo;
+  height: 77vh;
 }
 
 .settimebox:hover {
@@ -2464,12 +2466,9 @@ export default {
     width: 98% !important;
   }
 
-  .phasebox {
-    height: 78vh !important;
-  }
-
+  .phasebox,
   .center-pane {
-    height: 79vh !important;
+    height: 86vh !important;
   }
 }
 </style>

+ 19 - 9
TEAMModelBI/ClientApp/src/view/schoolmanage/schoolAnalyse.vue

@@ -17,8 +17,8 @@
         </div>
       </div>
     </div>
-    <div class="school-list">
-      <div class="attendclass" v-loading="allLoding.rank" element-loading-background="rgba(0, 0, 0, 0.5)">
+    <div class="school-list" v-loading="allLoding.rank" element-loading-background="rgba(0, 0, 0, 0.5)">
+      <div class="attendclass">
         <div class="attendclass-title">
           <div class="attendclass-title-icon">
             <svg class="attendclassIcon" aria-hidden="true">
@@ -58,7 +58,7 @@
           </el-table>
         </div>
       </div>
-      <div class="classexample" v-loading="allLoding.rank" element-loading-background="rgba(0, 0, 0, 0.5)">
+      <div class="classexample">
         <div class="attendclass-title">
           <div class="attendclass-title-icon">
             <svg class="attendclassIcon" aria-hidden="true">
@@ -97,7 +97,7 @@
           </el-table>
         </div>
       </div>
-      <div class="comprehensive" v-loading="allLoding.rank" element-loading-background="rgba(0, 0, 0, 0.5)">
+      <div class="comprehensive">
         <div class="attendclass-title">
           <div class="attendclass-title-icon">
             <svg class="attendclassIcon" aria-hidden="true">
@@ -215,7 +215,7 @@
     <div class="schoolList-all">
       <p class="school-list-title">学校列表:</p>
       <div class="school-tables">
-        <el-table :data="schoolDefault" height="25vh" style="width: 100%" v-loading="searchText.loading" element-loading-background="rgba(0, 0, 0, 0.5)" empty-text="暂无数据">
+        <el-table :data="schoolDefault" height="55vh" style="width: 100%" v-loading="searchText.loading" element-loading-background="rgba(0, 0, 0, 0.5)" empty-text="暂无数据">
           <el-table-column label="校徽" align="center">
             <template #default="scope">
               <el-image style="width: 50px; height: 50px" :src="scope.row.picture" fit="fill" v-if="scope.row.picture"></el-image>
@@ -229,7 +229,7 @@
               <el-input v-model="searchText.values" size="small" placeholder="搜索学校名称/简码" clearable />
             </template>
             <template #default="scope">
-              <el-button size="small" type="primary">前往查看</el-button>
+              <el-button size="small" type="primary" @click="detailsSchool(scope.row)">前往查看</el-button>
             </template>
           </el-table-column>
         </el-table>
@@ -1564,7 +1564,6 @@ export default {
           headerbasics.value[1].subnum = res.tchMonthCnt
           headerbasics.value[2].subnum = 0
           headerbasics.value[3].subnum = res.lessMthCnt
-          allLoding.value.headerData = false
           let beginsData = res.scRankCnts.sort((a, b) => a.openCnt < b.openCnt ? 1 : a.openCnt > b.openCnt ? -1 : 0)
           let activityDataInfo = res.scRankCnts.sort((a, b) => a.actCnt < b.actCnt ? 1 : a.actCnt > b.actCnt ? -1 : 0)
           let compositeData = res.scRankCnts.sort((a, b) => parseInt(a.openCnt) + parseInt(a.actCnt) + parseInt(a.lessCnt) + parseInt(a.interCnt) < parseInt(b.openCnt) + parseInt(b.actCnt) + parseInt(b.lessCnt) + parseInt(a.interCnt) ? 1 : parseInt(a.openCnt) + parseInt(a.actCnt) + parseInt(a.lessCnt) + parseInt(a.interCnt) > parseInt(b.openCnt) + parseInt(b.actCnt) + parseInt(b.lessCnt) + parseInt(a.interCnt) ? -1 : 0)
@@ -1585,6 +1584,7 @@ export default {
           activityData.value = activityDataInfo
           comprehensiveData.value = compositeData
           console.log(comprehensiveData.value, '查看1111')
+          allLoding.value.headerData = false
           allLoding.value.rank = false
           searchText.loading = false
           store.commit('clickCounselor', '')
@@ -1611,7 +1611,7 @@ export default {
       let nowstate = state
       let data = state === 'details' ? { schoolId: val } :
         store.state.areaClickCounselor && urlState ? { tmdId: store.state.areaClickCounselor, role: store.state.areaClickRoles } :
-          (roleA === 'admin' || roleA === 'leader') && !store.state.areaClickCounselor && state !== 'details' ? {} : ''
+          (roleA === 'admin' || roleA === 'leader') && !store.state.areaClickCounselor && state !== 'details' ? {} : { tmdId: user.tmdId }
       proxy.$api.getAllaspects(data).then((res) => {
         console.log(res, '课例等的返回')
         if (res.state === 200) {
@@ -2197,7 +2197,7 @@ export default {
 }
 .schoolList-all {
   width: 100%;
-  height: 35vh;
+  height: 65vh;
   padding: 1%;
   background-color: #fff;
 }
@@ -2430,6 +2430,16 @@ export default {
 .school-tables {
   padding: 0% 1%;
 }
+.notimage {
+  width: 50px;
+  height: 50px;
+  line-height: 50px;
+  text-align: center;
+  background-color: #bdc3c7;
+  font-size: 10px;
+  color: #ecf0f1;
+  margin: 0 auto;
+}
 </style>
 <style>
 /* .school-list .el-table .el-table__cell {

+ 142 - 17
TEAMModelBI/ClientApp/src/view/systemConfig/correlation.vue

@@ -10,9 +10,21 @@
         <div class="userlist-name">{{nowUsers.name}}({{nowUsers.mobile}})</div>
       </div>
     </div>
-    <p class="correlationbox-title">目前用户所关联学校:</p>
+    <div class="school-list-header">
+      <div class="correlationbox-titles">目前用户所关联学校:<span>关联数量:<span class="correlationbox-num">{{nowUsers.handleSchools.length}}</span></span></div>
+      <div class="correlationbox-btn">
+        <el-button type="primary" size="small" v-if="removeBatchschool.length >0 && PowerShow" @click="multipeRemove"> 移除选中学校</el-button>
+        <el-button type="primary" size="small" v-else-if="removeBatchschool.length ===0 && PowerShow" disabled>移除选中学校</el-button>
+      </div>
+    </div>
+    <!-- <p class="correlationbox-title">目前用户所关联学校:</p>
+    <div class="correlationbox-btn">
+      <el-button type="primary" size="small" v-if="multipleSchool.length >0 && PowerShow" @click="multipleCorrelation">关联选中学校</el-button>
+      <el-button type="primary" size="small" v-else-if="multipleSchool.length ===0 && PowerShow" disabled>关联选中学校</el-button>
+    </div> -->
     <div class="possessbox" v-if="nowUsers.handleSchools.length >0">
-      <el-table :data="nowUsers.handleSchools" style="width: 100%" height="20vh" size="small" v-loading="loadingData.possess" element-loading-text="数据加载中...">
+      <el-table :data="nowUsers.handleSchools" style="width: 100%" height="20vh" size="small" @selection-change="removeBatch" v-loading="loadingData.possess" element-loading-text="数据加载中...">
+        <el-table-column type="selection" v-if="PowerShow" />
         <el-table-column label="校徽" align="center">
           <template #default="scope">
             <el-image style="width: 40px; height: 40px;" :src="scope.row.picture" fit="fill" v-if="scope.row.picture"></el-image>
@@ -23,6 +35,16 @@
         <el-table-column prop="id" label="学校简码" align="center" />
         <!-- <el-table-column prop="name" label="版本" />
                 <el-table-column prop="name" label="目前顾问" /> -->
+        <el-table-column align="center">
+          <template #header>
+            <el-select v-model="areaList.existValue" placeholder="Select" size="small" @change="correlaSchool">
+              <el-option v-for="item in areaList.data" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+          </template>
+          <template #default="scope">
+            <span class="areaitem-name">{{scope.row.areaName}}</span><span class="areaitem-insti">({{scope.row.institution}})</span>
+          </template>
+        </el-table-column>
         <el-table-column fixed="right" label="操作" width='80' align="center" v-if="PowerShow">
           <template #default="scope">
             <el-button type="text" size="small" @click="removeSchool(scope.row,scope.$index)">取消关联</el-button>
@@ -64,7 +86,9 @@
               </el-select>
             </template>
             <template #default="scope">
-              <span class="areaitem-name">{{scope.row.areaName}}</span><span class="areaitem-insti">({{scope.row.institution}})</span>
+              <span class="areaitem-name">{{scope.row.areaName}}</span>
+              <span class="areaitem-insti" v-if="scope.row.institution">({{scope.row.institution}})</span>
+              <span class="areaitem-insti" v-else>{{scope.row.institution}}</span>
             </template>
           </el-table-column>
           <el-table-column fixed="right" label="操作" width='80' align="center" v-if="PowerShow">
@@ -81,23 +105,30 @@
 import { ref, getCurrentInstance, watch, onMounted } from 'vue'
 import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
 import { Search } from '@element-plus/icons'
+import { useStore } from 'vuex'
 export default {
   props: {
     userdata: {
       type: Object,
       default: () => { },
     },
+    areadata: {
+      type: Object,
+      default: () => [],
+    }
   },
   components: {
     Search
   },
   setup (props) {
     let { proxy } = getCurrentInstance()
+    const store = useStore()
     let PowerShow = proxy.$access.identifyPosition(JSON.parse(localStorage.getItem('id_token')))
     const tableDatas = ref([])
     let tableData = ref([])
     let nowUsers = ref()
     let multipleSchool = ref([])
+    let removeBatchschool = ref([])
     let schoolSearch = ref('')
     let original = ref([])
     let timer = ref('')
@@ -108,11 +139,14 @@ export default {
       list: false,
     })
     let areaList = ref({
+      existValue: 'all',
       value: 'all',
       data: [
         { value: 'all', label: '全部', situate: 'all' },
       ]
     })
+    //关联筛选原始data
+    let correlaData = ref([])
     onMounted(() => {
       //监听表格滚动事件
       // let table = mutipleTable.value._value.layout.table.refs.bodyWrapper;
@@ -128,8 +162,8 @@ export default {
       }
     }
     function getSchoolList (value, state) {
-      console.log(value, '触发下一页')
-      if (nextpageToken.value == null && state !== 'restart') {
+      console.log(value, nextpageToken.value, '触发下一页')
+      if ((nextpageToken.value === null) && state !== 'restart') {
         ElMessage.success('已经到最底了')
         return
       }
@@ -155,6 +189,7 @@ export default {
             console.log(areaList.value.data, '是否有数据')
             for (let y in res.schoolAssists) {
               let areaValue = res.schoolAssists[y].areaId
+              console.log(areaValue, '学区的值')
               res.schoolAssists[y].areaName = ''
               res.schoolAssists[y].institution = ''
               for (let i in areaList.value.data) {
@@ -192,9 +227,9 @@ export default {
           .then((res) => {
             console.log(res, '成功的返回')
             res.state === 200
-              ? (nowUsers.value.handleSchools.push(value), getSchoolList(), processingSchool(), ElMessage.success('操作成功'))
+              ? (nowUsers.value.handleSchools.push(value), getSchoolList('', 'restart'), processingSchool(), ElMessage.success('操作成功'))
               : res.state === 201
-                ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList())
+                ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList('', 'restart'))
                 : ''
           })
           .catch((error) => {
@@ -215,7 +250,7 @@ export default {
         proxy.$api
           .setAistschool(data)
           .then((res) => {
-            res.state === 200 ? (nowUsers.value.handleSchools.splice(index, 1), getSchoolList(), processingSchool(), ElMessage.success('操作成功')) : ''
+            res.state === 200 ? (nowUsers.value.handleSchools.splice(index, 1), getSchoolList('', 'restart'), processingSchool(), ElMessage.success('操作成功')) : ''
           })
           .catch((error) => {
             ElMessage.error('取消关联失败,API异常')
@@ -226,6 +261,9 @@ export default {
       multipleSchool.value = value
       console.log(multipleSchool.value, '111')
     }
+    function removeBatch (value) {
+      removeBatchschool.value = value
+    }
     function multipleCorrelation () {
       let schoolData = multipleSchool.value
       let schoolName = ''
@@ -255,7 +293,7 @@ export default {
           .then((res) => {
             console.log(res, '成功的返回')
             res.state === 200
-              ? ((nowUsers.value.handleSchools = nowUsers.value.handleSchools.concat(schoolData)), getSchoolList(), processingSchool(), ElMessage.success('操作成功'))
+              ? ((nowUsers.value.handleSchools = nowUsers.value.handleSchools.concat(schoolData)), getSchoolList('', 'restart'), processingSchool())
               : res.state === 201
                 ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList())
                 : ''
@@ -265,6 +303,54 @@ export default {
           })
       })
     }
+    function multipeRemove () {
+      let schoolData = removeBatchschool.value
+      let schoolName = ''
+      console.log(schoolData, '学校信息')
+      if (schoolData.length < 5) {
+        schoolData.forEach((item) => {
+          schoolName = schoolName ? schoolName + ',' + item.name : item.name
+        })
+      } else {
+        for (let i = 0; i < 5; i++) {
+          schoolName = schoolName ? schoolName + ',' + schoolData[i].name : schoolData[i].name
+        }
+        schoolName = schoolName + '等...'
+      }
+      ElMessageBox.confirm(`请问您确定将 ${schoolName} 移除学校关联,取消数据关联吗 ?`, '取消关联学校', {
+        confirmButtonText: proxy.$t(`commonMsg.confirm`),
+        cancelButtonText: proxy.$t(`commonMsg.closes`),
+        type: 'warning',
+        center: true,
+      }).then(() => {
+        let schoolArr = []
+        for (let s of schoolData) {
+          s.id ? schoolArr.push(s.id) : ''
+        }
+        let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'del' }
+        proxy.$api
+          .setAistschool(data)
+          .then((res) => {
+            if (res.state === 200) {
+              console.log(schoolData, '内容')
+              schoolData.forEach((item, index) => {
+                let iteId = item.id
+                console.log(iteId, 'ID值')
+                for (let e in nowUsers.value.handleSchools) {
+                  console.log(nowUsers.value.handleSchools, '值')
+                  iteId === nowUsers.value.handleSchools[e].id ? nowUsers.value.handleSchools.splice(e, 1) : ''
+                }
+              })
+              getSchoolList('', 'restart')
+              processingSchool()
+              ElMessage.success('操作成功')
+            }
+          })
+          .catch((error) => {
+            ElMessage.error('取消关联失败,API异常')
+          })
+      })
+    }
     function processingSchool (state) {
       console.log(tableData.value, original.value, '原始数据和变更数据')
       state ? tableData.value = original.value : ''
@@ -308,10 +394,10 @@ export default {
       })
     }
     //加载所有学区信息
-    function areaData () {
-      proxy.$api.getCapacity({}).then((res) => {
+    async function areaData () {
+      await proxy.$api.getCapacity({}).then((res) => {
         console.log(res, '学区信息')
-        res.state === 200 ? res.areas.forEach((item) => { areaList.value.data.push({ value: item.id, label: item.name, situate: item.institution }) }) : ''
+        res.state === 200 ? (res.areas.forEach((item) => { areaList.value.data.push({ value: item.id, label: item.name, situate: item.institution }) }), store.commit('getPoint', areaList.value.data)) : ''
       }).catch((error) => {
         ElMessage.error('API异常,获取学区失败')
       })
@@ -339,6 +425,8 @@ export default {
               }
             }
             tableData.value = res.joinAreaSchools
+            processingSchool()
+            nextpageToken.value = null
           }
           loadingData.value.list = false
         }).catch((error) => {
@@ -347,14 +435,44 @@ export default {
         })
       }
     }
+    //关联的筛选
+    function correlaSchool (value) {
+      console.log(value, '筛选')
+      let targetId = value
+      if (targetId === 'all') {
+        nowUsers.value.handleSchools = correlaData.value
+      } else {
+        let filterData = nowUsers.value.handleSchools.filter((item) => {
+          return item.areaId === targetId
+        })
+        nowUsers.value.handleSchools = filterData
+      }
+    }
+    //处理显示目前关联的
+    function nowRelevance (value) {
+      nowUsers.value = JSON.parse(JSON.stringify(value))
+      let nowUserdata = nowUsers.value
+      nowUserdata.handleSchools.forEach((item) => {
+        let areaIds = item.areaId
+        item.areaName = ''; item.institution = ''
+        for (let i of areaList.value.data) {
+          i.value === areaIds ? (item.areaName = i.label, item.institution = i.situate) : ''
+        }
+      })
+      nowUsers.value.handleSchools = nowUserdata.handleSchools
+      correlaData.value = nowUserdata.handleSchools
+      loadingData.value.possess = false
+    }
     watch(scrollHeight, (newdata, olddata) => {
       console.log(newdata, olddata, '监听的数据')
-      olddata === 'init' && newdata <= 0 ? getSchoolList(nextpageToken.value) : ''
+      if (newdata < olddata) {
+        newdata <= 0 ? getSchoolList(nextpageToken.value) : ''
+      }
     })
     watch(
       props,
       (newuser) => {
-        newuser ? (nowUsers.value = newuser.userdata, loadingData.value.possess = false, processingSchool(true)) : ''
+        newuser ? (areaList.value.data.push(...newuser.areadata), nowRelevance(newuser.userdata), processingSchool(true)) : ''
         console.log(nowUsers.value, '触发监听')
       },
       { immediate: true, deep: true }
@@ -367,7 +485,7 @@ export default {
       }
     })
     getSchoolList()
-    areaData()
+    // areaData()
     return {
       tableData,
       tableDatas,
@@ -387,7 +505,13 @@ export default {
       areaData,
       loadingData,
       areaList,
-      getAreaschool
+      getAreaschool,
+      removeBatchschool,
+      multipeRemove,
+      removeBatch,
+      nowRelevance,
+      correlaData,
+      correlaSchool
     }
   },
 }
@@ -476,7 +600,8 @@ export default {
   color: #ecf0f1;
   margin: 0 auto;
 }
-.areaitem-name {
+.areaitem-name,
+.correlationbox-num {
   color: #409eff;
 }
 .areaitem-insti {

File diff suppressed because it is too large
+ 568 - 377
TEAMModelBI/ClientApp/src/view/systemConfig/manageschool.vue


+ 16 - 5
TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue

@@ -94,11 +94,11 @@
         <el-tab-pane label="权限/身份" name="first">
           <Operates ref="roaming" :userdata="nowUser" @changeShow="changeState"></Operates>
         </el-tab-pane>
-        <el-tab-pane label="关联学校" name="second" v-if="(nowUser.handleRoles.includes('assist') || nowUser.handleRoles.includes('admin')) && nowUser.tmdId !==''">
-          <Correlation :userdata="nowUser"></Correlation>
+        <el-tab-pane label="关联学校" name="second" v-if="(nowUser.handleRoles.includes('assist') || nowUser.handleRoles.includes('admin') || nowUser.handleRoles.includes('sales')) && nowUser.tmdId !==''">
+          <Correlation :userdata="nowUser" :areadata="areaDatas"></Correlation>
         </el-tab-pane>
         <el-tab-pane label="管理学校" name="manegeschool" v-if="nowUser.tmdId !==''">
-          <Manageschool :userdata="nowUser"></Manageschool>
+          <Manageschool :userdata="nowUser" :areadata="areaDatas"></Manageschool>
         </el-tab-pane>
       </el-tabs>
       <div class="changeBtn" v-show="activeName === 'first'">
@@ -220,6 +220,7 @@ export default {
     let activeName = ref('first')
     let drawerChange = ref(false)
     let roaming = ref()
+    let areaDatas = ref([])
     const identityArr = [
       {
         value: 'rdc',
@@ -310,7 +311,6 @@ export default {
     function handleClick (index, data) {
       console.log(index, data, 'click')
       nowUser.value = data[index]
-      console.log(nowUser.value)
       drawer.value = true
       console.log(nowUser.value)
       // let userData = data.value[index]
@@ -474,6 +474,14 @@ export default {
         return val2.handleSchools.length - val1.handleSchools.length
       })
     }
+    function areaData () {
+      proxy.$api.getCapacity({}).then((res) => {
+        console.log(res, '学区信息')
+        res.state === 200 ? (res.areas.forEach((item) => { areaDatas.value.push({ value: item.id, label: item.name, situate: item.institution }) }), store.commit('getPoint', areaDatas.value)) : ''
+      }).catch((error) => {
+        ElMessage.error('API异常,获取学区失败')
+      })
+    }
     watch(filterText, (newdata) => {
       if (newdata.trim().length !== 0) {
         debounce(personnelSearch, 500)
@@ -481,6 +489,7 @@ export default {
         tableData.value = original.value
       }
     })
+    areaData()
     return {
       proxy,
       store,
@@ -516,7 +525,9 @@ export default {
       changeSubmit,
       roaming,
       schoolSort,
-      identityArr
+      identityArr,
+      areaData,
+      areaDatas
     }
   },
 }

+ 27 - 14
TEAMModelBI/ClientApp/src/view/teachermanage/traitmanage.vue

@@ -54,6 +54,10 @@
                   <p class="source">{{ $t(`abilityManages.source`) }}:<span class="source-title">{{ item.name}}</span></p>
                   <p class="source">{{ $t(`abilityManages.area`) }}:<span class="source-title">{{item.provName}}{{ item.cityName }}</span></p>
                   <p class="source">{{ $t(`abilityManages.affiliation`) }}:<span class="source-title">{{item.institution}}</span></p>
+                  <p class="source">引用标准:
+                    <span class="source-title" v-if="item.quotename" :title="item.quotename">{{item.quotename}}</span>
+                    <span class="source-title available" v-else>暂无</span>
+                  </p>
                 </div>
               </el-card>
               <!-- <div class="signboard" v-show="item.id==='bde5c011-2ae4-461a-b46c-5483ba72ae45'" title="即时同步" @click="synchronize">
@@ -87,14 +91,13 @@
                   </div>
                 </template>
                 <div class="information-box">
-                  <p class="source">{{ $t(`abilityManages.source`) }}:<span class="source-title">{{ item.name
-                            }}</span></p>
-                  <p class="source">{{ $t(`abilityManages.area`) }}:<span class="source-title">{{
-                                    item.provName
-                            }}{{ item.cityName }}</span></p>
-                  <p class="source">{{ $t(`abilityManages.affiliation`) }}:<span class="source-title">{{
-                                    item.institution
-                            }}</span></p>
+                  <p class="source">{{ $t(`abilityManages.source`) }}:<span class="source-title">{{ item.name}}</span></p>
+                  <p class="source">{{ $t(`abilityManages.area`) }}:<span class="source-title">{{item.provName}}{{ item.cityName }}</span></p>
+                  <p class="source">{{ $t(`abilityManages.affiliation`) }}:<span class="source-title">{{item.institution}}</span></p>
+                  <p class="source">引用标准:
+                    <span class="source-title" v-if="item.quotename" :title="item.quotename">{{item.quotename}}</span>
+                    <span class="source-title available" v-else>暂无</span>
+                  </p>
                 </div>
               </el-card>
             </div>
@@ -612,10 +615,10 @@ export default {
             element.name === '信息化能力工程2.0通识性课程' ? (element.no = '通用') : ''
           })
         }
-        if (res.abilities.length === 0) {
-          ElMessage.error(proxy.$t(`commonMsg.schemeError`))
-          return
-        }
+        // if (res.abilities.length === 0) {
+        //   ElMessage.error(proxy.$t(`commonMsg.schemeError`))
+        //   // return
+        // }
         res.abilities.sort(function (s, t) {
           var a = s.no.toLowerCase()
           var b = t.no.toLowerCase()
@@ -885,11 +888,18 @@ export default {
             item.id === 'bde5c011-2ae4-461a-b46c-5483ba72ae45' ? res.areas.unshift(res.areas.splice(index, 1)[0]) : ''
           })
           for (let i in res.areas) {
+            let quote = res.areas[i].quoteId
+            res.areas[i].quotename = ''
             i < 4 ? abilityProject.push(res.areas[i]) : citeAbility.value.push(res.areas[i])
+            for (let e in res.areas) {
+              console.log(res.areas[e].id, quote, '999999999999999')
+              res.areas[e].id === quote && quote !== null ? res.areas[i].quotename = res.areas[e].name + '—' + res.areas[e].institution : ''
+            }
           }
           store.commit('getPoint', res.areas)
           loadingData.value.preinstall = false
           loadingData.value.cite = false
+          console.log(res.areas)
         }
       }).catch((error) => {
         ElMessage.error('微能力获取异常')
@@ -1003,7 +1013,7 @@ export default {
 .cardbox {
   width: 19%;
   display: inline-block;
-  padding: 5px 10px;
+  padding: 0px 10px;
   margin-top: 10px;
   position: relative;
   cursor: pointer;
@@ -1062,7 +1072,7 @@ export default {
   font-size: 14px;
   color: #909399;
   text-align: left;
-  line-height: 45px;
+  line-height: 35px;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
@@ -1709,6 +1719,9 @@ export default {
 .intact-right:hover {
   background-color: rgba(99, 110, 114, 1) !important;
 }
+.available {
+  color: #909399 !important;
+}
 @keyframes mymove {
   0% {
     top: -35px;

+ 5 - 6
TEAMModelBI/Controllers/BINormal/AreaRelevantController.cs

@@ -69,16 +69,13 @@ namespace TEAMModelBI.Controllers.BINormal
                 //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
                 var isManyArea = false;
                 if (!string.IsNullOrEmpty($"{_isDefalue}"))
-                {
                     isManyArea = true;
-                }
-
                 List<JoinAreaSchool> joinAreaSchools = new();
                 string sqltxt = $"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period,c.areaId,c.standard,c.manyAreas FROM c WHERE c.areaId='{_areaId}'";
 
                 if (isManyArea)
                 {
-                    sqltxt = $"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period,c.areaId,c.standard,c.manyAreas FROM c join m in c.manyAreas WHERE c.areaId ='{_areaId}' or m.areaId='{_areaId}'";
+                    sqltxt = $"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period,c.areaId,c.standard,c.manyAreas FROM c join m in c.manyAreas WHERE (c.areaId ='{_areaId}' or m.areaId='{_areaId}')";
                 }
 
                 await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: sqltxt, requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")})) 
@@ -88,7 +85,7 @@ namespace TEAMModelBI.Controllers.BINormal
                     {
                         foreach(var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                         {
-                            JoinAreaSchool joinAreaSchool = new JoinAreaSchool
+                            JoinAreaSchool joinAreaSchool = new()
                             {
                                 id = obj.GetProperty("id").GetString(),
                                 name = obj.GetProperty("name").GetString(),
@@ -108,9 +105,10 @@ namespace TEAMModelBI.Controllers.BINormal
                             }
                             catch { }
 
-                            if (!string.IsNullOrEmpty($"{joinAreaSchool.id}")) 
+                            if (!string.IsNullOrEmpty($"{joinAreaSchool.id}"))
                             {
                                 joinAreaSchool.assists = await CommonFind.FindSchoolRoles(cosmosClient, joinAreaSchool.id, "assist");
+                                joinAreaSchool.scAdmin = await CommonFind.FindSchoolRoles(cosmosClient, joinAreaSchool.id, "admin");
                             }
 
                             joinAreaSchools.Add(joinAreaSchool);
@@ -612,6 +610,7 @@ namespace TEAMModelBI.Controllers.BINormal
             public string dist { get; set; }
             public List<SchoolArea> areas { get; set; } = new List<SchoolArea>();
             public List<SchoolTeacherRoles> assists { get; set; } = new List<SchoolTeacherRoles>();
+            public List<SchoolTeacherRoles> scAdmin { get; set; } = new List<SchoolTeacherRoles>();
         }
 
     }

+ 233 - 212
TEAMModelBI/Controllers/BINormal/BatchAreaController.cs

@@ -110,7 +110,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 from c");
+                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");
                 if (!string.IsNullOrEmpty($"{id}") && string.IsNullOrEmpty($"{name}"))
                     areaSql.Append($" where c.id='{id}'");
 
@@ -154,7 +154,8 @@ namespace TEAMModelBI.Controllers.BINormal
 
                 foreach (var area in areas)
                 {
-                    area.schoolCount = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"select value(count(c.id)) from c where c.areaId='{area.id}' and c.standard='{area.standard}'", "Base");
+                    //select value(count(c.id)) from c where c.areaId='{area.id}' and c.standard='{area.standard}'
+                    area.schoolCount = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"select value(count(c.id)) from c where c.areaId='{area.id}'", "Base");
 
                     area.aquoteRec = await table.QueryWhereString<AreaQuoteRecord>($"PartitionKey eq 'QuoteRecord' and  areaId eq '{area.id}'");
                     //List<AreaQuoteRecord> aqr = await table.QueryWhereString<AreaQuoteRecord>($"PartitionKey eq 'QuoteRecord' and  areaId eq '{area.id}'");
@@ -241,9 +242,16 @@ namespace TEAMModelBI.Controllers.BINormal
                         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 = "区级名称相同,请检测区级名称!" });
+                }
+
                 //区级的ID
                 string areaId = Guid.NewGuid().ToString();
-                Area addArea = new Area()
+                Area addArea = new()
                 {
                     id = areaId,
                     code = $"Base-Area",
@@ -254,7 +262,8 @@ namespace TEAMModelBI.Controllers.BINormal
                     cityName = $"{cityName}",
                     standard = $"{standard}",
                     standardName = $"{standardName}",
-                    institution = $"{institution}"
+                    institution = $"{institution}",
+                    quoteId = $"{_oldId}"
                 };
 
                 #region  区级管理员
@@ -651,7 +660,6 @@ namespace TEAMModelBI.Controllers.BINormal
                 //}
                 var table = tableClient.GetTableReference("IESLogin");
 
-
                 var responseSet = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync($"{_oldId}", new PartitionKey("AreaSetting"));
                 if (responseSet.Status == 200)
                 {
@@ -662,9 +670,9 @@ namespace TEAMModelBI.Controllers.BINormal
                 }
 
                 //保存引用记录
-                //await table.SaveOrUpdate<AreaQuoteRecord>(new AreaQuoteRecord() { PartitionKey = "QuoteRecord", RowKey = $"{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}", areaId = $"{_oldId}", quoteId = $"{_newId}", quoteName = $"{newName}", standard = $"{_newStandard}" });
+                await table.SaveOrUpdate<AreaQuoteRecord>(new AreaQuoteRecord() { PartitionKey = "QuoteRecord", RowKey = $"{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}", areaId = $"{_oldId}", quoteId = $"{_newId}", quoteName = $"{newName}", standard = $"{_newStandard}" });
 
-                List<string> abilityIds = new List<string>();  //册别的ID集合
+                List<string> abilityIds = new();  //册别的ID集合
 
                 //查询册别信息
                 await foreach (var tempAbility in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{_oldStandard}") }))
@@ -677,7 +685,7 @@ namespace TEAMModelBI.Controllers.BINormal
                     var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityIds, $"Ability-{_oldStandard}");
                 }
 
-                List<string> abilityTaskIds = new List<string>();  //章节ID集合
+                List<string> abilityTaskIds = new();  //章节ID集合
                 await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AbilityTask>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{_oldStandard}") }))
                 {
                     abilityTaskIds.Add(item.id);   //查询出来的章节信息ID添加到战绩集合
@@ -688,8 +696,8 @@ namespace TEAMModelBI.Controllers.BINormal
                     var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityTaskIds, $"AbilityTask-{_oldStandard}");
                 }
 
-                List<Task<ItemResponse<Ability>>> abilities = new List<Task<ItemResponse<Ability>>>();      //存储册别数据
-                List<Task<ItemResponse<AbilityTask>>> abilityTasks = new List<Task<ItemResponse<AbilityTask>>>();  //存储章节
+                List<Task<ItemResponse<Ability>>> abilities = new();      //存储册别数据
+                List<Task<ItemResponse<AbilityTask>>> abilityTasks = new();  //存储章节
 
                 //查询要复制区域的能力标准点 
                 await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{_newStandard}") }))
@@ -725,7 +733,7 @@ namespace TEAMModelBI.Controllers.BINormal
                 }
                 catch
                 {
-                    return Ok(new { state = 200, msg = "创区成功,能力标准点复制失败,遗留数据影响!" });
+                    return Ok(new { state = 200, msg = "能力标准点复制失败,遗留数据影响!" });
                 }
 
                 try
@@ -764,7 +772,7 @@ namespace TEAMModelBI.Controllers.BINormal
                 }
                 catch
                 {
-                    return Ok(new { state = 200, msg = "创区成功,能力标准创建成功,微能力点复制失败,遗留数据影响!" });
+                    return Ok(new { state = 200, msg = "能力标准创建成功,微能力点复制失败,遗留数据影响!" });
                 }
 
                 StandardFile saveFile = new();
@@ -821,6 +829,12 @@ namespace TEAMModelBI.Controllers.BINormal
                     tempSetting = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveSetting, new PartitionKey($"AreaSetting"));  //需要删除原来的区域设置数据在进行添加
                 }
 
+                //修改切换区级能力引用id
+                Area area = new();
+                area = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{_oldId}", new PartitionKey("Base-Area"));
+                area.quoteId = $"{_newId}";
+                await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<Area>(area, area.id, new PartitionKey(area.code));
+
                 //发送消息分区键
                 string partitionCode = "DelBeforeCopyAbility-mark";
                 //v2通知
@@ -1021,7 +1035,7 @@ namespace TEAMModelBI.Controllers.BINormal
             try
             {
                 string _oldId = "bde5c011-2ae4-461a-b46c-5483ba72ae45";
-                string _oldStandard = "standard27";
+                //string _oldStandard = "standard27";
                 string standardFileId = "02944f32-f534-3397-ea56-e6f1fc6c3714";
                 string standard = "standard2";
 
@@ -1040,252 +1054,257 @@ namespace TEAMModelBI.Controllers.BINormal
 
                 var table = tableClient.GetTableReference("IESLogin");
 
-                var responseSet = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync($"{_oldId}", new PartitionKey("AreaSetting"));
-                if (responseSet.Status == 200)
-                {
-                    using var fileJson = await JsonDocument.ParseAsync(responseSet.ContentStream);
-                    AreaSetting delSet = fileJson.ToObject<AreaSetting>();
-                    if (!string.IsNullOrEmpty(delSet.accessConfig))
-                        return Ok(new { state = 401, msg = "区域已经规定了,不能切换能能力" });
-                }
-
-                List<string> abilityIds = new List<string>();  //册别的ID集合
-
-                //查询册别信息
-                await foreach (var tempAbility in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{_oldStandard}") }))
-                {
-                    abilityIds.Add(tempAbility.id);  //查询出来册别ID添加册别ID集合
-                }
-                //删除册别
-                if (abilityIds.IsNotEmpty())
+                Area area = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{_oldId}", new PartitionKey("Base-Area"));
+                if (area != null)
                 {
-                    var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityIds, $"Ability-{_oldStandard}");
-                }
-
-                List<string> abilityTaskIds = new List<string>();  //章节ID集合
-                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AbilityTask>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{_oldStandard}") }))
-                {
-                    abilityTaskIds.Add(item.id);   //查询出来的章节信息ID添加到战绩集合
-                }
-                //删除章节
-                if (abilityTaskIds.IsNotEmpty())
-                {
-                    var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityTaskIds, $"AbilityTask-{_oldStandard}");
-                }
-                List<Task<ItemResponse<Ability>>> abilities = new();      //存储册别数据
-                List<Task<ItemResponse<AbilityTask>>> abilityTasks = new();  //存储章节
-
-                List<string> repeatAbilityId = new();
-                List<string> repeatAbilityTaskId = new();
-
-                foreach (var newstand in copyStand)
-                {
-                    try
+                    var responseSet = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync($"{_oldId}", new PartitionKey("AreaSetting"));
+                    if (responseSet.Status == 200)
                     {
-                        //查询要复制区域的能力标准点 
-                        await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{newstand.standard}") }))
-                        {
-                            if (!string.IsNullOrEmpty(item.blob))
-                                item.blob = item.blob.Replace($"/{newstand.standard}/", $"/{_oldStandard}/");
+                        using var fileJson = await JsonDocument.ParseAsync(responseSet.ContentStream);
+                        AreaSetting delSet = fileJson.ToObject<AreaSetting>();
+                        if (!string.IsNullOrEmpty(delSet.accessConfig))
+                            return Ok(new { state = 401, msg = "区域已经规定了,不能切换能能力" });
+                    }
 
-                            item.standard = $"{_oldStandard}";
-                            item.code = $"Ability-{_oldStandard}";
-                            item.school = $"{_oldStandard}";
+                    List<string> abilityIds = new();  //册别的ID集合
 
-                            //添加区能力标准点
-                            //abilities.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}")));
-                            //await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}"));
+                    //查询册别信息
+                    await foreach (var tempAbility in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{area.standard}") }))
+                    {
+                        abilityIds.Add(tempAbility.id);  //查询出来册别ID添加册别ID集合
+                    }
+                    //删除册别
+                    if (abilityIds.IsNotEmpty())
+                    {
+                        var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityIds, $"Ability-{area.standard}");
+                    }
 
-                            var respond = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(item.id, new PartitionKey(item.code));
-                            if (respond.Status != 200)
-                                abilities.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}")));
-                            else
-                                repeatAbilityId.Add(item.id);
-                        }
+                    List<string> abilityTaskIds = new List<string>();  //章节ID集合
+                    await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AbilityTask>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{area.standard}") }))
+                    {
+                        abilityTaskIds.Add(item.id);   //查询出来的章节信息ID添加到战绩集合
                     }
-                    catch
+                    //删除章节
+                    if (abilityTaskIds.IsNotEmpty())
                     {
-                        return Ok(new { state = 200, msg = "创区成功,能力标准点复制失败,遗留数据影响!" });
+                        var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityTaskIds, $"AbilityTask-{area.standard}");
                     }
+                    List<Task<ItemResponse<Ability>>> abilities = new();      //存储册别数据
+                    List<Task<ItemResponse<AbilityTask>>> abilityTasks = new();  //存储章节
 
-                    try
+                    List<string> repeatAbilityId = new();
+                    List<string> repeatAbilityTaskId = new();
+
+                    foreach (var newstand in copyStand)
                     {
-                        if (abilities.Count < 256)
+                        try
                         {
-                            await Task.WhenAll(abilities);
+                            //查询要复制区域的能力标准点 
+                            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{newstand.standard}") }))
+                            {
+                                if (!string.IsNullOrEmpty(item.blob))
+                                    item.blob = item.blob.Replace($"/{newstand.standard}/", $"/{area.standard}/");
+
+                                item.standard = $"{area.standard}";
+                                item.code = $"Ability-{area.standard}";
+                                item.school = $"{area.standard}";
+
+                                //添加区能力标准点
+                                //abilities.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}")));
+                                //await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}"));
+
+                                var respond = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(item.id, new PartitionKey(item.code));
+                                if (respond.Status != 200)
+                                    abilities.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{area.standard}")));
+                                else
+                                    repeatAbilityId.Add(item.id);
+                            }
                         }
-                        else
+                        catch
                         {
-                            int pages = (abilities.Count + 255) / 256;
-                            for (int i = 0; i < pages; i++)
+                            return Ok(new { state = 200, msg = "创区成功,能力标准点复制失败,遗留数据影响!" });
+                        }
+
+                        try
+                        {
+                            if (abilities.Count < 256)
                             {
-                                List<Task<ItemResponse<Ability>>> tempAbility = abilities.Skip((i) * 256).Take(256).ToList();
-                                await Task.WhenAll(tempAbility);
+                                await Task.WhenAll(abilities);
+                            }
+                            else
+                            {
+                                int pages = (abilities.Count + 255) / 256;
+                                for (int i = 0; i < pages; i++)
+                                {
+                                    List<Task<ItemResponse<Ability>>> tempAbility = abilities.Skip((i) * 256).Take(256).ToList();
+                                    await Task.WhenAll(tempAbility);
+                                }
                             }
                         }
-                    }
-                    catch
-                    {
-                        return Ok(new { state = 200, msg = "创区成功,能力标准点复制失败,遗留数据影响!" });
-                    }
+                        catch
+                        {
+                            return Ok(new { state = 200, msg = "创区成功,能力标准点复制失败,遗留数据影响!" });
+                        }
 
-                    try
-                    {
-                        //微能力点
-                        await foreach (var atask in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AbilityTask>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{newstand.standard}") }))
+                        try
                         {
-                            List<Tnode> tnodes = new();
-                            foreach (Tnode tnode in atask.children)
+                            //微能力点
+                            await foreach (var atask in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AbilityTask>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{newstand.standard}") }))
                             {
-                                if (tnode.rnodes != null)
+                                List<Tnode> tnodes = new();
+                                foreach (Tnode tnode in atask.children)
                                 {
-                                    List<Rnode> rnodes = new();
-                                    foreach (Rnode rnode in tnode.rnodes)
+                                    if (tnode.rnodes != null)
                                     {
-                                        if (!string.IsNullOrEmpty($"{rnode.link}"))
+                                        List<Rnode> rnodes = new();
+                                        foreach (Rnode rnode in tnode.rnodes)
                                         {
-                                            rnode.link = rnode.link.Replace($"/{newstand.standard}/", $"/{_oldStandard}/");
+                                            if (!string.IsNullOrEmpty($"{rnode.link}"))
+                                            {
+                                                rnode.link = rnode.link.Replace($"/{newstand.standard}/", $"/{area.standard}/");
+                                            }
+                                            rnodes.Add(rnode);
                                         }
-                                        rnodes.Add(rnode);
+                                        tnode.rnodes = rnodes;
                                     }
-                                    tnode.rnodes = rnodes;
+                                    tnodes.Add(tnode);
                                 }
-                                tnodes.Add(tnode);
-                            }
 
-                            atask.children = tnodes;
-                            atask.code = $"AbilityTask-{_oldStandard}";
-                            atask.standard = $"{_oldStandard}";
-                            atask.codeval = $"{_oldStandard}";
-
-                            var respond = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(atask.id, new PartitionKey(atask.code));
-                            if (respond.Status != 200)
-                                ////添加区能力标准点中的节点 
-                                //abilityTasks.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(atask, new PartitionKey($"AbilityTask-{_oldStandard}")));
-                                await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(atask, new PartitionKey($"AbilityTask-{_oldStandard}"));
-                            else
-                                repeatAbilityTaskId.Add(atask.id);
+                                atask.children = tnodes;
+                                atask.code = $"AbilityTask-{area.standard}";
+                                atask.standard = $"{area.standard}";
+                                atask.codeval = $"{area.standard}";
+
+                                var respond = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(atask.id, new PartitionKey(atask.code));
+                                if (respond.Status != 200)
+                                    ////添加区能力标准点中的节点 
+                                    //abilityTasks.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(atask, new PartitionKey($"AbilityTask-{_oldStandard}")));
+                                    await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(atask, new PartitionKey($"AbilityTask-{area.standard}"));
+                                else
+                                    repeatAbilityTaskId.Add(atask.id);
+                            }
+                        }
+                        catch
+                        {
+                            return Ok(new { state = 200, msg = "创区成功,能力标准创建成功,微能力点复制失败,遗留数据影响!" });
                         }
-                    }
-                    catch
-                    {
-                        return Ok(new { state = 200, msg = "创区成功,能力标准创建成功,微能力点复制失败,遗留数据影响!" });
-                    }
 
-                    //发送消息分区键
-                    string partitionCode = "DelBeforeCopyAbility-mark";
-
-                    //执行复制操作
-                    BatchCopyFile batchCopyFile = new();
-                    batchCopyFile.blobCntr = "teammodelos";
-                    batchCopyFile.oldFileName = $"{newstand.standard}";
-                    batchCopyFile.newFileName = $"{_oldStandard}";
-                    batchCopyFile.tmdid = $"{_tmdId}";
-                    batchCopyFile.tmdIds = new List<string> { $"{_tmdId}" };
-                    batchCopyFile.codeKey = partitionCode;
-                    batchCopyFile.tmdName = $"{_tmdName}";
-                    var messageBatchCopyFile = new ServiceBusMessage(batchCopyFile.ToJsonString());
-                    messageBatchCopyFile.ApplicationProperties.Add("name", "CopyStandardFile");
-                    try
-                    {
-                        //await _serviceBus.GetServiceBusClient().SendMessageAsync(activeTask, messageBatchCopyFile);  //先执行删除操作,在执行复制  单一
-                        await serBusClient.SendMessageAsync(activeTask, messageBatchCopyFile);  //先执行删除操作,在执行复制
-                    }
-                    catch (Exception)
-                    {
-                        return Ok(new { state = 201, msg = "能力点复制成功,复制能力点的文件失败," });
-                    }
+                        //发送消息分区键
+                        string partitionCode = "DelBeforeCopyAbility-mark";
+
+                        //执行复制操作
+                        BatchCopyFile batchCopyFile = new();
+                        batchCopyFile.blobCntr = "teammodelos";
+                        batchCopyFile.oldFileName = $"{newstand.standard}";
+                        batchCopyFile.newFileName = $"{area.standard}";
+                        batchCopyFile.tmdid = $"{_tmdId}";
+                        batchCopyFile.tmdIds = new List<string> { $"{_tmdId}" };
+                        batchCopyFile.codeKey = partitionCode;
+                        batchCopyFile.tmdName = $"{_tmdName}";
+                        var messageBatchCopyFile = new ServiceBusMessage(batchCopyFile.ToJsonString());
+                        messageBatchCopyFile.ApplicationProperties.Add("name", "CopyStandardFile");
+                        try
+                        {
+                            //await _serviceBus.GetServiceBusClient().SendMessageAsync(activeTask, messageBatchCopyFile);  //先执行删除操作,在执行复制  单一
+                            await serBusClient.SendMessageAsync(activeTask, messageBatchCopyFile);  //先执行删除操作,在执行复制
+                        }
+                        catch (Exception)
+                        {
+                            return Ok(new { state = 201, msg = "能力点复制成功,复制能力点的文件失败," });
+                        }
 
-                    //发送消息实体
-                    Notification notification = new()
-                    {
-                        hubName = "hita",
-                        type = "msg",
-                        from = $"BI:{_option.Location}:private",
-                        to = new List<string> { $"{_tmdId}" },
-                        label = $"{partitionCode}_start",
-                        body = new { location = _option.Location, biz = partitionCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
-                        expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
-                    };
+                        //发送消息实体
+                        Notification notification = new()
+                        {
+                            hubName = "hita",
+                            type = "msg",
+                            from = $"BI:{_option.Location}:private",
+                            to = new List<string> { $"{_tmdId}" },
+                            label = $"{partitionCode}_start",
+                            body = new { location = _option.Location, biz = partitionCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
+                            expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
+                        };
 
-                    var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
-                    var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
-                    var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
-                    var location = _option.Location;
-                    await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //发送站内发送消息
-                }
+                        var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
+                        var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+                        var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
+                        var location = _option.Location;
+                        await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //发送站内发送消息
+                    }
 
-                StandardFile saveFile = new();
-                //新政策文件
-                await foreach (StandardFile standardFile in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<StandardFile>(queryText: $"select value(c) from c where  c.id='{standardFileId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StandardFile") }))
-                {
-                    if (standardFile != null)
+                    StandardFile saveFile = new();
+                    //新政策文件
+                    await foreach (StandardFile standardFile in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<StandardFile>(queryText: $"select value(c) from c where  c.id='{standardFileId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StandardFile") }))
                     {
-                        standardFile.standard = $"{_oldStandard}";
-                        standardFile.id = $"{_oldId}";
+                        if (standardFile != null)
+                        {
+                            standardFile.standard = $"{area.standard}";
+                            standardFile.id = $"{_oldId}";
 
-                        saveFile = standardFile;
+                            saveFile = standardFile;
+                        }
                     }
-                }
 
-                StandardFile tempFile = new();
-                if (saveFile.id != null)
-                {
-                    var respFile = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(saveFile.id, new PartitionKey("StandardFile"));
-                    if (respFile.Status == 200)
+                    StandardFile tempFile = new();
+                    if (saveFile.id != null)
                     {
-                        using var json = await JsonDocument.ParseAsync(respFile.ContentStream);
-                        tempFile = json.ToObject<StandardFile>();
-                        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemAsync<StandardFile>(tempFile.id, new PartitionKey("StandardFile"));
-                    }
+                        var respFile = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(saveFile.id, new PartitionKey("StandardFile"));
+                        if (respFile.Status == 200)
+                        {
+                            using var json = await JsonDocument.ParseAsync(respFile.ContentStream);
+                            tempFile = json.ToObject<StandardFile>();
+                            await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemAsync<StandardFile>(tempFile.id, new PartitionKey("StandardFile"));
+                        }
 
-                    tempFile = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveFile, new PartitionKey($"StandardFile")); // 需要删除原来的政策文件数据在进行添加
-                }
+                        tempFile = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveFile, new PartitionKey($"StandardFile")); // 需要删除原来的政策文件数据在进行添加
+                    }
 
-                //if (tempFile.id != null)
-                //{
-                //    if (tempFile.id.Equals(saveFile.id))
-                //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<StandardFile>(saveFile, saveFile.id, new PartitionKey("StandardFile")); //直接替换以前的数据
-                //    else
-                //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveFile, new PartitionKey($"StandardFile")); // 需要删除原来的政策文件数据在进行添加
-                //}
+                    //if (tempFile.id != null)
+                    //{
+                    //    if (tempFile.id.Equals(saveFile.id))
+                    //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<StandardFile>(saveFile, saveFile.id, new PartitionKey("StandardFile")); //直接替换以前的数据
+                    //    else
+                    //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveFile, new PartitionKey($"StandardFile")); // 需要删除原来的政策文件数据在进行添加
+                    //}
 
-                //新的区域设置
-                AreaSetting saveSetting = new();
-                await foreach (AreaSetting areaSetting in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AreaSetting>(queryText: $"select value(c) from c where c.id='{standardFileId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("AreaSetting") }))
-                {
-                    if (areaSetting != null)
+                    //新的区域设置
+                    AreaSetting saveSetting = new();
+                    await foreach (AreaSetting areaSetting in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AreaSetting>(queryText: $"select value(c) from c where c.id='{standardFileId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("AreaSetting") }))
                     {
-                        areaSetting.accessConfig = null;
-                        areaSetting.id = $"{_oldId}";
+                        if (areaSetting != null)
+                        {
+                            areaSetting.accessConfig = null;
+                            areaSetting.id = $"{_oldId}";
 
-                        saveSetting = areaSetting;
+                            saveSetting = areaSetting;
+                        }
                     }
-                }
 
-                AreaSetting tempSetting = new();
-                if (saveSetting.id != null)
-                {
-                    var respSetting = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(saveSetting.id, new PartitionKey("AreaSetting"));
-                    if (respSetting.Status == 200)
+                    AreaSetting tempSetting = new();
+                    if (saveSetting.id != null)
                     {
-                        using var json = await JsonDocument.ParseAsync(respSetting.ContentStream);
-                        tempSetting = json.ToObject<AreaSetting>();
-                        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemAsync<AreaSetting>(saveSetting.id, new PartitionKey("AreaSetting"));
+                        var respSetting = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(saveSetting.id, new PartitionKey("AreaSetting"));
+                        if (respSetting.Status == 200)
+                        {
+                            using var json = await JsonDocument.ParseAsync(respSetting.ContentStream);
+                            tempSetting = json.ToObject<AreaSetting>();
+                            await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemAsync<AreaSetting>(saveSetting.id, new PartitionKey("AreaSetting"));
+                        }
+
+                        tempSetting = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveSetting, new PartitionKey($"AreaSetting"));  //需要删除原来的区域设置数据在进行添加
                     }
+                    //if (tempSetting.id != null)
+                    //{
+                    //    if (tempSetting.id.Equals(saveSetting.id))
+                    //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<AreaSetting>(saveSetting, saveSetting.id, new PartitionKey($"AreaSetting"));   //直接替换以前的数据
+                    //    else
+                    //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveSetting, new PartitionKey($"AreaSetting"));  //需要删除原来的区域设置数据在进行添加
+                    //}
 
-                    tempSetting = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveSetting, new PartitionKey($"AreaSetting"));  //需要删除原来的区域设置数据在进行添加
+                    return Ok(new { state = RespondCode.Ok, repeatAbilityId, repeatAbilityTaskId });
                 }
-
-                //if (tempSetting.id != null)
-                //{
-                //    if (tempSetting.id.Equals(saveSetting.id))
-                //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<AreaSetting>(saveSetting, saveSetting.id, new PartitionKey($"AreaSetting"));   //直接替换以前的数据
-                //    else
-                //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveSetting, new PartitionKey($"AreaSetting"));  //需要删除原来的区域设置数据在进行添加
-                //}
-
-                return Ok(new { state = RespondCode.Ok, repeatAbilityId, repeatAbilityTaskId });
+                else
+                    return Ok(new { state = RespondCode.NotFound, msg = "标准为空"}) ;
 
             }
             catch (Exception ex)
@@ -1312,6 +1331,8 @@ namespace TEAMModelBI.Controllers.BINormal
             public string standardName { get; set; }
             public string institution { get; set; }
             public int schoolCount { get; set; }
+            public long updateTime { get; set; }
+            public string quoteId { get; set; } = null;
             public bool cutArea { get; set; } = false;
             public List<AreaQuoteRecord> aquoteRec { get; set; } = new List<AreaQuoteRecord>();
         }

+ 26 - 24
TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs

@@ -169,7 +169,7 @@ namespace TEAMModelBI.Controllers.BISchool
                         CreateSchoolInfo createSchoolInfo = new CreateSchoolInfo()
                         {
                             province = bischool.province,
-                            id = "",
+                            id = bischool.id,
                             name = bischool.name,
                             city = bischool.city,
                             aname = "",
@@ -233,8 +233,15 @@ namespace TEAMModelBI.Controllers.BISchool
                                 {
                                     using var tchJson = await JsonDocument.ParseAsync(resTeache.ContentStream);
                                     teacher = tchJson.ToObject<Teacher>();
-                                    //教师存在,在该教师信息中添加要管理的学校信息
-                                    teacher.schools.Add(new Teacher.TeacherSchool { areaId = string.IsNullOrEmpty(bischool.areaId) ? "" : bischool.areaId, schoolId = createSchoolInfo.id, name = bischool.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() });
+                                    Teacher.TeacherSchool tchSc = null;
+                                    //var tempTch = teacher.schools.Select(x => x.schoolId.Equals(upSchool.id)).ToString();
+                                    tchSc = teacher.schools.Find(x => x.schoolId.Equals(upSchool.id));                                
+                                    if (tchSc == null)
+                                    {
+                                        //教师存在,在该教师信息中添加要管理的学校信息
+                                        teacher.schools.Add(new Teacher.TeacherSchool { areaId = string.IsNullOrEmpty(bischool.areaId) ? "" : bischool.areaId, schoolId = createSchoolInfo.id, name = bischool.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() });
+                                    }
+
                                     //await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, coreUser.id, new PartitionKey("Base"));
                                     SchoolTeacher schoolTeacher = new()
                                     {
@@ -533,18 +540,13 @@ namespace TEAMModelBI.Controllers.BISchool
                 if (jsonElement.TryGetProperty("pageSize", out JsonElement jsonPageSize))
                 {
                     if (!jsonPageSize.ValueKind.Equals(JsonValueKind.Undefined) && !jsonPageSize.ValueKind.Equals(JsonValueKind.Null) && jsonPageSize.TryGetInt32(out int tempPageSize))
-                    {
                         pageSize = tempPageSize;
-                    }
                 }
                 if (pageSize != null && pageSize.Value > 0)
-                {
                     iscontinuation = true;
-                }
+
                 if (jsonElement.TryGetProperty("contToken", out JsonElement ContToken))
-                {
                     pageToken = ContToken.GetString();
-                }
 
                 if (!string.IsNullOrEmpty($"{tmdId}"))
                 {
@@ -561,9 +563,7 @@ namespace TEAMModelBI.Controllers.BISchool
                         StringBuilder sqlTxt = new($"select c.id,c.code,c.schoolCode,c.name,c.region,c.province,c.city,c.dist,c.size,c.address,c.picture,c.type,c.scale,c.areaId,c.standard from c where c.id='{id}'");
 
                         if ($"{order}".Equals("desc"))
-                        {
                             sqlTxt.Append(" order by c.createTime desc");
-                        }
 
                         await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<AssistSchool>(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
                         {
@@ -600,9 +600,7 @@ namespace TEAMModelBI.Controllers.BISchool
                     }
 
                     if ($"{order}".Equals("desc"))
-                    {
                         stringBuilder.Append(" order by c.createTime desc");
-                    }
 
                     scCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", scCntSql.ToString(), "Base");
 
@@ -631,17 +629,11 @@ namespace TEAMModelBI.Controllers.BISchool
                     {
                         using var json = await JsonDocument.ParseAsync(response.ContentStream);
                         if (json.RootElement.TryGetProperty("serial", out JsonElement serial) && !serial.ValueKind.Equals(JsonValueKind.Null))
-                        {
                             item.serial = serial.ToObject<List<SchoolProductSumData>>().Select(x => x.prodCode).ToList();
-                        }
                         if (json.RootElement.TryGetProperty("service", out JsonElement service) && !service.ValueKind.Equals(JsonValueKind.Null))
-                        {
                             item.service = service.ToObject<List<SchoolProductSumData>>().Select(x => x.prodCode).ToList();
-                        }
                         if (json.RootElement.TryGetProperty("hard", out JsonElement hard) && !hard.ValueKind.Equals(JsonValueKind.Null))
-                        {
                             item.hard = hard.ToObject<List<SchoolProductSumDataHard>>().Select(x => x.prodCode).ToList();
-                        }
                     }
 
                     item.assists = await CommonFind.FindSchoolRoles(cosmosClient, item.id, "assist");
@@ -1323,7 +1315,6 @@ namespace TEAMModelBI.Controllers.BISchool
                 return Ok(new { state = RespondCode.Ok, createScInfo });
         }
 
-
         /// <summary>
         /// 添加多个学校添加多个管理员
         /// </summary>
@@ -1572,7 +1563,7 @@ namespace TEAMModelBI.Controllers.BISchool
         /// <param name="Language"></param>
         /// <param name="campusId"></param>
         /// <returns></returns>
-        public List<Period> PresetSchoolPeriod(List<string> period, string Language, string campusId)
+        public List<Period> PresetSchoolPeriod(List<PeriodType> period, string Language, string campusId)
         {
             var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
             StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
@@ -1603,7 +1594,7 @@ namespace TEAMModelBI.Controllers.BISchool
                     periods.Add(new Period
                     {
                         id = Guid.NewGuid().ToString(),
-                        name = x,
+                        name = x.pidName,
                         campusId = campusId,
                         semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
                         new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
@@ -1622,7 +1613,9 @@ namespace TEAMModelBI.Controllers.BISchool
                             income = schoolConfig.PresetExam[0].income,
                             eugenics = schoolConfig.PresetExam[0].eugenics,
                             touch = schoolConfig.PresetExam[0].touch
-                        }
+                        },
+                        type = x.pidType
+                        
                     });
                 });
             }
@@ -1723,7 +1716,7 @@ namespace TEAMModelBI.Controllers.BISchool
             /// <summary>
             /// 学校的学段
             /// </summary>
-            public List<string> period { get; set; }
+            public List<PeriodType> period { get; set; }
             /// <summary>
             /// 学校空间大小
             /// </summary>
@@ -1762,6 +1755,15 @@ namespace TEAMModelBI.Controllers.BISchool
             public string standard { get; set; }
         }
 
+        /// <summary>
+        /// 学段类型和学段名称
+        /// </summary>
+        public record PeriodType
+        {
+            public List<string> pidType { get; set; }
+            public string pidName { get; set; }
+        }
+
         /// <summary>
         /// 存在的学校
         /// </summary>

+ 36 - 31
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -91,31 +91,22 @@ namespace TEAMModelBI.Controllers.BISchool
                 if (jsonElement.TryGetProperty("pageSize", out JsonElement jsonPageSize))
                 {
                     if (!jsonPageSize.ValueKind.Equals(JsonValueKind.Undefined) && !jsonPageSize.ValueKind.Equals(JsonValueKind.Null) && jsonPageSize.TryGetInt32(out int tempPageSize))
-                    {
                         pageSize = tempPageSize;
-                    }
                 }
                 //是否需要进行分页查询,默认不分页
                 bool iscontinuation = false;
                 if (pageSize != null && pageSize.Value > 0)
-                {
                     iscontinuation = true;
-                }
+
                 if (jsonElement.TryGetProperty("contToken", out JsonElement ContToken))
-                {
                     pageToken = ContToken.GetString();
-                }
 
 
                 StringBuilder sqltxt = new($"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period,c.areaId,c.standard,c.manyAreas FROM c");
                 if (!string.IsNullOrEmpty($"{areaId}"))
-                {
-                    sqltxt.Append($" WHERE c.areaId !='{areaId}'");
-                }
+                    sqltxt.Append($" WHERE c.pk='School' and c.areaId !='{areaId}'");
                 else
-                {
-                    sqltxt.Append($" WHERE c.areaId ='' and c.standard = ''");
-                }
+                    sqltxt.Append($" WHERE c.pk='School' and (c.areaId = '' or c.areaId = null or IS_DEFINED(c.areaId) = false)");
 
                 List<NotAreaSchool> tempNotAreaSchools = new();
                 await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: sqltxt.ToString(), continuationToken: pageToken, requestOptions: new QueryRequestOptions() { MaxItemCount = pageSize, PartitionKey = new PartitionKey("Base") }))
@@ -200,9 +191,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 //jsonElement.TryGetProperty("site", out JsonElement site); //分开部署,就不需要,一站多用时,取消注释
                 var isManyArea = false;
                 if (!string.IsNullOrEmpty($"{isDefault}"))
-                {
                     isManyArea = true;
-                }
 
                 var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
                 List<string> schoolCodes = _schoolCode.ToObject<List<string>>();
@@ -797,17 +786,20 @@ namespace TEAMModelBI.Controllers.BISchool
         [HttpPost("del-manage")]
         public async Task<IActionResult> DelSchoolManage(JsonElement jsonElement)
         {
+            var (_tmdId, _tmdName, _, _, _, _) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
             if (!jsonElement.TryGetProperty("tmdId", out JsonElement tmdId)) return BadRequest();
             if (!jsonElement.TryGetProperty("scIds", out JsonElement _scIds)) return BadRequest();
             //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
 
             List<string> scIds = _scIds.ToObject<List<string>>();
             var cosmosClient = _azureCosmos.GetCosmosClient();
+            var tableClient = _azureStorage.GetCloudTableClient();
+            var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
             ////分开部署,就不需要,一站多用时,取消注释
             //if ($"{site}".Equals(BIConst.Global))
             //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
             List<string> existScId = new();
-
+            StringBuilder strMsg = new($"{_tmdName}【{_tmdId}】管理员账户将{tmdId}的账户移除学校:");
             SchoolTeacher scTeacher = null;
             foreach (var scId in scIds)
             {
@@ -819,6 +811,7 @@ namespace TEAMModelBI.Controllers.BISchool
                     if (scTeacher.roles.Contains("admin"))
                     {
                         scTeacher.roles.Remove("admin");
+                        strMsg.Append($"{scId},");
                         scTeacher = await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(scTeacher, scTeacher.id, new PartitionKey($"Teacher-{scId}"));
                     }
                     else
@@ -828,6 +821,9 @@ namespace TEAMModelBI.Controllers.BISchool
                     existScId.Add(scId);
             }
 
+            //保存操作记录
+            await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "schoolTeacher-updatee", strMsg.ToString(), _dingDing, httpContext: HttpContext);
+
             return Ok(new { state = RespondCode.Ok, existScId });
         }
 
@@ -881,10 +877,10 @@ namespace TEAMModelBI.Controllers.BISchool
                     foreach (var school in schools)
                     {
                         SchoolTeacher schoolTeacher = null;
-                        var existArea = teacher.schools.Find(f => f.schoolId.Equals($"{school.id}"));
-                        if (existArea == null)
+                        var existSchool = teacher.schools.Find(f => f.schoolId.Equals($"{school.id}"));
+                        if (existSchool == null)
                         {
-                            teacher.schools.Add(new Teacher.TeacherSchool { schoolId = $"{school.id}", name = $"{school.id}", status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = string.IsNullOrEmpty($"{school.picture}") ? "" : $"{school.picture}", areaId = string.IsNullOrEmpty($"{school.areaId}") ? "" : $"{school.areaId}" });
+                            teacher.schools.Add(new Teacher.TeacherSchool { schoolId = $"{school.id}", name = $"{school.name}", status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = string.IsNullOrEmpty($"{school.picture}") ? "" : $"{school.picture}", areaId = string.IsNullOrEmpty($"{school.areaId}") ? "" : $"{school.areaId}" });
                         }
 
                         var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{tmdId}", new PartitionKey($"Teacher-{school.id}"));
@@ -1132,17 +1128,13 @@ namespace TEAMModelBI.Controllers.BISchool
                 {
                     using var json = await JsonDocument.ParseAsync(response.ContentStream);
                     if (json.RootElement.TryGetProperty("serial", out JsonElement serial) && !serial.ValueKind.Equals(JsonValueKind.Null))
-                    {
                         schoolInfo.serial = serial.ToObject<List<ProductSumInfos>>();
-                    }
+
                     if (json.RootElement.TryGetProperty("service", out JsonElement service) && !service.ValueKind.Equals(JsonValueKind.Null))
-                    {
                         schoolInfo.service = service.ToObject<List<ProductSumInfos>>();
-                    }
+
                     if (json.RootElement.TryGetProperty("hard", out JsonElement hard) && !hard.ValueKind.Equals(JsonValueKind.Null))
-                    {
                         schoolInfo.hard = hard.ToObject<List<SchoolProductSumDataHard>>();
-                    }
                 }
 
                 schoolInfo.assists = await CommonFind.FindSchoolRoles(cosmosClient, schoolInfo.id, "assist");
@@ -2203,7 +2195,7 @@ namespace TEAMModelBI.Controllers.BISchool
 
 
         /// <summary>
-        /// 添加没有学段的学校
+        /// 添加学段的学校
         /// </summary>
         /// <param name="jsonElement"></param>
         /// <returns></returns>
@@ -2212,11 +2204,14 @@ namespace TEAMModelBI.Controllers.BISchool
         public async Task<IActionResult> SetAllScPeriod(JsonElement jsonElement)
         {
             jsonElement.TryGetProperty("Language", out JsonElement Language);
+            jsonElement.TryGetProperty("scId", out JsonElement scId);
+            jsonElement.TryGetProperty("periodName", out JsonElement periodName);
             var cosmosClient = _azureCosmos.GetCosmosClient();
             var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
             StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
             StringBuilder stringBuilder = new();
             string text;
+            string scName = "默认学段";
             while ((text = streamReader.ReadLine()) != null)
             {
                 stringBuilder.Append(text.ToString());
@@ -2237,20 +2232,30 @@ namespace TEAMModelBI.Controllers.BISchool
             }
             string campusId = Guid.NewGuid().ToString();
 
-            string noPeriodScSql = $"SELECT value(c) FROM c where c.code='Base' and c.period=[]";
+            StringBuilder noPeriodScSql = new("SELECT value(c) FROM c ");
             List<School> allSc = new();
 
-            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(noPeriodScSql,requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")}))
+            if (!string.IsNullOrEmpty($"{scId}"))
+                noPeriodScSql.Append($" where c.id='{scId}'");
+            else
+                noPeriodScSql.Append($" where c.code='Base' and c.period=[]");
+
+            if (!string.IsNullOrEmpty($"{periodName}"))
+                scName = $"{periodName}";
+
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(noPeriodScSql.ToString(),requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")}))
             {
                 allSc.Add(item);
             }
-
             foreach (var school in allSc)
             {
+                if (school.campuses.Count > 0)
+                    campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
+                
                 school.period.Add(new Period
                 {
                     id = Guid.NewGuid().ToString(),
-                    name = "默认学段",
+                    name = scName,
                     campusId = campusId,
                     semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
                         new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
@@ -2271,8 +2276,8 @@ namespace TEAMModelBI.Controllers.BISchool
                         touch = schoolConfig.PresetExam[0].touch
                     }
                 });
-
-                school.campuses.Add(new Campus { name = school.name, id = campusId });
+                if (!school.campuses.Select(x => x.id).Contains(campusId))
+                    school.campuses.Add(new Campus { name = school.name, id = campusId });
 
                 School rSchool = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey("Base"));
             }

+ 38 - 4
TEAMModelBI/Controllers/BITable/IES5OAuthController.cs

@@ -1,4 +1,6 @@
-using DocumentFormat.OpenXml.Spreadsheet;
+using Azure.Cosmos;
+using Azure.Storage.Blobs;
+using DocumentFormat.OpenXml.Spreadsheet;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
@@ -7,9 +9,12 @@ using System.Collections.Generic;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
+using TEAMModelBI.Filter;
+using TEAMModelBI.Tool.Extension;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Table;
 
@@ -21,11 +26,13 @@ namespace TEAMModelBI.Controllers.BITable
     {
 
         public readonly AzureStorageFactory _azureStorage;
+        private readonly AzureCosmosFactory _azureCosmos;
         public readonly DingDing _dingDing;
         public readonly Option _option;
-        public IES5OAuthController(AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option)
+        public IES5OAuthController(AzureStorageFactory azureStorage, AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option)
         {
             _azureStorage = azureStorage;
+            _azureCosmos = azureCosmos;
             _dingDing = dingDing;
             _option = option?.Value;
         }
@@ -66,18 +73,25 @@ namespace TEAMModelBI.Controllers.BITable
         /// </summary>
         /// <param name="oAuthShow"></param>
         /// <returns></returns>
+        [AuthToken(Roles = "admin,rdc,sales")]
         [HttpPost("set-oauthshow")]
         public async Task<IActionResult> UpOAuthShow(OAuthShow oAuthShow)
         {
             var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOAuth");
+
+            var (_tmdId, _tmdName, _, _, _, _) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
+            var cosmosClinet = _azureCosmos.GetCosmosClient();
+            var tableClient = _azureStorage.GetCloudTableClient();
+            var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
+            StringBuilder msg = new($"{_tmdName}[{_tmdId}]");
             List<OAuthShow> oAuthShows = new();
             List<OAuthShow> queryOs = new();
-
+            ArtSetting artSetting = new();
             if (!string.IsNullOrEmpty(oAuthShow.RowKey))
             {
                 string osSql = $" PartitionKey eq 'OAuthShow' and RowKey eq '{oAuthShow.RowKey}'";
                 queryOs = await table.QueryWhereString<OAuthShow>(osSql);
-
+                msg.Append($"修改RowKy为{oAuthShow.RowKey}授权信息");
                 if (queryOs.Count > 0)
                 {
                     foreach (var item in queryOs)
@@ -102,13 +116,33 @@ namespace TEAMModelBI.Controllers.BITable
                     oAuthShow.PartitionKey = "OAuthShow";
                     oAuthShow.Status = 1;
                     oAuthShow.RowKey = $"{oAuthShow.Type}-{oAuthShow.Domain}-{oAuthShow.Code}";
+
+                    msg.Append($"添加RowKy为{oAuthShow.RowKey}授权信息");
                     oAuthShow = await table.SaveOrUpdate<OAuthShow>(oAuthShow);
                     oAuthShows.Add(oAuthShow);
+                    if (oAuthShow.Type.Equals("art")) 
+                    {
+                        var isExist = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync($"{oAuthShow.Code}", new PartitionKey("ArtSetting"));
+                        if (isExist.Status != 200)
+                        {
+                            artSetting = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<ArtSetting>("default", new PartitionKey("ArtSetting"));
+                            artSetting.id = oAuthShow.Code;
+                            artSetting = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync<ArtSetting>(artSetting, new PartitionKey("ArtSetting"));
+                        }
+                        else
+                        {
+                            //保存操作记录
+                            await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "schoolTeacher-add", msg.ToString(), _dingDing, httpContext: HttpContext);
+                            return Ok(new { state = RespondCode.Created, msg = "已授权,区级艺术设置文件已存在!" });
+                        }
+                    }
                 }
                 else
                     return Ok(new { state = RespondCode.Conflict, msg = "已存在该授权。" });
             }
 
+            //保存操作记录
+            await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "schoolTeacher-add", msg.ToString(), _dingDing, httpContext: HttpContext);
             return Ok(new { state = RespondCode.Ok, oAuthShows });
         }
 

+ 52 - 20
TEAMModelBI/Controllers/BITest/TestController.cs

@@ -53,6 +53,7 @@ using Azure.Storage.Blobs;
 using Azure.Storage.Blobs.Specialized;
 using System.Web;
 using Azure.Storage.Sas;
+using DocumentFormat.OpenXml.Drawing.Diagrams;
 
 namespace TEAMModelBI.Controllers.BITest
 {
@@ -1478,36 +1479,67 @@ namespace TEAMModelBI.Controllers.BITest
         {
 
             List<Task<CopyFromUriOperation>> filelist = new List<Task<CopyFromUriOperation>>();
-            var azureClient = _azureStorage.GetBlobContainerClient($"0-public");//获取容器连接地址
+            //var azureClient = _azureStorage.GetBlobContainerClient($"0-public");//获取容器连接地址
+
+            ////查询目录下所有容器路径
+            //await foreach (BlobItem blobItem in azureClient.GetBlobsAsync(BlobTraits.None, BlobStates.None, $"TestMP4Max/"))
+            //{
+            //    string newurl = $"{blobItem.Name}".Replace($"/SourceFile/", $"/SourceFiles/");//替换成新的容器路径
+            //    var urlSas = _azureStorage.GetBlobSAS($"0-public", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
+            //    //await azureClient.GetBlobClient(newurl).StartCopyFromUriAsync(new Uri(urlSas));
+            //    filelist.Add(azureClient.GetBlobClient(newurl).StartCopyFromUriAsync(new Uri(urlSas)));
+            //    //await azureClient.GetBlobClient(newurl).SyncCopyFromUriAsync(new Uri(urlSas));  //添加复制文件到集合执行复制操作
+            //}
+            //if (filelist.Count <= 256)
+            //{
+            //    await Task.WhenAll(filelist);
+            //}
+            //else
+            //{
+            //    int pages = (filelist.Count + 255) / 256;
+            //    for (int i = 0; i < pages; i++)
+            //    {
+            //        List<Task<CopyFromUriOperation>> rspBlobCopyInfos = filelist.Skip((i) * 256).Take(256).ToList();
+            //        await Task.WhenAll(rspBlobCopyInfos);
+            //    }
+            //}
+
+            var azureClient = _azureStorage.GetBlobContainerClient($"1636016499");//获取容器连接地址
 
             //查询目录下所有容器路径
-            await foreach (BlobItem blobItem in azureClient.GetBlobsAsync(BlobTraits.None, BlobStates.None, $"TestMP4Max/"))
+            await foreach (BlobItem blobItem in azureClient.GetBlobsAsync(BlobTraits.None, BlobStates.None, $"doc"))
             {
-                string newurl = $"{blobItem.Name}".Replace($"/SourceFile/", $"/SourceFiles/");//替换成新的容器路径
-                var urlSas = _azureStorage.GetBlobSAS($"0-public", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
+                string newurl = $"{blobItem.Name}".Replace($"doc/", $"/SourceFiles/");//替换成新的容器路径
+                var urlSas = _azureStorage.GetBlobSAS($"1636016499", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
                 //await azureClient.GetBlobClient(newurl).StartCopyFromUriAsync(new Uri(urlSas));
-                filelist.Add(azureClient.GetBlobClient(newurl).StartCopyFromUriAsync(new Uri(urlSas)));
+                await azureClient.GetBlobClient(newurl).StartCopyFromUriAsync(new Uri(urlSas));
                 //await azureClient.GetBlobClient(newurl).SyncCopyFromUriAsync(new Uri(urlSas));  //添加复制文件到集合执行复制操作
-
-            }
-            if (filelist.Count <= 256)
-            {
-                await Task.WhenAll(filelist);
             }
-            else
-            {
-                int pages = (filelist.Count + 255) / 256;
-                for (int i = 0; i < pages; i++)
-                {
-                    List<Task<CopyFromUriOperation>> rspBlobCopyInfos = filelist.Skip((i) * 256).Take(256).ToList();
-                    await Task.WhenAll(rspBlobCopyInfos);
-                }
-            }
-
 
             return Ok(new { state = 200 , filelist });
         }
 
+        [HttpPost("test-copy-file")]
+        public async Task<IActionResult> TestCaopyFile()
+        {
+            string blobName = "cswznb";
+            string oldFile = "https://teammodeltest.blob.core.chinacloudapi.cn/cswznb/survey%2Fd011c05b-c009-0a53-428f-b871a58092c7%2Findex.json";//"https://teammodeltest.blob.core.chinacloudapi.cn/1636016499/yxpt%2Fstandard2%2FTEAMModelOS%E6%95%B0%E6%8D%AE%E5%BA%93.doc";
+            string oldId = "survey";
+            string newId = "survey1";
+
+            List<Task<CopyFromUriOperation>> filelist = new();   //可复制256M以上文件
+            var set = await BatchCopyFileService.SingleCopyFile(_azureStorage, blobName, oldFile, oldId, newId);
+
+            //var azureClient = _azureStorage.GetBlobContainerClient($"{blobName}");//获取容器连接地址
+            //string newurl = oldFile.Substring(oldFile.IndexOf($"{blobName}/") + $"{blobName}/".Length).Replace($"{oldId}", $"{newId}");//替换成新的容器路径
+            //string oldFileName = oldFile.Substring(oldFile.IndexOf($"{blobName}/") + $"{blobName}/".Length);
+            //var urlSas = _azureStorage.GetBlobSAS($"{blobName}", $"{HttpUtility.UrlDecode(oldFileName)}", BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
+            ////var respCopy =  azureClient.GetBlobClient(HttpUtility.UrlDecode(newurl)).SyncCopyFromUri(new Uri(urlSas));    //可复制256M以下文件
+            //var respCopy1 = await azureClient.GetBlobClient(HttpUtility.UrlDecode(newurl)).StartCopyFromUriAsync(new Uri(urlSas));    //可复制256M以上文件
+
+            return Ok(new { state = 200 });
+        }
+
         public class linqTest
         {
             public string id { get; set; }

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

@@ -13,6 +13,10 @@ using System.Text;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Context.BI;
+using Azure.Core;
+using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
+using TEAMModelOS.SDK.Context.Constant;
+using DocumentFormat.OpenXml.Wordprocessing;
 
 namespace TEAMModelBI.Controllers.Census
 {
@@ -33,6 +37,117 @@ namespace TEAMModelBI.Controllers.Census
             _option = option?.Value;
         }
 
+        /// <summary>
+        /// 查询学校试题
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-list")]
+        public async Task<IActionResult> GetList(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("code", out JsonElement code)) return BadRequest();
+            jsonElement.TryGetProperty("scope", out JsonElement scope);
+            Dictionary<string, object> dic = new();
+            if (jsonElement.TryGetProperty("periodId", out JsonElement periodId))
+                dic.Add("periodId", periodId);
+            if (jsonElement.TryGetProperty("subjectId", out JsonElement subjectId))
+                dic.Add("subjectId", subjectId);
+            if (jsonElement.TryGetProperty("gradeIds", out JsonElement gradeIds))
+                dic.Add("gradeIds", gradeIds);
+            if (jsonElement.TryGetProperty("type", out JsonElement type))
+                dic.Add("type", type);
+            if (jsonElement.TryGetProperty("level", out JsonElement level))
+                dic.Add("level", level);
+            if (jsonElement.TryGetProperty("field", out JsonElement field))
+                dic.Add("field", field);
+            if (jsonElement.TryGetProperty("isSort", out JsonElement isSort))
+            {
+                if (!string.IsNullOrEmpty($"{isSort}"))
+                {
+                    if (bool.Parse($"{isSort}") == true)
+                        dic.Add("@DESC", "createTime");
+                    else
+                        dic.Add("@ASC", "createTime");
+                }
+                else
+                    dic.Add("@ASC", "createTime");
+            }
+            if (jsonElement.TryGetProperty("pid", out JsonElement pd))
+            {
+                if (pd.ValueKind != JsonValueKind.Null)
+                    dic.Add("pid", pd.ToString());
+                else
+                    dic.Add("pid", null);
+            }
+
+            var cosmosClinet = _azureCosmos.GetCosmosClient();
+            StringBuilder sql = new("select c.id,c.code,c.repairResource, c.periodId,c.question,c.useCount,c.level,c.field,c.knowledge,c.type,c.option,c.createTime,c.answer,c.explain,c.children,c.score,c.gradeIds,c.subjectId,c.blob,c.scope from c ");
+            AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dic, sql);
+            List<object> items = new();
+            if (scope.ToString().Equals("private"))
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{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())
+                        {
+                            items.Add(obj.ToObject<object>());
+                        }
+                    }
+                }
+            }
+            else if (scope.ToString().Equals("school"))
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{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())
+                        {
+                            items.Add(obj.ToObject<object>());
+                        }
+                    }
+                }
+            }
+            else
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{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())
+                        {
+                            items.Add(obj.ToObject<object>());
+                        }
+                    }
+                }
+
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{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())
+                        {
+                            items.Add(obj.ToObject<object>());
+                        }
+                    }
+                }
+            }
+
+            return Ok(new { state = RespondCode.Ok ,cnt = items.Count, items });
+        }
+
+
         /// <summary>
         /// 查询所有试题数量
         /// </summary>

+ 191 - 1
TEAMModelBI/Controllers/Census/PaperController.cs

@@ -1,9 +1,17 @@
 using Azure.Cosmos;
+using Azure.Storage.Blobs;
+using Azure.Storage.Blobs.Models;
+using Azure.Storage.Sas;
+using DocumentFormat.OpenXml.Drawing.Diagrams;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Primitives;
 using System;
 using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
@@ -11,9 +19,12 @@ using TEAMModelBI.Models;
 using TEAMModelBI.Tool;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Context.BI;
+using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
 
 namespace TEAMModelBI.Controllers.Census
 {
@@ -37,6 +48,172 @@ namespace TEAMModelBI.Controllers.Census
             _option = option?.Value;
         }
 
+        /// <summary>
+        /// 查询学校试卷列表
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-list")]
+        public async Task<IActionResult> GetList(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("code", out JsonElement code)) return BadRequest();
+            jsonElement.TryGetProperty("scope", out JsonElement _scope);
+
+            string scope = "school";
+            if (string.IsNullOrEmpty($"{_scope}"))
+                scope = $"{_scope}";
+            StringBuilder sql = new($"select value(c) from c where c.scope='{scope}'");
+
+            if (!jsonElement.TryGetProperty("periodId", out JsonElement periodId)) return BadRequest();
+            if (!jsonElement.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
+            if (!jsonElement.TryGetProperty("gradeIds", out JsonElement gradeIds)) return BadRequest();
+            if (!jsonElement.TryGetProperty("isSort", out JsonElement isSort)) return BadRequest();
+            if (!string.IsNullOrEmpty($"{periodId}"))
+                sql.Append($" and c.periodId ='{periodId}' ");
+            if (!string.IsNullOrEmpty($"{subjectId}"))
+            {
+                List<string> subIds = subjectId.ToObject<List<string>>();
+                if (subIds.Count > 1)
+                {
+                    sql.Append($" and c.subjectId in (");
+                    for (int i = 0; i < subIds.Count; i++)
+                    {
+                        if (i == (subIds.Count - 1))
+                            sql.Append($"'{subIds[i]}'");
+                        else
+                            sql.Append($"{subIds[i]},");
+                    }
+                }
+                else if(subIds.Count ==1)
+                {
+                    sql.Append($" and c.subjectId='{subjectId[0]}'");
+                }            
+            }
+            if (!string.IsNullOrEmpty($"{gradeIds}"))
+                sql.Append($" and ARRAY_CONTAINS(c.gradeIds,'{gradeIds}')");
+
+            if (bool.Parse($"{isSort}") == true)
+                sql.Append(" Order By c.createTime DESC");
+            else
+                sql.Append(" Order By c.createTime ASC");
+            
+            var cosmosClinet = _azureCosmos.GetCosmosClient();
+
+            List<Paper> papers = new();
+            if (scope.ToString().Equals("school"))
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Paper>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
+                {
+                    papers.Add(item);
+                }
+            }
+            return Ok(new { state = RespondCode.Ok,cnt = papers.Count, papers });
+        }
+
+        /// <summary>
+        /// 复制试卷信息到另外一个学校
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("copy-infos")]
+        public async Task<IActionResult> CopyInfos(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("papers", out JsonElement jsPapers)) return BadRequest();
+
+            List<CopyPaper> papers = jsPapers.ToObject<List<CopyPaper>>();
+
+            var cosmosClinet = _azureCosmos.GetCosmosClient();
+            foreach (var cItem in papers)
+            {
+                Paper paper = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Paper>(cItem.oldId, new PartitionKey($"Paper-{cItem.oldSc}"));
+                paper.periodId = cItem.newPrdId;
+                paper.subjectId = cItem.newSubId;
+                paper.subjectName = cItem.newSubName;
+                paper.gradeIds = cItem.newGrId;
+                paper.code = $"Paper-{cItem.newSc}";
+
+                var resState = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(paper.id, new PartitionKey(paper.code));
+                if (resState.Status == 200)
+                    paper.id = Guid.NewGuid().ToString();
+
+                paper = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<Paper>(paper, new PartitionKey(paper.code));
+
+
+                var oldBobCilent = _azureStorage.GetBlobContainerClient(containerName: $"{cItem.oldSc}");
+                var newBobCilent = _azureStorage.GetBlobContainerClient(containerName: $"{cItem.newSc}");
+
+                string blobUrl = "";
+                if (paper.blob.IndexOf('/') == 0)
+                    blobUrl = $"{paper.blob}".Substring(1, paper.blob.Length - 1);
+                else
+                    blobUrl = $"{paper.blob}";
+
+                List<Task<CopyFromUriOperation>> filelist = new();   //可复制256M以上文件
+                await foreach (BlobItem blobItem in oldBobCilent.GetBlobsAsync(BlobTraits.None, BlobStates.None, blobUrl))
+                {
+                    var urlSas = _azureStorage.GetBlobSAS($"{cItem.oldSc}", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
+                    filelist.Add(newBobCilent.GetBlobClient(blobItem.Name).StartCopyFromUriAsync(new Uri(urlSas)));
+                    ////序列化数据修改数据
+                    //if (blobItem.Name.EndsWith(".json"))
+                    //{
+                    //    BlobClient tempClient = oldBobCilent.GetBlobClient(blobItem.Name);
+                    //    using (var meomoryStream = new MemoryStream())
+                    //    {
+                    //        StringBuilder itemStr = new();
+                    //        BlobClient tempBlobClient = oldBobCilent.GetBlobClient(blobItem.Name);
+                    //        BlobDownloadInfo download = tempBlobClient.Download();
+                    //        var content = download.Content;
+                    //        string text;
+                    //        using (var streamReader = new StreamReader(content))
+                    //        {
+                    //            while ((text = streamReader.ReadLine()) != null)
+                    //            {
+                    //                if (streamReader.EndOfStream)
+                    //                    itemStr.Append($"{text.ToString()}");
+                    //                else
+                    //                    itemStr.Append($"{text.ToString()},");
+                    //            }
+                    //            streamReader.Close();
+                    //        }
+                    //        string input = itemStr.ToString();
+                    //        BlobItemInfo blobbItemInfo = input.ToObject<BlobItemInfo>();
+
+                    //        //var response = oldBobCilent.GetBlobClient($"{blobItem.Name}").DownloadTo(meomoryStream);
+                    //        //BlobItemInfo blobbItemInfo = Encoding.UTF8.GetString(meomoryStream.ToArray()).ToString().ToObject<BlobItemInfo>();
+                    //        blobbItemInfo.exercise.periodId = cItem.newPrdId;
+                    //        blobbItemInfo.exercise.gradeIds = cItem.newGrId;
+
+                    //        blobbItemInfo.exercise.subjectId = cItem.newSubId;
+
+                    //        var urlSas = _azureStorage.GetBlobSAS($"{cItem.newSc}", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
+
+                    //        var ster = newBobCilent.UploadFileByContainer(blobbItemInfo.ToJsonString(), blobItem.Name, blobbItemInfo.id);
+                    //    }
+                    //}
+                }
+                if (filelist.Count <= 256)
+                {
+                    await Task.WhenAll(filelist);
+                }
+                else
+                {
+                    int pages = (filelist.Count + 255) / 256;
+                    for (int i = 0; i < pages; i++)
+                    {
+                        List<Task<CopyFromUriOperation>> rspBlobCopyInfos = filelist.Skip((i) * 256).Take(256).ToList(); //可复制256M以上文件
+                        //List<Task<Response<BlobCopyInfo>>> rspBlobCopyInfos = filelist.Skip((i) * 256).Take(256).ToList(); //复制256M以下文件
+                        await Task.WhenAll(rspBlobCopyInfos);
+                    }
+                }
+
+            }
+            return Ok(new { state = RespondCode.Ok});
+        }
+
+ 
+
         /// <summary>
         /// 查询试卷的数量统计集合
         /// </summary>
@@ -315,7 +492,7 @@ namespace TEAMModelBI.Controllers.Census
             //if ($"{site}".Equals(BIConst.Global))
             //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
 
-            List<object> paperInfos = new List<object>();
+            List<object> paperInfos = new();
             string sqlTxt = $"select * from c where c.id='{paperId}' and c.pk='Paper'";
 
             if (!string.IsNullOrEmpty($"{isPersonal}"))
@@ -371,5 +548,18 @@ namespace TEAMModelBI.Controllers.Census
             public Dictionary<string, long> yearPaper { get; set; }
         }
 
+
+        public record CopyPaper 
+        {
+            public string oldId { get; set; }
+            public string oldSc { get; set; }
+            public string newSc { get; set; }
+            public string newPrdId { get; set; }
+            public string newSubId { get; set; }
+            public string newSubName { get; set; }
+            public List<string> newGrId { get; set; }
+
+        }
+
     }
 }

+ 49 - 0
TEAMModelBI/Models/ItemInfo.cs

@@ -0,0 +1,49 @@
+using DocumentFormat.OpenXml.Office2010.ExcelAc;
+using System.Collections.Generic;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelBI.Models
+{
+    /// <summary>
+    /// 试题的结构
+    /// </summary>
+    public class BlobItemInfo
+    {
+        public string id { get; set; }
+
+        public string pid { get; set; }
+        public Exercise exercise { get; set; }
+        public int render { get; set; }
+        public Questions item { get; set; }
+    }
+
+    public class Exercise
+    {
+        public List<string> answer { get; set; }
+        public string explain { get; set; }
+        public string type { get; set; }
+        public int opts { get; set; }
+        public List<string> knowledge { get; set; }
+        public int field { get; set; }
+        public int level { get; set; }
+        public string periodId { get; set; }
+        public List<string> gradeIds { get; set; }
+        public string subjectId { get; set; }
+        public List<string> children { get; set; } = new List<string>();
+        public string scope { get; set; }
+        public int score { get; set; }
+        public List<Repair> repair { get; set; } = new List<Repair>();
+    }
+
+    public class Questions 
+    {
+        public string question { get; set; }
+        public List<OptionInfo> option { get; set; }
+    }
+
+    public class OptionInfo 
+    {
+        public string code { get; set; }
+        public string value { get; set; }
+    }
+}

+ 3 - 3
TEAMModelBI/TEAMModelBI.csproj

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

+ 6 - 2
TEAMModelBI/Tool/CommonFind.cs

@@ -189,10 +189,14 @@ namespace TEAMModelBI.Tool
         public static async Task<int> GetSqlValueCount(CosmosClient cosmosClient, string container, string SqlTxt,string code = null) 
         {
             int totals = 0;
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", container).GetItemQueryIterator<int>(queryText: SqlTxt, requestOptions: string.IsNullOrEmpty(code) ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+            try
             {
-                totals = item;
+                await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", container).GetItemQueryIterator<int>(queryText: SqlTxt, requestOptions: string.IsNullOrEmpty(code) ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+                {
+                    totals = item;
+                }
             }
+            catch{ }
 
             return totals;
         }

+ 1 - 1
TEAMModelBI/Tool/CosmosBank/SchoolWay.cs

@@ -24,7 +24,7 @@ namespace TEAMModelBI.Tool.CosmosBank
             List<BaseInfo> advSchools = new();
             foreach (var item in schoolIds)
             {
-                await foreach (var info in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<BaseInfo>(queryText: $"select c.id,c.name,c.picture from c where c.id='{item}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                await foreach (var info in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<BaseInfo>(queryText: $"select c.id,c.name,c.picture,c.areaId from c where c.id='{item}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
                 {
                     advSchools.Add(info);
                 }

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

@@ -628,7 +628,7 @@ namespace TEAMModelOS.FunctionV4
                 }
                 info.standard = Math.Round(total > 0 ? Math.Pow(powSum / total, 0.5) : 0, 2);
                 double NewsRate = allScore > 0 ? Math.Round(NewsRateScore / allScore * 100, 2) : 0;
-                double qrate = Math.Round(qk / total * 100, 2);
+                double qrate = Math.Round(total >0?qk / total * 100:0, 2);
                 settlement.rate = NewsRate;
                 settlement.score = NewsRateScore;
                 settlement.stus = losStu;

+ 98 - 5
TEAMModelOS.FunctionV4/HttpTrigger/IESHttpTrigger.cs

@@ -1,7 +1,8 @@
 using Azure.Cosmos;
 using Azure.Storage.Blobs.Models;
+using Azure.Storage.Sas;
 using HTEXLib.COMM.Helpers;
-using Microsoft.AspNetCore.Mvc;
+using HTEXLib.Models;
 using Microsoft.Azure.Cosmos.Table;
 using Microsoft.Azure.Functions.Worker;
 using Microsoft.Azure.Functions.Worker.Http;
@@ -13,17 +14,19 @@ using System.Dynamic;
 using System.IO;
 using System.Linq;
 using System.Net;
+using System.Net.Http;
+using System.Net.Http.Json;
 using System.Reflection;
-using System.Runtime.InteropServices;
+using System.Security.Policy;
 using System.Text;
 using System.Text.Json;
 using System.Threading;
 using System.Threading.Tasks;
+using System.Web;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
-using TEAMModelOS.SDK.Models.Cosmos.Teacher;
 using TEAMModelOS.SDK.Models.Table;
 using static TEAMModelOS.SDK.Models.Teacher;
 using PuppeteerSharp;
@@ -38,13 +41,15 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
         private readonly DingDing _dingDing;
         private readonly AzureStorageFactory _azureStorage;
         private readonly AzureRedisFactory _azureRedis;
+        private readonly HttpClient _httpClient;
         public IESHttpTrigger(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage
-      , AzureRedisFactory azureRedis)
+      , AzureRedisFactory azureRedis, HttpClient httpClient)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
             _azureStorage = azureStorage;
             _azureRedis = azureRedis;
+            _httpClient = httpClient;
         }
         /// <summary>
         /// 网页截图参数
@@ -243,7 +248,7 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
                                     foreach (var subject in subjects)
                                     {
                                         //获取同名学科,且没绑定的
-                                        var sub = period.subjects.FindAll(sub => sub.name.Equals(subject) && string.IsNullOrWhiteSpace(sub.bindId));
+                                        var sub = period.subjects.FindAll(sub => sub.name.Contains(subject) && string.IsNullOrWhiteSpace(sub.bindId));
                                         if (sub.IsNotEmpty())
                                         {
                                             sub[0].bindId = unBindId;
@@ -931,5 +936,93 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
                 return response;
             }
         }
+        /// <summary>
+        /// 艺术评测报告生成
+        /// </summary>
+        /// <param name="msg"></param>
+        /// <returns></returns>
+        [Function("gen-art-pdf")]
+        public async Task<HttpResponseData> GenArtPDF([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData req) {
+            var response = req.CreateResponse(HttpStatusCode.OK);
+            string data = await new StreamReader(req.Body).ReadToEndAsync();
+            var json = JsonDocument.Parse(data).RootElement;
+            json.TryGetProperty("studentPdfs", out JsonElement _studentPdfs);
+            json.TryGetProperty("schoolCode", out JsonElement _schoolCode);
+            List<ArtStudentPdf> studentPdfs = _studentPdfs.Deserialize<List<ArtStudentPdf>>();
+            List<Task<string>> uploads = new List<Task<string>>();
+            studentPdfs.ForEach(x => {
+                x.blob =  $"art/{x.artId}/report/{x.studentId}.json";
+                uploads.Add(_azureStorage.GetBlobContainerClient($"{_schoolCode}").UploadFileByContainer(x.ToJsonString(), "art", $"{x.artId}/report/{x.studentId}.json", true));
+            });
+            var uploadJsonUrls= await Task.WhenAll(uploads);
+            var list =uploadJsonUrls.ToList();
+            List<string> urls = new List<string>();
+            (string uri, string sas) =  _azureStorage.GetBlobContainerSAS($"{_schoolCode}",Azure.Storage.Sas.BlobContainerSasPermissions.Read);
+            studentPdfs.ForEach(x => {
+                string atrUrl = "https://teammodelos.blob.core.chinacloudapi.cn/0-public/art-report-template/report.html";
+                var s = _azureStorage.GetBlobSAS($"{_schoolCode}", x.blob, BlobSasPermissions.Read);
+                s = $"{HttpUtility.UrlEncode($"{s}", Encoding.UTF8)}";
+                string url = $"{atrUrl}?url={s}&pdfpath={x.artId}/report/{x.studentId}";
+                urls.Add(url);
+                //var a = list.Find(l => l.Contains(x.studentId));
+                //if (a != null) {
+
+                //    a = $"{HttpUtility.UrlEncode($"{a}?{sas}", Encoding.UTF8)}";
+                //    string url = $"{atrUrl}?url={a}&pdfpath={x.artId}/report/{x.studentId}";
+                //    urls.Add(url);
+                //}
+            });
+            string env = "release";
+            if (Environment.GetEnvironmentVariable("Option:Location").Contains("Test",StringComparison.CurrentCultureIgnoreCase)||
+                Environment.GetEnvironmentVariable("Option:Location").Contains("Dep", StringComparison.CurrentCultureIgnoreCase)) {
+                env = "develop";
+            }
+            var screenshot = new ScreenshotDto
+            {
+                width = 1080,
+                height = 1920,
+                urls = urls,
+                fileNameKey = "pdfpath",
+                cnt = $"{_schoolCode}",
+                root = "art",
+                pagesize = 5,
+                env = env
+            };
+            var st=  screenshot.ToJsonString();
+            var httpResponse= await _httpClient.PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/screen/screenshot-pdf",
+               screenshot
+            );
+            List<string> resUrls = new List<string>();
+            if (httpResponse.StatusCode == HttpStatusCode.OK) {
+                JsonElement json_res = await httpResponse.Content.ReadFromJsonAsync<JsonElement>();
+                resUrls= json_res.GetProperty("urls").Deserialize<List<string>>();
+            }
+            await  response.WriteAsJsonAsync(new { data =new { count= studentPdfs.Count , resUrls } });
+            return response;
+        }
+
+
+        public class ScreenshotDto
+        {
+            public int width { get; set; } = 1920;
+            public int height { get; set; } = 1080;
+            public string? url { get; set; }
+            /// <summary>
+            /// 批量地址
+            /// </summary>
+            public List<string> urls { get; set; } = new List<string>();
+            /// <summary>
+            /// 提取参数的唯一id作为文件名
+            /// </summary>
+            public string? fileNameKey { get; set; }
+            /// <summary>
+            /// 存在哪个容器里
+            /// </summary>
+            public string? cnt { get; set; }
+            public int delay { get; set; }
+            public int pagesize { get; set; } = 5;
+            public string? root { get; set; }
+            public string? env { get; set; } = "release";
+        }
     }
 }

+ 6 - 2
TEAMModelOS.FunctionV4/Lang/en-us.json

@@ -20,6 +20,10 @@
   "create-school": [ "Create schools in batches", "{tmdname}You successfully created schools in batch with Bi" ],
   "copy-file_area": [ "Batch copy file start", "{tmdname}您用BI创区成功开始复制区域文件" ],
   "art-template-comment1": "{studentName}同学,你在本次艺术评测活动中整体{level}。",
-  "art-template-comment2": "你在本次活动中{quotasHigh}等指标取得很好的成绩,希望继续保持。",
-  "art-template-comment3": "你在本次活动中{quotasLow}等指标有待提高,希望进一步加强。"
+  "art-template-comment2": "你在本次考核中{quotasHigh}等指标取得很好的成绩,希望继续保持。",
+  "art-template-comment3": "你在本次考核中{quotasLow}等指标有待提高,希望进一步加强。",
+  "art-template-comment4": "你在本次考核中{pointHigh}等知识点取得很好的成绩,希望继续保持。",
+  "art-template-comment5": "你在本次考核中{pointLow}等知识有待提高,希望进一步加强。",
+  "art-template-subject_music": "其实音乐殿堂的门槛并没有你想的那么高,对吧?希望你继续努力能够在这里欣赏到更美丽的风景!跳动的音符充满魅力,每个人的生活都离不开音乐,加油吧,相信你在音乐中会有所收获的。",
+  "art-template-subject_painting": "你敢于探素,乐于欣赏,在五彩的画笔中快乐成长,如果你再多一点耐心、仔细刻画,一定会更棒!你积极热爱美术,总是充满快乐,希望你能够坚持美术学习,永不放弃,在美术的道路上快乐地成长!"
 }

+ 6 - 2
TEAMModelOS.FunctionV4/Lang/zh-cn.json

@@ -20,6 +20,10 @@
   "create-school": [ "批量创建学校", "{tmdname}您用BI批量创建学校成功" ],
   "copy-file_area": [ "批复制文件开始", "{tmdname}您用BI创区成功开始复制区域文件" ],
   "art-template-comment1": "{studentName}同学,你在本次艺术评测活动中整体{level}。",
-  "art-template-comment2": "你在本次活动中{quotasHigh}等指标取得很好的成绩,希望继续保持。",
-  "art-template-comment3": "你在本次活动中{quotasLow}等指标有待提高,希望进一步加强。"
+  "art-template-comment2": "你在本次考核中{quotasHigh}等指标取得很好的成绩,希望继续保持。",
+  "art-template-comment3": "你在本次考核中{quotasLow}等指标有待提高,希望进一步加强。",
+  "art-template-comment4": "你在本次考核中{pointHigh}等知识点取得很好的成绩,希望继续保持。",
+  "art-template-comment5": "你在本次考核中{pointLow}等知识有待提高,希望进一步加强。",
+  "art-template-subject_music": "其实音乐殿堂的门槛并没有你想的那么高,对吧?希望你继续努力能够在这里欣赏到更美丽的风景!跳动的音符充满魅力,每个人的生活都离不开音乐,加油吧,相信你在音乐中会有所收获的。",
+  "art-template-subject_painting": "你敢于探素,乐于欣赏,在五彩的画笔中快乐成长,如果你再多一点耐心、仔细刻画,一定会更棒!你积极热爱美术,总是充满快乐,希望你能够坚持美术学习,永不放弃,在美术的道路上快乐地成长!"
 }

+ 6 - 2
TEAMModelOS.FunctionV4/Lang/zh-tw.json

@@ -20,6 +20,10 @@
   "create-school": [ "批量創建學校", "{tmdname}您用BI批量創建學校成功" ],
   "copy-file_area": [ "批復制文件開始", "{tmdname}您用BI创区成功开始复制区域文件" ],
   "art-template-comment1": "{studentName}同学,你在本次艺术评测活动中整体{level}。",
-  "art-template-comment2": "你在本次活动中{quotasHigh}等指标取得很好的成绩,希望继续保持。",
-  "art-template-comment3": "你在本次活动中{quotasLow}等指标有待提高,希望进一步加强。"
+  "art-template-comment2": "你在本次考核中{quotasHigh}等指标取得很好的成绩,希望继续保持。",
+  "art-template-comment3": "你在本次考核中{quotasLow}等指标有待提高,希望进一步加强。",
+  "art-template-comment4": "你在本次考核中{pointHigh}等知识点取得很好的成绩,希望继续保持。",
+  "art-template-comment5": "你在本次考核中{pointLow}等知识有待提高,希望进一步加强。",
+  "art-template-subject_music": "其实音乐殿堂的门槛并没有你想的那么高,对吧?希望你继续努力能够在这里欣赏到更美丽的风景!跳动的音符充满魅力,每个人的生活都离不开音乐,加油吧,相信你在音乐中会有所收获的。",
+  "art-template-subject_painting": "你敢于探素,乐于欣赏,在五彩的画笔中快乐成长,如果你再多一点耐心、仔细刻画,一定会更棒!你积极热爱美术,总是充满快乐,希望你能够坚持美术学习,永不放弃,在美术的道路上快乐地成长!"
 }

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/BI/AreaQuoteRecord.cs

@@ -11,7 +11,7 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
     /// <summary>
     /// 区域引用记录
     /// </summary>
-    [TableName(Name = "IESLogin")]
+    [TableName(Name = "BIRecord")]
     public class AreaQuoteRecord : TableEntity
     {
         public string areaId { get; set; }

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

@@ -46,6 +46,7 @@ namespace TEAMModelOS.SDK.Models
         public string id { get; set; }
         public string name { get; set; }
         public string picture { get; set; }
+        public string areaId { get; set; }
     }
 
     /// <summary>

+ 3 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs

@@ -359,6 +359,9 @@ namespace TEAMModelOS.SDK.Models
         /// 学生互动率
         /// </summary>
         public double clientInteractionAverge { get; set; } = 0;
+        /// <summary>
+        /// 测验次数
+        /// </summary>
         public int examCount { get; set; }
         public LearningCategory learningCategory { get; set; }
     }

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

@@ -44,6 +44,9 @@ namespace TEAMModelOS.SDK.Models
         public string institution { get; set; }
         public long updateTime { get; set; }
 
-
+        /// <summary>
+        /// 引用id
+        /// </summary>
+        public string quoteId { get; set; } = null;
     }
 }

+ 209 - 0
TEAMModelOS.SDK/Models/Cosmos/Student/OverallEducation.cs

@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.Student
+{
+    /// <summary>
+    /// 德智体美劳全面
+    /// </summary>
+    public class OverallEducation : CosmosEntity
+    {
+        // id="2021-semesterId"
+        /// <summary>
+        /// 
+        /// </summary>
+        public string semesterName { get; set; }
+        /// <summary>
+        /// 所属学年,学年跨年,按上一年。 2021学年包含 2021年和2022年,且2022年上半年的学期也属于2021
+        /// </summary>
+        public int year { get; set; }
+        /// <summary>
+        /// 学期id
+        /// </summary>
+        public string semesterId { get; set; }
+        /// <summary>
+        /// 学校编码
+        /// </summary>
+        public string schoolCode { get; set; }
+        /// <summary>
+        /// 学生id
+        /// </summary>
+        public string studentId { get; set; }
+        /// <summary>
+        /// 学生姓名
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 所属行政班
+        /// </summary>
+        public string  classId { get; set; } 
+        /// <summary>
+        /// 学段
+        /// </summary>
+        public string periodId { get; set; }
+        /// <summary>
+        /// 年级
+        /// </summary>
+        public int grade { get; set; }
+        /// <summary>
+        /// 德育
+        /// </summary>
+        public List<EducationScore> virtue { get; set; } = new List<EducationScore>();
+        /// <summary>
+        /// 智育
+        /// </summary>
+        public List<EducationScore> intelligence { get; set; } = new List<EducationScore>();
+        /// <summary>
+        /// 体育
+        /// </summary>
+        public List<EducationScore> sports { get; set; } = new List<EducationScore>();
+        /// <summary>
+        /// 艺术
+        /// </summary>
+        public List<EducationScore> art { get; set; } = new List<EducationScore>();
+        /// <summary>
+        /// 劳动
+        /// </summary>
+        public List<EducationScore> labour { get; set; } = new List<EducationScore>();
+
+    }
+    public class EducationScore {
+        /// <summary>
+        /// //评测名称
+        /// </summary>
+        public string examName { get; set; } 
+        /// <summary>
+        /// //用于数据新增或更新
+        /// </summary>
+        public string examId { get; set; }
+        /// <summary>
+        /// //评测时间,13位时间戳
+        /// </summary>
+        public long examDate { get; set; } 
+        /// <summary>
+        ///  //评测类型 期末,期中,季考,月考,周考,测验,练习,作业,课中
+        /// </summary>
+        public string examType { get; set; }
+        /// <summary>
+        /// 满分
+        /// </summary>
+        public double full { get; set; } = 100;
+        /// <summary>
+        /// 总分得分率
+        /// </summary>
+        public double rate { get; set; }
+        /// <summary>
+        /// 总分等级
+        /// </summary>
+        public double level { get; set; }
+        /// <summary>
+        /// //总成绩
+        /// </summary>
+        public double sumScore { get; set; }
+        /// <summary>
+        /// 细项优秀率
+        /// </summary>
+        public double excellenceRate { get; set; }
+        /// <summary>
+        /// 细项及格率
+        /// </summary>
+        public double passRate { get; set; }
+        /// <summary>
+        /// 考核项目数据
+        /// </summary>
+        public List<ItemScore> itemScore { get; set; } = new List<ItemScore>();
+    }
+
+    /// <summary>
+    /// 考核项目数据
+    /// </summary>
+    public class ItemScore
+    {
+        /// <summary>
+        /// 项目名称
+        /// </summary>
+        public string name { get; set; }//项目名称
+        /// <summary>
+        /// 项目分数
+        /// </summary>
+        public double score { get; set; }//
+        /// <summary>
+        /// 评分等级
+        /// </summary>
+        public double level { get; set; }
+        /// <summary>
+        /// 细项考核时间
+        /// </summary>
+        public long time { get; set; }
+    }
+
+
+    /// <summary>
+    /// 保存学生画像  第三方传入的学校
+    /// </summary>
+    public class Portrait
+    {
+        public string schoolCode { get; set; } //学校编码
+        public string studentId { get; set; }//学生编号
+        public string name { get; set; }//学生姓名
+        public string classId { get; set; }//行政班id
+        public string periodId { get; set; }//学段id
+        public string subjectId { get; set; }//体育科目id
+        public List<SemesterData> semesterData { get; set; }//学期数据
+    }
+
+    /// <summary>
+    /// 学期数据
+    /// </summary>
+    public class SemesterData
+    {
+        /// <summary>
+        /// //评测名称
+        /// </summary>
+        public string examName { get; set; } 
+        /// <summary>
+        /// //用于数据新增或更新
+        /// </summary>
+        public string examId { get; set; }
+        /// <summary>
+        ///  //评测时间,13位时间戳
+        /// </summary>
+        public long examDate { get; set; }
+        /// <summary>
+        ///  //评测类型 期末,期中,季考,月考,周考,测验,练习,作业,课中
+        /// </summary>
+        public string examType { get; set; } 
+        /// <summary>
+        /// //所属学年,学年跨年,按上一年。
+        /// </summary>
+        public int year { get; set; }
+        /// <summary>
+        /// 学期,与semesterId选填其一
+        /// </summary>
+        public int semester { get; set; }
+        /// <summary>
+        /// //学期id 
+        /// </summary>
+        public string semesterId { get; set; }
+        /// <summary>
+        /// //总成绩
+        /// </summary>
+        public double sumScore { get; set; }
+        /// <summary>
+        /// //优秀率
+        /// </summary>
+        public double excellenceRate { get; set; }
+        /// <summary>
+        /// //及格率
+        /// </summary>
+
+        public double passRate { get; set; }
+        /// <summary>
+        /// //考核项目数据
+        /// </summary>
+        public List<ItemScore> itemScore { get; set; } 
+    }
+}

+ 125 - 0
TEAMModelOS.SDK/Models/Cosmos/Student/StudentArtResult.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -65,4 +66,128 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public List<Attachment> files { get; set; }
     }
+    public class ArtStudentPdf
+    {
+        public string schoolName { get; set; }
+        public string periodId { get; set; }
+        public string periodName { get; set; }
+        public string schoolCode { get; set; }
+        public string studentId { get; set; }
+        public string studentName { get; set; }
+        public string picture { get; set; }
+        public List<string> classNames { get; set; } = new List<string>();
+        public string artName { get; set; }
+        public string artId { get; set; }
+        public string level { get; set; }
+        public double score { get; set; }
+        /// <summary>
+        /// 评语
+        /// </summary>
+        public string comment { get; set; }
+        public List<ArtQuotaPdf> allSubjectQuotas { get; set; } = new List<ArtQuotaPdf>();
+        public List<ArtSubjectPdf> subjectPdfs { get; set; } = new List<ArtSubjectPdf>();
+        public string blob { get; set;}
+    }
+    /// <summary>
+    /// 艺术评测科目PDF
+    /// </summary>
+    public class ArtSubjectPdf {
+        /// <summary>
+        /// 科目id
+        /// </summary>
+        public string subjectId { get; set; }
+        /// <summary>
+        /// 科目id
+        /// </summary>
+        public string subjectName { get; set; }
+        /// <summary>
+        /// 知识点
+        /// </summary>
+        public List<ArtPointPdf> pointPdfs { get; set; } = new List<ArtPointPdf>();
+        public string comment { get; set; }
+    }
+
+    /// <summary>
+    /// 艺术评测知识点PDF
+    /// </summary>
+    public class ArtPointPdf
+    {
+        /// <summary>
+        /// 艺术评测考核维度
+        /// </summary>
+        public string dimension { get; set; }
+        /// <summary>
+        /// 艺术评测考核知识块
+        /// </summary>
+        public string block { get; set; }
+        /// <summary>
+        /// 艺术评测考核知识点
+        /// </summary>
+        public string point { get; set; }
+        /// <summary>
+        /// 得分
+        /// </summary>
+        public double score { get; set; }
+        /// <summary>
+        /// 得分率
+        /// </summary>
+        public double percent { get; set; }
+        /// <summary>
+        /// 知识点配分
+        /// </summary>
+        public double totalScore { get; set; }
+    }
+
+
+    /// <summary>
+    /// 艺术评测指标维度PDF输出。
+    /// </summary>
+    public class ArtQuotaPdf
+    {
+        public string quota1 { get; set; }
+        public string quota2 { get; set; }
+        public string quota3 { get; set; }
+        public string quotaN1 { get; set; }
+        public string quotaN2 { get; set; }
+        public string quotaN3 { get; set; }
+        public double quotaP1 { get; set; }
+        public double quotaP2 { get; set; }
+        public double quotaP3 { get; set; }
+        public string quotaId { get; set; }
+        public string quotaName { get; set; }
+        public string scoreData { get; set; }
+        public double score { get; set; }
+        public string percent { get; set; }
+        public string level { get; set; }
+    }
+    public class StudentArt
+    {
+        [Required(ErrorMessage = "studentId 必须设置")]
+        public string studentId { get; set; }
+        public double totalScore { get; set; } = -1;
+        public List<ArtResult> results { get; set; } = new List<ArtResult>();
+        public List<ArtSubjectScore> subjectScores { get; set; } = new List<ArtSubjectScore>();
+    }
+    public class ArtResult
+    {
+        /// <summary>
+        /// 任务id
+        /// </summary>
+        [Required(ErrorMessage = "taskId 必须设置")]
+        public string taskId { get; set; }
+        /// <summary>
+        /// 科目id
+        /// </summary>
+        [Required(ErrorMessage = "subjectId 必须设置")]
+        public string subjectId { get; set; }
+        /// <summary>
+        /// 指标id
+        /// </summary>
+        [Required(ErrorMessage = "quotaId 必须设置")]
+        public string quotaId { get; set; }
+        /// <summary>
+        /// 分数
+        /// </summary>
+        public double score { get; set; }
+    }
 }

+ 30 - 0
TEAMModelOS.SDK/Models/Service/BatchCopyFileService.cs

@@ -9,6 +9,7 @@ using Azure;
 using Azure.Storage.Sas;
 using System.Linq;
 using Azure.Storage.Blobs.Specialized;
+using System.Web;
 
 namespace TEAMModelOS.SDK.Models.Service
 {
@@ -81,8 +82,37 @@ namespace TEAMModelOS.SDK.Models.Service
                 await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-Batch-CopyFile \n {ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
                 return -1;
             }
+        }
 
+        /// <summary>
+        /// 修复研修平台多人使用个账户,分开账户复制文件时使用
+        /// </summary>
+        /// <param name="_azureStorage"></param>
+        /// <param name="blobName"></param>
+        /// <param name="oldFile"></param>
+        /// <param name="oldId"></param>
+        /// <param name="newId"></param>
+        /// <returns></returns>
+        public static async Task<int> SingleCopyFile(AzureStorageFactory _azureStorage, string blobName, string oldFile, string oldId, string newId)
+        {
+            try
+            {
+                var azureClient = _azureStorage.GetBlobContainerClient($"{blobName}");//获取容器连接地址
+                string newurl = oldFile.Substring(oldFile.IndexOf($"{blobName}/") + $"{blobName}/".Length).Replace($"{oldId}", $"{newId}");//替换成新的容器路径
+                string oldFileName = oldFile.Substring(oldFile.IndexOf($"{blobName}/") + $"{blobName}/".Length);
+                var urlSas = _azureStorage.GetBlobSAS($"{blobName}", $"{HttpUtility.UrlDecode(oldFileName)}", BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
+                //var respCopy =  azureClient.GetBlobClient(HttpUtility.UrlDecode(newurl)).SyncCopyFromUri(new Uri(urlSas));    //可复制256M以下文件
+                var respCopy1 = await azureClient.GetBlobClient(HttpUtility.UrlDecode(newurl)).StartCopyFromUriAsync(new Uri(urlSas));    //可复制256M以上文件
 
+                if (!string.IsNullOrEmpty($"{respCopy1.Id}"))
+                    return 200;
+                else
+                    return 400;
+            }
+            catch(Exception ex)
+            {
+                return 400;
+            }
         }
 
     }

+ 61 - 6
TEAMModelOS.SDK/Models/Service/Common/ActivityStudentService.cs

@@ -52,8 +52,8 @@ namespace TEAMModelOS.SDK.Services
             {
                 return (msgid, -1);
             }
-
-            try
+            
+             try
             {
                 //1.再次检查投票
                 var client = _azureCosmos.GetCosmosClient();
@@ -69,12 +69,38 @@ namespace TEAMModelOS.SDK.Services
                 {
 
                     //判断投票时间是否在起止时间内
-                    if (curr >= vote.startTime && curr <= vote.endTime)
+
+                    string optfrom = "";
+                    ///操作来源,如果是研修的,不限制,否则现在活动结束后不能再投票或者提交问卷作答。
+                    if (request.TryGetProperty("optfrom", out JsonElement _optFrom))
+                    {
+                        optfrom = $"{_optFrom}";
+                    }
+                    // if (curr >= vote.startTime && curr <= vote.endTime)
+                    bool intime=true;//默认有效期内
+                    var endDtae = DateTimeOffset.FromUnixTimeMilliseconds(vote.endTime); 
+                    if (!string.IsNullOrWhiteSpace(optfrom) && optfrom.Equals("train"))
+                    { //"optfrom":"train"  代表是研修的
+                        if (curr >= vote.startTime)
+                        {
+                            intime = true;
+                          
+                        }
+                        else { intime = false; }
+                        endDtae = DateTimeOffset.UtcNow;
+                    }
+                    else {
+                        if (curr >= vote.startTime && curr <= vote.endTime)
+                        {
+                            intime = true;
+                            endDtae = DateTimeOffset.FromUnixTimeMilliseconds(vote.endTime);
+                        }
+                        else { intime = false; }
+                    }
+                    if (intime)
                     {
                         string endField = null;
-
                         string Field = "";
-                        var endDtae = DateTimeOffset.FromUnixTimeMilliseconds(vote.endTime);
                         RedisValue value;
                         switch (vote.times)
                         {
@@ -546,8 +572,37 @@ namespace TEAMModelOS.SDK.Services
                 }
                 if (survey != null)
                 {
+                    string optfrom = "";
+                    ///操作来源,如果是研修的,不限制,否则现在活动结束后不能再投票或者提交问卷作答。
+                    if (request.TryGetProperty("optfrom", out JsonElement _optFrom))
+                    {
+                        optfrom = $"{_optFrom}";
+                    }
+                    // if (curr >= vote.startTime && curr <= vote.endTime)
+                    bool intime = true;//默认有效期内
+                    var endDtae = DateTimeOffset.FromUnixTimeMilliseconds(survey.endTime);
+                    if (!string.IsNullOrWhiteSpace(optfrom) && optfrom.Equals("train"))
+                    { //"optfrom":"train"  代表是研修的
+                        if (curr >= survey.startTime)
+                        {
+                            intime = true;
+
+                        }
+                        else { intime = false; }
+                        endDtae = DateTimeOffset.UtcNow;
+                    }
+                    else
+                    {
+                        if (curr >= survey.startTime && curr <= survey.endTime)
+                        {
+                            intime = true;
+                            endDtae = DateTimeOffset.FromUnixTimeMilliseconds(survey.endTime);
+                        }
+                        else { intime = false; }
+                    }
                     //判断投票时间是否在起止时间内
-                    if (curr >= survey.startTime && curr <= survey.endTime)
+                    //    if (curr >= survey.startTime && curr <= survey.endTime)
+                    if (intime)
                     {
                         if (request.TryGetProperty("record", out JsonElement _record))
                         {

+ 1 - 0
TEAMModelOS/ClientApp/package.json

@@ -109,6 +109,7 @@
     "babel-plugin-component": "^1.1.1",
     "babel-plugin-import": "^1.12.0",
     "babel-polyfill": "^6.26.0",
+    "clean-webpack-plugin": "^4.0.0",
     "cross-env": "^5.2.1",
     "css-loader": "^4.2.1",
     "eslint": "^5.16.0",

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

@@ -464,12 +464,12 @@ const LANG_EN_US = {
         teachSpace: 'Allocated to teachers',
         homework: 'Homework',
         train: 'Study',
-        records: 'Lesson Record',
+        records: 'Lesson',
         over: 'Remaining',
         syllabus: 'Syllabus',
         itemAndPaper: 'Question Bank',
         appData: 'Application Data',
-        content: 'Content',
+        content: 'Material',
         used: 'Used:',
         expired: 'Service Due Date:',
         prodCont: 'Service Content:',
@@ -504,6 +504,7 @@ const LANG_EN_US = {
         hadExp: '(Expired)',
         unused: '(Not activated)',
         forever: '(Permanent)',
+        longTime: 'Long Term Authorization',
         useInfo: 'Use Status:',
         unband: 'Unbind Device',
         cancel: 'Cancel',
@@ -4143,7 +4144,7 @@ const LANG_EN_US = {
         sit4: 'stuYear: Required. Student enrollment year (usually the year he/she entered the school), e.g. 2022',
         sit5: "className: Required. Student's Class, e.g., 101",
         sit6: "classYear: Required. Usually the same as the enrolled year but depends on the student’s grade level, for example, classYear will not be the same as the enrollment year if the student is retained. E.g. 2020.",
-        sit7: 'classId: Required. Class ID, e.g. 20200101',
+        sit7: 'classId: Required. Class ID',
         sit8: 'Incorrect ID format',
         sit9: 'Incorrect seat number format',
         sit10: 'Incorrect class ID format',
@@ -4211,6 +4212,17 @@ const LANG_EN_US = {
                 title1: "Recent",
                 title2: "Due Today",
             },
+            menus: {
+                title1: "My Course",
+                title2: "Login Guide",
+            },
+            loginGuidance: {
+                tips1: "Computer Login Process",
+                tips2: "Browse ",
+                tips5: " and click Student to enter the login page",
+                tips3: "Use your registered TEAM Model account to log in",
+                tips4: "Use the account/password assigned by the school to login",
+            },
         },
         public: {
             noData: 'No data yet',
@@ -5434,7 +5446,9 @@ const LANG_EN_US = {
             trainList: 'Study List',
             trainCheck: 'Study Evaluation',
             activity: 'Activity Platform',
-            trainSystem: 'Research Platform'
+            trainSystem: 'Research Platform',
+            artExam:'Evaluation activity',
+            artExam1:'Evaluation and assessment',
         },
         compt: {
             cusWare: 'Teaching Material',
@@ -5611,6 +5625,8 @@ const LANG_EN_US = {
     },
     // 教师管理
     teachContent: {
+        ext1:'Please keep the suffix and source file suffix',
+        ext2:'consistent!',
         recent: 'Recent',
         recentTips: 'Temporary cache of up to 20 recently uploaded resources.The cache will be cleared when you exit the account or change computers.',
         filterRes: 'HiTeach',
@@ -5644,7 +5660,7 @@ const LANG_EN_US = {
         props6: 'File uploaded successfully!',
         props7: 'Not enough storage space!',
         uploadText: 'Tap or drag to upload',
-        resTips: 'HiTeach generates teaching materials that only support HTEX format previews',
+        resTips: 'Format generated by HiTeach: HTEX Files',
         calcing: 'Calculating...',
         blobFull: '(Full)',
         otherType: 'Other types',

+ 75 - 59
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -504,6 +504,7 @@ const LANG_ZH_CN = {
         hadExp: '(已到期)',
         unuse: '(未启用)',
         forever: '(永久授权)',
+        longTime: '长期授权',
         useInfo: '使用状况:',
         unband: '解绑设备',
         cancel: '取消',
@@ -1109,7 +1110,7 @@ const LANG_ZH_CN = {
         classStuErr: '获取班级名单失败',
         unGroup: '未分组学生',
         setGroupName: '请设置组名',
-        filterExpList:'到期名单',
+        filterExpList: '到期名单',
 
         //NewCusMgt.vue
         schdTable: '课表模式',
@@ -3064,13 +3065,13 @@ const LANG_ZH_CN = {
         attendCount: '出席率',
         groupCount: '小组数',
         totalPoint: '总记分',
-        collateTaskCount: '任务总数',
+        collateTaskCount: '合作学习',
         collateCount: '作品总数',
-        pushCount: '推送资源数',
+        pushCount: '差异教学',
         score: '总互动分',
         interactionCount: '互动题数',
-        clientInteractionCount: '互动总数',
-        examQuizCount: '测验总题数',
+        clientInteractionCount: '互动教学',
+        examQuizCount: '精准教学',
         examPointRate: '测验得分率',
         action: '操作',
         allTable: '课例数据汇总表',
@@ -3095,7 +3096,7 @@ const LANG_ZH_CN = {
             pie1: '教研组',
             pie2: '课例类别',
             pie3: '年级',
-            pie4: '科',
+            pie4: '科',
             title2: '课例趋势图',
             title3: '减负数据分析',
             title4: '常用科技工具统计',
@@ -3421,7 +3422,7 @@ const LANG_ZH_CN = {
         dashboard: {
             title: '校园大数据',
             title3: '五育并举大数据看板',
-            block1: '教学数据',
+            block1: '教学数据看板',
             block2: '教室物联',
             block3: '德育评价',
             block4: '学情分析',
@@ -3432,7 +3433,7 @@ const LANG_ZH_CN = {
             comingSoon: '即将上线',
             loading: '加载中',
             quit: '退出',
-            title2: '教学数据',
+            title2: '教学数据看板',
         },
         // 播放视频
         video: {
@@ -3686,7 +3687,7 @@ const LANG_ZH_CN = {
         irsRep: 'IRS号码重复',
         noRep: '座号重复',
         getTeachersErr: '获取教师列表失败',
-        gdFreeze:'已毕业的班级不能被删除和修改',
+        gdFreeze: '已毕业的班级不能被删除和修改',
 
         //ClassMgt.vue
         className: '名称',
@@ -4128,7 +4129,7 @@ const LANG_ZH_CN = {
         idWarning: '警告:Excel 內账号重复!',
         idFormatWarning: '错误:学生账号格式为4-12位数字',
         gradeWarning: '警告:年级错误',
-        setNoErr: "错误:座位号已在校內重复",
+        setNoErr: "错误:座号与校内该班级已有学生重复",
         downloadText: '(下载名单模板)',
         idRepErr: '账号已存在,将覆盖原有账号',
         stuYearErr: '学生学级数据错误',
@@ -4146,7 +4147,7 @@ const LANG_ZH_CN = {
         sit4: 'stuYear: 必填,学生入学年 ex:2020',
         sit5: 'className: 必填,学生班级ex:2020级1班',
         sit6: 'classYear: 必填,班级年,通常与学生入学年相同 ex:2020',
-        sit7: 'classId: 必填,班级编号ex:20200101',
+        sit7: 'classId: 必填,班级编号',
         sit8: 'id格式错误',
         sit9: '座号格式错误',
         sit10: '班级id格式错误',
@@ -4214,6 +4215,17 @@ const LANG_ZH_CN = {
                 title1: "近期",
                 title2: "今日到期",
             },
+            menus: {
+                title1: "参与课程",
+                title2: "登录指引",
+            },
+            loginGuidance: {
+                tips1: "电脑端登录指引",
+                tips2: "浏览 ",
+                tips5: " 点击学生身份,进入学生登录页面",
+                tips3: "使用注册过的手机号,或选择微信进行醍摩豆账号登录",
+                tips4: "使用学校分配的账号密码进行校内账号登录",
+            },
         },
         public: {
             noData: '暂无数据',
@@ -5438,7 +5450,9 @@ const LANG_ZH_CN = {
             trainList: '研修名单',
             trainCheck: '研修考核',
             activity: '活动平台',
-            trainSystem: '研修平台'
+            trainSystem: '研修平台',
+            artExam: '评测活动',
+            artExam1: '评测考核',
         },
         compt: {
             cusWare: '课件',
@@ -5615,6 +5629,8 @@ const LANG_ZH_CN = {
     },
     // 教师管理
     teachContent: {
+        ext1: '请保持后缀名与源文件后缀名',
+        ext2: '一致!',
         recent: '最近',
         recentTips: '临时缓存最近上传的资源,最多保存20条。退出账号或更换电脑缓存记录将会被清空。',
         filterRes: '教材',
@@ -6012,7 +6028,7 @@ const LANG_ZH_CN = {
         cusType: '学校课程:学校分配的课程,不允许自行新增、修改、删除。 \n个人课程:您自己创建的课程,可以根据需要进行修改和调整。',
         semester: '您可自行设定学校的学期和入学期,如果没有设置入学期系统会默认设置第一个学期为入学期。',
         time: '可设定学校作息时间,用于设置课程表。若未设置则无法设置课表。',
-        stuModel: 'Id:学生学号(4-12位数字)\npw:密码(若不输入,预设值等于学生学号)\nname:学生姓名\nstuYear:学生入学年ex:2020\nclassName:学生班级ex:2020级1班\nclassYear :班级年,通常与学生入学年相同ex:2020\nclassId:班级编号ex:20200101',
+        stuModel: 'Id:学生学号(4-12位数字)\npw:密码(若不输入,预设值等于学生学号)\nname:学生姓名\nstuYear:学生入学年ex:2020\nclassName:学生班级ex:2020级1班\nclassYear :班级年,通常与学生入学年相同ex:2020\nclassId:班级编号',
         cusInfo: '依据学校定义的学科,建立所属归类的课程 Ex:”语文”学科下的 “阅读理解”',
         cusTea: '加入负责该类课程授课的所有授课教师',
         sCusClass: '加入教师该课程所负责的学生班级',
@@ -6934,51 +6950,51 @@ const LANG_ZH_CN = {
         rate: '占比'
     },
     // 艺术评价模块
-    ae:{
-        ae0:'评测',
-        ae1:'材料',
-        ae2:'名称',
-        ae3:'请输入艺术评测活动名称',
-        ae4:'学科',
-        ae5:'请选择艺术评测活动学科',
-        ae6:'班级',
-        ae7:'时间',
-        ae8:'请设置评测时间',
-        ae9:'评价指标',
-        ae10:'音乐',
-        ae11:'美术',
-        ae12:'艺术评测发布成功',
-        ae13:'艺术评测发布失败',
-        ae14:'试卷复制失败',
-        ae15:'查询发布对象失败',
-        ae16:'评测试卷:',
-        ae17:'重选',
-        ae18:'请挑选评测试卷',
-        ae19:'作答方式:',
-        ae20:'默认排序',
-        ae21:'乱序作答',
-        ae22:'挑选艺术评测试卷',
-        ae23:'试卷来源:',
-        ae24:'醍摩豆',
-        ae25:'本校',
-        ae26:'返回试卷列表',
-        ae27:'参数异常',
-        ae28:'艺术评测活动',
-        ae29:'未提交',
-        ae30:'暂无区级艺术评测指标',
-        ae31:'删除艺术评测活动',
-        ae32:'是否确认删除',
-        ae33:'删除成功',
-        ae34:'删除失败',
-        ae35:'获取班级列表失败',
-        ae36:'提交时间',
-        ae37:'材料描述:',
-        ae38:'请输入材料描述...',
-        ae39:'请完成评价指标详细设置',
-        ae40:'请完成',
-        ae41:'详细设置',
-        ae42:'试卷不可用',
-        ae43:'艺术评测试卷只能包含客观题(单选、多选、判断),请重新挑选试卷或前往试卷库修改当前试卷。',
-        ae44:'试卷数据异常',
+    ae: {
+        ae0: '评测',
+        ae1: '材料',
+        ae2: '名称',
+        ae3: '请输入艺术评测活动名称',
+        ae4: '学科',
+        ae5: '请选择艺术评测活动学科',
+        ae6: '班级',
+        ae7: '时间',
+        ae8: '请设置评测时间',
+        ae9: '评价指标',
+        ae10: '音乐',
+        ae11: '美术',
+        ae12: '艺术评测发布成功',
+        ae13: '艺术评测发布失败',
+        ae14: '试卷复制失败',
+        ae15: '查询发布对象失败',
+        ae16: '评测试卷:',
+        ae17: '重选',
+        ae18: '请挑选评测试卷',
+        ae19: '作答方式:',
+        ae20: '默认排序',
+        ae21: '乱序作答',
+        ae22: '挑选艺术评测试卷',
+        ae23: '试卷来源:',
+        ae24: '醍摩豆',
+        ae25: '本校',
+        ae26: '返回试卷列表',
+        ae27: '参数异常',
+        ae28: '艺术评测活动',
+        ae29: '未提交',
+        ae30: '暂无区级艺术评测指标',
+        ae31: '删除艺术评测活动',
+        ae32: '是否确认删除',
+        ae33: '删除成功',
+        ae34: '删除失败',
+        ae35: '获取班级列表失败',
+        ae36: '提交时间',
+        ae37: '材料描述:',
+        ae38: '请输入材料描述...',
+        ae39: '请完成评价指标详细设置',
+        ae40: '请完成',
+        ae41: '详细设置',
+        ae42: '试卷不可用',
+        ae43: '艺术评测试卷只能包含客观题(单选、多选、判断),请重新挑选试卷或前往试卷库修改当前试卷。',
+        ae44: '试卷数据异常',
     }
 }

+ 69 - 53
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -469,7 +469,7 @@ const LANG_ZH_TW = {
         syllabus: '課綱',
         itemAndPaper: '試題試卷',
         appData: '應用數據',
-        content: '內容',
+        content: '教材',
         used: '已使用:',
         expired: '服務到期日:',
         prodCont: '服務內容:',
@@ -504,6 +504,7 @@ const LANG_ZH_TW = {
         hadExp: '(已到期)',
         unuse: '(未啟用)',
         forever: '(永久授權)',
+        longTime: '長期授權',
         useInfo: '使用狀況:',
         unband: '解綁設備',
         cancel: '取消',
@@ -1109,7 +1110,7 @@ const LANG_ZH_TW = {
         classStuErr: '獲取班級名單失敗',
         unGroup: '未分組學生',
         setGroupName: '請設定組名',
-        filterExpList:'到期名單',
+        filterExpList: '到期名單',
 
         //NewCusMgt.vue
         schdTable: '課表模式',
@@ -3097,7 +3098,7 @@ const LANG_ZH_TW = {
             pie1: '教師群組',
             pie2: '課堂類別',
             pie3: '年級',
-            pie4: '科',
+            pie4: '科',
             title2: '課堂趨勢圖',
             title3: '活動類型分析',
             title4: '常用科技工具統計',
@@ -3687,7 +3688,7 @@ const LANG_ZH_TW = {
         irsRep: 'IRS號碼重複',
         noRep: '座號重複',
         getTeachersErr: '獲取教師列表失敗',
-        gdFreeze:'已畢業的班級不能被刪除和修改',
+        gdFreeze: '已畢業的班級不能被刪除和修改',
 
         //ClassMgt.vue
         className: '名稱',
@@ -4129,7 +4130,7 @@ const LANG_ZH_TW = {
         idWarning: '警告:Excel 內帳號重複! ',
         idFormatWarning: '錯誤:學生帳號格式為4-12位數字',
         gradeWarning: '警告:年級錯誤',
-        setNoErr: "錯誤:座號已在校內重複",
+        setNoErr: "錯誤:座號與校內該班級已有學生重復",
         downloadText: '(下載名單模板)',
         idRepErr: '帳號已存在,將覆蓋原有帳號',
         stuYearErr: '學生學級數據錯誤',
@@ -4147,7 +4148,7 @@ const LANG_ZH_TW = {
         sit4: 'stuYear: 必填,學生入學年 ex:2020',
         sit5: 'className: 必填,學生班級ex:2020級1班',
         sit6: 'classYear: 必填,班級年,通常與學生入學年相同 ex:2020',
-        sit7: 'classId: 必填,班級編號ex:20200101',
+        sit7: 'classId: 必填,班級編號',
         sit8: 'id格式錯誤',
         sit9: '座號格式錯誤',
         sit10: '班級id格式錯誤',
@@ -4215,6 +4216,17 @@ const LANG_ZH_TW = {
                 title1: "近期",
                 title2: "今日到期",
             },
+            menus: {
+                title1: "參與課程",
+                title2: "登入指引",
+            },
+            loginGuidance: {
+                tips1: "電腦端登入使用流程",
+                tips2: "瀏覽 ",
+                tips5: " 選擇學生身份,進入學生登入頁面",
+                tips3: "使用註冊過的帳密,或選擇第三方進行醍摩豆帳號登入",
+                tips4: "使用學校分配的學生帳密來進行校內帳號登入",
+            },
         },
         public: {
             noData: '暫無資料',
@@ -5439,7 +5451,9 @@ const LANG_ZH_TW = {
             trainList: '研習名單',
             trainCheck: '研習審核',
             activity: '活動平臺',
-            trainSystem: '研習平臺'
+            trainSystem: '研習平臺',
+            artExam: '評測活動',
+            artExam1: '評測考核',
         },
         compt: {
             cusWare: '教材',
@@ -5616,6 +5630,8 @@ const LANG_ZH_TW = {
     },
     // 教师管理
     teachContent: {
+        ext1: '請保持後綴名與源文件後綴名',
+        ext2: '一致!',
         recent: '最近',
         recentTips: '暫存最近上傳的資源,最多儲存20條。 登出帳號或是更換電腦,暫存紀錄將會被清空。 ',
         filterRes: '教材',
@@ -6934,51 +6950,51 @@ const LANG_ZH_TW = {
         rate: '比例'
     },
     // 艺术评价模块
-    ae:{
-        ae0:'評量',
-        ae1:'材料',
-        ae2:'名稱',
-        ae3:'請輸入藝術評量活動名稱',
-        ae4:'學科',
-        ae5:'請選擇藝術評量活動科目',
-        ae6:'班級',
-        ae7:'時間',
-        ae8:'請設置評量時間',
-        ae9:'評量指標',
-        ae10:'音樂',
-        ae11:'美術',
-        ae12:'藝術評量發布成功',
-        ae13:'藝術評量發布失敗',
-        ae14:'試卷複製失敗',
-        ae15:'查詢發佈對象失敗',
-        ae16:'評量試卷:',
-        ae17:'重選',
-        ae18:'請挑選評量試卷',
-        ae19:'作答方式:',
-        ae20:'預設排序',
-        ae21:'亂序作答',
-        ae22:'挑選藝術評量試卷',
-        ae23:'試卷來源:',
-        ae24:'醍摩豆',
-        ae25:'本校',
-        ae26:'返回試卷列表',
-        ae27:'參數異常',
-        ae28:'藝術評量活動',
-        ae29:'未提交',
-        ae30:'暫無區級藝術評量指標',
-        ae31:'刪除藝術評量活動',
-        ae32:'是否確認刪除',
-        ae33:'刪除成功',
-        ae34:'刪除失敗',
-        ae35:'獲取班級列表失敗',
-        ae36:'繳交時間',
-        ae37:'資料描述:',
-        ae38:'請輸入資料描述...',
-        ae39:'請完成評量指標詳細設定',
-        ae40:'請完成',
-        ae41:'詳細設定',
-        ae42:'試卷不可用',
-        ae43:'藝術評量試卷只能包含客觀類題型(單選、複選、是非),請重新挑選試卷或前往試卷庫修改當前試卷。 ',
-        ae44:'試卷資料異常',
+    ae: {
+        ae0: '評量',
+        ae1: '材料',
+        ae2: '名稱',
+        ae3: '請輸入藝術評量活動名稱',
+        ae4: '學科',
+        ae5: '請選擇藝術評量活動科目',
+        ae6: '班級',
+        ae7: '時間',
+        ae8: '請設置評量時間',
+        ae9: '評量指標',
+        ae10: '音樂',
+        ae11: '美術',
+        ae12: '藝術評量發布成功',
+        ae13: '藝術評量發布失敗',
+        ae14: '試卷複製失敗',
+        ae15: '查詢發佈對象失敗',
+        ae16: '評量試卷:',
+        ae17: '重選',
+        ae18: '請挑選評量試卷',
+        ae19: '作答方式:',
+        ae20: '預設排序',
+        ae21: '亂序作答',
+        ae22: '挑選藝術評量試卷',
+        ae23: '試卷來源:',
+        ae24: '醍摩豆',
+        ae25: '本校',
+        ae26: '返回試卷列表',
+        ae27: '參數異常',
+        ae28: '藝術評量活動',
+        ae29: '未提交',
+        ae30: '暫無區級藝術評量指標',
+        ae31: '刪除藝術評量活動',
+        ae32: '是否確認刪除',
+        ae33: '刪除成功',
+        ae34: '刪除失敗',
+        ae35: '獲取班級列表失敗',
+        ae36: '繳交時間',
+        ae37: '資料描述:',
+        ae38: '請輸入資料描述...',
+        ae39: '請完成評量指標詳細設定',
+        ae40: '請完成',
+        ae41: '詳細設定',
+        ae42: '試卷不可用',
+        ae43: '藝術評量試卷只能包含客觀類題型(單選、複選、是非),請重新挑選試卷或前往試卷庫修改當前試卷。 ',
+        ae44: '試卷資料異常',
     }
 }

+ 11 - 0
TEAMModelOS/ClientApp/src/api/areaArt.js

@@ -27,6 +27,9 @@ export default {
     delArt: function (data) {
         return post('/common/art/delete', data)
     },
+    delAreaArt: function (data) {
+        return post('/school/area/delete-art', data)
+    },
     /* 艺术评测考核页面 */
     findArtResults: function (data) {
         return post('/school/art/review', data)
@@ -42,5 +45,13 @@ export default {
     /* 获取艺术评测看板数据 */
     findArtDashAnalysis: function (data) {
         return post('/analysis/art/statistics', data)
+    },
+    /* 获取学区学校列表 */
+    findAreaSchoolList: function (data) {
+        return post('/school/area/find-school', data)
+    },
+    /* 区级艺术评测数据看板 */
+    areaArtAna: function (data) {
+        return post('/school/area/analysis-area-art', data)
     }
 }

BIN
TEAMModelOS/ClientApp/src/assets/dashboard/student/icon-crown.png


BIN
TEAMModelOS/ClientApp/src/assets/dashboard/student/icon_crown.png


BIN
TEAMModelOS/ClientApp/src/assets/dashboard/student/icon_crown2.png


BIN
TEAMModelOS/ClientApp/src/assets/dashboard/student/icon_crown3.png


BIN
TEAMModelOS/ClientApp/src/assets/image/c-import-stu-cn.png


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

@@ -610,26 +610,26 @@ export default {
           child: [
             {
               icon: 'iconfont icon-test',
-              name: '评测活动',
+              name: this.$t('system.menu.artExam'),
               router: '/home/mgtArtExam',
               tag: '',
               role: 'admin',
               permission: '',
               menuName: 'mgtArtExam',
-              isShow: this.$store.state.config.srvAdrType === 'test'
+              isShow: this.IES5Menu && this.$store.state.config.srvAdr == 'China'
             },
             {
               icon: 'iconfont icon-test',
-              name: '评测考核',
+              name: this.$t('system.menu.artExam1'),
               router: '/home/ArtAssessment',
               tag: '',
               role: 'admin',
               permission: '',
               menuName: 'ArtAssessment',
-              isShow: this.$store.state.config.srvAdrType === 'test'
+              isShow: this.IES5Menu && this.$store.state.config.srvAdr == 'China'
             },
           ],
-          isShow: this.$store.state.config.srvAdrType === 'test'
+          isShow: this.IES5Menu && this.$store.state.config.srvAdr == 'China'
         },
         // 学情分析
         {
@@ -950,16 +950,16 @@ export default {
       }
       this.isShowLogo = cloudSetting.logoStatus === 'open'
     }
-    this.$EventBus.$off('onGlobalLoading')
-    this.$EventBus.$on('onGlobalLoading', val => {
-      this.getSystemLevel()
-    })
   },
   mounted() {
     this.$EventBus.$off('onLogoStatusChange')
     this.$EventBus.$on('onLogoStatusChange', val => {
       this.isShowLogo = val === 'open'
     })
+    this.$EventBus.$off('onGlobalLoading')
+    this.$EventBus.$on('onGlobalLoading', val => {
+      this.getSystemLevel()
+    })
     this.getSystemLevel()
   },
   watch: {

+ 1 - 1
TEAMModelOS/ClientApp/src/components/dashboard/art/RightBotR.vue

@@ -8,7 +8,7 @@
     <div class="bg-color-black" style="display:flex;align-items:center;padding-top:40px;flex-direction:column;">
       <!-- <BaseAwardPie></BaseAwardPie> -->
       <dv-capsule-chart :config="config2" style="width:300px;height:300px" />
-      <dv-active-ring-chart :config="config" style="width:300px;height:300px" />
+      <!-- <dv-active-ring-chart :config="config" style="width:300px;height:300px" /> -->
     </div>
   </div>
 </template>

+ 147 - 0
TEAMModelOS/ClientApp/src/components/dashboard/student/BaseCircle.vue

@@ -0,0 +1,147 @@
+<template>
+  <div :id="circleId" class="art-echart"></div>
+</template>
+<script>
+export default {
+  props: {
+    circleId: {
+      type: String,
+      default: ''
+    },
+    percent: {
+      type: Number,
+      default: ''
+    },
+    subTitle: {
+      type: String,
+      default: ''
+    },
+    chatName: {
+      type: String,
+      default: ''
+    },
+  },
+  data() {
+    return {
+      option: null,
+    }
+  },
+  methods: {
+    doRender() {
+      let myChart = this.$echarts.init(document.getElementById(this.circleId))
+      let option = {
+        title: [
+          {
+            text: this.subTitle,
+            x: 'center',
+            top: '50%',
+            textStyle: {
+              color: '#FFFFFF',
+              fontSize: 16,
+              fontWeight: '100',
+            },
+          },
+          {
+            text: this.chatName,
+            x: 'center',
+            bottom: '10%',
+            textStyle: {
+              color: '#FFFFFF',
+              fontSize: 16,
+              fontWeight: 'bold',
+            },
+          },
+          {
+            text: this.percent + '%',
+            x: 'center',
+            top: '30%',
+            textStyle: {
+              fontSize: '32',
+              color: '#FFFFFF',
+              foontWeight: '600',
+            },
+          },
+        ],
+        polar: {
+          radius: ['55%', '70%'],
+          center: ['50%', '40%'],
+        },
+        angleAxis: {
+          max: 100,
+          show: false,
+        },
+        radiusAxis: {
+          type: 'category',
+          show: true,
+          axisLabel: {
+            show: false,
+          },
+          axisLine: {
+            show: false,
+          },
+          axisTick: {
+            show: false,
+          },
+        },
+        series: [
+          {
+            name: '',
+            type: 'bar',
+            roundCap: true,
+            barWidth: 30,
+            showBackground: true,
+            backgroundStyle: {
+              color: 'rgba(66, 66, 66, .3)',
+            },
+            data: [this.percent],
+            coordinateSystem: 'polar',
+            itemStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
+                  {
+                    offset: 0,
+                    color: '#16CEB9',
+                  },
+                  {
+                    offset: 1,
+                    color: '#6648FF',
+                  },
+                ]),
+              },
+            },
+          },
+
+        ],
+      };
+
+      myChart.clear()
+      myChart.setOption(option)
+      window.addEventListener('resize', function () {
+        myChart.resize()
+      })
+
+    }
+  },
+  mounted() {
+    this.doRender()
+  },
+  //   watch: {
+  //     '$store.state.dashboard.artDashboard': {
+  //       deep: true,
+  //       immediate: true,
+  //       handler(n, o) {
+
+  //       }
+  //     }
+  //   }
+}
+</script>
+
+<style>
+.art-echart {
+  width: 100%;
+  height: 100%;
+  margin: 0 auto;
+  display: block;
+}
+</style>

+ 2 - 2
TEAMModelOS/ClientApp/src/components/dashboard/student/BaseProgressBar.vue

@@ -70,7 +70,7 @@ export default {
           },
         },
         grid: {
-          x: 35,
+          x: 85,
           y: 2,
           x2: 20,
           y2: 20,
@@ -97,7 +97,7 @@ export default {
         },
         yAxis: {
           type: "category",
-          data: ["评测", "问卷", "投票", "作业"],
+          data: ["核酸检测", "义捐灾区", "义务劳动", "主动做家务"],
           axisLine: {
             lineStyle: {
               color: "#44A0B7",

+ 1 - 1
TEAMModelOS/ClientApp/src/components/dashboard/studentAll/BaseScoreBar.vue

@@ -323,7 +323,7 @@ export default {
             color: '#00dcf1',
             padding: [0, 0, 0, 20],
           },
-          data: ['60分以下', '60分-70分', '70分-80分', '80分-90分', '90分以上'],
+          data: ['非常稳定', '一般稳定', '偶尔粗心', '经常粗心'],
           show: true,
           type: 'category',
           axisLabel: {

+ 128 - 126
TEAMModelOS/ClientApp/src/components/echart/acPie/chart.vue

@@ -1,131 +1,133 @@
 <template>
-	<div style="height: 100%;">
-		<!-- 年度开工率 -->
-		<Echart :options="options" id="bottomLeftChart" height="100%" width="100%"></Echart>
-	</div>
+  <div style="height: 100%;">
+    <!-- 年度开工率 -->
+    <Echart :options="options" id="bottomLeftChart" height="100%" width="100%"></Echart>
+  </div>
 </template>
 
 <script>
-	import Echart from '@/common/echart'
-	export default {
-		data(vm) {
-			return {
-				options: {},
-				acData:[],
-				acArr: [vm.$t('lessonRecord.echarts.ac1'),vm.$t('lessonRecord.echarts.ac2'),vm.$t('lessonRecord.echarts.ac3'),vm.$t('lessonRecord.echarts.ac4'),vm.$t('lessonRecord.echarts.ac5'),vm.$t('lessonRecord.echarts.ac6'),vm.$t('lessonRecord.echarts.ac7'),vm.$t('lessonRecord.echarts.ac8')]
-			};
-		},
-		components: {
-			Echart,
-		},
-		props: {
-			cdata: {
-				type: Object,
-				default: () => ({})
-			},
-		},
-		watch: {
-			cdata: {
-				handler(newData) {
-					var colorList = [
-					    '#0090ff',
-						'#06d3c4',
-						'#ffbc32',
-						'#2ccc44',
-						'#ff3976',
-						'#6173d6',
-						'#914ce5',
-						'#42b1cc',
-						'#ff55ac',
-						'#0090ff',
-						'#06d3c4',
-						'#ffbc32',
-						'#2ccc44',
-						'#26c898',
-						'#6173d6',
-						'#914ce5',
-					];
-					let that = this
-					let acJson = this.$store.state.dashboard.researchDashboard.exams
-					if(acJson){
-						this.acData = this.acArr.map((i,index) => {
-							return {
-								name:i,
-								value:acJson[index] || 0
-							}
-						})
-					}
-					this.options = {
-						tooltip: {
-							trigger: 'item',
-						},
-						legend: {
-							top: '2%',
-							left: 'center',
-							data:this.acArr
-						},
-						series: [{
-								type: 'pie',
-								radius: ['40%', '60%'],
-								center: ['50%', '55%'],
-								itemStyle: {
-									borderRadius: 20,
-									borderColor: 'rgba(0,0,0,0)',
-									borderWidth: 2,
-									color: function (params) {
-										return colorList[params.dataIndex];
-									},
-								},
-								label: {
-									show: false,
-									position: 'center',
-								},
-								labelLine: {
-									show: false,
-								},
-								data: that.acData
-							},
-							{
-								type: 'pie',
-								selectedMode: 'single',
-								radius: [0, '30%'],
-								center: ['50%', '55%'],
-								itemStyle: {
-									borderRadius: 20,
-									borderColor: 'rgba(0,0,0,0)',
-									borderWidth: 2,
-									color: function (params) {
-										return colorList[colorList.length - 1 - params.dataIndex];
-									},
-								},
-								label: {
-									position: 'inner',
-									fontSize: 14,
-								},
-								labelLine: {
-									show: true,
-									smooth: 0.2,
-								},
-								data: [{
-										value: acJson[0] + acJson[3],
-										name: that.$t('lessonRecord.echarts.online')
-									},
-									{
-										value: acJson[2] + acJson[5],
-										name: that.$t('lessonRecord.echarts.offline')
-									},
-									{
-										value: acJson[1] + acJson[4],
-										name: that.$t('lessonRecord.echarts.mid')
-									},
-								]
-							},
-						],
-					};
-				},
-				immediate: true,
-				deep: true
-			},
-		},
-	}
+import Echart from '@/common/echart'
+export default {
+  data(vm) {
+    return {
+      options: {},
+      acData: [],
+      acArr: [vm.$t('lessonRecord.echarts.ac1'), vm.$t('lessonRecord.echarts.ac2'), vm.$t('lessonRecord.echarts.ac3'), vm.$t('lessonRecord.echarts.ac4')]
+    };
+  },
+  components: {
+    Echart,
+  },
+  props: {
+    cdata: {
+      type: Object,
+      default: () => ({})
+    },
+  },
+  watch: {
+    cdata: {
+      handler(newData) {
+        var colorList = [
+          '#0090ff',
+          '#06d3c4',
+          '#ffbc32',
+          '#2ccc44',
+          '#ff3976',
+          '#6173d6',
+          '#914ce5',
+          '#42b1cc',
+          '#ff55ac',
+          '#0090ff',
+          '#06d3c4',
+          '#ffbc32',
+          '#2ccc44',
+          '#26c898',
+          '#6173d6',
+          '#914ce5',
+        ];
+        let that = this
+        let acJson = this.$store.state.dashboard.researchDashboard.exams
+        if (acJson) {
+          this.acData = this.acArr.map((i, index) => {
+            return {
+              name: i,
+              value: acJson[index] || 0
+            }
+          })
+        }
+        this.options = {
+          tooltip: {
+            trigger: 'item',
+          },
+          legend: {
+            top: '5%',
+            left: 'center',
+            width: '80%',
+            itemWidth: 30,
+            data: this.acArr
+          },
+          series: [{
+            type: 'pie',
+            radius: ['40%', '60%'],
+            center: ['50%', '55%'],
+            itemStyle: {
+              borderRadius: 20,
+              borderColor: 'rgba(0,0,0,0)',
+              borderWidth: 2,
+              color: function (params) {
+                return colorList[params.dataIndex];
+              },
+            },
+            label: {
+              show: false,
+              position: 'center',
+            },
+            labelLine: {
+              show: false,
+            },
+            data: that.acData
+          },
+          {
+            type: 'pie',
+            selectedMode: 'single',
+            radius: [0, '30%'],
+            center: ['50%', '55%'],
+            itemStyle: {
+              borderRadius: 20,
+              borderColor: 'rgba(0,0,0,0)',
+              borderWidth: 2,
+              color: function (params) {
+                return colorList[colorList.length - 1 - params.dataIndex];
+              },
+            },
+            label: {
+              position: 'inner',
+              fontSize: 14,
+            },
+            labelLine: {
+              show: true,
+              smooth: 0.2,
+            },
+            data: [{
+              value: acJson[0] + acJson[3],
+              name: that.$t('lessonRecord.echarts.online')
+            },
+            {
+              value: acJson[2] + acJson[5],
+              name: that.$t('lessonRecord.echarts.offline')
+            },
+            {
+              value: acJson[1] + acJson[4],
+              name: that.$t('lessonRecord.echarts.mid')
+            },
+            ]
+          },
+          ],
+        };
+      },
+      immediate: true,
+      deep: true
+    },
+  },
+}
 </script>

+ 132 - 133
TEAMModelOS/ClientApp/src/components/echart/techBar/chart.vue

@@ -1,139 +1,138 @@
 <template>
-	<div style="height: 100%;">
-		<!-- 年度开工率 -->
-		<Echart :options="options" id="bottomLeftChart" height="100%" width="100%"></Echart>
-	</div>
+  <div style="height: 100%;">
+    <!-- 年度开工率 -->
+    <Echart :options="options" id="bottomLeftChart" height="100%" width="100%"></Echart>
+  </div>
 </template>
 
 <script>
-	import Echart from '@/common/echart'
-	export default {
-		data() {
-			return {
-				options: {},
-				techArr: ['计分板', '计时器', '挑人', '即问即答', '作品观摩', '页面接受', '二次作答', '抢权', '翻牌', '统计', '同步测验', 'HiTA提交', '推送',
-					'智慧挑人', '课中评测'
-				]
-			};
-		},
-		components: {
-			Echart,
-		},
-		props: {
-			cdata: {
-				type: Object,
-				default: () => ({})
-			},
-		},
-		methods: {
-			getRandomArr(min, max) {
-				var data = [];
-				for (var i = 1; i < 10; i++) {
-					data.push(this.$tools.randomNum(min, max));
-				}
-				return data;
-			}
-		},
-		watch: {
-			cdata: {
-				handler(newData) {
-					let yLabel = this.techArr
-					let yData = []
-					let that = this
-					for (let i = 0; i < this.techArr.length; i++) {
-						yData.push(this.$tools.randomNum(50, 200))
-					}
-					yData.sort((a,b) => { return b-a})
+import Echart from '@/common/echart'
+export default {
+  data() {
+    return {
+      options: {},
+      techArr: ['互动教学', '差异教学', '合作学习', '精准教学']
+    };
+  },
+  components: {
+    Echart,
+  },
+  props: {
+    cdata: {
+      type: Object,
+      default: () => ({})
+    },
+  },
+  methods: {
+    getRandomArr(min, max) {
+      var data = [];
+      for (var i = 1; i < 10; i++) {
+        data.push(this.$tools.randomNum(min, max));
+      }
+      return data;
+    }
+  },
+  watch: {
+    cdata: {
+      handler(newData) {
+        let yLabel = this.techArr
+        let yData = []
+        let that = this
+        for (let i = 0; i < this.techArr.length; i++) {
+          yData.push(this.$tools.randomNum(50, 200))
+        }
+        yData.sort((a, b) => { return b - a })
 
-					this.options = {
-						grid: {
-							width:"92%",
-							left: '2%',
-							right: '5%',
-							bottom: '0%',
-							top: '5%',
-							containLabel: true,
-						},
-						tooltip: {
-							trigger: 'axis',
-							axisPointer: {
-								type: 'none',
-							},
-							formatter: function(params) {
-								return (
-									params[0].name +
-									'<br/>' +
-									"<span style='display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:rgba(36,207,233,0.9)'></span>" +
-									params[0].seriesName +
-									' : ' +
-									params[0].value +
-									' <br/>'
-								);
-							},
-						},
-						xAxis: {
-							show: false,
-							type: 'value',
-						},
-						yAxis: [{
-								type: 'category',
-								inverse: true,
-								axisLabel: {
-									show: true,
-									margin: 15,
-									textStyle: {
-										color: '#fdfdfd',
-									},
-								},
-								splitLine: {
-									show: false,
-								},
-								axisTick: {
-									show: false,
-								},
-								axisLine: {
-									show: false,
-								},
-								data: yLabel,
-							}
-						],
-						series: [{
-							name: '次数',
-							type: 'bar',
-							zlevel: 1,
-							label: {
-								show: true, //开启显示
-								position: "right", //在上方显示
-								textStyle: { //数值样式
-									color: "#FFFFFF",
-									fontSize: 12,
-								}
-							},
-							itemStyle: {
-								barBorderRadius: 20,
-								color: {
-								    type: 'linear',
-								    x: 0,
-								    y: 0,
-								    x2: 1,
-								    y2: 0,
-								    colorStops: [{
-								        offset: 0,
-								        color: 'rgb(57,89,255,1)' // 0% 处的颜色
-								    }, {
-								        offset: 1,
-								        color: 'rgb(46,200,207,1)' // 100% 处的颜色
-								    }]
-								}
-							},
-							barWidth: 10,
-							data: yData,
-						}],
-					};
-				},
-				immediate: true,
-				deep: true
-			},
-		},
-	}
+        this.options = {
+          grid: {
+            width: "88%",
+            height: "60%",
+            left: '4%',
+            right: '10%',
+            bottom: '0%',
+            top: '5%',
+            containLabel: true,
+          },
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'none',
+            },
+            formatter: function (params) {
+              return (
+                params[0].name +
+                '<br/>' +
+                "<span style='display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:rgba(36,207,233,0.9)'></span>" +
+                params[0].seriesName +
+                ' : ' +
+                params[0].value +
+                ' <br/>'
+              );
+            },
+          },
+          xAxis: {
+            show: false,
+            type: 'value',
+          },
+          yAxis: [{
+            type: 'category',
+            inverse: true,
+            axisLabel: {
+              show: true,
+              margin: 15,
+              textStyle: {
+                color: '#fdfdfd',
+              },
+            },
+            splitLine: {
+              show: false,
+            },
+            axisTick: {
+              show: false,
+            },
+            axisLine: {
+              show: false,
+            },
+            data: yLabel,
+          }
+          ],
+          series: [{
+            name: '次数',
+            type: 'bar',
+            zlevel: 1,
+            label: {
+              show: true, //开启显示
+              position: "right", //在上方显示
+              textStyle: { //数值样式
+                color: "#FFFFFF",
+                fontSize: 12,
+              }
+            },
+            itemStyle: {
+              barBorderRadius: 20,
+              color: {
+                type: 'linear',
+                x: 0,
+                y: 0,
+                x2: 1,
+                y2: 0,
+                colorStops: [{
+                  offset: 0,
+                  color: 'rgb(57,89,255,1)' // 0% 处的颜色
+                }, {
+                  offset: 1,
+                  color: 'rgb(46,200,207,1)' // 100% 处的颜色
+                }]
+              }
+            },
+            barWidth: 15,
+            data: yData,
+          }],
+        };
+      },
+      immediate: true,
+      deep: true
+    },
+  },
+}
 </script>

+ 156 - 0
TEAMModelOS/ClientApp/src/components/research-dashboard/BaseTechBar.vue

@@ -0,0 +1,156 @@
+<template>
+  <div id="baseTechBar" class="art-echart"></div>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      option: null,
+    }
+  },
+  methods: {
+    doRender(data) {
+      let myChart = this.$echarts.init(document.getElementById('baseTechBar'))
+      var echartsData = {
+        title: 'title',
+        city: ['互动教学', '合作学习', '差异教学', '精准教学'],
+        legend: data.legend,
+        data: data.data,
+      };
+      var colors = ['#F56679', '#4C98FB', '#8CDF6C', '#9D50E0'];
+      let option = {
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: { type: 'shadow' },
+        },
+        color: colors,
+        legend: {
+          bottom: 10,
+          left: 'center',
+          itemWidth: 10,
+          itemHeight: 10,
+          padding: [5, 10],
+          textStyle: {
+            fontSize: 14,
+            color: '#96A4F4',
+            padding: [3, 0, 0, 0],
+          },
+          data: echartsData.legend,
+        },
+        grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '15%',
+          containLabel: true,
+        },
+        xAxis: {
+          type: 'category',
+          axisLabel: {
+            color: '#cecece',
+            rotate: 0,//倾斜度
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#cecece',
+            },
+            width: 5,
+          },
+          axisTick: {
+            show: false,
+          },
+          data: echartsData.city,
+        },
+        yAxis: {
+          name: '单位:次',
+          type: 'value',
+          axisLabel: {
+            color: '#cecece',
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#cecece',
+            },
+            width: 5,
+          },
+          axisTick: {
+            show: false,
+          },
+          splitLine: {
+            lineStyle: {
+              color: 'rgba(150, 164, 244, 0.3)',
+            },
+          },
+        },
+        series: [],
+      };
+      for (var i = 0; i < echartsData.legend.length; i++) {
+        option.series.push({
+          name: echartsData.legend[i],
+          type: 'bar',
+          stack: '总数',
+          barWidth: '35',
+          label: {
+            show: false,
+            position: 'insideRight',
+          },
+          data: echartsData.data[i],
+          itemStyle: {
+            barBorderRadius: 50,
+            normal: {
+              label: {
+                show: true, //开启显示
+                position: 'top', //在上方显示
+                textStyle: {
+                  //数值样式
+                  color: '#fff',
+                  fontSize: 14,
+                  fontWeight: 600,
+                },
+              },
+            },
+          },
+        });
+      }
+      myChart.clear()
+      myChart.setOption(option)
+      window.addEventListener('resize', function () {
+        myChart.resize()
+      })
+
+    }
+  },
+  mounted() {
+    let pieJson = this.$store.state.dashboard.researchDashboard
+    let echartJson = {
+      legend: pieJson.teachingCount.map(i => i.name),
+      data: pieJson.teachingCount.map(i => {
+        return [i.clientInteractionCount, i.collateTaskCount, i.pushCount, i.examCount]
+      })
+    }
+    this.doRender(echartJson)
+  },
+  computed: {
+    isTestSite() {
+      return window.location.host.includes('test.teammodel.cn')
+    },
+  }
+  //   watch: {
+  //     '$store.state.dashboard.artDashboard': {
+  //       deep: true,
+  //       immediate: true,
+  //       handler(n, o) {
+
+  //       }
+  //     }
+  //   }
+}
+</script>
+
+<style>
+.art-echart {
+  width: 100%;
+  height: 100%;
+  margin: 0 auto;
+  display: block;
+}
+</style>

+ 112 - 119
TEAMModelOS/ClientApp/src/components/research-dashboard/LeftBottom.vue

@@ -1,133 +1,126 @@
 <template>
-	<div id="bottomLeft">
-		<p class="dashboard-block-title">
-			<Icon type="md-pie" />
-			<span>{{ $t('lessonRecord.echarts.title1') }}</span>
-			<dv-decoration-3 class="dv-dec-3" />
-		</p>
-		<div class="bg-color-black">
-			<div class="pie-item">
-				<BasePie :title="$t('lessonRecord.echarts.pie3')" :pieData="gradeData"/>
-			</div>
-			<div class="pie-item">
-				<BasePie :title="$t('lessonRecord.echarts.pie4')" :pieData="subjectData"/>
-			</div>
-			<div class="pie-item">
-				<BasePie :title="$t('lessonRecord.echarts.pie1')" :pieData="groupData"/>
-			</div>
-			<div class="pie-item">
-				<BasePie :title="$t('lessonRecord.echarts.pie2')" :pieData="cateData"/>
-			</div>
-		</div>
-	</div>
+  <div id="bottomLeft">
+    <p class="dashboard-block-title">
+      <Icon type="md-pie" />
+      <span>{{ $t('lessonRecord.echarts.title1') }}</span>
+      <dv-decoration-3 class="dv-dec-3" />
+    </p>
+    <div class="bg-color-black">
+      <div class="pie-item">
+        <BasePie :title="$t('lessonRecord.echarts.pie3')" :pieData="gradeData" />
+      </div>
+      <div class="pie-item">
+        <BasePie :title="$t('lessonRecord.echarts.pie4')" :pieData="subjectData" />
+      </div>
+      <div class="pie-item">
+        <BasePie :title="$t('lessonRecord.echarts.pie1')" :pieData="groupData" />
+      </div>
+      <div class="pie-item">
+        <BasePie :title="$t('lessonRecord.echarts.pie2')" :pieData="cateData" />
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
-	import BasePie from '@/components/echart/pie/index'
-	export default {
-		components: {
-			BasePie
-		},
-		data() {
-			return {
-				groupData: [],
-				cateData:[],
-				gradeData:[],
-				subjectData:[]
-			}
-		},
-		created() {
-			let pieJson = this.$store.state.dashboard.researchDashboard
-			let curPeriod = this.$store.state.user.curPeriod
-			console.log(curPeriod.subjects.map(i => i.id))
-			if(pieJson){
-				this.gradeData = pieJson.classify_grade.map(i => {
-					return {
-						name:curPeriod.grades[+i.name],
-						value:i.value
-					}
-				})
-				
-				this.subjectData = pieJson.classify_sub.map(i => {
-					let findSubject = curPeriod.subjects.find(j => j.id === i.name)
-					return {
-						name:findSubject ? findSubject.name : this.$t('vote.form.noMatchDataTip'),
-						value:i.value
-					}
-				})
-				
-				if(!pieJson.classify_group.length){
-					this.groupData = [{
-						name:this.$t('lessonRecord.echarts.noGroup'),
-						value:0
-					}]
-				}else{
-					this.groupData = pieJson.classify_group.map(i => {
-						return {
-							name:i.name,
-							value:i.value
-						}
-					})
-				}
-				
-				if(!pieJson.classify_type.length){
-					this.cateData = [{
-						name:this.$t('lessonRecord.echarts.noType'),
-						value:0
-					}]
-				}else{
-					this.cateData = pieJson.classify_type.map(i => {
-						return {
-							name:i.name,
-							value:i.value
-						}
-					})
-				}
-				
-			}
-		},
-	}
+import BasePie from '@/components/echart/pie/index'
+export default {
+  components: {
+    BasePie
+  },
+  data() {
+    return {
+      groupData: [],
+      cateData: [],
+      gradeData: [],
+      subjectData: []
+    }
+  },
+  created() {
+    let pieJson = this.$store.state.dashboard.researchDashboard
+    let curPeriod = this.$store.state.user.curPeriod
+    console.log(curPeriod.subjects.map(i => i.id))
+    if (pieJson) {
+      this.gradeData = pieJson.classify_grade
+      this.subjectData = pieJson.classify_sub.map(i => {
+        let findSubject = curPeriod.subjects.find(j => j.id === i.name)
+        return {
+          name: findSubject ? findSubject.name : this.$t('vote.form.noMatchDataTip'),
+          value: i.value
+        }
+      })
+
+      if (!pieJson.classify_group.length) {
+        this.groupData = [{
+          name: this.$t('lessonRecord.echarts.noGroup'),
+          value: 0
+        }]
+      } else {
+        this.groupData = pieJson.classify_group.map(i => {
+          return {
+            name: i.name,
+            value: i.value
+          }
+        })
+      }
+
+      if (!pieJson.classify_type.length) {
+        this.cateData = [{
+          name: this.$t('lessonRecord.echarts.noType'),
+          value: 0
+        }]
+      } else {
+        this.cateData = pieJson.classify_type.map(i => {
+          return {
+            name: i.name,
+            value: i.value
+          }
+        })
+      }
+
+    }
+  },
+}
 </script>
 
 <style lang="less" scoped>
-	@box-height: 100%;
-	@box-width: 100%;
-
-	#bottomLeft {
-		padding: 20px 16px;
-		height: @box-height;
-		width: @box-width;
-		display: flex;
-		flex-direction: column;
-		justify-content: space-between;
+@box-height: 100%;
+@box-width: 100%;
 
+#bottomLeft {
+  padding: 20px 16px;
+  height: @box-height;
+  width: @box-width;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
 
-		.bg-color-black {
-			height: 96%;
-			padding-top: 10px;
-			display: flex;
-			flex-wrap: wrap;
-			justify-content: center;
-			align-items: center;
+  .bg-color-black {
+    height: 96%;
+    padding-top: 10px;
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: center;
+    align-items: center;
 
-			.pie-item {
-				width: 48%;
-				height: 48%;
-			}
-		}
+    .pie-item {
+      width: 48%;
+      height: 48%;
+    }
+  }
 
-		.text {
-			color: #c3cbde;
-		}
+  .text {
+    color: #c3cbde;
+  }
 
-		.chart-box {
-			margin-top: 16px;
-			width: 170px;
-			height: 170px;
+  .chart-box {
+    margin-top: 16px;
+    width: 170px;
+    height: 170px;
 
-			.active-ring-name {
-				padding-top: 10px;
-			}
-		}
-	}
+    .active-ring-name {
+      padding-top: 10px;
+    }
+  }
+}
 </style>

+ 144 - 145
TEAMModelOS/ClientApp/src/components/research-dashboard/LeftTop.vue

@@ -1,168 +1,167 @@
 <template>
-	<div id="left-top-box">
-		<!-- <p class="dashboard-block-title">
+  <div id="left-top-box">
+    <!-- <p class="dashboard-block-title">
 			<Icon type="md-cube" />
 			<span>累计数据</span>
 		</p> -->
-		<div class="up">
-			<div class="bg-color-black item" v-for="item in titleItem" :key="item.title">
-				<p class="ml-3 colorBlue fw-b fs-xl">{{ item.title }}</p>
-				<countTo :startVal='0' :endVal='item.number' :duration='2000' class="count-num"></countTo>
-			</div>
-		</div>
-	</div>
+    <div class="up">
+      <div class="bg-color-black item" v-for="item in titleItem" :key="item.title">
+        <p class="ml-3 colorBlue fw-b fs-xl">{{ item.title }}</p>
+        <countTo :startVal='0' :endVal='item.number' :duration='2000' class="count-num"></countTo>
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
-	import countTo from 'vue-count-to'
-	export default {
-		data(vm) {
-			return {
-				titleItem: [
-					{
-						title: vm.$t('lessonRecord.echarts.count1'),
-						key:'total',
-						number: 0
-					},
-					{
-						title: vm.$t('lessonRecord.echarts.count2'),
-						key:'today',
-						number: 0
-					},
-					{
-						title: vm.$t('lessonRecord.echarts.count3'),
-						key:'week',
-						number: 0,
-					},
-					{
-						title: vm.$t('lessonRecord.echarts.count4'),
-						key:'month',
-						number: 0
-					},
-					{
-						title: vm.$t('lessonRecord.echarts.count5'),
-						key:'semester',
-						number: 0
-					},
-					{
-						title: vm.$t('lessonRecord.echarts.count6'),
-						number: 0
-					},
-					{
-						title: vm.$t('lessonRecord.echarts.count7'),
-						number: 0
-					},
-					{
-						title: vm.$t('lessonRecord.echarts.count8'),
-						number: 0
-					},
-					{
-						title: vm.$t('lessonRecord.echarts.count9'),
-						number: 0
-					},
-					{
-						title: vm.$t('lessonRecord.echarts.count10'),
-						number: 0
-					}
-				],
-			}
-		},
-		components: {
-			countTo
-		},
-		created() {
-			let totalJson = this.$store.state.dashboard.researchDashboard.total
-			let allJson = this.$store.state.dashboard.researchDashboard
-			if(totalJson){
-				totalJson.forEach(i => {
-					this.titleItem.find(j => j.key === i.name).number = i.value
-				})
-				this.titleItem[5].number = allJson.teachCount
-				this.titleItem[6].number = allJson.taskCount
-				this.titleItem[7].number = allJson.workCount
-				this.titleItem[8].number = allJson.examQuizCount
-				this.titleItem[9].number = allJson.interactCount
-			}
-		}
-	}
+import countTo from 'vue-count-to'
+export default {
+  data(vm) {
+    return {
+      titleItem: [
+        {
+          title: vm.$t('lessonRecord.echarts.count1'),
+          key: 'total',
+          number: 0
+        },
+        {
+          title: vm.$t('lessonRecord.echarts.count2'),
+          key: 'today',
+          number: 0
+        },
+        {
+          title: vm.$t('lessonRecord.echarts.count3'),
+          key: 'week',
+          number: 0,
+        },
+        {
+          title: vm.$t('lessonRecord.echarts.count4'),
+          key: 'month',
+          number: 0
+        },
+        {
+          title: vm.$t('lessonRecord.echarts.count5'),
+          key: 'semester',
+          number: 0
+        },
+        {
+          title: vm.$t('lessonRecord.echarts.count6'),
+          number: 0
+        },
+        // {
+        // 	title: vm.$t('lessonRecord.echarts.count7'),
+        // 	number: 0
+        // },
+        // {
+        // 	title: vm.$t('lessonRecord.echarts.count8'),
+        // 	number: 0
+        // },
+        // {
+        // 	title: vm.$t('lessonRecord.echarts.count9'),
+        // 	number: 0
+        // },
+        // {
+        // 	title: vm.$t('lessonRecord.echarts.count10'),
+        // 	number: 0
+        // }
+      ],
+    }
+  },
+  components: {
+    countTo
+  },
+  created() {
+    let totalJson = this.$store.state.dashboard.researchDashboard.total
+    let allJson = this.$store.state.dashboard.researchDashboard
+    if (totalJson) {
+      totalJson.forEach(i => {
+        this.titleItem.find(j => j.key === i.name).number = i.value
+      })
+      this.titleItem[5].number = allJson.teachCount
+      // this.titleItem[6].number = allJson.taskCount
+      // this.titleItem[7].number = allJson.workCount
+      // this.titleItem[8].number = allJson.examQuizCount
+      // this.titleItem[9].number = allJson.interactCount
+    }
+  }
+}
 </script>
 
 <style lang="less" scoped>
-	#left-top-box {
-		display: flex;
-		flex-direction: column;
-		justify-content: space-between;
-		height: 100%;
-		padding: 2%;
-		
+#left-top-box {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  height: 100%;
+  padding: 2%;
 
-		.up {
-			width: 100%;
-			height: 100%;
-			display: flex;
-			flex-wrap: wrap;
+  .up {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-wrap: wrap;
 
-			.item {
-				width: 18.2%;
-				border-radius: 6px;
-				padding: 8px;
-				margin: 0.3% 0.9% 1.3% 0.9%;
+    .item {
+      width: 14.8%;
+      border-radius: 6px;
+      padding: 8px;
+      margin: 0.3% 0.9% 1.3% 0.9%;
 
-				.count-num {
-					display: inline-block;
-					margin-top: 5px;
-					font-size: 28px;
-					font-weight: bold;
-				}
-			}
-		}
+      .count-num {
+        display: inline-block;
+        margin-top: 5px;
+        font-size: 28px;
+        font-weight: bold;
+      }
+    }
+  }
 
-		.down {
-			padding: 6px 4px;
-			padding-bottom: 0;
-			width: 100%;
-			display: flex;
-			height: 510px;
-			flex-wrap: wrap;
-			justify-content: space-between;
+  .down {
+    padding: 6px 4px;
+    padding-bottom: 0;
+    width: 100%;
+    display: flex;
+    height: 510px;
+    flex-wrap: wrap;
+    justify-content: space-between;
 
-			.bg-color-black {
-			}
+    .bg-color-black {
+    }
 
-			.ranking {
-				padding: 10px;
-				width: 59%;
+    .ranking {
+      padding: 10px;
+      width: 59%;
 
-				.dv-scr-rank-board {
-					height: 225px;
-				}
-			}
+      .dv-scr-rank-board {
+        height: 225px;
+      }
+    }
 
-			.percent {
-				width: 40%;
-				display: flex;
-				flex-wrap: wrap;
+    .percent {
+      width: 40%;
+      display: flex;
+      flex-wrap: wrap;
 
-				.item {
-					width: 50%;
-					height: 120px;
+      .item {
+        width: 50%;
+        height: 120px;
 
-					span {
-						margin-top: 8px;
-						font-size: 14px;
-						display: flex;
-						justify-content: center;
-					}
-				}
+        span {
+          margin-top: 8px;
+          font-size: 14px;
+          display: flex;
+          justify-content: center;
+        }
+      }
 
-				.water {
-					width: 100%;
+      .water {
+        width: 100%;
 
-					.dv-wa-le-po {
-						height: 120px;
-					}
-				}
-			}
-		}
-	}
+        .dv-wa-le-po {
+          height: 120px;
+        }
+      }
+    }
+  }
+}
 </style>

+ 49 - 53
TEAMModelOS/ClientApp/src/components/research-dashboard/RightBotR.vue

@@ -1,66 +1,62 @@
 <template>
-	<div id="TechBar">
-		<p class="dashboard-block-title">
-			<Icon type="md-podium" />
-			<span>{{ $t('lessonRecord.echarts.title4') }}</span>
-			<dv-decoration-3 class="dv-dec-3" />
-		</p>
-		<div class="bg-color-black">
-			<!-- <TechBar></TechBar> -->
-			<div style="width: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;margin-top: 50px;">
-				<img src="../../assets/image/none.png" width="200px">
-				<span>{{ $t('lessonRecord.echarts.noData') }}</span>
-			</div>
-		</div>
-	</div>
+  <div id="TechBar">
+    <p class="dashboard-block-title">
+      <Icon type="md-podium" />
+      <span>常用教学法统计</span>
+      <dv-decoration-3 class="dv-dec-3" />
+    </p>
+    <div class="bg-color-black">
+      <TechBar></TechBar>
+    </div>
+  </div>
 </template>
 
 <script>
-	import TechBar from '@/components/echart/techBar/index.vue'
-	export default {
-		components:{
-			TechBar
-		},
-		data() {
-			return {
-				
-			}
-		},
-		mounted() {},
-		methods: {}
-	}
+import TechBar from '@/components/research-dashboard/BaseTechBar'
+export default {
+  components: {
+    TechBar
+  },
+  data() {
+    return {
+      isTestSite: true
+    }
+  },
+  mounted() { },
+  methods: {}
+}
 </script>
 
 <style lang="less" scoped>
-	@box-height: 100%;
-	@box-width: 100%;
+@box-height: 100%;
+@box-width: 100%;
 
-	#TechBar {
-		padding: 16px;
-		padding-top: 20px;
-		height: @box-height;
-		width: @box-width;
-		display: flex;
-		flex-direction: column;
-		justify-content: space-between;
-		border-radius: 5px;
+#TechBar {
+  padding: 16px;
+  padding-top: 20px;
+  height: @box-height;
+  width: @box-width;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  border-radius: 5px;
 
-		.bg-color-black {
-			height: 94%;
-		}
+  .bg-color-black {
+    height: 94%;
+  }
 
-		.text {
-			color: #c3cbde;
-		}
+  .text {
+    color: #c3cbde;
+  }
 
-		.body-box {
-			border-radius: 10px;
-			overflow: hidden;
+  .body-box {
+    border-radius: 10px;
+    overflow: hidden;
 
-			.dv-scr-board {
-				width: 270px;
-				height: 340px;
-			}
-		}
-	}
+    .dv-scr-board {
+      width: 270px;
+      height: 340px;
+    }
+  }
+}
 </style>

+ 6 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/VoteResultChart.vue

@@ -86,3 +86,9 @@ export default {
     }
 };
 </script>
+
+<style scoped>
+#main {
+    height: 350px;
+}
+</style>

+ 11 - 11
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue

@@ -109,15 +109,15 @@
                             </div>
                             <div v-if="item.type === 'Exam' || item.type === 'Atr'" class="list-new-test">
                                 <div class="paper-item-school">
-                                    <span class="paper-owner" v-if="item.owner === 'school'" style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
-                                    <span class="paper-owner" v-else>{{ $t('studentWeb.public.private') }}</span>
-                                    <span class="paper-extType" :style="{'border-color': item.owner === 'school' ? '#88a1d8' :'#ababab'}" v-if="item.source === '0'">
+                                    <span class="paper-owner" v-if="item.owner === 'teacher'">{{ $t('studentWeb.public.private') }}</span>
+                                    <span class="paper-owner" v-else style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
+                                    <span class="paper-extType" :style="{'border-color': item.owner === 'teacher' ? '#ababab' : '#88a1d8'}" v-if="item.source === '0'">
                                         {{ $t("studentWeb.exam.source.evMode1") }}
                                     </span>
-                                    <span class="paper-source" :style="{'border-color': item.owner === 'school' ? '#88a1d8' :'#ababab', color: '#2f98a9'}" v-if="item.source === '1'">
+                                    <span class="paper-source" :style="{'border-color': item.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#2f98a9'}" v-if="item.source === '1'">
                                         {{ $t("studentWeb.exam.source.evMode2") }}
                                     </span>
-                                    <span class="paper-extType" :style="{'border-color': item.owner === 'school' ? '#88a1d8' :'#ababab', color: '#b68268'}" v-if="item.source === '2'">
+                                    <span class="paper-extType" :style="{'border-color': item.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#b68268'}" v-if="item.source === '2'">
                                         {{ $t("studentWeb.exam.source.evMode3") }}
                                     </span>
                                     <span class="paper-extType" style="border-color: #88a1d8; color: #9fa91d;" v-if="item.source === null">
@@ -126,29 +126,29 @@
                                     
                                     <!-- 课中评量才判断:qamode:0(书面问答),1(纸本测验) -->
                                     <template v-if="item.source === '1'">
-                                        <span class="paper-extType" :style="{'border-color': item.owner === 'school' ? '#88a1d8' :'#ababab', color: '#b68268'}"
+                                        <span class="paper-extType" :style="{'border-color': item.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#b68268'}"
                                             v-if="item.qamode"
                                         >
                                             {{ $t("studentWeb.exam.source.evMode21") }}
                                         </span>
-                                        <span class="paper-extType" :style="{'border-color': item.owner === 'school' ? '#88a1d8' :'#ababab', color: '#b68268'}"
+                                        <span class="paper-extType" :style="{'border-color': item.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#b68268'}"
                                             v-else
                                         >
                                             {{ $t("studentWeb.exam.source.evMode22") }}
                                         </span>
                                     </template>
                                     <span v-if="item.ext.type === 'regular'" class="paper-extType"
-                                        :style="{'border-color': item.owner === 'school' ? '#88a1d8' :'#ababab', color: '#dc8f57'}"
+                                        :style="{'border-color': item.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#dc8f57'}"
                                     >
                                         {{ $t('totalAnalysis.ti_text6') }}
                                     </span>
                                     <span v-if="item.ext.type === 'simulation'" class="paper-extType"
-                                        :style="{'border-color': item.owner === 'school' ? '#88a1d8' :'#ababab', color: '#76ae38'}"
+                                        :style="{'border-color': item.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#76ae38'}"
                                     >
                                         {{ $t('totalAnalysis.ti_text7') }}
                                     </span>
                                     <span v-if="item.ext.type === 'normal'" class="paper-extType"
-                                        :style="{'border-color': item.owner === 'school' ? '#88a1d8' :'#ababab', color: '#a69b17'}"
+                                        :style="{'border-color': item.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#a69b17'}"
                                     >
                                         {{ $t('totalAnalysis.ti_text8') }}
                                     </span>
@@ -163,7 +163,7 @@
                                 <!-- <p class="list-item-time isScore" v-show="timeStatus(item) == 'finish'">
                                     得分率:20%
                                 </p> -->
-                                <p v-if="item.owner === 'school'">
+                                <p v-if="item.owner != 'teacher'">
                                     <span v-if="item.ext">
                                         <span v-if="item.ext.subjects">
                                             <span v-for="(item, index) in item.ext.subjects" :key="index"

+ 208 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewMobile.less

@@ -0,0 +1,208 @@
+.home-view {
+    padding: 0.7rem 1rem;
+
+    .home-card {
+        margin-top: 15px;
+        box-shadow: 0px 2px 13px rgba(0, 0, 0, 0.1);
+        border: 1px solid rgba(0, 0, 0, 0.2);
+        border-radius: 5px;
+        background-color: #fff;
+        padding: 15px;
+
+        &:hover {
+            box-shadow: 0px 2px 30px rgba(0, 0, 0, 0.2);
+        }
+    }
+
+    .home-head {
+        margin-top: 0;
+        // height: 400px;
+        min-height: 400px;
+        overflow: hidden;
+        padding-bottom: 10px;
+        // display: flex;
+
+        .home-join {
+            height: calc(100% - 40px);
+            margin-bottom: 10px;
+        }
+
+        .join-class {
+            display: inline-block;
+            width: 18%;
+            border-radius: 10px;
+            border: 1px solid #f4f7f4;
+            padding: 10px;
+            margin: 5px 15px 10px;
+            cursor: pointer;
+            background-color: #f4f7f4;
+
+            .class-name {
+                // color: #02B35A;
+                font-size: 16px;
+                font-weight: bold;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+                margin-bottom: 10px;
+            }
+
+            .class-number-time {
+                display: flex;
+                justify-content: space-between;
+            }
+
+            .paper-item-school {
+                font-weight: bolder;
+                height: 20px;
+                line-height: 18px;
+                // padding: 5px 2px;
+                // margin-top: 10px;
+                // margin-right: 20px;
+                margin-bottom: 5px;
+                // cursor: pointer;
+                display: inline-flex;
+                font-size: 12px;
+
+                &>span {
+                    padding: 0 5px;
+                    white-space: pre;
+                }
+
+                .paper-owner {
+                    background-color: #ababab;
+                    color: #fff;
+                    border-radius: 5px 0 0 5px;
+                }
+
+                .paper-extType {
+                    border: 1px solid #ababab;
+                    border-radius: 0 5px 5px 0;
+                    border-left: none;
+                }
+
+                .paper-source {
+                    border: 1px solid #ababab;
+                    // border-radius: 0 5px 5px 0;
+                }
+            }
+
+            &:hover {
+                background: linear-gradient(-270deg, #fafafa, #d4ede1);
+                color: #03966a;
+            }
+        }
+        
+        .no-class {
+            font-size: 25px;
+            font-weight: bold;
+            text-align: center;
+            margin-top: 50px;
+            color: #64AE16;
+        }
+    }
+
+    .home-list-title {
+        font-size: 16px;
+        // margin-bottom: 15px;
+        display: flex;
+        justify-content: space-between;
+    }
+
+    .other-box {
+        // height: 455px;
+        min-height: 400px;
+    }
+
+    .no-data {
+        text-align: center;
+        min-height: 455px;
+        padding-top: 80px;
+
+        img {
+            width: 50%;
+        }
+    }
+
+    .no-data-notice {
+
+        text-align: center;
+        min-height: 212px;
+        // padding-top: 40px;
+
+        img {
+            width: 40%;
+        }
+    }
+
+    .list-new {
+        display: flex;
+        align-items: center;
+        border-bottom: 1px solid rgba(0, 0, 0, .1);
+        padding: 15px 10px;
+
+        .list-new-test {
+            display: flex;
+            justify-content: space-between;
+            flex-direction: column;
+        }
+
+        .list-new-img {
+            width: 50%;
+            margin-right: 5px;
+
+            &>img {
+                width: 100%;
+                min-width: 9.5rem;
+                min-height: 4.5rem;
+            }
+        }
+
+        .list-new-icon {
+            margin-right: 15px;
+        }
+    }
+
+    .demo-carousel {
+        margin-bottom: 20px;
+        text-align: center;
+
+        img {
+            width: 100%;
+        }
+    }
+
+    .home-menu {
+        position: absolute;
+        top: 13px;
+        z-index: 99;
+    }
+}
+
+@media screen and (max-width: 1280px) {
+    .home-view {
+        .home-list-title {
+            display: block;
+        }
+
+        .activity-box {
+            height: 305px;
+        }
+
+        .other-box {
+            // height: 330px;
+        }
+
+        .home-head .join-class {
+            width: 30%;
+        }
+    }
+}
+
+@media screen and (max-width: 574px) {
+    .home-view {
+        .home-head .join-class {
+            width: 90%;
+        }
+    }
+}

+ 436 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewMobile.vue

@@ -0,0 +1,436 @@
+<template>
+    <div class="home-view">
+        <div class="home-menu">
+            <Dropdown trigger="click" @on-click="menuVisible">
+                <a href="javascript:void(0)" class="sidebar-toggle">
+                    <Icon class="menu-icon" type="md-menu" color="#02b35a" />
+                </a>
+                <template #list>
+                    <DropdownMenu>
+                        <DropdownItem :name="item.name" v-for="item in menus" :key="item.name">{{ item.value }}</DropdownItem>
+                    </DropdownMenu>
+                </template>
+            </Dropdown>
+        </div>
+        <div style="overflow: hidden; height: 92vh;">
+            <vuescroll ref="datawrap">
+                <div class="home-head home-card" id="Card1">
+                    <p class="home-title-name">
+                        {{ $t("studentWeb.home.title.joinClass") }}
+                        <Icon type="md-add-circle" color="#02B35A" size="17" title="加入课程" @click="addCourse = true" />
+                    </p>
+                    <div class="home-join" v-if="getAllCourse.length">
+                        <vuescroll>
+                            <div class="join-class" v-for="(item, index) in getAllCourse" :key="index">
+                                <p class="class-name" :title="`${item.name} - ${item.listName}`">{{ item.name }} - {{ item.listName }}</p>
+                                <p class="class-number-time">
+                                    <!-- <span>{{ '班级人数' }}</span> -->
+                                    <span class="paper-item-school">
+                                        <span class="paper-owner" v-if="item.scope === 'school'" style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
+                                        <span class="paper-owner" v-else>{{ $t('studentWeb.public.private') }}</span>
+                                        <span class="paper-extType">
+                                            {{ item.teacherName }}
+                                        </span>
+                                    </span>
+                                    <span>{{ item.courseAddDate }}</span>
+                                </p>
+                            </div>
+                        </vuescroll>
+                    </div>
+                    <div class="no-class" v-else>
+                        <p>{{ $t("studentWeb.home.title.title1") }}</p>
+                        <p>{{ $t("studentWeb.home.title.title2") }}</p>
+                    </div>
+                </div>
+                <div class="home-card" id="Card2">
+                    <p class="home-title-name">{{ $t("studentWeb.home.title.classRecord") }}</p>
+                    <div v-if="classRecord.length" class="other-box">
+                        <vuescroll>
+                            <div v-for="(classRecord, cIndex) in classRecord" :key="cIndex" class="list-new">
+                                <!-- <div style="display: flex;"> -->
+                                    <div class="list-new-img">
+                                        <img :src="classRecord.CoverImage ? classRecord.CoverImage : './noData.png'" alt="">
+                                        <p class="list-item-time">{{ classRecord.startTime }}</p>
+                                    </div>
+                                    <div class="list-new-test">
+                                        <p>{{ classRecord.name }}</p>
+                                        <p class="list-item-time" style="color: #76ae38;">{{ classRecord.classNames }}</p>
+                                        <span>
+                                            <Icon type="md-time" color="#24B880" />
+                                            {{ classRecord.time }}
+                                        </span>
+                                    </div>
+                                <!-- </div> -->
+                            </div>
+                        </vuescroll>
+                    </div>
+                    <div v-else class="no-data">
+                        <img src="./noData.png" alt="">
+                        <p>{{ $t("studentWeb.public.noData") }}</p>
+                    </div>
+                </div>
+                <div class="home-card" id="Card3">
+                    <div class="home-list-title">
+                        <p class="home-title-name">{{ $t("studentWeb.home.title.notice1") }}</p>
+                        <div class="select-time">
+                            <Select v-model="timeSelect" size="small" style="width: 100px;">
+                                <Option value="all">{{ $t("studentWeb.home.timeType.title1") }}</Option>
+                                <Option value="today">{{ $t("studentWeb.home.timeType.title2") }}</Option>
+                            </Select>
+                        </div>
+                    </div>
+                    <div class="other-box">
+                        <vuescroll>
+                            <div v-if="!allNotice.length" class="no-data">
+                                <img src="./noData.png" alt="">
+                                <p>{{ $t("studentWeb.public.noData") }}</p>
+                            </div>
+                            <div v-else>
+                                <div v-for="(cNotice, nIndex) in allNotice" :key="nIndex" class="list-new" @click="getNoticeInfo(cNotice)">
+                                    <div class="list-new-icon">
+                                        <Icon custom="iconfont icon-notify" size="30" />
+                                    </div>
+                                    <div class="list-new-test">
+                                        <p class="list-item-title">
+                                            <span>{{ cNotice.title }}</span>
+                                        </p>
+                                        <p>
+                                            {{ cNotice.content }}
+                                        </p>
+                                        <p class="list-item-time">
+                                            {{ cNotice.start }} ~ {{ cNotice.end }}
+                                        </p>
+                                    </div>
+                                </div>
+                            </div>
+                        </vuescroll>
+                    </div>
+                </div>
+                <div class="home-card" id="Card4">
+                <p class="home-title-name">{{ $t("studentWeb.home.loginGuidance.tips1") }}</p>
+                <Carousel>
+                    <CarouselItem>
+                        <div class="demo-carousel">
+                            <img :src="require(`./login-${language}.png`)" alt="">
+                            <span>
+                                {{ $t("studentWeb.home.loginGuidance.tips2") }}
+                                {{ loginUrl }}
+                                {{ $t("studentWeb.home.loginGuidance.tips5") }}
+                            </span>
+                        </div>
+                    </CarouselItem>
+                    <CarouselItem>
+                        <div class="demo-carousel">
+                            <img :src="require(`./student-${language}.png`)" alt="">
+                            <span>{{ $t("studentWeb.home.loginGuidance.tips3") }}</span>
+                        </div>
+                    </CarouselItem>
+                    <CarouselItem>
+                        <div class="demo-carousel">
+                            <img :src="require(`./student-${language}.png`)" alt="">
+                            <span>{{ $t("studentWeb.home.loginGuidance.tips4") }}</span>
+                        </div>
+                    </CarouselItem>
+                </Carousel>
+                </div>
+            </vuescroll>
+        </div>
+    </div>
+</template>
+
+<script>
+import BlobTool from "@/utils/blobTool.js"
+import { mapGetters, mapState } from 'vuex'
+export default {
+    data () {
+        return {
+            MyNo: "11", //接收NavBar 選定的那一頁icon標示
+            MyName: "",
+            isLoading: false,
+            groups: {
+                school: [],
+                private: [],
+            },
+            classIds: [],
+            classRecord: [], //课堂记录
+            activityList: [], //活动
+            classNotice: [], //班级公告
+            courseNotice: [], //课程公告
+            allNotice: [],
+            timeSelect: "all",
+            menus: [{
+                    name: '1',
+                    value: this.$t("studentWeb.home.menus.title1")
+                }, {
+                    name: '2',
+                    value: this.$t("studentWeb.courseContent.classRecord")
+                }, {
+                    name: '3',
+                    value: this.$t("studentWeb.home.title.notice1")
+                }, {
+                    name: '4',
+                    value: this.$t("studentWeb.home.menus.title2")
+                }
+            ],
+        }
+    },
+    mounted () {
+        this.MyName = this.$t("studentWeb.homeViewTitle")
+        this.$emit("onNavNo", this.MyNo)
+        this.$emit("onNavName", this.MyName)
+        this.getGroupList()
+        console.log(window.location.host);
+    },
+    methods: {
+        getGroupList() {
+            // return new Promise(resolve => {
+                this.isLoading = true
+                this.groups = {
+                    school: [],
+                    private: [],
+                }
+                this.classRecord = []
+                // this.getSas(this.userInfo.azp)
+                this.$api.studentWeb.getAllGrouplist({}).then(res => {
+                    if(res.groups.length) {
+                        let groupIds = []
+                        this.classIds = [...res.groups]
+                        res.groups.forEach(item => {
+                            if(item.scope === 'school') {
+                                this.groups.school.push(item.id)
+                            } else if(item.scope === 'private') {
+                                this.groups.private.push(item.id)
+                            }
+                            groupIds.push(item.id)
+                        })
+                        this.getSchool("school", this.groups.school)
+                        this.getNotice(groupIds)
+                    }
+                }).finally(() => {
+                    // resolve(groups)
+                })
+            // })
+        },
+        getNotice(classes) {
+            this.classNotice = []
+            this.courseNotice = []
+            this.$api.studentWeb.getAllNotice({classes}).then(async res => {
+                // type:class(班级公告)  course(课程公告)
+                if(res.notices.length) {
+                    let teaIds = []
+                    res.notices.forEach(item => {
+                        teaIds.push(item.creatorId)
+                    })
+                    let teaidNames = await this.getTeacherName(teaIds)
+                    res.notices.forEach(item => {
+                        item.start = this.dateFormat(item.startTime)
+                        item.end = this.dateFormat(item.endTime)
+                        item.className = []
+                        item.classes.forEach(classes => {
+                            let names = this.classIds.find(ids => {
+                                return ids.id === classes
+                            })
+                            if(names) {
+                                item.className.push(names.name)
+                            }
+                        })
+                        let nameIds = teaidNames.find(names => {
+                            return names.id === item.creatorId
+                        })
+                        item.teacherName = !nameIds ? undefined : nameIds.name
+                        if(item.type === "class") {
+                            this.classNotice.push(item)
+                        } else {
+                            this.courseNotice.push(item)
+                        }
+                        this.allNotice = this.classNotice.concat(this.courseNotice)
+                    })
+                }
+            })
+        },
+        getSchool(type, groupIds, end) {
+            if(groupIds.length) {
+                let param = {
+                    scope: type, //school:传school,private:传tmdid
+                    school: type === "school" ? this.userInfo.azp : "",
+                    category: [],
+                    subjectId: [],
+                    grade: [],
+                    doubleGreen: false,
+                    quality: false,
+                    DESC: "startTime",
+                    pageCount: 999, //返回六条数据(分页)
+                    // week: true,
+                    today: false,
+                    continuationToken: null, //返回的有值的话,下次查询就要用这个值
+                    groupIds,
+                }
+                this.$api.studentWeb.getClassRecord(param).then(async res => {
+                    if(res.lessonRecords.length) {
+                        let creatId = []
+                        let sasInfo = undefined
+                        if(type === "school") {
+                            sasInfo = await this.getSas(this.userInfo.azp)
+                        }
+                        res.lessonRecords.forEach(item => {
+                            item.startTime = this.dateFormat(item.startTime)
+                            let sec = item.duration % 60
+                            let min = parseInt(item.duration / 60)
+                            let mins = min >= 60 ? min % 60 : min
+                            let hour = parseInt(min / 60)
+                            item.time = `${hour < 10 ? ('0' + hour) : hour}:${mins < 10 ? ('0' + mins) : mins}:${sec < 10 ? ('0' + sec) : sec}`
+                            if(type === "school") {
+                                item.eNote = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Note.pdf?${sasInfo.sas}`
+                                item.CoverImage = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Record/CoverImage.jpg?${sasInfo.sas}`
+                            } else {
+                                if(!creatId.includes(item.tmdid)) {
+                                    creatId.push(item.tmdid)
+                                }
+                                item.eNote = ""
+                                item.CoverImage = ""
+                            }
+                            let className = this.getAllCourse.find(course => {
+                                return item.courseId === course.id || item.courseId === course.subject.id
+                            })
+                            item.classNames = className ? className.name : ""
+                            item.myNote = []
+                            this.classRecord.push(item)
+                        })
+                        if(type === "private") {
+                            creatId.forEach(async item => {
+                                let sasInfoP = await this.getSas(item)
+                                this.classRecord = this.classRecord.map(record => {
+                                    if(record.scope === "private" && record.tmdid === item) {
+                                        record.eNote = `${sasInfoP.url}/${sasInfoP.name}/records/${record.id}/Note.pdf?${sasInfoP.sas}`
+                                        record.CoverImage = `${sasInfoP.url}/${sasInfoP.name}/records/${record.id}/Record/CoverImage.jpg?${sasInfoP.sas}`
+                                    }
+                                    return record
+                                })
+                                await this.getTrainFiles(sasInfoP, "private")
+                            })
+                        } else {
+                            this.getTrainFiles(sasInfo, "school")
+                        }
+                    }
+                    if(!end) {
+                        this.getSchool("private", this.groups.private, true)
+                    }
+                }).finally(() => {
+                    this.isLoading = false
+                })
+            } else if(!end) {
+                this.getSchool("private", this.groups.private, true)
+            }
+        },
+        // 查找活动的视频和文件
+        getTrainFiles(sasInfo, scope) {
+            return new Promise((r, j) => {
+                let blobTool = new BlobTool(sasInfo.url, sasInfo.name, "?" + sasInfo.sas, scope)
+                let promiseArr = []
+                let recList = [...this.classRecord]
+                if(scope === "school") {
+                    recList.forEach((item, index) => {
+                        promiseArr.push(new Promise((r, j) => {
+                            blobTool.listBlob({
+                                prefix: `records/${item.id}/Clients/${this.userInfo.sub}/Task/NoteSelfNote`
+                            }).then(
+                                res => {
+                                    let imgList = []
+                                    res.blobList.forEach(list => {
+                                        imgList.push(`${list.url}?${sasInfo.sas}`)
+                                    })
+                                    this.classRecord[index].myNote = imgList
+                                    r(res)
+                                },
+                                err => {
+
+                                }
+                            )
+                        }))
+                    })
+                } else {
+                    recList.forEach((item, index) => {
+                        if(item.scope === "private" && item.tmdid === sasInfo.name) {
+                            promiseArr.push(new Promise((r, j) => {
+                                blobTool.listBlob({
+                                    prefix: `records/${item.id}/Clients/${this.userInfo.sub}/Task/NoteSelfNote`
+                                }).then(
+                                    res => {
+                                        let imgList = []
+                                        res.blobList.forEach(list => {
+                                            imgList.push(`${list.url}?${sasInfo.sas}`)
+                                        })
+                                        this.classRecord[index].myNote = imgList
+                                        r(res)
+                                    },
+                                    err => {
+
+                                    }
+                                )
+                            }))
+                        }
+                    })
+                }
+                Promise.all(promiseArr).then(res => {
+                })
+            })
+        },
+        getTeacherName(id) {
+            return new Promise((r, j) => {
+                this.$api.studentWeb.getTeacherName({id}).then(res => {
+                    r(res)
+                }).catch(e => {
+                    j(e)
+                })
+            })
+        },
+        //时间格式化处理
+        dateFormat(timestamp) {
+            var date = new Date(timestamp)
+            var Y = date.getFullYear() + '-'
+            var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'
+            var D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' '
+            var H = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ":"
+            var Min = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())
+            var S = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()) + " "
+            return Y + M + D + H + Min;
+        },
+        getSas(info) {
+            return new Promise(async (r, j) => {
+                let code = info
+                let sasInfo = await this.$tools.getBlobSas(code)
+                r(sasInfo)
+            })
+        },
+        menuVisible(value) {
+            // document.getElementById(`Card${value}`).scrollIntoView({behavior: "smooth", inline: "nearest"})
+            
+            this.$refs["datawrap"].scrollIntoView('#Card' + value, 0)
+        },
+    },
+    computed: {
+        ...mapGetters(['getAllCourse']),
+        ...mapState({userInfo: state => state.userInfo,}),
+        language() {
+            return localStorage.getItem('local')
+        },
+        loginUrl() {
+            return window.location.host
+        },
+    }
+}
+</script>
+
+<style lang="less" scoped>
+@import './HomeViewMobile.less';
+.home-view {
+    .home-title-name {
+        font-size: 16px;
+        border-left: 5px solid #24b880;
+        padding-left: 10px;
+        height: 20px;
+        line-height: 20px;
+        margin-bottom: 10px;
+    }
+}
+</style>

BIN
TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-en-us.png


BIN
TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-zh-cn.png


BIN
TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-zh-tw.png


+ 7 - 7
TEAMModelOS/ClientApp/src/components/student-web/HomeView/newHomeView.vue

@@ -92,16 +92,16 @@
                                 </div>
                                 <div class="list-new-test">
                                     <div class="paper-item-school">
-                                        <span class="paper-owner" v-if="activity.owner === 'school'" style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
-                                        <span class="paper-owner" v-else>{{ $t('studentWeb.public.private') }}</span>
+                                        <span class="paper-owner" v-if="activity.owner === 'teacher'">{{ $t('studentWeb.public.private') }}</span>
+                                        <span class="paper-owner" v-else style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
                                         <template v-if="activity.type == 'Exam' || activity.type == 'Atr'">
-                                            <span class="paper-extType" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab'}" v-if="activity.source === '0'">
+                                            <span class="paper-extType" :style="{'border-color': activity.owner === 'teacher' ? '#ababab' : '#88a1d8'}" v-if="activity.source === '0'">
                                                 {{ $t("studentWeb.exam.source.evMode1") }}
                                             </span>
-                                            <span class="paper-source" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab', color: '#2f98a9'}" v-if="activity.source === '1'">
+                                            <span class="paper-source" :style="{'border-color': activity.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#2f98a9'}" v-if="activity.source === '1'">
                                                 {{ $t("studentWeb.exam.source.evMode2") }}
                                             </span>
-                                            <span class="paper-extType" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab', color: '#b68268'}" v-if="activity.source === '2'">
+                                            <span class="paper-extType" :style="{'border-color': activity.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#b68268'}" v-if="activity.source === '2'">
                                                 {{ $t("studentWeb.exam.source.evMode3") }}
                                             </span>
                                             <span class="paper-extType" style="border-color: #88a1d8; color: #9fa91d;" v-if="activity.source === null">
@@ -109,12 +109,12 @@
                                             </span>
                                             <!-- 课中评量才判断:qamode:0(书面问答),1(纸本测验) -->
                                             <template v-if="activity.source === '1'">
-                                                <span class="paper-extType" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab', color: '#b68268'}"
+                                                <span class="paper-extType" :style="{'border-color': activity.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#b68268'}"
                                                     v-if="activity.qamode"
                                                 >
                                                     {{ $t("studentWeb.exam.source.evMode21") }}
                                                 </span>
-                                                <span class="paper-extType" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab', color: '#b68268'}"
+                                                <span class="paper-extType" :style="{'border-color': activity.owner === 'teacher' ? '#ababab' : '#88a1d8', color: '#b68268'}"
                                                     v-else
                                                 >
                                                     {{ $t("studentWeb.exam.source.evMode22") }}

BIN
TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-en-us.png


BIN
TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-zh-cn.png


BIN
TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-zh-tw.png


+ 48 - 28
TEAMModelOS/ClientApp/src/router/routes.js

@@ -110,6 +110,11 @@ export const routes = [{
     path: '/sso',
     component: () => import('@/view/sso/Index.vue')
 },
+//单点登录-学生端
+{
+    path: '/student',
+    component: () => import('@/view/sso/StudentIndex.vue')
+},
 {
     path: '/schoolList',
     component: () => import('@/view/Home'),
@@ -1071,24 +1076,6 @@ export const routes = [{
             activeName: 'discuss'
         }
     },
-    //投票
-    /* {
-        path: 'privateVote',
-        name: 'privateVote',
-        component: () => import('@/view/jyzx/Vote.vue'),
-        meta: {
-            activeName: 'privateVote'
-        }
-    },
-    //问卷
-    {
-        path: 'privateQuestionnaire',
-        name: 'privateQuestionnaire',
-        component: () => import('@/view/jyzx/Question.vue'),
-        meta: {
-            activeName: 'privateQuestionnaire'
-        }
-    }, */
     //学校数据看板
     {
         path: 'Dashboard',
@@ -1108,15 +1095,15 @@ export const routes = [{
             middleware: ['login', 'ability:admin,dashboard-read'],
         }
     },
-    {
-        name: 'artDashboard',
-        path: '/artDashboard',
-        component: () => import('@/view/dashboard/Art.vue'),
-        meta: {
-            activeName: 'Dashboard',
-            middleware: ['login', 'ability:admin,dashboard-read'],
-        }
-    },
+    // {
+    //     name: 'artDashboard',
+    //     path: '/artDashboard',
+    //     component: () => import('@/view/dashboard/Art.vue'),
+    //     meta: {
+    //         activeName: 'Dashboard',
+    //         middleware: ['login', 'ability:admin,dashboard-read'],
+    //     }
+    // },
     {
         name: 'moralDashboard',
         path: '/moralDashboard',
@@ -1138,7 +1125,26 @@ export const routes = [{
     {
         name: 'stuDashboard',
         path: '/stuDashboard',
-        component: () => import('@/view/dashboard/StudentAll.vue'),
+        // component: () => import('@/view/dashboard/StudentAll.vue'),
+        component: () => import('@/view/dashboard/fiveEdu/FiveEdu.vue'),
+        meta: {
+            activeName: 'Dashboard',
+            middleware: ['login', 'ability:admin,dashboard-read'],
+        }
+    },
+    {
+        name: 'artDashboard',
+        path: '/artDashboard',
+        component: () => import('@/view/dashboard/Art.vue'),
+        meta: {
+            activeName: 'Dashboard',
+            middleware: ['login', 'ability:admin,dashboard-read'],
+        }
+    },
+    {
+        name: 'fiveEdu',
+        path: '/fiveEdu',
+        component: () => import('@/view/dashboard/fiveEdu/FiveEdu.vue'),
         meta: {
             activeName: 'Dashboard',
             middleware: ['login', 'ability:admin,dashboard-read'],
@@ -1361,6 +1367,11 @@ export const routes = [{
             path: "homeView",
             component: () => import('@/components/student-web/HomeView/newHomeView'),
         },
+        {
+            name: "HomeViewMobile",
+            path: "homeViewMobile",
+            component: () => import('@/components/student-web/HomeView/HomeViewMobile'),
+        },
         {
             name: "courseList",
             path: "courseList",
@@ -1499,6 +1510,15 @@ export const routes = [{
             },
             children: []
         },
+        // {
+        //     name: 'artDashboard',
+        //     path: '/artDashboard',
+        //     component: () => import('@/view/dashboard/Art.vue'),
+        //     meta: {
+        //         activeName: 'Dashboard',
+        //         middleware: ['login', 'ability:admin,dashboard-read'],
+        //     }
+        // },
         {
             path: 'areaArtSetting',
             name: 'areaArtSetting',

+ 33 - 8
TEAMModelOS/ClientApp/src/view/areaArtExam/DataView.vue

@@ -48,16 +48,16 @@
             </div>
         </div>
         <div class="table-header-wrap">
-            <Select v-model="schoolId" style="width: 200px;margin-right:10px" placeholder="学校">
+            <Select v-model="value" style="width: 200px;margin-right:10px" placeholder="学校" @on-change="onSchoolChange">
                 <Option v-for="item in schoolList" :value="item.id" :key="item.id">{{ item.name }}</Option>
             </Select>
-            <Select v-model="classId" style="width: 200px">
+            <Select v-model="classId" style="width: 200px" placeholder="班级">
                 <Option v-for="item in classList" :value="item.id" :key="item.id">{{ item.name }}</Option>
             </Select>
             <Input search v-model="keyword" placeholder="搜索学生..." style="margin-left:10px;width: 200px" @on-search="searchStudent" />
         </div>
         <div class="table-scroll-wrap">
-            <vuescroll>
+            <vuescroll v-if="artInfo.classes && artInfo.classes.length">
                 <Table :columns="columns" :data="tableDataShow" border>
                     <template slot-scope="{ row }" v-for="s in slotList" :slot="s">
                         <div :key="s" style="padding:5px 5px">
@@ -75,9 +75,10 @@
                     </template>
                 </Table>
             </vuescroll>
+            <TipsInfo v-else msg="学校尚未选择参与班级"></TipsInfo>
         </div>
         <!-- 分页 -->
-        <div class="page-wrap">
+        <div class="page-wrap" v-if="artInfo.classes && artInfo.classes.length">
             <Page show-total size="small" :current="currentPage" :total="tableData.length" :page-size="pageSize" @on-change="pageChange" />
         </div>
     </div>
@@ -107,7 +108,21 @@ export default {
             default: () => {
                 return []
             }
-        }
+        },
+        schoolList: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        },
+        value: {
+            type: String,
+            default: ''
+        },
+    },
+    model: {
+        prop: "value", //绑定的值,通过父组件传递
+        event: "on-school-change", //自定义时间名    
     },
     computed: {
         curClass() {
@@ -159,8 +174,7 @@ export default {
     },
     data() {
         return {
-            schoolList:[],
-            schoolId:'',
+            // schoolId:'',
             keyword: '',
             pageSize: 10,
             currentPage: 1,
@@ -172,6 +186,9 @@ export default {
         }
     },
     methods: {
+        onSchoolChange(){
+            this.$emit('on-school-change',this.value)
+        },
         searchStudent() {
             this.tableData = this.oringinData.filter(item => item.name.includes(this.keyword))
             this.pageChange(1)
@@ -248,7 +265,15 @@ export default {
                     this.classId = ''
                 }
             }
-        }
+        },
+        // schoolList:{
+        //     immediate:true,
+        //     handler(n,o){
+        //         if(n && n.length && !this.schoolId){
+        //             this.schoolId = n[0].id
+        //         }
+        //     }
+        // }
     }
 }
 </script>

+ 75 - 39
TEAMModelOS/ClientApp/src/view/areaArtExam/Mgt.vue

@@ -34,27 +34,26 @@
                         评价指标
                     </span>
                 </div>
-                <DataView :artInfo="artInfo" :quotaFirstLevel="quotaFirstLevel" :classList="classList" v-if="curBarIndex === 0"></DataView>
+                <DataView v-model="schoolId" @on-school-change="handleSchoolChange(1)" :artInfo="artInfo" :quotaFirstLevel="quotaFirstLevel" :classList="classList" v-if="curBarIndex === 0" :schoolList="schoolListShow"></DataView>
                 <div v-else-if="curBarIndex === 1" class="quo-detail-wrap">
                     <vuescroll style="background:white">
                         <Tabs v-model="tabName" style="padding: 0px 10px;margin-top:15px">
                             <template slot="extra">
                                 <div class="art-filter-wrap">
-                                    <!-- <span>{{$t('ae.ae6')}}:</span> -->
-                                    <Select v-model="schoolId" style="width: 200px" placeholder="学校">
-                                        <Option v-for="item in schoolList" :value="item.id" :key="item.id">{{ item.name }}</Option>
+                                    <Select v-model="schoolId" style="width: 200px;margin-right:10px" placeholder="学校" transfer @on-change="handleSchoolChange(2)">
+                                        <Option v-for="item in schoolListShow" :value="item.id" :key="item.id">{{ item.name }}</Option>
                                     </Select>
-                                    <Select v-model="classId" style="width: 200px" placeholder="班级">
+                                    <Select v-model="classId" style="width: 200px;margin-right:10px" placeholder="班级">
                                         <Option v-for="item in classList" :value="item.id" :key="item.id">{{ item.name }}</Option>
                                     </Select>
-                                    <!-- <span style="margin-left:10px">{{$t('ae.ae4')}}:</span> -->
                                     <Select v-model="subjectId" style="width: 120px" placeholder="学科">
                                         <Option v-for="item in subjectList" :value="item.id" :key="item.id">{{ item.name }}</Option>
                                     </Select>
                                 </div>
                             </template>
                             <TabPane v-for="(item, index) in tabListShow" :key="index" :label="item.label" :name="item.name">
-                                <AcQuos :artInfo="artInfo" :treeData="tabTree[item.name]" :curClass="curClass" :subjectId="subjectId"></AcQuos>
+                                <AcQuos v-if="artInfo.classes && artInfo.classes.length" :artInfo="artInfo" :treeData="tabTree[item.name]" :curClass="curClass" :subjectId="subjectId"></AcQuos>
+                                <TipsInfo v-else msg="学校尚未选择参与班级"></TipsInfo>
                             </TabPane>
                         </Tabs>
                     </vuescroll>
@@ -73,8 +72,9 @@ export default {
     },
     data() {
         return {
-            schoolId:'',
-            schoolList:[],
+            hasPublish: true,
+            schoolId: '',
+            schoolList: [],
             tabName: '',
             split: 0.2,
             artList: [],
@@ -87,7 +87,7 @@ export default {
             classId: '',
             subjectId: '',
             curBarIndex: 0,
-            tabTree: {}
+            tabTree: {},
         }
     },
     computed: {
@@ -120,9 +120,35 @@ export default {
         },
         subjectList() {
             return this.artInfo?.subjects || []
+        },
+        schoolListShow() {
+            if (this.artList[this.curIndex] && this.artList[this.curIndex].sc && this.schoolList.length) {
+                let data = this.schoolList.filter(item => {
+                    let has = this.artList[this.curIndex].sc?.find(s => item.id === s.code)
+                    return !!has
+                })
+                return data
+            }
+            return this.schoolList
         }
     },
     methods: {
+        handleSchoolChange(value) {
+            console.log(value)
+            this.findArtSummary()
+        },
+        getAreaSchoolList() {
+            this.$api.areaArt.findAreaSchoolList({
+                id: sessionStorage.getItem('areaId')
+            }).then(
+                res => {
+                    this.schoolList = res.sc
+                },
+                err => {
+                    this.$Message.error("获取学校列表失败")
+                }
+            )
+        },
         selectBar(tab) {
             this.curBarIndex = tab
         },
@@ -153,9 +179,9 @@ export default {
                 onOk: () => {
                     let requestData = {
                         id: this.artList[this.curIndex].id,
-                        code: this.$store.state.userInfo.schoolCode
+                        areaId: sessionStorage.getItem('areaId')
                     }
-                    this.$api.areaArt.delArt(requestData).then(
+                    this.$api.areaArt.delAreaArt(requestData).then(
                         res => {
                             this.$Message.success(this.$t('ae.ae33'))
                             let index = this.curIndex
@@ -174,9 +200,9 @@ export default {
             this.classId = ''
             this.subjectId = ''
             this.curIndex = index
-            setTimeout(() => {
-                this.findArtSummary()
-            })
+            //TODO过滤学校
+            this.schoolId = this.schoolListShow[0] ? this.schoolListShow[0].id : ''
+            this.findArtSummary()
         },
         toCreate() {
             this.$router.push({
@@ -191,33 +217,40 @@ export default {
             this.$api.areaArt.findAreaArtList(params).then(
                 (res) => {
                     this.artList = res.arts
-                    if (this.artList.length) this.findArtSummary()
+                    if (this.artList.length) this.selectArt(0)
                 },
                 (err) => { }
             )
         },
         findArtSummary() {
-            // this.classList = []
-            // let params = {
-            //     id: this.artList[this.curIndex].id,
-            //     code: this.$store.state.userInfo.schoolCode
-            // }
-            // this.$api.areaArt.findArtSummary(params).then(
-            //     (res) => {
-            //         this.artInfo = res.art
-            //         this.tabListShow = this.tabList.filter(item => {
-            //             return !!this.artInfo.settings.find(s => s.id.includes(item.name))
-            //         })
-            //         if (this.tabListShow.length) {
-            //             this.tabName = this.tabListShow[0].name
-            //         }
-            //         this.handleTabTree()
-            //         if (this.artInfo?.classes) {
-            //             this.getClassList()
-            //         }
-            //     },
-            //     (err) => { }
-            // )
+            if (!this.schoolId) return
+            let sArt = this.artList[this.curIndex].sc?.find(item => item.code === this.schoolId)
+            if (!sArt) return
+            let sId = sArt.id
+            this.classList = []
+            let params = {
+                id: sId,
+                code: this.schoolId
+            }
+            this.$api.areaArt.findArtSummary(params).then(
+                (res) => {
+                    this.artInfo = res.art
+                    this.tabListShow = this.tabList.filter(item => {
+                        return !!this.artInfo.settings.find(s => s.id.includes(item.name))
+                    })
+                    if (this.tabListShow.length) {
+                        this.tabName = this.tabListShow[0].name
+                    }
+                    this.handleTabTree()
+                    this.classes = []
+                    if (this.artInfo?.classes?.length) {
+                        this.getClassList()
+                    } else {
+                        this.hasPublish = false
+                    }
+                },
+                (err) => { }
+            )
         },
         curSettings(tabName) {
             if (tabName && this.artInfo?.settings) {
@@ -257,7 +290,7 @@ export default {
         getClassList() {
             let req = {
                 ids: this.artInfo.classes,
-                schoolId: this.$store.state.userInfo.schoolCode
+                schoolId: this.schoolId
             }
             this.$api.common.getGroupListByIds(req).then(
                 res => {
@@ -270,6 +303,7 @@ export default {
         },
     },
     created() {
+        this.getAreaSchoolList()
         this.getAreaSetting()
     },
     watch: {
@@ -279,6 +313,8 @@ export default {
             handler(n, o) {
                 if (n && n.length) {
                     this.classId = n[0].id
+                } else {
+                    this.classId = ''
                 }
             }
         },
@@ -297,7 +333,7 @@ export default {
 </script>
 
 <style lang="less" scoped>
-.art-exam-list-wrap{
+.art-exam-list-wrap {
     height: 100%;
 }
 .quo-detail-wrap {

+ 3 - 3
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaLayout.vue

@@ -417,7 +417,7 @@ export default {
               menuName: 'areaArtMgt',
             }
           ],
-          isShow: this.isShowStudentMenu && this.isShowArtMenu
+          isShow: this.isShowArtMenu
         },
         {
           icon: 'iconfont icon-sports',
@@ -461,9 +461,9 @@ export default {
       return res
     },
     isShowArtMenu() {
-      let schoolProfile = JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8"))
+      let schoolProfile = JSON.parse(decodeURIComponent(localStorage.school_profile || '{}', "utf-8"))
       let areaArt = schoolProfile.areaShows?.find(item => item.code == this.areaId && item.status === 1)
-      return !!areaArt
+      return (!!areaArt && !this.$jsFn.checkJinNiu() && !this.$jsFn.checkTrain() && this.srvAdr == 'China') || this.$store.state.config.srvAdrType === 'test'
     },
     rotateIcon() {
       return ["collapse-icon", this.isCollapsed ? "rotate-icon" : ""]

+ 146 - 38
TEAMModelOS/ClientApp/src/view/art/AreaArt.vue

@@ -1,6 +1,8 @@
 <template>
     <div class="area-data-container">
-        <vuescroll ref="art-dasboard">
+        <EmptyData v-if="emptyData"></EmptyData>
+        <vuescroll v-else ref="art-dasboard">
+            <Loading v-show="isLoading"></Loading>
             <back-to-top @on-to-top="backToTop"></back-to-top>
             <div class="tab-box" style="padding:0px 20px 5px 20px;">
                 <span class="pane" style="line-height:30px;padding:2px;margin-right:30px" @click="tabClick('primary')" :class="{ active: periodId === 'primary' }">
@@ -84,20 +86,6 @@
                     </div>
                 </div>
             </div>
-            <!-- 课程被挤占情况 -->
-            <div class="online-train-wrap">
-                <h4 class="block-title">课程被挤占情况(音乐)</h4>
-                <div class="chart-data-wrap">
-                    <OccupyCourse :schools="musicOcc"></OccupyCourse>
-                </div>
-            </div>
-            <!-- 课程被挤占情况 -->
-            <div class="online-train-wrap">
-                <h4 class="block-title">课程被挤占情况(美术)</h4>
-                <div class="chart-data-wrap">
-                    <OccupyCourse :schools="drawOcc"></OccupyCourse>
-                </div>
-            </div>
             <!-- 学校列表 -->
             <div class="online-train-wrap">
                 <div style="height:30px">
@@ -109,10 +97,10 @@
                         <img class="school-img" :src="item.picture || defImg">
                         <div style="margin-left:10px;height:fit-content;">
                             <p class="school-name" :title="item.name">{{item.name}}</p>
-                            <p class="school-value">
+                            <!-- <p class="school-value">
                                 <span>学生人数:</span>
                                 <span>{{item.stuNum}}人</span>
-                            </p>
+                            </p> -->
                             <p class="school-value">
                                 <span>音乐及格率:</span>
                                 <span>{{item.musicPass || 0}}%</span>
@@ -148,10 +136,13 @@ export default {
     },
     data() {
         return {
+            emptyData: false,
+            isLoading: false,
             keyword: '',
             primaryData: {},
             middleData: {},
             periodId: 'primary',
+            allData: {}
         }
     },
     computed: {
@@ -162,35 +153,52 @@ export default {
                 return this.middleData
             }
         },
+        curPeriodData() {
+            let data = {}
+            if (this.periodId == 'primary') {
+                data.periodInfo = this.allData.pSchool || {}
+                data.overall = this.allData.psubject || []
+                data.knData = this.allData.allBlock?.find(item => item.school == '小学') || {}
+                data.examData = this.allData.pschoolScore || []
+                data.awardData = this.allData.opt?.find(item => item.per == '小学') || {}
+            } else {
+                data.periodInfo = this.allData.hSchool || {}
+                data.overall = this.allData.hsubject || []
+                data.knData = this.allData.allBlock?.find(item => item.school == '初中') || {}
+                data.examData = this.allData.hschoolScore || []
+                data.awardData = this.allData.opt?.find(item => item.per == '初中') || {}
+            }
+            return data
+        },
         // 头部统计数据
         topData() {
-            let { schoolNum, classNum, studentNum, subjectNum } = this.curData.periodInfo
+            let { scCount, classCount, stuCount, subjectCount } = this.curPeriodData.periodInfo
             let topData = [
                 {
                     icon: 'ios-people',
                     color: '#2d8cf0',
-                    number: schoolNum,
+                    number: scCount || 0,
                     text: '学校数量',
                     type: 'num'
                 },
                 {
                     icon: 'md-cube',
                     color: '#2db7f5',
-                    number: classNum,
+                    number: classCount || 0,
                     text: '班级数量',
                     type: 'num'
                 },
                 {
                     icon: 'md-thumbs-up',
                     color: '#ff9900',
-                    number: subjectNum,
+                    number: subjectCount || 0,
                     text: '学科数',
                     type: 'num'
                 },
                 {
                     icon: 'md-bookmark',
                     color: '#5cadff',
-                    number: studentNum,
+                    number: stuCount || 0,
                     text: '学生人数',
                     type: 'num'
                 },
@@ -206,23 +214,35 @@ export default {
         },
         //总览数据
         overallData() {
-            return this.curData.overall
+            return this.curPeriodData.overall
         },
         // 音乐知识点数据
         musicKn() {
-            return this.curData.musicKn
+            let musicKn = this.curPeriodData.knData.sub?.find(item => item.key === 'subject_music')
+            let formatData = []
+            if (musicKn && musicKn.sl) {
+                formatData = this.formatKnData(musicKn)
+            }
+            return formatData
         },
         //美术知识点数据
         drawKn() {
-            return this.curData.drawKn
+            let drawKn = this.curPeriodData.knData.sub?.find(item => item.key === 'subject_painting')
+            let formatData = []
+            if (drawKn && drawKn.sl) {
+                formatData = this.formatKnData(drawKn)
+            }
+            return formatData
         },
         //音乐评测数据
         musicExam() {
-            return this.curData.musicExam
+            let examData = this.curPeriodData.examData
+            return this.formatExamData(examData, 'subject_music')
         },
         //音乐评测数据
         drawExam() {
-            return this.curData.drawExam
+            let examData = this.curPeriodData.examData
+            return this.formatExamData(examData, 'subject_painting')
         },
         //课程被挤占情况
         musicOcc() {
@@ -233,18 +253,30 @@ export default {
         },
         // 获奖情况
         musicAward() {
-            return this.curData.musicAward
+            let awardData = this.curPeriodData.awardData
+            if (awardData && awardData.subject?.length) {
+                return this.formatAwardData(awardData, 'subject_music')
+            }
+            return []
         },
         drawAward() {
-            return this.curData.drawAward
+            let awardData = this.curPeriodData.awardData
+            if (awardData && awardData.subject?.length) {
+                return this.formatAwardData(awardData, 'subject_painting')
+            }
+            return []
         },
         schoolList() {
-            let data = this.curData.musicExam.map((item, index) => {
+            let data = this.curPeriodData.examData.map((item, index) => {
+                let music = item.scores.find(s => s.subjectId == 'subject_music')
+                let musicPass = music ? music.pass : 0
+                let draw = item.scores.find(s => s.subjectId == 'subject_painting')
+                let drawPass = draw ? draw.pass : 0
                 return {
                     name: item.name,
-                    stuNum: item.stuNum,
-                    musicPass: item.passRate,
-                    drawPass: this.curData.drawExam[index].passRate
+                    code: item.code,
+                    musicPass: musicPass,
+                    drawPass: drawPass
                 }
             })
             return data
@@ -261,16 +293,92 @@ export default {
         this.defImg = require('@/assets/image/def-school-img.png')
         this.primaryData = require('./data/primary.json')
         this.middleData = require('./data/middle.json')
+        this.getAreaArtAnalysis()
     },
     methods: {
-        toSchoolDetail(school) {
-            this.$router.push({
-                name: 'schoolArt',
-                params: {
-                    schoolInfo: school
+        formatAwardData(awardData, subject) {
+            let subjectData = awardData.subject.find(item => item.sub === subject)
+            if (subjectData && subjectData.key) {
+                let res = {}
+                let data = []
+                subjectData.key.forEach(school => {
+                    for (const level in school) {
+                        if (res[level]) {
+                            res[level] += school[level]
+                        } else {
+                            res[level] = school[level]
+                        }
+                    }
+                })
+                for (const key in res) {
+                    data.push({
+                        "name": key,
+                        "value": res[key]
+                    })
+                }
+                return data
+            }
+            return []
+        },
+        formatExamData(examData, subject) {
+            if (examData && examData.length) {
+                let data = examData.map(school => {
+                    let item = {
+                        name: school.name
+                    }
+                    let resource = school.scores.find(i => i.subjectId === subject) || {}
+                    console.log('333', resource)
+                    return Object.assign(item, resource)
+                })
+                console.log(2222, data)
+                return data
+            }
+            return []
+        },
+        formatKnData(data) {
+            return data.sl.map(item => {
+                let level2 = item.kno?.length ? item.kno[0] : ''
+                let level1 = ''
+                if (level2) {
+                    let d = data.blk.find(dim => dim.name === level2)
+                    level1 = d?.dim.length ? d.dim[0] : ''
                 }
+                return {
+                    "name": item.key,
+                    "level1": level1,
+                    "level2": level2,
+                    "val": item.scores
+                }
+            })
+        },
+        //获取区级艺术统计数据
+        getAreaArtAnalysis() {
+            this.isLoading = true
+            this.$api.areaArt.areaArtAna({
+                id: sessionStorage.getItem('areaId')
+            }).then(
+                res => {
+                    if (res?.code === 400) {
+                        this.emptyData = true
+                    } else {
+                        this.allData = res
+                    }
+                }
+            ).finally(() => {
+                this.isLoading = false
             })
         },
+        toSchoolDetail(school) {
+            let artInfo = this.curPeriodData.examData?.find(item => item.code == school.code)
+            if (artInfo) {
+                this.$router.push({
+                    name: 'schoolArt',
+                    params: {
+                        artInfo
+                    }
+                })
+            }
+        },
         backToTop() {
             this.$refs['art-dasboard'].scrollTo(
                 {

+ 22 - 7
TEAMModelOS/ClientApp/src/view/art/SchoolArt.less

@@ -1,4 +1,4 @@
-@mainColor: #568aea;
+@mainColor: #284c8e;
 
 #artIndex {
   color: #d3d6dd;
@@ -8,7 +8,9 @@
   // transform-origin: left top;
   overflow: hidden;
   position: relative;
-
+  font-family: "微軟正黑體",
+    "Microsoft JhengHei UI",
+    "Microsoft JhengHei";
 
 
   .tools {
@@ -22,10 +24,11 @@
     cursor: pointer;
 
     .time-text {
-      font-size: 20px;
+      font-size: 30px;
       margin-right: 20px;
-      font-weight: 600;
+      font-weight: 200;
       color: #9f9f9f;
+      font-family: 'staticFont';
     }
   }
 
@@ -35,14 +38,25 @@
     color: @mainColor  !important;
   }
 
+  .dashboard-select-subject {
+    .ivu-select-selection {
+      width: 140px !important;
+    }
+  }
+
+  .ivu-select-selected-value {
+    font-size: 14px !important;
+  }
+
   .ivu-select-selection,
   .ivu-input {
     background-color: #021f554a !important;
-    width: 130px;
+    width: 200px;
     border-color: @mainColor;
     border-radius: 5px;
     height: 30px;
     margin-right: 10px;
+    font-size: 14px;
   }
 
   .ivu-input {
@@ -81,6 +95,7 @@
 
   .ivu-select-item {
     color: #fff;
+    font-size: 16px;
 
     &:hover {
       background-color: #01928bd6;
@@ -289,12 +304,12 @@
 
         &-top {
           width: 100%;
-          height: 30%;
+          height: 40%;
         }
 
         &-bottom {
           width: 100%;
-          height: 65%;
+          height: 55%;
           display: flex;
 
           .right-bottom-single {

+ 170 - 39
TEAMModelOS/ClientApp/src/view/art/SchoolArt.vue

@@ -3,18 +3,29 @@
     <div class="bg">
       <dv-loading v-if="loading">{{ $t('researchCenter.dashboard.loading') }}</dv-loading>
       <div v-else class="host-body">
+        <!-- 实时北京时间 -->
         <div class="tools">
           <span class="time-text">{{ dateYear }} <span style="display: inline-block; margin: 0 5px;color: #0fa2fe;">{{ dateDay }}</span> </span>
           <span class="icon iconfont icon-tuichuquanping" style="font-size: 22px;" :title="$t('researchCenter.dashboard.quit')" @click="goBack"></span>
         </div>
+        <!-- 学校基础信息 及 活动、科目选择 -->
         <div class="school-info">
           <img :src="schoolInfo.schoolLogo">
           <span class="school-info-name">{{ schoolInfo.schoolName }}</span>
           <span class="school-info-period">{{ schoolInfo.periodName }}</span>
-          <span class="school-info-semester">{{ schoolInfo.curSemester }}</span>
-          <span :class="['dashboard-menu',activeMenu === 'music' ? 'dashboard-menu-active' : '']" @click="onChangeSubject('music')">音乐</span>
-          <span :class="['dashboard-menu',activeMenu === 'paint' ? 'dashboard-menu-active' : '']" @click="onChangeSubject('paint')">美术</span>
+          <span class="school-info-semester" v-if="!$route.params.artInfo">{{ schoolInfo.curSemester }}</span>
+          <div style="margin-left: 15px">
+            <Select v-model="activeAcIndex" @on-change="onAcChange">
+              <Option v-for="(item,index) in acList" :value="index">{{ item.name }}</Option>
+            </Select>
+          </div>
+          <div class="dashboard-select-subject">
+            <Select v-model="curSubjectIndex" @on-change="onSubjectChange">
+              <Option v-for="(item,index) in subjectList" :value="index">{{ item.name }}</Option>
+            </Select>
+          </div>
         </div>
+        <!-- 头部标题 -->
         <div class="d-flex jc-center" style="margin-top:-5px">
           <dv-decoration-10 class="dv-dec-10" />
           <div class="d-flex jc-center">
@@ -27,7 +38,7 @@
           </div>
           <dv-decoration-10 class="dv-dec-10-s" />
         </div>
-
+        <!-- 图表区域 -->
         <div class="body-box">
           <div class="left-box">
             <div class="left-box-top">
@@ -37,7 +48,7 @@
             </div>
             <div class="left-box-center">
               <dv-border-box-12>
-                <RightTop :school="schoolInfo.schoolName" />
+                <RightTop />
               </dv-border-box-12>
             </div>
           </div>
@@ -77,15 +88,14 @@ import RightTop from '@/components/dashboard/art/RightTop'
 export default {
   data() {
     return {
-      schoolInfo: {
-        schoolName: '',
-        schoolLogo: '',
-        periodName: '',
-        curSemester: ''
-      },
+      activeAcIndex: 0,
+      acList: [],
+      curAcSummary: null,
+      subjectList: [],
+      activeMenu: 'music',
       activeClassIndex: -1,
       activeGradeIndex: 0,
-      activeMenu: 'music',
+      curSubjectIndex: 0,
       timing: null,
       loading: true,
       dateDay: null,
@@ -109,60 +119,181 @@ export default {
     clearInterval(this.timing)
   },
   created() {
-    this.defImg = require('@/assets/image/def-school-img.png')
-    this.curPeriod = this.$store.state.user.curPeriod
-    this.$store.state.dashboard.classType = 'all'
-    let routerData = this.$route.params
-    this.schoolInfo.schoolName = routerData && routerData.schoolInfo ? routerData.schoolInfo.name : ''
-    sessionStorage.setItem('artSchool', this.schoolInfo.schoolName)
+    let params = this.$route.params
+    /* 从区级选择任意一个学校跳转过来的 */
+    console.log(params)
+    if (params.artInfo) {
+      this.findAreaSchoolAnalysis(params.artInfo)
+    } else {
+      this.findArtList()
+    }
     this.onChangeSubject('music')
-    this.cancelLoading()
-    console.log(routerData)
   },
   methods: {
-    onChangeClass(classIndex) {
-      this.$store.commit('setRandomArtData', { index: classIndex, subject: this.activeMenu })
-    },
-    onChangeGrade(gradeIndex) {
-      this.activeClassIndex = -1
-      this.onChangeClass(-1)
-    },
     onChangeSubject(subject) {
       this.activeMenu = subject
-      this.$store.commit('setArtDashboardData', { subject, school: this.schoolInfo.schoolName })
+      this.$store.commit('setArtDashboardData', { subject })
       this.$store.commit('setRandomArtData', 'all')
     },
-    getDashboardData() {
-      let semesterRange = this.$tools.getSemesterTimeRange()
-      this.$api.lessonRecord.getDashboardData({
-        "stime": semesterRange.st,
-        "etime": semesterRange.et,
+    /* 查询区级任意一个学校的艺术评测看板数据 */
+    findAreaSchoolAnalysis(artInfo) {
+      this.$api.areaArt.findArtSummary({
+        id: artInfo.artId,
+        code: artInfo.code
+      }).then(
+        (res) => {
+          if (!res.error) {
+            this.curAcSummary = res.art
+            // 根据勾选的指标 展示表格的列 其中用户信息列和总分列是固定展示
+            this.subjectList = res.art.subjects
+            this.curSubjectIndex = 0
+            let curSubjectId = this.subjectList[this.curSubjectIndex].id
+            this.acList = [{
+              id: artInfo.artId,
+              name: res.art.name
+            }]
+            this.loading = true
+            // 获取看板数据
+            this.$api.areaArt.findArtDashAnalysis({
+              "code": artInfo.code,
+              "periodId": artInfo.perId,
+              "subjectId": curSubjectId,
+              "areaId": sessionStorage.getItem('areaId'),
+              "id": artInfo.artId,
+              "classIds": res.art.classes,
+              'examId': res.art.settings.find(i => i.id === 'quota_21').task.find(k => k.subject === curSubjectId).acId
+            }).then(analysisRes => {
+              console.log(analysisRes)
+              if (analysisRes.code === 500) {
+                this.$Message.error('数据获取异常')
+              } else {
+                console.error(analysisRes)
+                // 保存到vuex
+                this.$store.commit('artDashboard/setAnalysisJson', analysisRes)
+              }
+              this.cancelLoading()
+            })
+          }
+        },
+        (err) => {
+          this.$Message.error(err)
+        }
+      )
+    },
+    /* 查询活动列表 */
+    findArtList() {
+      let params = {
+        code: this.$store.state.userInfo.schoolCode
+      }
+      this.$api.areaArt.findArtList(params).then(
+        (res) => {
+          this.acList = res.arts.filter(i => i.progress === 'finish')
+          if (this.acList.length) {
+            this.onAcChange(0)
+          }
+        },
+        (err) => { }
+      )
+    },
+    /* 查询艺术活动详情 */
+    findArtSummary(acId) {
+      let params = {
+        id: acId,
+        code: this.$store.state.userInfo.schoolCode
+      }
+      this.$api.areaArt.findArtSummary(params).then(
+        (res) => {
+          if (!res.error) {
+            this.curAcSummary = res.art
+            // 根据勾选的指标 展示表格的列 其中用户信息列和总分列是固定展示
+            this.subjectList = res.art.subjects
+            this.curSubjectIndex = 0
+            this.onSubjectChange()
+          }
+        },
+        (err) => {
+          this.$Message.error(err)
+        }
+      )
+    },
+    /* 活动切换 */
+    onAcChange(val) {
+      this.activeAcIndex = val
+      this.findArtSummary(this.acList[val].id)
+    },
+    /* 科目切换 */
+    onSubjectChange() {
+      let curSubjectId = this.subjectList[this.curSubjectIndex].id
+      this.loading = true
+      // 获取看板数据
+      this.$api.areaArt.findArtDashAnalysis({
         "code": this.$store.state.userInfo.schoolCode,
-        "periodId": this.$store.state.user.curPeriod.id
+        "periodId": this.schoolInfo.periodId,
+        "subjectId": curSubjectId,
+        "areaId": sessionStorage.getItem('areaId'),
+        "id": this.acList[this.activeAcIndex].id,
+        "classIds": this.curAcSummary.classes,
+        'examId': this.curAcSummary.settings.find(i => i.id === 'quota_21').task.find(k => k.subject === curSubjectId).acId
       }).then(res => {
-        this.$store.commit('setRearchDashboardData', res)
+        // 保存到vuex
+        this.$store.commit('artDashboard/setAnalysisJson', res)
         this.cancelLoading()
       })
     },
+    /* 返回上级 */
     goBack() {
       this.$tools.exitFullscreen()
+      // this.$router.push('/home/Dashboard')
+      // if (localStorage.getItem('platform') === 'area') {
+      //   this.$router.push('/area/areaArt')
+      // } else {
+      //   this.$router.push('/home/Dashboard')
+      // }
       this.$router.go(-1)
     },
+    /* 格式化最新时间 */
     timeFn() {
       this.timing = setInterval(() => {
         this.dateDay = this.$tools.formatTime(new Date(), 'hh:mm:ss')
         this.dateYear = this.$tools.formatTime(new Date(), 'yyyy-MM-dd')
       }, 1000)
     },
+    /* 取消加载 */
     cancelLoading() {
       setTimeout(() => {
         this.loading = false
-      }, 1000)
+      }, 100)
     },
   },
+  computed: {
+    schoolInfo() {
+      let artInfo = this.$route.params.artInfo
+      if (artInfo) {
+        return {
+          schoolName: artInfo.name,
+          schoolLogo: '',
+          periodName: artInfo.perName,
+          periodId: artInfo.perId,
+          curSemester: ''
+        }
+      } else {
+        let store_user = this.$store.state.user
+        let semesterRange = this.$tools.getSemesterTimeRange()
+        return {
+          schoolName: store_user.schoolProfile.school_base.name,
+          schoolLogo: store_user.schoolProfile.school_base.picture,
+          periodName: store_user.curPeriod.name,
+          periodId: store_user.curPeriod.id,
+          curSemester: semesterRange.name
+        }
+      }
+
+    }
+  }
 }
 </script>
-<style lang="less" scope>
-@import "./SchoolArt.less";
-@import "../dashboard/style.less";
+
+<style lang="less">
+@import "SchoolArt.less";
 </style>
+

+ 1 - 1
TEAMModelOS/ClientApp/src/view/art/echart/KngLevel.vue

@@ -116,7 +116,7 @@ export default {
             deep: true,
             immediate: true,
             handler(n, o) {
-                if (n) {
+                if (n && n.length) {
                     this.$nextTick(() => {
                         let level1Arr = [...new Set(n.map(i => i.level1))]
                         let level2Arr = [...new Set(n.map(i => i.level2))]

+ 19 - 5
TEAMModelOS/ClientApp/src/view/art/echart/KngPoint.vue

@@ -135,11 +135,25 @@ export default {
             })
         }
     },
-    mounted() {
-        this.$nextTick(() => {
-            let allPoints = this.kngData
-            this.doRender(allPoints)
-        })
+    // mounted() {
+    //     this.$nextTick(() => {
+    //         let allPoints = this.kngData
+    //         this.doRender(allPoints)
+    //     })
+    // },
+    watch: {
+        kngData: {
+            deep: true,
+            immediate: true,
+            handler(n, o) {
+                if (n && n.length) {
+                    this.$nextTick(() => {
+                        let allPoints = this.kngData
+                        this.doRender(allPoints)
+                    })
+                }
+            }
+        }
     }
 }
 </script>

+ 36 - 34
TEAMModelOS/ClientApp/src/view/art/echart/Overall.vue

@@ -71,7 +71,9 @@ export default {
                 },
                 xAxis: {
                     type: 'category',
-                    data: data.map(i => i.className),
+                    data: data.map(i => {
+                        return i.name === 'subject_music' ? '音乐' : '美术'
+                    }),
                     axisLine: {
                         lineStyle: {
                             // color: '#eee'
@@ -176,7 +178,7 @@ export default {
                                 barBorderRadius: 11,
                             }
                         },
-                        data: data.map(i => i.hScore)
+                        data: data.map(i => i.max)
                     },
                     {
                         name: '最低分',
@@ -196,7 +198,7 @@ export default {
                                 barBorderRadius: 11,
                             }
                         },
-                        data: data.map(i => i.lScore)
+                        data: data.map(i => i.min)
                     },
                     {
                         name: '优秀率',
@@ -204,7 +206,6 @@ export default {
                         yAxisIndex: 1,
                         symbolSize: '10',
                         zlevel: 3,
-
                         color: '#23bcca',
                         areaStyle: {
                             normal: {
@@ -227,7 +228,7 @@ export default {
 
                             }
                         },
-                        data: data.map(i => i.excellentRate),
+                        data: data.map(i => i.excellent),
                     },
                     {
                         name: '良好率',
@@ -255,36 +256,37 @@ export default {
                                 borderWidth: 12
                             }
                         },
-                        data: data.map(i => i.goodRate),
+                        data: data.map(i => i.pass),
                     },
-                    {
-                        name: '待提高率',
-                        type: 'line',
-                        yAxisIndex: 1,
-                        symbolSize: '10',
-                        zlevel: 3,
-                        areaStyle: {
-                            normal: {
-                                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-                                    offset: 0,
-                                    color: 'rgba(237, 64, 20, 0.1)'
-                                }, {
-                                    offset: 0.8,
-                                    color: 'rgba(237, 64, 20, 0.2)'
-                                }], false),
-                                shadowColor: 'rgba(0, 0, 0, 0.1)',
-                                shadowBlur: 10
-                            }
-                        },
-                        itemStyle: {
-                            normal: {
-                                color: 'rgb(237, 64, 20)',
-                                borderColor: 'rgba(237, 64, 20,0.17)',
-                                borderWidth: 12
-                            }
-                        },
-                        data: data.map(i => i.improveRate),
-                    }]
+                    // {
+                    //     name: '待提高率',
+                    //     type: 'line',
+                    //     yAxisIndex: 1,
+                    //     symbolSize: '10',
+                    //     zlevel: 3,
+                    //     areaStyle: {
+                    //         normal: {
+                    //             color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                    //                 offset: 0,
+                    //                 color: 'rgba(237, 64, 20, 0.1)'
+                    //             }, {
+                    //                 offset: 0.8,
+                    //                 color: 'rgba(237, 64, 20, 0.2)'
+                    //             }], false),
+                    //             shadowColor: 'rgba(0, 0, 0, 0.1)',
+                    //             shadowBlur: 10
+                    //         }
+                    //     },
+                    //     itemStyle: {
+                    //         normal: {
+                    //             color: 'rgb(237, 64, 20)',
+                    //             borderColor: 'rgba(237, 64, 20,0.17)',
+                    //             borderWidth: 12
+                    //         }
+                    //     },
+                    //     data: data.map(i => i.improveRate),
+                    // }
+                ]
             };
             myChart.clear()
             myChart.setOption(this.option)

+ 3 - 3
TEAMModelOS/ClientApp/src/view/art/echart/SchoolComp.vue

@@ -235,7 +235,7 @@ export default {
                                 barBorderRadius: 11,
                             }
                         },
-                        data: data.map(i => i.hScore)
+                        data: data.map(i => i.max)
                     },
                     {
                         name: '优秀率',
@@ -265,7 +265,7 @@ export default {
 
                             }
                         },
-                        data: data.map(i => i.excellentRate),
+                        data: data.map(i => i.excellent),
                     },
                     {
                         name: '及格率',
@@ -293,7 +293,7 @@ export default {
                                 borderWidth: 12
                             }
                         },
-                        data: data.map(i => i.passRate),
+                        data: data.map(i => i.pass),
                     }
                 ]
             };

+ 36 - 9
TEAMModelOS/ClientApp/src/view/artexam/Create.vue

@@ -44,6 +44,11 @@
                     <FormItem :label="$t('ae.ae7')" prop="time" style="margin-top: 30px">
                         <DatePicker v-model="artInfo.time" transfer type="datetimerange" placement="bottom-start" :placeholder="$t('ae.ae8')" @on-change="handleSetTime" style="width: 100%"></DatePicker>
                     </FormItem>
+                    <FormItem label="学校" style="margin-top: 30px" v-if="isArea">
+                        <Select v-model="artInfo.schools" style="" multiple placeholder="请选择施测学校,默认所有学校">
+                            <Option v-for="item in schoolList" :value="item.id" :key="item.id">{{ item.name }}</Option>
+                        </Select>
+                    </FormItem>
                 </Form>
                 <!-- 高级设置 -->
                 <Form ref="seniorInfo" :model="artInfo" :rules="trainRule" :label-width="100" class="art-form" label-colon v-show="step == 1">
@@ -120,7 +125,8 @@ export default {
         };
         let _this = this
         return {
-            examInfoList:[],
+            schoolList: [],
+            examInfoList: [],
             isArea: false,
             defaultQuos: ['quota_2'],
             subjectList: [
@@ -151,7 +157,8 @@ export default {
                 time: [],
                 targets: [],
                 subjects: [],
-                setting: []
+                setting: [],
+                schools: []
             },
             settingDetail: {},
             baseRule: {
@@ -290,8 +297,7 @@ export default {
             })
         },
         handleCheckChange(data) {
-            if (!this.settingDetail[data.quoid])
-                this.settingDetail[data.quoid] = {}
+            if (!this.settingDetail[data.quoid]) this.settingDetail[data.quoid] = {}
             this.settingDetail[data.quoid]["checked"] = data.data
         },
         handleTypeChange(data) {
@@ -448,9 +454,14 @@ export default {
                     promise = this.$api.areaArt.saveAreaArt({
                         id: sessionStorage.getItem("areaId"),
                         art: params,
-                        artExam:this.examInfoList
+                        artExam: this.examInfoList,
+                        schoolId: this.artInfo.schools.length ? this.artInfo.schools : undefined
                     })
                 } else {
+                    params.period = {
+                        id: this.curPeriod.id,
+                        name: this.curPeriod.name
+                    }
                     promise = this.$api.areaArt.saveArt({
                         art: params
                     })
@@ -484,7 +495,7 @@ export default {
                         id: this.$jsFn.uuid(),
                         code: this.$store.state.userInfo.schoolCode,
                         school: this.$store.state.userInfo.schoolCode,
-                        name: `${this.artInfo.name}-${setting.subject}`,
+                        name: `${this.artInfo.name}-${setting.subject === 'subject_music' ? '音乐' : '美术'}`,
                         creatorId: this.$store.state.userInfo.TEAMModelId,
                         // type: this.evaluationInfo.type,
                         period: {
@@ -548,6 +559,7 @@ export default {
                             "?" + paperSas.sas,
                             "school"
                         )
+                        debugger
                         reses.forEach((res, index) => {
                             let targetFolder = "exam/" + res.exam.id + "/paper/"
                             //这里评测都是单科处理
@@ -579,7 +591,8 @@ export default {
             return new Promise(async (r, j) => {
                 try {
                     simplePaper.scope = "school"
-                    let fullPaper = await this.$evTools.getFullPaper(
+                    simplePaper.code = simplePaper.schoolId
+                    let fullPaper = await this.$evTools.getStuPaper(
                         simplePaper
                     )
                     if (fullPaper) {
@@ -669,7 +682,6 @@ export default {
         },
         checkSettingInfo() {
             let isErr = false
-            console.log(this.settingDetail)
             let settings = Object.keys(this.settingDetail)
             if (!settings.length || (settings.length != this.artInfo.setting.length)) {
                 return this.$Message.error(this.$t('ae.ae39'))
@@ -726,13 +738,28 @@ export default {
         treeChange(data) {
             console.log(data)
             this.artInfo.targets = data.map((item) => item[1])
-        }
+        },
+        getAreaSchoolList() {
+            this.$api.areaArt.findAreaSchoolList({
+                id: sessionStorage.getItem('areaId')
+            }).then(
+                res => {
+                    this.schoolList = res.sc
+                },
+                err => {
+                    this.$Message.error("获取学校列表失败")
+                }
+            )
+        },
     },
     created() {
         this.getAreaSetting()
         console.log(this.$route)
         // 判断是否为区级发布
         this.isArea = this.$route.name === 'areaCreateArtMgt'
+        if (this.isArea) {
+            this.getAreaSchoolList()
+        }
     }
 }
 </script>

+ 2 - 1
TEAMModelOS/ClientApp/src/view/artexam/ExamSetting.vue

@@ -149,7 +149,8 @@ export default {
             this.previewPaper = {}
             try {
                 this.paperListShow[index].scope = 'school'
-                this.previewPaper = await this.$evTools.getFullPaper(this.paperListShow[index])
+                this.paperListShow[index].code = this.paperListShow[index].schoolId
+                this.previewPaper = await this.$evTools.getStuPaper(this.paperListShow[index])
                 setTimeout(() => {
                     this.isPreview = true
                 }, 400)

+ 10 - 5
TEAMModelOS/ClientApp/src/view/artexam/Mgt.vue

@@ -23,7 +23,7 @@
                                 <Icon type="md-time" size="16" />{{$jsFn.dateFormat(item.startTime)}}-{{$jsFn.dateFormat(item.endTime)}}
                             </p>
                         </div>
-                        <EmptyData v-show="artList.length" :top="100"></EmptyData>
+                        <EmptyData v-show="!artList.length" :top="100"></EmptyData>
                     </vuescroll>
                 </div>
             </div>
@@ -42,7 +42,10 @@
                         评价指标
                     </span>
                 </div>
-                <DataView :artInfo="artInfo" :quotaFirstLevel="quotaFirstLevel" :classList="classList" v-if="curBarIndex === 0"></DataView>
+                <div v-if="!artList.length" class="publish-art-box">
+                    <EmptyData v-if="artList.length"></EmptyData>
+                </div>
+                <DataView :artInfo="artInfo" :quotaFirstLevel="quotaFirstLevel" :classList="classList" v-else-if="curBarIndex === 0"></DataView>
                 <div v-else-if="curBarIndex === 1" class="quo-detail-wrap">
                     <vuescroll style="background:white">
                         <Tabs v-model="tabName" style="padding: 0px 10px;margin-top:15px">
@@ -217,7 +220,7 @@ export default {
                                 id: this.$jsFn.uuid(),
                                 code: this.$store.state.userInfo.schoolCode,
                                 school: this.$store.state.userInfo.schoolCode,
-                                name: `${this.artInfo.name}-${task.subject}`,
+                                name: `${this.artInfo.name}-${task.subject === 'subject_music' ? '音乐' : '美术'}`,
                                 creatorId: this.$store.state.userInfo.TEAMModelId,
                                 period: {
                                     id: this.curPeriod.id,
@@ -343,7 +346,8 @@ export default {
             return new Promise(async (r, j) => {
                 try {
                     simplePaper.scope = "school"
-                    let fullPaper = await this.$evTools.getFullPaper(simplePaper)
+                    simplePaper.code = "hbcn"
+                    let fullPaper = await this.$evTools.getStuPaper(simplePaper)
                     if (fullPaper) {
                         let apiPaper = {}
                         apiPaper.id = fullPaper.id
@@ -481,7 +485,8 @@ export default {
         toDetailPage(index) { },
         findArtList() {
             let params = {
-                code: this.$store.state.userInfo.schoolCode
+                code: this.$store.state.userInfo.schoolCode,
+                periodId: this.curPeriod.id
             }
             this.$api.areaArt.findArtList(params).then(
                 (res) => {

+ 113 - 112
TEAMModelOS/ClientApp/src/view/artexam/QuoTree.vue

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

+ 10 - 3
TEAMModelOS/ClientApp/src/view/assessment/ArtAssessment.vue

@@ -21,7 +21,7 @@
           </Option>
         </Select>
         <!-- 搜索框 -->
-        <Input v-special-char v-model="searchVal" search :placeholder="$t('ability.place1')" style="width: 180px;margin-left: 15px;" @on-search="doFilter" />
+        <Input v-special-char v-model="searchVal" search :placeholder="$t('ability.place1')" style="width: 180px;margin-left: 15px;" @on-search="onSearch" />
       </div>
       <div class="right">
         <p>查询结果:共 <span>{{ totalCount }}</span> 人, 优秀 <span :style="{color:colorList[0]}">{{ levelCount[0] }}</span> 人, 良好 <span :style="{color:colorList[1]}">{{ levelCount[1] }}</span> 人, 合格 <span :style="{color:colorList[2]}">{{ levelCount[2] }}</span> 人, 不合格 <span :style="{color:colorList[3]}">{{ levelCount[3] }}</span> 人 </p>
@@ -183,7 +183,7 @@ export default {
   },
   data(vm) {
     return {
-      colorList: ['#23c466', '#c47c18', '#c49258', '#ff0000'],
+      colorList: ['#23c466', '#23c466', '#c47c18', '#c47c18', '#c49258', '#c49258', '#ff0000'],
       levelCount: [0, 0, 0, 0],
       totalCount: 0,
       previewModal: false,
@@ -525,6 +525,13 @@ export default {
       this.originList = []
       this.doFilter()
     },
+    /* 搜索名称 */
+    onSearch() {
+      this.continueToken = null
+      this.assessmentList = [];
+      this.originList = []
+      this.doFilter()
+    },
     /* 查询操作 */
     doFilter() {
       this.expandedArr = []
@@ -546,7 +553,7 @@ export default {
           this.originList = this._.cloneDeep(this.assessmentList)
           this.levelCount = new Array(this.artSettings.reviewLevel.length).fill(0)
           this.calcQuotaScores(stuResults)
-          this.calcFinalCounts(res.scores)
+          this.calcFinalCounts(res.subjectScore[0].name)
         } else {
           this.$Message.error('Fail')
         }

+ 10 - 3
TEAMModelOS/ClientApp/src/view/auth/Product.vue

@@ -31,7 +31,7 @@
                             </Button>
                             <p class="product-status" style="margin-top:5px" v-show="item.isPay">
                                 <!-- 时间 -->
-                                <span>
+                                <span v-if="!item.isFov">
                                     {{$t('auth.expired')}}
                                     <span class="expire-time">
                                         {{$jsFn.dateFormat(item.start)}}
@@ -41,6 +41,9 @@
                                         {{$jsFn.dateFormat(item.end)}}
                                     </span>
                                 </span>
+                                <span v-else style="color:#2db7f5;font-weight:800;font-size:18px">
+                                    {{$t('auth.longTime')}}
+                                </span>
                             </p>
                         </div>
                     </div>
@@ -248,6 +251,7 @@ export default {
                     name: this.$t('auth.module1'),
                     start: 0,
                     end: 0,
+                    isFov: false,
                     image: require("@/assets/image/module2.jpg"),
                     content: this.$t('auth.content1'),
                     isPay: 0,
@@ -260,6 +264,7 @@ export default {
                     name: this.$t('auth.module2'),
                     start: 0,
                     end: 0,
+                    isFov: false,
                     image: require("@/assets/image/module1.jpg"),
                     content: this.$t('auth.content2'),
                     isPay: 0,
@@ -272,6 +277,7 @@ export default {
                     name: this.$t('auth.module3'),
                     start: 0,
                     end: 0,
+                    isFov: false,
                     image: require("@/assets/image/module3.jpg"),
                     content: this.$t('auth.content3'),
                     isPay: 0,
@@ -365,8 +371,9 @@ export default {
                 let svc = services.find(s => s.prodCode == item.prodCode)
                 if (svc) {
                     item.isPay = 1
-                    item.start = svc.avaliableStartDate 
-                    item.end = svc.avaliableEndDate 
+                    item.start = svc.avaliableStartDate
+                    item.end = svc.avaliableEndDate
+                    item.isFov = new Date(svc.avaliableEndDate * 1000).getFullYear() >= 2200 ? true : false
                 }
             })
             //获取学校规模授权数量

+ 90 - 13
TEAMModelOS/ClientApp/src/view/dashboard/Art.vue

@@ -13,7 +13,7 @@
           <img :src="schoolInfo.schoolLogo">
           <span class="school-info-name">{{ schoolInfo.schoolName }}</span>
           <span class="school-info-period">{{ schoolInfo.periodName }}</span>
-          <span class="school-info-semester">{{ schoolInfo.curSemester }}</span>
+          <span class="school-info-semester" v-if="!$route.params.artInfo">{{ schoolInfo.curSemester }}</span>
           <div style="margin-left: 15px">
             <Select v-model="activeAcIndex" @on-change="onAcChange">
               <Option v-for="(item,index) in acList" :value="index">{{ item.name }}</Option>
@@ -112,14 +112,23 @@ export default {
     RightTop,
   },
   mounted() {
-    this.$tools.fullScreen(document.getElementById('artIndex'))
+    this.$nextTick(() => {
+      this.$tools.fullScreen(document.getElementById('artIndex'))
+    })
     this.timeFn()
   },
   beforeDestroy() {
     clearInterval(this.timing)
   },
   created() {
-    this.findArtList()
+    let params = this.$route.params
+    /* 从区级选择任意一个学校跳转过来的 */
+    console.log(params)
+    if (params.artInfo) {
+      this.findAreaSchoolAnalysis(params.artInfo)
+    } else {
+      this.findArtList()
+    }
     this.onChangeSubject('music')
   },
   methods: {
@@ -128,6 +137,51 @@ export default {
       this.$store.commit('setArtDashboardData', { subject })
       this.$store.commit('setRandomArtData', 'all')
     },
+    /* 查询区级任意一个学校的艺术评测看板数据 */
+    findAreaSchoolAnalysis(artInfo) {
+      this.$api.areaArt.findArtSummary({
+        id: artInfo.artId,
+        code: artInfo.code
+      }).then(
+        (res) => {
+          if (!res.error) {
+            this.curAcSummary = res.art
+            // 根据勾选的指标 展示表格的列 其中用户信息列和总分列是固定展示
+            this.subjectList = res.art.subjects
+            this.curSubjectIndex = 0
+            let curSubjectId = this.subjectList[this.curSubjectIndex].id
+            this.acList = [{
+              id: artInfo.artId,
+              name: res.art.name
+            }]
+            this.loading = true
+            // 获取看板数据
+            this.$api.areaArt.findArtDashAnalysis({
+              "code": artInfo.code,
+              "periodId": artInfo.perId,
+              "subjectId": curSubjectId,
+              "areaId": sessionStorage.getItem('areaId'),
+              "id": artInfo.artId,
+              "classIds": res.art.classes,
+              'examId': res.art.settings.find(i => i.id === 'quota_21').task.find(k => k.subject === curSubjectId).acId
+            }).then(analysisRes => {
+              console.log(analysisRes)
+              if (analysisRes.code === 500) {
+                this.$Message.error('数据获取异常')
+              } else {
+                console.error(analysisRes)
+                // 保存到vuex
+                this.$store.commit('artDashboard/setAnalysisJson', analysisRes)
+              }
+              this.cancelLoading()
+            })
+          }
+        },
+        (err) => {
+          this.$Message.error(err)
+        }
+      )
+    },
     /* 查询活动列表 */
     findArtList() {
       let params = {
@@ -138,6 +192,11 @@ export default {
           this.acList = res.arts.filter(i => i.progress === 'finish')
           if (this.acList.length) {
             this.onAcChange(0)
+          } else {
+            this.$Message.warning('未查询到已结束的艺术评测活动!')
+            setTimeout(() => {
+              this.$router.go(-1)
+            }, 1000)
           }
         },
         (err) => { }
@@ -191,7 +250,13 @@ export default {
     /* 返回上级 */
     goBack() {
       this.$tools.exitFullscreen()
-      this.$router.push('/home/Dashboard')
+      // this.$router.push('/home/Dashboard')
+      // if (localStorage.getItem('platform') === 'area') {
+      //   this.$router.push('/area/areaArt')
+      // } else {
+      //   this.$router.push('/home/Dashboard')
+      // }
+      this.$router.go(-1)
     },
     /* 格式化最新时间 */
     timeFn() {
@@ -204,20 +269,32 @@ export default {
     cancelLoading() {
       setTimeout(() => {
         this.loading = false
-      }, 1000)
+      }, 100)
     },
   },
   computed: {
     schoolInfo() {
-      let store_user = this.$store.state.user
-      let semesterRange = this.$tools.getSemesterTimeRange()
-      return {
-        schoolName: store_user.schoolProfile.school_base.name,
-        schoolLogo: store_user.schoolProfile.school_base.picture,
-        periodName: store_user.curPeriod.name,
-        periodId: store_user.curPeriod.id,
-        curSemester: semesterRange.name
+      let artInfo = this.$route.params.artInfo
+      if (artInfo) {
+        return {
+          schoolName: artInfo.name,
+          schoolLogo: '',
+          periodName: artInfo.perName,
+          periodId: artInfo.perId,
+          curSemester: ''
+        }
+      } else {
+        let store_user = this.$store.state.user
+        let semesterRange = this.$tools.getSemesterTimeRange()
+        return {
+          schoolName: store_user.schoolProfile.school_base.name,
+          schoolLogo: store_user.schoolProfile.school_base.picture,
+          periodName: store_user.curPeriod.name,
+          periodId: store_user.curPeriod.id,
+          curSemester: semesterRange.name
+        }
       }
+
     }
   }
 }

File diff suppressed because it is too large
+ 60 - 43
TEAMModelOS/ClientApp/src/view/dashboard/Index.vue


+ 7 - 3
TEAMModelOS/ClientApp/src/view/dashboard/Research.less

@@ -192,12 +192,12 @@
 
         &-top {
           width: 100%;
-          height: 24%;
+          height: 12%;
         }
 
         &-bottom {
           width: 100%;
-          height: 71%;
+          height: 83%;
         }
       }
 
@@ -219,9 +219,13 @@
           display: flex;
 
           .right-bottom-single {
-            width: 50%;
+            width: 60%;
             height: 100%;
           }
+
+          .right {
+            width: 40%;
+          }
         }
       }
     }

+ 150 - 150
TEAMModelOS/ClientApp/src/view/dashboard/Research.vue

@@ -1,160 +1,160 @@
 <template>
-	<div id="index" ref="appRef">
-		<div class="bg">
-			<dv-loading v-if="loading">{{ $t('researchCenter.dashboard.loading') }}</dv-loading>
-			<div v-else class="host-body">
-				<div class="tools">
-					<span class="time-text">{{ dateYear }}  <span style="display: inline-block; margin: 0 5px;color: #0fa2fe;">{{ dateDay }}</span>    </span>
-					<!-- <span type="iconfont icon-tuichuquanping" @click="goBack" color="#0fa2fe"/> -->
-					<span class="icon iconfont icon-tuichuquanping" style="font-size: 22px;" :title="$t('researchCenter.dashboard.quit')" @click="goBack"></span>
-					<!-- <span class="icon iconfont icon-tuichuquanping" @click="goBack" style="width: 20px;"></span> -->
-				</div>
-				<div class="school-info">
-					<img :src="schoolInfo.schoolLogo">
-					<span class="school-info-name">{{ schoolInfo.schoolName }}</span>
-					<span class="school-info-period">{{ schoolInfo.periodName }}</span>
-					<span class="school-info-semester">{{ schoolInfo.curSemester }}</span>
-				</div>
-				<div class="d-flex jc-center">
-					<dv-decoration-10 class="dv-dec-10" />
-					<div class="d-flex jc-center">
-						<dv-decoration-8 class="dv-dec-8" :color="['#568aea', '#000000']" />
-						<div class="title">
-							<span class="title-text">{{ $t('researchCenter.dashboard.title2') }}</span>
-							<dv-decoration-6 class="dv-dec-6" :reverse="true" :color="['#50e3c2', '#67a1e5']" />
-						</div>
-						<dv-decoration-8 class="dv-dec-8" :reverse="true" :color="['#568aea', '#000000']" />
-					</div>
-					<dv-decoration-10 class="dv-dec-10-s" />
-				</div>
+  <div id="index" ref="appRef">
+    <div class="bg">
+      <dv-loading v-if="loading">{{ $t('researchCenter.dashboard.loading') }}</dv-loading>
+      <div v-else class="host-body">
+        <div class="tools">
+          <span class="time-text">{{ dateYear }} <span style="display: inline-block; margin: 0 5px;color: #0fa2fe;">{{ dateDay }}</span> </span>
+          <!-- <span type="iconfont icon-tuichuquanping" @click="goBack" color="#0fa2fe"/> -->
+          <span class="icon iconfont icon-tuichuquanping" style="font-size: 22px;" :title="$t('researchCenter.dashboard.quit')" @click="goBack"></span>
+          <!-- <span class="icon iconfont icon-tuichuquanping" @click="goBack" style="width: 20px;"></span> -->
+        </div>
+        <div class="school-info">
+          <img :src="schoolInfo.schoolLogo">
+          <span class="school-info-name">{{ schoolInfo.schoolName }}</span>
+          <span class="school-info-period">{{ schoolInfo.periodName }}</span>
+          <span class="school-info-semester">{{ schoolInfo.curSemester }}</span>
+        </div>
+        <div class="d-flex jc-center">
+          <dv-decoration-10 class="dv-dec-10" />
+          <div class="d-flex jc-center">
+            <dv-decoration-8 class="dv-dec-8" :color="['#568aea', '#000000']" />
+            <div class="title">
+              <span class="title-text">{{ $t('researchCenter.dashboard.title2') }}</span>
+              <dv-decoration-6 class="dv-dec-6" :reverse="true" :color="['#50e3c2', '#67a1e5']" />
+            </div>
+            <dv-decoration-8 class="dv-dec-8" :reverse="true" :color="['#568aea', '#000000']" />
+          </div>
+          <dv-decoration-10 class="dv-dec-10-s" />
+        </div>
 
-				<div class="body-box">
-					<div class="left-box">
-						<div class="left-box-top">
-							<dv-border-box-12>
-								<LeftTop />
-							</dv-border-box-12>
-						</div>
-						<div class="left-box-bottom">
-							<dv-border-box-12>
-								<LeftBottom />
-							</dv-border-box-12>
-						</div>
-					</div>
+        <div class="body-box">
+          <div class="left-box">
+            <div class="left-box-top">
+              <dv-border-box-12>
+                <LeftTop />
+              </dv-border-box-12>
+            </div>
+            <div class="left-box-bottom">
+              <dv-border-box-12>
+                <LeftBottom />
+              </dv-border-box-12>
+            </div>
+          </div>
 
-					<div class="right-box">
-						<div class="right-box-top">
-							<dv-border-box-12>
-								<RightTop />
-							</dv-border-box-12>
-						</div>
-						<div class="right-box-bottom">
-							<div class="right-bottom-single">
-								<dv-border-box-12>
-									<RightBotL />
-								</dv-border-box-12>
-							</div>
-							<div class="right-bottom-single">
-								<dv-border-box-12>
-									<RightBotR />
-								</dv-border-box-12>
-							</div>
-						</div>
-					</div>
-				</div>
-			</div>
-		</div>
-	</div>
+          <div class="right-box">
+            <div class="right-box-top">
+              <dv-border-box-12>
+                <RightTop />
+              </dv-border-box-12>
+            </div>
+            <div class="right-box-bottom">
+              <div class="right-bottom-single">
+                <dv-border-box-12>
+                  <RightBotR />
+                </dv-border-box-12>
+              </div>
+              <div class="right-bottom-single right">
+                <dv-border-box-12>
+                  <RightBotL />
+                </dv-border-box-12>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
-	import drawMixin from "@/utils/drawMixin";
-	import RightBotR from '@/components/research-dashboard/RightBotR'
-	import RightBotL from '@/components/research-dashboard/RightBotL'
-	import LeftTop from '@/components/research-dashboard/LeftTop'
-	import LeftBottom from '@/components/research-dashboard/LeftBottom'
-	import RightTop from '@/components/research-dashboard/RightTop'
-	export default {
-		// mixins: [drawMixin],
-		data() {
-			return {
-				timing: null,
-				loading: true,
-				dateDay: null,
-				dateYear: null,
-				dateWeek: null,
-				weekday: ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
-			}
-		},
-		components: {
-			RightBotR,
-			RightBotL,
-			LeftTop,
-			LeftBottom,
-			RightTop,
-		},
-		mounted() {
-			this.$tools.fullScreen(document.getElementById('index'))
-			this.timeFn()
-			// this.cancelLoading()
-		},
-		beforeDestroy() {
-			clearInterval(this.timing)
-		},
-		created() {
-			this.curPeriod = this.$store.state.user.curPeriod
-			this.getDashboardData()
-		},
-		methods: {
-			getDashboardData(){
-				let semesterRange = this.$tools.getSemesterTimeRange()
-				this.$api.lessonRecord.getDashboardData({
-					"stime": semesterRange.st,
-					"etime": semesterRange.et,
-					"code": this.$store.state.userInfo.schoolCode,
-					"periodId":this.$store.state.user.curPeriod.id
-				}).then(res => {
-					if(res.code && res.code == 404){
-						this.$Message.warning(this.$t('lessonRecord.noRecordTip'))
-					}else{
-						this.$store.commit('setRearchDashboardData',res)
-					}
-					this.cancelLoading()
-				})
-			},
-			goBack() {
-				this.$tools.exitFullscreen()
-				this.$router.push('/home/Dashboard')
-			},
-			timeFn() {
-				this.timing = setInterval(() => {
-					this.dateDay = this.$tools.formatTime(new Date(), 'hh:mm:ss')
-					this.dateYear = this.$tools.formatTime(new Date(), 'yyyy-MM-dd')
-					this.dateWeek = this.weekday[new Date().getDay()]
-				}, 1000)
-			},
-			cancelLoading() {
-				setTimeout(() => {
-					this.loading = false
-				}, 1000)
-			},
-		},
-		computed:{
-			schoolInfo(){
-				let store_user = this.$store.state.user
-				let semesterRange = this.$tools.getSemesterTimeRange()
-				return {
-					schoolName:store_user.schoolProfile.school_base.name,
-					schoolLogo:store_user.schoolProfile.school_base.picture,
-					periodName:store_user.curPeriod.name,
-					curSemester:semesterRange.name
-				}
-			}
-		}
-	}
+import drawMixin from "@/utils/drawMixin";
+import RightBotR from '@/components/research-dashboard/RightBotR'
+import RightBotL from '@/components/research-dashboard/RightBotL'
+import LeftTop from '@/components/research-dashboard/LeftTop'
+import LeftBottom from '@/components/research-dashboard/LeftBottom'
+import RightTop from '@/components/research-dashboard/RightTop'
+export default {
+  // mixins: [drawMixin],
+  data() {
+    return {
+      timing: null,
+      loading: true,
+      dateDay: null,
+      dateYear: null,
+      dateWeek: null,
+      weekday: ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
+    }
+  },
+  components: {
+    RightBotR,
+    RightBotL,
+    LeftTop,
+    LeftBottom,
+    RightTop,
+  },
+  mounted() {
+    this.$tools.fullScreen(document.getElementById('index'))
+    this.timeFn()
+    // this.cancelLoading()
+  },
+  beforeDestroy() {
+    clearInterval(this.timing)
+  },
+  created() {
+    this.curPeriod = this.$store.state.user.curPeriod
+    this.getDashboardData()
+  },
+  methods: {
+    getDashboardData() {
+      let semesterRange = this.$tools.getSemesterTimeRange()
+      this.$api.lessonRecord.getDashboardData({
+        "stime": semesterRange.st,
+        "etime": semesterRange.et,
+        "code": this.$store.state.userInfo.schoolCode,
+        "periodId": this.$store.state.user.curPeriod.id
+      }).then(res => {
+        if (res.code && res.code == 404) {
+          this.$Message.warning(this.$t('lessonRecord.noRecordTip'))
+        } else {
+          this.$store.commit('setRearchDashboardData', res)
+        }
+        this.cancelLoading()
+      })
+    },
+    goBack() {
+      this.$tools.exitFullscreen()
+      this.$router.push('/home/Dashboard')
+    },
+    timeFn() {
+      this.timing = setInterval(() => {
+        this.dateDay = this.$tools.formatTime(new Date(), 'hh:mm:ss')
+        this.dateYear = this.$tools.formatTime(new Date(), 'yyyy-MM-dd')
+        this.dateWeek = this.weekday[new Date().getDay()]
+      }, 1000)
+    },
+    cancelLoading() {
+      setTimeout(() => {
+        this.loading = false
+      }, 1000)
+    },
+  },
+  computed: {
+    schoolInfo() {
+      let store_user = this.$store.state.user
+      let semesterRange = this.$tools.getSemesterTimeRange()
+      return {
+        schoolName: store_user.schoolProfile.school_base.name,
+        schoolLogo: store_user.schoolProfile.school_base.picture,
+        periodName: store_user.curPeriod.name,
+        curSemester: semesterRange.name
+      }
+    }
+  }
+}
 </script>
 
 <style lang="less">
-	@import 'Research.less';
-	@import 'style.less';
+@import "Research.less";
+@import "style.less";
 </style>

+ 201 - 0
TEAMModelOS/ClientApp/src/view/dashboard/Student.less

@@ -10,6 +10,207 @@
     "Microsoft JhengHei UI",
     "Microsoft JhengHei";
 
+  .school-info {
+    position: absolute;
+    left: 30px;
+    top: 40px;
+    font-size: 20px;
+    font-weight: bold;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+
+
+
+    &-name {
+      margin: 0 10px;
+    }
+
+    &-period {
+      font-size: 12px;
+      background-color: #2d2d2d;
+      display: inline-block;
+      padding: 2px 10px;
+      border-radius: 4px;
+      margin-right: 5px;
+    }
+
+    &-semester {
+      font-size: 12px;
+      background-color: #2d2d2d;
+      display: inline-block;
+      padding: 2px 10px;
+      border-radius: 4px;
+      margin-right: 5px;
+    }
+
+    .dashboard-menu {
+      margin-left: 20px;
+      cursor: pointer;
+
+      &-active {
+        border-bottom: 2px solid #fff;
+      }
+    }
+
+    img {
+      border-radius: 50%;
+      width: 25px;
+    }
+  }
+
+  .border-box-content {
+    padding: 15px;
+  }
+
+  .dashboard-block {
+    position: relative;
+    width: 100%;
+    height: 100%;
+    // margin: 10px;
+    // padding: 0px;
+    display: inline-flex;
+    flex-direction: column;
+    box-sizing: border-box;
+    border-radius: 10px;
+    background-color: #4685fa11;
+
+    .person {
+      position: absolute;
+      left: 0;
+      top: 0;
+      bottom: 0;
+      right: 0;
+      margin: auto;
+      width: 280px;
+    }
+
+    .block-title {
+      width: 100%;
+      display: flex;
+      padding: 10px;
+      font-size: 18px;
+      font-weight: bold;
+      align-items: center;
+
+
+      &::before {
+        content: '';
+        display: inline-block;
+        width: 5px;
+        height: 15px;
+        margin-right: 10px;
+        border-radius: 5px;
+        background-color: #6184ec;
+      }
+    }
+
+    .block-content {
+      width: 100%;
+      height: 100%;
+      display: flex;
+      padding: 10px;
+
+      .honor-avatar {
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: center;
+        align-items: space-between;
+        width: 100%;
+
+        .honor-item {
+          position: relative;
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          justify-content: space-around;
+          width: 33.3%;
+
+          .img-avatar {
+            border-radius: 50%;
+            border: 3px solid #58a8bb;
+            cursor: pointer;
+          }
+
+          .img-crown {
+            position: absolute;
+            top: -17px;
+            left: 28px;
+          }
+        }
+      }
+
+      .static-wrap {
+        display: flex;
+        width: 100%;
+        justify-content: space-around;
+        align-items: center;
+
+        .item {
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          justify-content: center;
+
+          .num {
+            font-size: 46px;
+            font-weight: bold;
+            font-family: staticFont;
+            color: #1dd86b;
+          }
+
+
+          .label {
+            font-weight: bold;
+            color: #a1a5a5;
+          }
+        }
+      }
+    }
+
+    .cicle2 {
+      width: 80%;
+      height: 100%;
+      background: url(./circle.png) no-repeat center;
+      background-size: 100%;
+      position: absolute;
+      top: 27%;
+      left: 10%;
+      transform-style: preserve-3d;
+      transform: translateX(-50%) rotateX(75deg);
+      animation: rotate2 15s linear infinite;
+    }
+
+    @keyframes rotate2 {
+      0% {
+        transform: rotateX(75deg) rotateZ(0);
+      }
+
+      100% {
+        transform: rotateX(75deg) rotateZ(360deg);
+      }
+    }
+  }
+
+  .tools {
+    position: absolute;
+    right: 30px;
+    top: 40px;
+    font-size: 26px;
+    font-weight: bold;
+    display: flex;
+    align-items: center;
+    cursor: pointer;
+
+    .time-text {
+      font-size: 30px;
+      margin-right: 20px;
+      font-weight: 200;
+      color: #9f9f9f;
+      font-family: 'staticFont';
+    }
+  }
+
   .bg {
     width: 100%;
     height: 100%;

+ 0 - 0
TEAMModelOS/ClientApp/src/view/dashboard/Student.vue


Some files were not shown because too many files changed in this diff