Kaynağa Gözat

Merge branch 'master' into ZJ/ms2022516

zhouj1203@hotmail.com 3 yıl önce
ebeveyn
işleme
9502dfd748
100 değiştirilmiş dosya ile 12292 ekleme ve 3303 silme
  1. 22 3
      TEAMModelAPI/Startup.cs
  2. 1 1
      TEAMModelBI/ClientApp/package.json
  3. 1 1
      TEAMModelBI/ClientApp/public/index.html
  4. 2 1
      TEAMModelBI/ClientApp/src/App.vue
  5. BIN
      TEAMModelBI/ClientApp/src/assets/img/redacts.png
  6. 1 1
      TEAMModelBI/ClientApp/src/components/Ability.vue
  7. 3 3
      TEAMModelBI/ClientApp/src/components/AbilityTree.vue
  8. 4 2
      TEAMModelBI/ClientApp/src/components/echarts/test/online.vue
  9. 4 2
      TEAMModelBI/ClientApp/src/language/lang/zh-cn.js
  10. 5 0
      TEAMModelBI/ClientApp/src/store/index.js
  11. 205 58
      TEAMModelBI/ClientApp/src/view/areaServe/areamanage.vue
  12. 32 6
      TEAMModelBI/ClientApp/src/view/common/aside.vue
  13. 118 20
      TEAMModelBI/ClientApp/src/view/common/header.vue
  14. 584 458
      TEAMModelBI/ClientApp/src/view/created/created.vue
  15. 374 208
      TEAMModelBI/ClientApp/src/view/index/index.vue
  16. 15 1
      TEAMModelBI/ClientApp/src/view/login.vue
  17. 128 48
      TEAMModelBI/ClientApp/src/view/participation/index.vue
  18. 250 92
      TEAMModelBI/ClientApp/src/view/participation/setAbility.vue
  19. 212 68
      TEAMModelBI/ClientApp/src/view/schoolServe/school.vue
  20. 434 182
      TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue
  21. 4 3
      TEAMModelBI/ClientApp/src/view/schoolmanage/index.vue
  22. 47 13
      TEAMModelBI/ClientApp/src/view/systemConfig/index.vue
  23. 133 52
      TEAMModelBI/ClientApp/src/view/teachermanage/school.vue
  24. 401 101
      TEAMModelBI/ClientApp/src/view/teachermanage/traitmanage.vue
  25. 90 0
      TEAMModelBI/Controllers/BIHome/AnalyseFileController.cs
  26. 75 85
      TEAMModelBI/Controllers/BIHome/OnLineController.cs
  27. 32 6
      TEAMModelBI/Controllers/BISchool/AreaRelevantController.cs
  28. 133 117
      TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs
  29. 112 17
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  30. 25 13
      TEAMModelBI/Controllers/BITest/Ies5TestController.cs
  31. 4761 0
      TEAMModelBI/JsonFile/TempFile/PT1H.json
  32. 345 5
      TEAMModelOS.FunctionV4/HttpTrigger/IESHttpTrigger.cs
  33. 25 0
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  34. 3 3
      TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj
  35. 39 0
      TEAMModelOS.SDK/Helper/Common/ReflectorExtensions/ReflectorExtensions.cs
  36. 21 46
      TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs
  37. 39 2
      TEAMModelOS.SDK/Models/Cosmos/Common/LessonStudentRecord.cs
  38. 12 0
      TEAMModelOS.SDK/Models/Cosmos/School/School.cs
  39. 44 0
      TEAMModelOS.SDK/Models/Cosmos/Teacher/OnLinRec.cs
  40. 8 3
      TEAMModelOS.SDK/Models/Service/Common/TeacherService.cs
  41. 2 2
      TEAMModelOS.SDK/Models/Table/OpenApi.cs
  42. 111 66
      TEAMModelOS/ClientApp/public/lang/en-US.js
  43. 56 10
      TEAMModelOS/ClientApp/public/lang/zh-CN.js
  44. 133 88
      TEAMModelOS/ClientApp/public/lang/zh-TW.js
  45. 0 85
      TEAMModelOS/ClientApp/src/App.vue
  46. 4 1
      TEAMModelOS/ClientApp/src/api/lessonRecord.js
  47. 9 3
      TEAMModelOS/ClientApp/src/api/serviceDriveAuth.js
  48. 4 0
      TEAMModelOS/ClientApp/src/api/studentWeb.js
  49. BIN
      TEAMModelOS/ClientApp/src/assets/image/qrcode_tw.png
  50. 5 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/classmate-commentPages.less
  51. 16 1
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/course-content.less
  52. 64 30
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/course-list.less
  53. 9 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/homework.less
  54. 1 1
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-view.css
  55. 32 34
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  56. 1 1
      TEAMModelOS/ClientApp/src/common/BaseUserPoptip.vue
  57. 0 1
      TEAMModelOS/ClientApp/src/components/app-root.vue
  58. 10 3
      TEAMModelOS/ClientApp/src/components/dashboard/art/BaseLessonLineBar.vue
  59. 239 0
      TEAMModelOS/ClientApp/src/components/dashboard/art/BaseStuLineBar.vue
  60. 9 10
      TEAMModelOS/ClientApp/src/components/dashboard/art/LeftTop.vue
  61. 6 3
      TEAMModelOS/ClientApp/src/components/dashboard/art/RightTop.vue
  62. 17 1
      TEAMModelOS/ClientApp/src/components/homework/BaseHwTable.less
  63. 780 685
      TEAMModelOS/ClientApp/src/components/homework/BaseHwTable.vue
  64. 64 36
      TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ClassRecord.less
  65. 12 10
      TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ClassRecord.vue
  66. 1 1
      TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/DataCount.vue
  67. 2 2
      TEAMModelOS/ClientApp/src/components/student-web/EventView/BillBoardandLightBox.vue
  68. 4 5
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/ClassmateCommentPages.vue
  69. 12 4
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Homework.vue
  70. 21 2
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/HomeworkFeedback.vue
  71. 28 4
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReport.vue
  72. 3 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/ScoreBarChart.vue
  73. 13 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue
  74. 13 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/SubjectMould.vue
  75. 269 221
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/composePaper.vue
  76. 201 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/composePaperHw.vue
  77. 3 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue
  78. 25 3
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/ClassPoint.vue
  79. 3 3
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/ExamPerform.vue
  80. 19 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/HomeworkPoint.vue
  81. 14 11
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseListView.vue
  82. 1 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseView/SchoolReport.vue
  83. 25 7
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewnnnnew.less
  84. 182 43
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewnnnnew.vue
  85. 3 3
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/newHomeView.vue
  86. 2 0
      TEAMModelOS/ClientApp/src/components/student-web/achievement/MyAchievement.vue
  87. 30 30
      TEAMModelOS/ClientApp/src/router/routes.js
  88. 141 130
      TEAMModelOS/ClientApp/src/static/Global.js
  89. 4 0
      TEAMModelOS/ClientApp/src/store/module/config.js
  90. 717 16
      TEAMModelOS/ClientApp/src/store/module/dashboard.js
  91. 8 1
      TEAMModelOS/ClientApp/src/store/module/studentWeb.js
  92. 1 1
      TEAMModelOS/ClientApp/src/store/module/user.js
  93. 6 0
      TEAMModelOS/ClientApp/src/utils/blobTool.js
  94. 1 0
      TEAMModelOS/ClientApp/src/utils/editorLangEn.js
  95. 1 0
      TEAMModelOS/ClientApp/src/utils/editorLangTw.js
  96. 151 106
      TEAMModelOS/ClientApp/src/utils/editorTools.js
  97. 5 5
      TEAMModelOS/ClientApp/src/utils/evTools.js
  98. 49 1
      TEAMModelOS/ClientApp/src/utils/js-fn.js
  99. 6 0
      TEAMModelOS/ClientApp/src/utils/public.js
  100. 0 0
      TEAMModelOS/ClientApp/src/view/Home.vue

+ 22 - 3
TEAMModelAPI/Startup.cs

@@ -20,6 +20,7 @@ using TEAMModelOS.SDK.Helper.Common.ReflectorExtensions;
 using System.Reflection;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK;
+using TEAMModelOS.SDK.Models;
 
 namespace TEAMModelAPI
 {
@@ -98,7 +99,7 @@ namespace TEAMModelAPI
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
-        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+        public void Configure(IApplicationBuilder app, IWebHostEnvironment env,AzureStorageFactory azureStorage)
         {
             if (env.IsDevelopment())
             {
@@ -116,14 +117,32 @@ namespace TEAMModelAPI
                 endpoints.MapControllers();
             });
 #if DEBUG
-            //在开发模式时,自检 [ApiToken(Auth = "1")] 有重复的接口
+            //在开发模式时,自检 [ApiToken(Auth = "1")] 有重复的接口 https://teammodelos.table.core.chinacloudapi.cn/IESOpenApi
             List<ApiTokenAttribute> auths = new List<ApiTokenAttribute>();
             List<Attribute> attributes = ReflectorExtensions.GetMethodCustomAttribute<ApiTokenAttribute>(new string[] { "TEAMModelAPI" });
+            List<OpenApi> openApis = new List<OpenApi>();
             attributes.ForEach(x => {
                 ApiTokenAttribute attribute = (ApiTokenAttribute)x;
+                openApis.Add(new OpenApi { 
+                    PartitionKey="IES5-API",
+                    RowKey= attribute.Auth,
+                    auth=int.Parse(attribute.Auth),
+                   // descr=attribute.Name,
+                   method="POST",
+                   name=attribute.Name,
+                    
+                });
                 auths.Add(attribute);
             });
-            auths.GroupBy(x => x.Auth).ToList().ForEach(x => { if (x.Count() > 1) { throw new Exception($"接口Auth重复定义{x.ToList()}"); } });
+          
+            auths.GroupBy(x => x.Auth).ToList().ForEach(x => {
+                if (x.Count() > 1) 
+                { 
+                    throw new Exception($"接口Auth重复定义{x.ToList()}"); 
+                } 
+            });
+
+            var table =  azureStorage.GetCloudTableClient().GetTableReference("IESOpenApi");
 #endif
         }
     }

+ 1 - 1
TEAMModelBI/ClientApp/package.json

@@ -28,7 +28,7 @@
         "qs": "^6.10.1",
         "splitpanes": "^3.1.1",
         "vue": "^3.2.0",
-        "vue-i18n": "^9.2.0-beta.32",
+        "vue-i18n": "^9.2.0-beta.35",
         "vue-loader-v16": "npm:vue-loader@^16.0.0-alpha.3",
         "vue-router": "^4.0.0-rc.5",
         "vue3-count-to": "^1.1.2",

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

@@ -11,7 +11,7 @@
     </title>
 </head>
 <script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
-<script src="https://at.alicdn.com/t/font_2934132_ghuo4dq8cwd.js"></script>
+<script src="https://at.alicdn.com/t/font_2934132_i31vghogqe.js"></script>
 
 <body>
     <noscript>

+ 2 - 1
TEAMModelBI/ClientApp/src/App.vue

@@ -11,6 +11,7 @@ export default {
 <style>
 #app {
     min-width: 1280px;
-    max-width: 1920px;
+    max-width: 100%;
+    font-family: 微軟正黑體, Microsoft JhengHei UI, Microsoft JhengHei !important;
 }
 </style>

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


+ 1 - 1
TEAMModelBI/ClientApp/src/components/Ability.vue

@@ -474,7 +474,7 @@ export default {
     /* width: 600px !important; */
     position: sticky !important;
     top: 0px;
-    background-color: #e9eef3;
+    /* background-color: #e9eef3;*/
     z-index: 999;
     height: 40px;
     line-height: 40px;

+ 3 - 3
TEAMModelBI/ClientApp/src/components/AbilityTree.vue

@@ -605,9 +605,9 @@ export default {
     justify-content: space-between;
 }
 .left-box {
-    width: 600px;
+    width: 42%;
     border-right: 1px dashed rgb(180, 178, 178);
-    padding-right: 20px;
+    /* padding-right: 20px; */
     height: 85vh;
     margin-top: 35px;
     overflow: hidden;
@@ -616,7 +616,7 @@ export default {
     overflow-y: auto;
 }
 .left-box .el-tree {
-    width: 600px;
+    width: 100%;
 }
 .right-box {
     width: 58%;

+ 4 - 2
TEAMModelBI/ClientApp/src/components/echarts/test/online.vue

@@ -16,7 +16,7 @@ export default {
         },
         lineData: {
             type: Array,
-            default: () => {},
+            default: () => { },
         },
         title: {
             type: String,
@@ -87,6 +87,7 @@ class InitChart {
         this.state.chart = echarts.init(this.myEcharts.value)
         this.state.chart.setOption({
             // backgroundColor: '#fff',
+            color: datas.color ? datas.color : [],
             grid: {
                 x: 0,
                 y: 0,
@@ -286,5 +287,6 @@ class InitChart {
     }
 }
 </script>
-<style lang="less"></style>
+<style lang="less">
+</style>
 

+ 4 - 2
TEAMModelBI/ClientApp/src/language/lang/zh-cn.js

@@ -200,8 +200,8 @@ const zh_cn = {
             schoolinfo: {
                 serialnum: '编号',
                 name: '学校名称',
-                phase: '学段',
                 type: '学校类型',
+                phase: '学段类型',
                 assistant: '预设管家',
                 assistantHint: '预设管家手机号码',
                 location: '学校所属位置',
@@ -218,13 +218,15 @@ const zh_cn = {
             hint: {
                 name: 'name: 学校名称',
                 admin: 'admin: 管理员账号',
-                period: ' period: 学类型',
+                period: ' period: 学类型',
                 size: ' size: 空间大小',
                 region: 'region: 国家',
                 province: 'province: 省份',
                 city: 'city: 市级',
                 dist: 'dist: 区域',
                 address: 'address: 详细地址',
+                scales: 'scale:学校规模',
+                types: 'type:学校类型'
             }
         },
         redactSet: '基础设置',

+ 5 - 0
TEAMModelBI/ClientApp/src/store/index.js

@@ -16,6 +16,7 @@ export default createStore({
         changbtnShow: false,
         schoolPower: {},
         nowSchool: {},
+        indexTitle: false
     },
     mutations: {
         //修改组织架构
@@ -63,6 +64,10 @@ export default createStore({
         //当前选中学校 (用于 我参与的学校管理)
         schoolDataInfo(state, value) {
             state.nowSchool = value
+        },
+        //检测是否是首页显示title
+        updateTitlestate(state, value) {
+            state.indexTitle = value
         }
     },
     actions: {},

+ 205 - 58
TEAMModelBI/ClientApp/src/view/areaServe/areamanage.vue

@@ -3,16 +3,21 @@
         <div class="nowtitle">
             <div class="select-List">
                 <div class="province-box">
-                    <span>{{$t('areaManages.selector.provinceName')}}:</span>
-                    <el-select v-model="provinceOptions.provinceValue" :placeholder="$t('areaManages.selector.provinceDefault')" @change="areaSelctChange(provinceOptions.provinceValue,'province')">
-                        <el-option v-for="item in provinceOptions.optionInfo" :key="item.code" :label="item.name" :value="item.name">
+                    <!-- <span>{{$t('areaManages.selector.provinceName')}}:</span> -->
+                    <el-select v-model="provinceOptions.provinceValue"
+                        :placeholder="$t('areaManages.selector.provinceDefault')"
+                        @change="areaSelctChange(provinceOptions.provinceValue, 'province')">
+                        <el-option v-for="item in provinceOptions.optionInfo" :key="item.code" :label="item.name"
+                            :value="item.name">
                         </el-option>
                     </el-select>
                 </div>
                 <div class="city-box">
-                    <span>{{$t('areaManages.selector.cityName')}}:</span>
-                    <el-select v-model="cityOptions.cityValue" :placeholder="$t('areaManages.selector.cityDefault')" @change="areaSelctChange(cityOptions.cityValue,'city')">
-                        <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name" :value="item.name">
+                    <!-- <span>{{$t('areaManages.selector.cityName')}}:</span> -->
+                    <el-select v-model="cityOptions.cityValue" :placeholder="$t('areaManages.selector.cityDefault')"
+                        @change="areaSelctChange(cityOptions.cityValue, 'city')">
+                        <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name"
+                            :value="item.name">
                         </el-option>
                     </el-select>
                 </div>
@@ -44,7 +49,7 @@
                     </div>
                     <span class="text">{{$t(`areaManages.found.creation`)}}</span>
                 </a> -->
-                <el-button size="small" color="#81ecec">
+                <el-button size="small" color="#81ecec" type="primary">
                     <svg class="created-icon" aria-hidden="true">
                         <use xlink:href="#icon-chuangjiandizhisuoyin"></use>
                     </svg>
@@ -53,8 +58,10 @@
             </div>
         </div>
         <div class="traitfrom">
-            <el-table :data="optionData" style="width: 100%" :highlight-current-row="true" height="74vh" v-loading="loading" :empty-text='$t(`commonMsg.nodataTable`)'>
-                <el-table-column prop="index" :label="$t(`areaManages.areaTable.serialnum`)" type=index sortable align="center" />
+            <el-table :data="optionData" style="width: 100%" :highlight-current-row="true" height="74vh"
+                v-loading="loading" :empty-text='$t(`commonMsg.nodataTable`)'>
+                <el-table-column prop="index" :label="$t(`areaManages.areaTable.serialnum`)" type=index sortable
+                    align="center" />
                 <el-table-column prop="name" :label="$t(`areaManages.areaTable.name`)" align="center" />
                 <el-table-column prop="schoolCount" label="区内学校数量" align="center" sortable :sort-method="areaSort" />
                 <el-table-column prop="location" label="位置" align="center" />
@@ -63,7 +70,8 @@
                 <el-table-column prop="standardName" :label="$t(`areaManages.areaTable.project`)" align="center" />
                 <el-table-column :label="$t(`areaManages.areaTable.operate`)" align="center" v-if="PowerShow">
                     <template #default="scope">
-                        <el-button size="mini" @click="operation(scope.$index, scope.row,true)" type="primary">{{$t(`areaManages.areaTable.operate`)}}</el-button>
+                        <el-button size="mini" @click="operation(scope.$index, scope.row, true)" type="primary">
+                            {{ $t(`areaManages.areaTable.operate`) }}</el-button>
                     </template>
                 </el-table-column>
             </el-table>
@@ -73,20 +81,38 @@
                 <el-tabs v-model="activeName">
                     <el-tab-pane :label="$t(`areaManages.operational.areaAddSchool.title`)" name="add">
                         <div class="haveSchool">
-                            <div class="schoolLeft" v-if="notjoinSchool.length !==0">
-                                <p>{{$t(`areaManages.operational.areaAddSchool.schooltitle`)}}</p>
+                            <div class="schoolLeft" v-if="notjoinSchool.length !== 0">
+                                <p>{{ $t(`areaManages.operational.areaAddSchool.schooltitle`) }}</p>
                                 <ul>
-                                    <li class="details-list-school" v-for="(item,index) in notjoinSchool" :key="item.id" :class="{'active':position===index}">
+                                    <li class="details-list-school" v-for="(item, index) in notjoinSchool"
+                                        :key="item.id" :class="{ 'active': position === index }">
                                         <div class="list-school-logo">
-                                            <el-image style="width: 60px; height: 60px" :src="item.picture" :fit="fill"></el-image>
+                                            <el-image style="width: 60px; height: 60px" :src="item.picture" :fit="fill">
+                                            </el-image>
                                         </div>
                                         <div class="list-school-name">
-                                            <div>{{$t(`areaManages.operational.areaAddSchool.schoolList.name`)}}:<span>{{item.name}}</span></div>
-                                            <div>{{$t(`areaManages.operational.areaAddSchool.schoolList.grading`)}}:<span>{{item.period[0]}}</span></div>
-                                            <div>{{$t(`areaManages.operational.areaAddSchool.schoolList.code`)}}:<span>{{item.id}}</span></div>
-                                            <div>{{$t(`areaManages.operational.areaAddSchool.schoolList.location`)}}:<span>{{item.province}}{{item.city}}{{item.dist}}</span></div>
+                                            <div>
+                                                {{ $t(`areaManages.operational.areaAddSchool.schoolList.name`)
+                                                }}:<span>{{ item.name }}</span>
+                                            </div>
+                                            <div>
+                                                {{ $t(`areaManages.operational.areaAddSchool.schoolList.grading`)
+                                                }}:<span>{{ item.period[0] }}</span>
+                                            </div>
+                                            <div>
+                                                {{ $t(`areaManages.operational.areaAddSchool.schoolList.code`)
+                                                }}:<span>{{ item.id }}</span>
+                                            </div>
+                                            <div>
+                                                {{ $t(`areaManages.operational.areaAddSchool.schoolList.location`)
+                                                }}:<span>{{ item.province }}{{ item.city }}{{ item.dist }}</span>
+                                            </div>
                                         </div>
-                                        <el-popconfirm :confirm-button-text="$t(`areaManages.operational.areaAddSchool.add`)" :cancel-button-text="$t(`commonMsg.closes`)" :title="$t(`areaManages.operational.areaAddSchool.addschoolHint`)" @confirm="areaAddschool(item.schoolCode,$event)" @cancel="position=''">
+                                        <el-popconfirm
+                                            :confirm-button-text="$t(`areaManages.operational.areaAddSchool.add`)"
+                                            :cancel-button-text="$t(`commonMsg.closes`)"
+                                            :title="$t(`areaManages.operational.areaAddSchool.addschoolHint`)"
+                                            @confirm="areaAddschool(item.schoolCode, $event)" @cancel="position = ''">
                                             <template #reference>
                                                 <div class="addiconsx" @click="changeStyle(index)">
                                                     <svg class="areaaddschool" aria-hidden="true">
@@ -99,27 +125,46 @@
                                 </ul>
                             </div>
                             <div class="noData" v-else>
-                                <div>{{$t(`commonMsg.nodataTable`)}}</div>
+                                <div>{{ $t(`commonMsg.nodataTable`) }}</div>
                             </div>
                             <div class="schoolRight">
-                                <div class="schoolRight-title">{{$t(`areaManages.operational.areaAddSchool.tabletitle`)}}</div>
+                                <div class="schoolRight-title">
+                                    {{ $t(`areaManages.operational.areaAddSchool.tabletitle`) }}</div>
                                 <div class="schoolRight-table">
                                     <el-table :data="tableDatas" style="width: 100%" max-height="500" height='500'>
-                                        <el-table-column prop="index" :label="$t(`areaManages.operational.areaAddSchool.tables.serialnum`)" width="100" type="index" />
-                                        <el-table-column :label="$t(`areaManages.operational.areaAddSchool.tables.badge`)" width="100" align="center">
+                                        <el-table-column prop="index"
+                                            :label="$t(`areaManages.operational.areaAddSchool.tables.serialnum`)"
+                                            width="100" type="index" />
+                                        <el-table-column
+                                            :label="$t(`areaManages.operational.areaAddSchool.tables.badge`)"
+                                            width="100" align="center">
                                             <template #default="scope">
-                                                <el-image style="width: 70px; height: 70px" :src="scope.row.picture" fit="fill"></el-image>
+                                                <el-image style="width: 70px; height: 70px" :src="scope.row.picture"
+                                                    fit="fill"></el-image>
                                             </template>
                                         </el-table-column>
-                                        <el-table-column prop="name" :label="$t(`areaManages.operational.areaAddSchool.tables.name`)" width="170" align="center" />
-                                        <el-table-column prop="id" :label="$t(`areaManages.operational.areaAddSchool.tables.brevityCode`)" width="120" align="center" />
-                                        <el-table-column prop="province" :label="$t(`areaManages.operational.areaAddSchool.tables.province`)" width="100" align="center" />
-                                        <el-table-column prop="city" :label="$t(`areaManages.operational.areaAddSchool.tables.city`)" width="100" align="center" />
-                                        <el-table-column prop="dist" :label="$t(`areaManages.operational.areaAddSchool.tables.area`)" width="100" align="center" />
-                                        <el-table-column fixed="right" :label="$t(`areaManages.operational.areaAddSchool.tables.operate`)" width="100">
+                                        <el-table-column prop="name"
+                                            :label="$t(`areaManages.operational.areaAddSchool.tables.name`)" width="170"
+                                            align="center" />
+                                        <el-table-column prop="id"
+                                            :label="$t(`areaManages.operational.areaAddSchool.tables.brevityCode`)"
+                                            width="120" align="center" />
+                                        <el-table-column prop="province"
+                                            :label="$t(`areaManages.operational.areaAddSchool.tables.province`)"
+                                            width="100" align="center" />
+                                        <el-table-column prop="city"
+                                            :label="$t(`areaManages.operational.areaAddSchool.tables.city`)" width="100"
+                                            align="center" />
+                                        <el-table-column prop="dist"
+                                            :label="$t(`areaManages.operational.areaAddSchool.tables.area`)" width="100"
+                                            align="center" />
+                                        <el-table-column fixed="right"
+                                            :label="$t(`areaManages.operational.areaAddSchool.tables.operate`)"
+                                            width="100">
                                             <template #default="scope">
-                                                <el-button type="text" size="small" @click.prevent="deleteRow(scope.$index, scope.row)">
-                                                    {{$t(`areaManages.operational.areaAddSchool.tables.areaRemove`)}}
+                                                <el-button type="text" size="small"
+                                                    @click.prevent="deleteRow(scope.$index, scope.row)">
+                                                    {{ $t(`areaManages.operational.areaAddSchool.tables.areaRemove`) }}
                                                 </el-button>
                                             </template>
                                         </el-table-column>
@@ -129,16 +174,30 @@
                         </div>
                     </el-tab-pane>
                     <el-tab-pane :label="$t(`areaManages.operational.abilitys.title`)" name="adjust">
-                        <div class="areaAbilitys" v-if="abilityModel ===true">
+                        <div class="areaAbilitys" v-if="abilityModel === true">
                             <Ability :selectObject="currentlySelect.standard"></Ability>
                         </div>
-                        <div class="cuttable" v-else-if="abilityModel ===false">
-                            <div class="nowAbility"><i class="diansInfo"></i><span class="now-title">{{$t(`areaManages.operational.abilitys.now`)}}:</span><span class="contents">{{currentlySelect.name}}—{{currentlySelect.standardName}}—{{currentlySelect.institution}}</span></div>
-                            <el-table :data="tableData" style="width: 100%" :highlight-current-row="true" @row-click="cutpitch">
-                                <el-table-column prop="index" :label="$t(`areaManages.operational.abilitys.tables.serialnum`)" width="180" type=index align="center" />
-                                <el-table-column prop="standardName" :label="$t(`areaManages.operational.abilitys.tables.name`)" width="180" align="center" />
-                                <el-table-column prop="name" :label="$t(`areaManages.operational.abilitys.tables.source`)" align="center" />
-                                <el-table-column prop="institution" :label="$t(`areaManages.operational.abilitys.tables.affiliation`)" align="center" />
+                        <div class="cuttable" v-else-if="abilityModel === false">
+                            <div class="nowAbility"><i class="diansInfo"></i><span class="now-title">{{
+                                    $t(`areaManages.operational.abilitys.now`)
+                            }}:</span><span class="contents">{{
+        currentlySelect.name
+}}—{{ currentlySelect.standardName }}—{{
+        currentlySelect.institution
+}}</span>
+                            </div>
+                            <el-table :data="tableData" style="width: 100%" :highlight-current-row="true"
+                                @row-click="cutpitch">
+                                <el-table-column prop="index"
+                                    :label="$t(`areaManages.operational.abilitys.tables.serialnum`)" width="180"
+                                    type=index align="center" />
+                                <el-table-column prop="standardName"
+                                    :label="$t(`areaManages.operational.abilitys.tables.name`)" width="180"
+                                    align="center" />
+                                <el-table-column prop="name"
+                                    :label="$t(`areaManages.operational.abilitys.tables.source`)" align="center" />
+                                <el-table-column prop="institution"
+                                    :label="$t(`areaManages.operational.abilitys.tables.affiliation`)" align="center" />
                                 <el-table-column label="" width="100" align="center">
                                     <template #default="scope">
                                         <svg class="cuticon" aria-hidden="true" v-show="scope.row.laterPitch">
@@ -148,30 +207,40 @@
                                 </el-table-column>
                             </el-table>
                             <div class="cuttable-btn">
-                                <el-button type="primary" @click="confirm">{{$t(`commonMsg.confirm`)}}</el-button>
-                                <el-button @click="adjustmentbox = false">{{$t(`commonMsg.closes`)}}</el-button>
+                                <el-button type="primary" @click="confirm">{{ $t(`commonMsg.confirm`) }}</el-button>
+                                <el-button @click="adjustmentbox = false">{{ $t(`commonMsg.closes`) }}</el-button>
                             </div>
                         </div>
                     </el-tab-pane>
                 </el-tabs>
-                <div class="cut-ability" v-if="activeName ==='adjust'" @click="abilityModel=!abilityModel">
+                <div class="cut-ability" v-if="activeName === 'adjust'" @click="abilityModel = !abilityModel">
                     <el-button type="primary" size="small" plain>
                         <svg class="cuticon" aria-hidden="true">
                             <use :xlink:href="cutbtnTitle.icon"></use>
                         </svg>
-                        {{cutbtnTitle.name}}
+                        {{ cutbtnTitle.name }}
                     </el-button>
                 </div>
             </el-dialog>
             <el-dialog v-model="CutNotarize" width="50%" :before-close="handleClose" :show-close="false">
-                <div class="reminder">注意:<span>{{$t(`areaManages.operational.abilitys.cuthint`)}}</span></div>
+                <div class="reminder">注意:<span>{{ $t(`areaManages.operational.abilitys.cuthint`) }}</span></div>
                 <div class="cutboxs">
                     <div class="now">
-                        <p><span class="cutbox-title">{{$t(`areaManages.operational.abilitys.objdata.name`)}}:</span><span class="cutbox-name">{{currentlySelect.name}}</span></p>
+                        <p><span class="cutbox-title">{{ $t(`areaManages.operational.abilitys.objdata.name`)
+                        }}:</span><span class="cutbox-name">{{ currentlySelect.name }}</span></p>
                         <div class="restbox">
-                            <div><span class="general-title">{{$t(`areaManages.operational.abilitys.objdata.project`)}}:</span><span class="general-content">{{currentlySelect.standardName}}</span></div>
-                            <div><span class="general-title">{{$t(`areaManages.operational.abilitys.objdata.affiliation`)}}:</span><span class="general-content">{{currentlySelect.institution}}</span></div>
-                            <div><span class="general-title">{{$t(`areaManages.operational.abilitys.objdata.areas`)}}:</span><span class="general-content">{{currentlySelect.provName}}{{currentlySelect.cityName}}</span></div>
+                            <div><span class="general-title">{{ $t(`areaManages.operational.abilitys.objdata.project`)
+                            }}:</span><span class="general-content">{{ currentlySelect.standardName }}</span>
+                            </div>
+                            <div><span class="general-title">{{
+                                    $t(`areaManages.operational.abilitys.objdata.affiliation`)
+                            }}:</span><span class="general-content">{{ currentlySelect.institution }}</span>
+                            </div>
+                            <div><span class="general-title">{{ $t(`areaManages.operational.abilitys.objdata.areas`)
+                            }}:</span><span class="general-content">{{ currentlySelect.provName }}{{
+        currentlySelect.cityName
+}}</span>
+                            </div>
                         </div>
                     </div>
                     <div class="cutpastIcon" :loading="true">
@@ -180,27 +249,39 @@
                         </svg>
                     </div>
                     <div class="now">
-                        <p><span class="cutbox-title">{{$t(`areaManages.operational.abilitys.objdata.name`)}}:</span><span class="cutbox-name">{{replaceProject.name}}</span></p>
+                        <p><span class="cutbox-title">{{ $t(`areaManages.operational.abilitys.objdata.name`)
+                        }}:</span><span class="cutbox-name">{{ replaceProject.name }}</span></p>
                         <div class="restbox">
-                            <div><span class="general-title">{{$t(`areaManages.operational.abilitys.objdata.project`)}}:</span><span class="general-content">{{replaceProject.standardName}}</span></div>
-                            <div><span class="general-title">{{$t(`areaManages.operational.abilitys.objdata.affiliation`)}}:</span><span class="general-content">{{replaceProject.institution}}</span></div>
-                            <div><span class="general-title">{{$t(`areaManages.operational.abilitys.objdata.areas`)}}:</span><span class="general-content">{{replaceProject.provName}}{{replaceProject.city}}</span></div>
+                            <div><span class="general-title">{{ $t(`areaManages.operational.abilitys.objdata.project`)
+                            }}:</span><span class="general-content">{{ replaceProject.standardName }}</span>
+                            </div>
+                            <div><span class="general-title">{{
+                                    $t(`areaManages.operational.abilitys.objdata.affiliation`)
+                            }}:</span><span class="general-content">{{ replaceProject.institution }}</span>
+                            </div>
+                            <div><span class="general-title">{{ $t(`areaManages.operational.abilitys.objdata.areas`)
+                            }}:</span><span class="general-content">{{ replaceProject.provName }}{{
+        replaceProject.city
+}}</span>
+                            </div>
                         </div>
                     </div>
                 </div>
                 <template #footer>
                     <div class="hint" v-show="loadingForm.cutAbility">
-                        <p>{{$t(`areaManages.operational.abilitys.cutTitle`)}}</p>
+                        <p>{{ $t(`areaManages.operational.abilitys.cutTitle`) }}</p>
                         <loadingsz></loadingsz>
                         <!-- <el-table v-loading="loadingForm.cutAbility" empty-text="   " style="width: 100%">
                         </el-table> -->
                     </div>
                     <div class="cut-footer">
                         <span class="dialog-footer">
-                            <el-button @click="CutNotarize = false" v-if="loadingForm.cutAbility===false">{{$t(`commonMsg.closes`)}}</el-button>
-                            <el-button disabled v-else>{{$t(`commonMsg.closes`)}}</el-button>
+                            <el-button @click="CutNotarize = false" v-if="loadingForm.cutAbility === false">
+                                {{ $t(`commonMsg.closes`) }}</el-button>
+                            <el-button disabled v-else>{{ $t(`commonMsg.closes`) }}</el-button>
                             <!-- <el-button type="primary" @click="loadingForm.cutAbility=true" :loading="loadingForm.cutAbility">确认</el-button> -->
-                            <el-button type="primary" @click="notarizeAbility(),loadingForm.cutAbility=true" :loading="loadingForm.cutAbility">{{$t(`commonMsg.confirm`)}}</el-button>
+                            <el-button type="primary" @click="notarizeAbility(), loadingForm.cutAbility = true"
+                                :loading="loadingForm.cutAbility">{{ $t(`commonMsg.confirm`) }}</el-button>
                         </span>
                     </div>
                 </template>
@@ -346,6 +427,7 @@ export default {
                 oldStandard: currentlySelect.value.standard,
                 newId: newPrecept.value.id,
                 newStandard: newPrecept.value.standard,
+                newName:replaceProject.value.name,
                 tmdId: user.tmdId,
                 tmdName: user.tmdName,
             }
@@ -528,12 +610,14 @@ export default {
     /* background-color: #fff; */
     padding: 5px 10px;
 }
+
 .boxselect {
     width: 20%;
     display: inline-block;
     margin-top: 1.5%;
     padding-right: 1%;
 }
+
 .created-areaicon {
     width: 1.3em;
     height: 1.3em;
@@ -542,22 +626,26 @@ export default {
     overflow: hidden;
     margin-top: -135px;
 }
+
 .schoolLeft {
     width: 35%;
     padding: 0.5%;
     border-right: 1px dashed #ccc;
     float: left;
 }
+
 .schoolLeft p {
     line-height: 20px;
     margin-bottom: 0;
     color: #909399;
 }
+
 .schoolLeft ul {
     padding: 0;
     max-height: 530px;
     overflow-y: auto;
 }
+
 .details-list-school {
     padding: 20px 40px 20px 15px;
     display: flex;
@@ -565,41 +653,51 @@ export default {
     line-height: 22px;
     position: relative;
 }
+
 .details-list-school:hover {
     background-color: #dadada;
 }
+
 .details-list-school:hover .addiconsx {
     display: inline-block;
 }
+
 .active {
     background-color: #dadada;
 }
+
 /* .active .addicon {
     display: block;
 } */
 .list-school-logo {
     width: 20%;
 }
+
 .list-school-name {
     width: 65%;
     padding-left: 1%;
 }
+
 .list-school-name div {
     font-size: 14px;
     color: #909399;
 }
+
 .list-school-name div span {
     color: #303133;
 }
+
 .addiconsx {
     position: absolute;
     right: 5%;
     top: 35%;
     display: none;
 }
+
 .addiconsx:hover {
     cursor: pointer;
 }
+
 .areaaddschool {
     width: 2em !important;
     height: 2em !important;
@@ -607,28 +705,34 @@ export default {
     fill: currentColor !important;
     overflow: hidden !important;
 }
+
 .schoolRight {
     width: 60%;
     float: left;
 }
+
 .schoolRight-title {
     width: 100%;
     text-align: center;
     font-weight: 800;
     font-size: 18px;
 }
+
 .schoolRight-table {
     min-height: 55vh;
     padding: 1% 2%;
 }
+
 .cut-ability {
     position: absolute;
     top: 0%;
     right: 3%;
 }
+
 .nowAbility {
     line-height: 20px;
 }
+
 .diansInfo {
     content: '';
     display: inline-block;
@@ -637,15 +741,18 @@ export default {
     margin-right: 10px;
     margin-bottom: 2px;
 }
+
 .now-title {
     color: #757575;
     font-weight: 600;
     font-size: 14px;
 }
+
 .contents {
     font-size: 14px;
     font-weight: 550;
 }
+
 .cuticon {
     width: 1.1em;
     height: 1.1em;
@@ -654,12 +761,14 @@ export default {
     overflow: hidden;
     margin-right: 5px;
 }
+
 .cutboxs {
     display: flex;
     width: 80%;
     margin: 0 auto;
     text-align: center;
 }
+
 .now {
     width: 35%;
     line-height: 20px;
@@ -669,22 +778,27 @@ export default {
     text-align: center;
     background-color: aliceblue;
 }
+
 .cutbox-title {
     color: #757575;
     font-size: 16px;
 }
+
 .restbox {
     text-align: left;
 }
+
 .cutbox-name {
     color: #333;
     font-size: 16px;
     font-weight: 600;
 }
+
 .general-title {
     font-size: 14px;
     color: #757575;
 }
+
 .cutsbigIcon {
     width: 5.5em;
     height: 5.5em;
@@ -693,20 +807,24 @@ export default {
     overflow: hidden;
     margin-top: 35%;
 }
+
 .cutpastIcon {
     width: 15%;
     text-align: center;
     margin: 0% 5%;
 }
+
 .reminder {
     font-size: 14px;
     line-height: 120px;
     color: red;
 }
+
 .cut-footer {
     text-align: center;
     line-height: 60px;
 }
+
 .noData {
     width: 35%;
     height: 60vh;
@@ -714,6 +832,7 @@ export default {
     border-right: 1px dashed #ccc;
     float: left;
 }
+
 .noData div {
     width: 100%;
     height: 100%;
@@ -726,24 +845,28 @@ export default {
     align-items: center;
     color: #ccc;
 }
+
 .select-List {
     line-height: 60px;
     text-align: left;
-    padding: 1% 2%;
+    padding: 1%;
     width: 75%;
     float: left;
     font-weight: normal;
 }
+
 .province-box,
 .city-box,
 .dist-box,
 .close-box {
     display: inline-block;
 }
+
 .city-box,
 .dist-box {
     margin-left: 1%;
 }
+
 .closebtnIcon {
     width: 1.8em;
     height: 1.8em;
@@ -752,17 +875,21 @@ export default {
     overflow: hidden;
     margin-left: 8px;
 }
+
 .closebtnIcon:hover {
     cursor: pointer;
 }
+
 .hint {
     width: 100%;
     text-align: center;
 }
+
 .hint p {
     font-size: 16px;
     color: #1da1f2;
 }
+
 .created-icon {
     width: 1.3em;
     height: 1.3em;
@@ -777,26 +904,32 @@ export default {
     margin-top: 5% !important;
     margin-left: 150px !important;
 }
+
 .traitfrom {
     width: 98%;
     margin: 0 auto;
     /* padding: 1%; */
 }
+
 .traitfrom .el-form-item {
     width: 50%;
     margin: 0 auto;
 }
+
 .traitfrom .el-form-item__label {
     font-size: 16px;
 }
+
 .traitfrom .el-select {
     width: 100%;
 }
+
 .nowtitle {
     font-weight: bold;
     line-height: 20px;
     text-align: right;
 }
+
 .cuttable {
     width: 98%;
     padding: 1%;
@@ -804,14 +937,17 @@ export default {
     overflow-y: hidden;
     position: relative;
 }
+
 .cuttable-btn {
     width: 16%;
     margin: 0 auto;
 }
+
 .adjustmentDialog .el-dialog__header {
     line-height: 60px;
     padding: 0px !important;
 }
+
 .cuticon {
     width: 2em;
     height: 2em;
@@ -820,40 +956,51 @@ export default {
     overflow: hidden;
     margin-right: 5px;
 }
+
 .adjustmentDialog .el-dialog {
     line-height: 60px;
 }
+
 .details-list-school .el-image {
     margin-top: 25%;
 }
+
 .areamanabox .el-table__header-wrapper {
     line-height: 60px;
 }
+
 .cuttable .el-table--fit {
     width: 100%;
     height: 58vh;
     overflow: auto;
 }
+
 .adjustmentDialog .el-dialog {
     --el-dialog-margin-top: 9vh;
 }
+
 .adjustmentDialog .el-dialog__body {
     padding-top: 0px !important;
 }
+
 .adjustmentDialog .el-tabs__header {
     margin: 0px !important;
 }
+
 .adjustmentDialog .el-dialog__headerbtn {
     top: -15px;
     right: 8px;
 }
+
 .manage-table .el-image {
     margin-top: 3%;
 }
+
 .traitfrom .el-table::before,
 .schoolRight-table .el-table::before {
     width: 0px;
 }
+
 .areamanabox .el-tabs__header {
     height: 50px !important;
     line-height: 50px !important;

+ 32 - 6
TEAMModelBI/ClientApp/src/view/common/aside.vue

@@ -4,27 +4,29 @@
             <img src="@/assets/img/logox.png">
         </div>
         <el-aside :width="menuWidth">
-            <el-menu :default-active="currentRoutePath" :default-openeds="opens" class="el-menu-vertical-demo" :collapse="isCollapse" @select="handleSelect" :collapse-transition="locksetting" background-color="#1d1e23" text-color="#fff" unique-opened="true">
+            <el-menu :default-active="currentRoutePath" :default-openeds="opens" class="el-menu-vertical-demo"
+                :collapse="isCollapse" @select="handleSelect" :collapse-transition="locksetting"
+                background-color="#1d1e23" text-color="#fff" unique-opened="true">
                 <div v-for="item in menuList" :key="item.sort" class="menu-title">
                     <el-menu-item v-if="!item.child.length" :index="item.router">
                         <svg class="icon" aria-hidden="true">
                             <use :xlink:href="item.icon"></use>
                         </svg>
-                        <span @click="routerskip(item.router)">{{item.name}}</span>
+                        <span @click="routerskip(item.router)">{{ item.name }}</span>
                     </el-menu-item>
                     <el-sub-menu :index="item.sort" v-else>
                         <template #title>
                             <svg class="icon" aria-hidden="true">
                                 <use :xlink:href="item.icon"></use>
                             </svg>
-                            {{item.name}}
+                            {{ item.name }}
                         </template>
                         <el-menu-item v-for="items in item.child" :key="items.sort" :index="items.router">
                             <div @click="routerskip(items.router)" class="subordinate">
                                 <svg class="icon" aria-hidden="true">
                                     <use :xlink:href="items.icon"></use>
                                 </svg>
-                                {{items.name}}
+                                {{ items.name }}
                             </div>
                         </el-menu-item>
                     </el-sub-menu>
@@ -327,6 +329,9 @@ export default {
             //router内容
             let nowUrl = routers.currentRoute.value.path
             console.log(nowUrl, '现在url')
+            nowUrl.includes('/home/index') ? store.commit('updateTitlestate',true):store.commit('updateTitlestate',false)
+            console.log(nowUrl.includes('/home/index'), '11111222333')
+            console.log(store.state.indexTitle)
         })
         watch(
             store.state,
@@ -349,6 +354,7 @@ export default {
             console.log(val, '跳转的')
             console.log(proxy)
             routers.push(val)
+            val.includes('/home/index') ? store.commit('updateTitlestate',true):store.commit('updateTitlestate',false)
         }
         function mouseOver() {
             if (lockState.value) {
@@ -417,12 +423,14 @@ export default {
 .asidebox {
     position: relative;
 }
+
 .el-aside {
     background-color: #d3dce6;
     color: var(--el-text-color-primary);
     text-align: center;
     line-height: 200px;
 }
+
 .el-container:nth-child(5) .el-aside,
 .el-container:nth-child(6) .el-aside {
     line-height: 260px;
@@ -431,7 +439,8 @@ export default {
 .el-container:nth-child(7) .el-aside {
     line-height: 320px;
 }
-body > .el-container {
+
+body>.el-container {
     margin-bottom: 40px;
 }
 
@@ -443,15 +452,19 @@ body > .el-container {
 .el-container:nth-child(7) .el-aside {
     line-height: 320px;
 }
+
 .el-menu-vertical-demo:not(.el-menu--collapse) {
     width: 200px;
     min-height: 400px;
 }
+
 @font-face {
-    font-family: 'iconfont'; /* Project id 2934132 */
+    font-family: 'iconfont';
+    /* Project id 2934132 */
     src: url('https://at.alicdn.com/t/font_2934132_tn15yic1prg.woff2?t=1636790178979') format('woff2'), url('https://at.alicdn.com/t/font_2934132_tn15yic1prg.woff?t=1636790178979') format('woff'),
         url('https://at.alicdn.com/t/font_2934132_tn15yic1prg.ttf?t=1636790178979') format('truetype');
 }
+
 .iconfont {
     font-family: 'iconfont' !important;
     font-size: 22px;
@@ -460,12 +473,15 @@ body > .el-container {
     -webkit-text-stroke-width: 0.2px;
     -moz-osx-font-smoothing: grayscale;
 }
+
 .el-radio-button__inner {
     font-size: 18px !important;
 }
+
 .el-radio-button {
     background-color: rgb(238, 241, 246) !important;
 }
+
 .icon,
 .lockicon {
     width: 1.5em;
@@ -475,6 +491,7 @@ body > .el-container {
     overflow: hidden;
     margin-right: 25px;
 }
+
 .lockicon {
     width: 1em;
     height: 1em;
@@ -483,9 +500,11 @@ body > .el-container {
     overflow: hidden;
     margin-right: 5px;
 }
+
 .lockicon:hover {
     cursor: pointer;
 }
+
 .locks {
     position: absolute;
     width: 64px;
@@ -494,29 +513,36 @@ body > .el-container {
     line-height: 40px;
     border-top: 1px solid #ccc;
 }
+
 .MenuBox {
     width: 64px;
 }
+
 .viewbox .el-header {
     background-color: #1d1e23 !important;
     opacity: 0.97 !important;
     border-bottom: 2px solid #1cc0f3;
 }
+
 .viewbox .el-main {
     background-color: #fdfdfd;
 }
+
 .logobox {
     width: 100%;
     line-height: 58px;
     border-bottom: 2px solid #1cc0f3;
     text-align: center;
 }
+
 .MenuBox .el-menu-vertical-demo {
     overflow: hidden;
 }
+
 .subordinate {
     padding-left: 10px;
 }
+
 .el-menu--inline {
     background-color: #101117;
 }

+ 118 - 20
TEAMModelBI/ClientApp/src/view/common/header.vue

@@ -1,21 +1,12 @@
 <template>
     <el-header style="text-align: right; font-size: 12px">
-        <div class="logsbox" :title="$t(`header.log`)" @click="pushlog">
-            <!-- <div class="iconimg">
-                <svg class="log-icon" aria-hidden="true">
-                    <use xlink:href="#icon-caozuorizhi-copy"></use>
-                </svg>
+        <div class="logsbox">
+           <div v-show="store.state.indexTitle"><span>TEAMModel·BI 数据监控系统</span></div>
+            <div class="showTime" @click="detectionsize(screen.state)" v-show="store.state.indexTitle">
+                    <svg class="skip" aria-hidden="true">
+                        <use :xlink:href="screen.icon"></use>
+                    </svg>
             </div>
-            <div class="icontext">
-                <sapn style="color:#fff">操作日志</sapn>
-            </div> -->
-            <!-- <el-button plain icon="el-icon-s-order" size="mini">{{$t(`header.log`)}}</el-button> -->
-            <!-- <el-button size="small">
-                <svg class="log-icon" aria-hidden="true">
-                    <use xlink:href="#icon-caozuorizhi-copy"></use>
-                </svg>
-                <span>操作日志</span>
-            </el-button> -->
         </div>
         <div class="userbox">
             <el-dropdown>
@@ -55,6 +46,8 @@ import { reactive, toRefs, getCurrentInstance, ref, onMounted } from 'vue'
 import { ElMessage } from 'element-plus'
 import router from '@/router/index.js'
 import jwt_decode from 'jwt-decode'
+import { useRouter } from 'vue-router'
+import { useStore } from 'vuex'
 export default {
     setup() {
         let { proxy } = getCurrentInstance()
@@ -62,9 +55,46 @@ export default {
         let state = ref({
             circleUrl: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
         })
+        let screen = ref({
+            icon: '#icon-quanping-copy',
+            state: false,
+        })
+        let titleShow=ref(false)
         const isAdmin = jwt_decode(JSON.parse(localStorage.getItem('id_token'))).roles.includes('admin')
+        const routers = useRouter()
+        const store = useStore()
         onMounted(() => {
             state.value.circleUrl = user.avatar ? user.avatar : false
+                        window.onresize = function () {
+                var explorer = window.navigator.userAgent.toLowerCase()
+                console.log(explorer, '全屏的值')
+                console.log(routers.currentRoute.value.path, '当前的路由')
+                if (routers.currentRoute.value.path.indexOf('/home/index') === -1) {
+                    return
+                }
+                if (explorer.indexOf('chrome') > 0) {
+                    //webkit
+                    if (document.body.scrollHeight === window.screen.height && document.body.scrollWidth === window.screen.width) {
+                        // alert('全屏')
+                        fullScreen()
+                        // screen.value.icon = '#icon-tuichuquanping-fill-copy'
+                    } else {
+                        // alert('不全屏')
+                        // exitFullscreen()
+                        // screen.value.icon = '#icon-quanping-copy'
+                    }
+                } else {
+                    //IE 9+  fireFox
+                    if (window.outerHeight === window.screen.height && window.outerWidth === window.screen.width) {
+                        // alert('全屏')
+                        fullScreen()
+                    } else {
+                        // alert('不全屏')
+                        // exitFullscreen()
+                    }
+                }
+                console.log(Width, Height, '宽高值')
+            }
         })
         function quit() {
             router.push('/login')
@@ -75,16 +105,65 @@ export default {
             localStorage.removeItem('organization')
             // localStorage.clear()
         }
-        function pushlog() {
-            router.push('/home/log')
+        // function pushlog() {
+        //     router.push('/home/log')
+        // }
+         //查看当前状态 切换成全屏或不全屏
+        function detectionsize(state) {
+            console.log(state)
+            fullScreen()
+        }
+        //全屏
+        function fullScreen() {
+            console.log('调用全屏')
+            var element = document.documentElement
+            let aside = document.getElementsByClassName('MenuBox')
+            let header = document.getElementsByClassName('el-header')
+            if (element.requestFullscreen) {
+                element.requestFullscreen()
+            } else if (element.msRequestFullscreen) {
+                element.msRequestFullscreen()
+            } else if (element.mozRequestFullScreen) {
+                element.mozRequestFullScreen()
+            } else if (element.webkitRequestFullscreen) {
+                element.webkitRequestFullscreen()
+            }
+            aside[0].style.display = 'none'
+            header[0].style.display = 'none'
+            screen.value.state = true
+        }
+        //退出全屏
+        function exitFullscreen() {
+            console.log('调用半屏')
+            let aside = document.getElementsByClassName('MenuBox')
+            let header = document.getElementsByClassName('el-header')
+            if (document.exitFullscreen) {
+                console.log(document.exitFullscreen)
+                document.exitFullscreen()
+            } else if (document.msExitFullscreen) {
+                document.msExitFullscreen()
+            } else if (document.mozCancelFullScreen) {
+                document.mozCancelFullScreen()
+            } else if (document.webkitExitFullscreen) {
+                document.webkitExitFullscreen()
+            }
+            aside[0].style.display = 'block'
+            header[0].style.display = 'block'
+            screen.value.state = false
         }
         return {
             state,
             proxy,
             user,
             quit,
-            pushlog,
             isAdmin,
+            screen,
+            detectionsize,
+            fullScreen,
+            exitFullscreen,
+            titleShow,
+            routers,
+            store
         }
     },
 }
@@ -113,8 +192,21 @@ export default {
     margin-top: 5px;
 }
 .logsbox {
-    padding-top: 0.35%;
-    padding-right: 0.5%;
+   color:#fff;
+   font-size:34px;
+   text-align: center;
+   width:95%;
+   line-height: 50px;;
+   position: relative;
+}
+.skip {
+    width: 25px;
+    height: 25px;
+    fill: currentColor;
+    overflow: hidden;
+    margin-right: 5px;
+    vertical-align: 20px;
+    cursor: pointer;
 }
 .iconimg,
 .icontext {
@@ -124,6 +216,12 @@ export default {
 .icontext {
     margin-top: 2%;
 }
+.showTime {
+    position: absolute;
+    top: 15%;
+    right: 5%;
+    font-size: 0.25rem;
+}
 </style>
 <style>
 .header-icon {

Dosya farkı çok büyük olduğundan ihmal edildi
+ 584 - 458
TEAMModelBI/ClientApp/src/view/created/created.vue


Dosya farkı çok büyük olduğundan ihmal edildi
+ 374 - 208
TEAMModelBI/ClientApp/src/view/index/index.vue


+ 15 - 1
TEAMModelBI/ClientApp/src/view/login.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="backgorundbox">
         <div class="loginbox">
-            <div class="logintitle">{{$t(`login.title`)}}</div>
+            <div class="logintitle">{{ $t(`login.title`) }}</div>
             <!-- <div class="usrpwd" v-if="loginModel">
                 <div class='userbox' style="margin-bottom:10%">
                     <el-input v-model="user" placeholder="醍摩豆ID/手机号码" prefix-icon="el-icon-user" />
@@ -234,6 +234,7 @@ export default {
     position: relative;
     /* filter: blur(2px); */
 }
+
 .loginbox {
     position: absolute;
     width: 550px;
@@ -243,10 +244,12 @@ export default {
     border-radius: 10px;
     box-shadow: 1px 1px 5px #ccc;
 }
+
 .usrpwd {
     height: 330px;
     text-align: center;
 }
+
 .logintitle {
     text-align: center;
     font-size: 20px;
@@ -254,15 +257,18 @@ export default {
     margin-bottom: 8%;
     margin-top: 5%;
 }
+
 .userbox {
     text-align: center;
     width: 60%;
     margin: 0 auto;
     position: relative;
 }
+
 .none {
     display: none;
 }
+
 .loginbtn {
     position: absolute;
     display: block;
@@ -272,6 +278,7 @@ export default {
     height: 44px;
     line-height: 43px;
 }
+
 .not_has_more {
     margin: 30px 0px 20px 0px;
     line-height: 50px;
@@ -284,6 +291,7 @@ export default {
     color: rgba(140, 142, 165, 1);
     line-height: 30px;
 }
+
 .not_has_more::after,
 .not_has_more::before {
     position: absolute;
@@ -294,12 +302,15 @@ export default {
     top: 15px;
     right: 28%;
 }
+
 .not_has_more::after {
     left: 28%;
 }
+
 .ddlogin {
     margin-top: 3%;
 }
+
 .cut {
     position: absolute;
     top: 0px;
@@ -311,10 +322,12 @@ export default {
     height: 45px;
     border-radius: 30px;
 }
+
 .el-loading-spinner {
     margin-top: 0 !important;
     transform: translateY(-50%);
 }
+
 .el-loading-text {
     padding-top: 50px;
     background-image: url('../assets/img/loading2.gif') !important;
@@ -322,6 +335,7 @@ export default {
     background-position: top center;
     background-size: 75px auto;
 }
+
 .el-loading-spinner .circular {
     display: none;
 }

+ 128 - 48
TEAMModelBI/ClientApp/src/view/participation/index.vue

@@ -1,29 +1,38 @@
 <template>
     <!--学校列表-->
-    <div class="schoolbox" v-show="models==='default'">
+    <div class="schoolboxtad" v-show="models === 'default'">
         <div class="select-List">
             <div class="province-box">
-                <span>{{$t(`areaManages.selector.provinceName`)}}:</span>
-                <el-select v-model="provinceOptions.provinceValue" :placeholder="$t(`areaManages.selector.provinceDefault`)" @change="areaSelctChange(provinceOptions.provinceValue,'province')">
-                    <el-option v-for="item in provinceOptions.optionInfo" :key="item.code" :label="item.name" :value="item.name">
+                <span>{{ $t(`areaManages.selector.provinceName`) }}:</span>
+                <el-select v-model="provinceOptions.provinceValue"
+                    :placeholder="$t(`areaManages.selector.provinceDefault`)"
+                    @change="areaSelctChange(provinceOptions.provinceValue, 'province')">
+                    <el-option v-for="item in provinceOptions.optionInfo" :key="item.code" :label="item.name"
+                        :value="item.name">
                     </el-option>
                 </el-select>
             </div>
             <div class="city-box">
-                <span>{{$t(`areaManages.selector.cityName`)}}:</span>
-                <el-select v-model="cityOptions.cityValue" :placeholder="$t(`areaManages.selector.cityDefault`)" @change="areaSelctChange(cityOptions.cityValue,'city')">
-                    <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name" :value="item.name">
+                <span>{{ $t(`areaManages.selector.cityName`) }}:</span>
+                <el-select v-model="cityOptions.cityValue" :placeholder="$t(`areaManages.selector.cityDefault`)"
+                    @change="areaSelctChange(cityOptions.cityValue, 'city')">
+                    <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name"
+                        :value="item.name">
                     </el-option>
                 </el-select>
             </div>
             <div class="dist-box">
-                <span>{{$t(`areaManages.selector.areaName`)}}:</span>
-                <el-select v-model="distOptions.distValue" filterable allow-create default-first-option :placeholder="$t(`areaManages.selector.areaDefault`)" @change="areaSelctChange(distOptions.distValue,'dist')">
-                    <el-option v-for="item in distOptions.distInfo" :key="item.code" :label="item.name" :value="item.name">
+                <span>{{ $t(`areaManages.selector.areaName`) }}:</span>
+                <el-select v-model="distOptions.distValue" filterable allow-create default-first-option
+                    :placeholder="$t(`areaManages.selector.areaDefault`)"
+                    @change="areaSelctChange(distOptions.distValue, 'dist')">
+                    <el-option v-for="item in distOptions.distInfo" :key="item.code" :label="item.name"
+                        :value="item.name">
                     </el-option>
                 </el-select>
             </div>
-            <div class="close-box" v-show="provinceOptions.provinceValue || cityOptions.cityValue ||distOptions.distValue">
+            <div class="close-box"
+                v-show="provinceOptions.provinceValue || cityOptions.cityValue || distOptions.distValue">
                 <svg class="closebtnIcon" aria-hidden="true" @click="closeSelectarea">
                     <use xlink:href="#icon-quxiao"></use>
                 </svg>
@@ -38,8 +47,10 @@
             </el-button>
         </div> -->
         <div class="school-list">
-            <el-table :data="tableData" style="width: 100%" height="75vh" v-loading="loading" element-loading-text="加载中...">
-                <el-table-column prop="index" :label="$t(`schoolManages.tables.serialnum`)" type="index" sortable align="center" />
+            <el-table :data="tableData" style="width: 100%" height="75vh" v-loading="loading"
+                element-loading-text="加载中...">
+                <el-table-column prop="index" :label="$t(`schoolManages.tables.serialnum`)" type="index" sortable
+                    align="center" />
                 <el-table-column :label="$t(`schoolManages.tables.badge`)" width="150" align="center">
                     <template #default="scope">
                         <el-image style="width: 70px; height: 70px" :src="scope.row.picture" fit="fill"></el-image>
@@ -53,9 +64,14 @@
                 </el-table-column> -->
                 <el-table-column :label="$t(`schoolManages.tables.scale`)" class="school-table-edition" align="center">
                     <template #default="scope">
-                        <el-image style="width: 80px; height: 80px" :src="imgData.basics" fit="fill" v-if="scope.row.scale ===0"></el-image>
-                        <el-image style="width: 80px; height: 80px" :src="imgData.standard" fit="fill" v-else-if="scope.row.scale ===500 && scope.row.hard.length===0 && scope.row.serial.length ===0 && scope.row.service.length ===0"></el-image>
-                        <el-image style="width: 80px; height: 80px" :src="imgData.specialty" fit="fill" v-else-if="scope.row.scale ===500 && (scope.row.hard.length !=0 || scope.row.serial.length !=0 || scope.row.service.length !=0)"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.basics" fit="fill"
+                            v-if="scope.row.scale === 0"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.standard" fit="fill"
+                            v-else-if="scope.row.scale === 500 && scope.row.hard.length === 0 && scope.row.serial.length === 0 && scope.row.service.length === 0">
+                        </el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.specialty" fit="fill"
+                            v-else-if="scope.row.scale === 500 && (scope.row.hard.length != 0 || scope.row.serial.length != 0 || scope.row.service.length != 0)">
+                        </el-image>
                     </template>
                 </el-table-column>
                 <el-table-column prop="id" :label="$t(`schoolManages.tables.brevityCode`)" align="center" />
@@ -65,7 +81,7 @@
                             <svg class="created-icon" aria-hidden="true">
                                 <use xlink:href="#icon-shuju"></use>
                             </svg>
-                            {{scope.row.lessonCount}}
+                            {{ scope.row.lessonCount }}
                         </div>
                         <div v-else>暂无</div>
                     </template>
@@ -76,7 +92,7 @@
                 <el-table-column prop="size" :label="$t(`schoolManages.tables.spacesize`)" align="center" />
                 <el-table-column :label="$t(`schoolManages.tables.assis`)" align="center">
                     <template #default="scope">
-                        <div v-if="scope.row.assisName">{{scope.row.assisName}}</div>
+                        <div v-if="scope.row.assisName">{{ scope.row.assisName }}</div>
                         <div v-else>暂无</div>
                     </template>
                 </el-table-column>
@@ -101,9 +117,10 @@
                     </template>
                 </el-table-column>
                 <!-- <el-table-column prop="state" label="状态" width="110" align="center" /> -->
-                <el-table-column :label="$t(`schoolManages.tables.operate`)" align="center" v-if="PowerShow">
+                <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)">
+                            {{ $t(`schoolManages.tables.operatecontent`) }}</el-button>
                         <!-- <el-button type="danger" size="small" @click="removeSchool(scope.row,scope.$index)">删除</el-button> -->
                     </template>
                 </el-table-column>
@@ -113,12 +130,13 @@
     <!--学校列表end-->
     <!--编辑学校页面-->
     <div class="schoolDeatils">
-        <div class="backbtn" v-if="models==='details' && PowerShow">
-            <el-button class="changebtn" v-if="store.state.changbtnShow && changebtns" @click="getSetschool()" size="small">
+        <div class="backbtn" v-if="models === 'details' && PowerShow">
+            <el-button class="changebtn" v-if="store.state.changbtnShow && changebtns" @click="getSetschool()"
+                size="small">
                 <svg class="changebtn-areaicon" aria-hidden="true">
                     <use xlink:href="#icon-wenjian"></use>
                 </svg>
-                <span class="changebtn-title">{{$t(`schoolManages.gradSet.save`)}}</span>
+                <span class="changebtn-title">{{ $t(`schoolManages.gradSet.save`) }}</span>
             </el-button>
             <el-button type="primary" size="small" @click="schoolClose">
                 <svg class="back-icon" aria-hidden="true">
@@ -127,20 +145,23 @@
                 返回
             </el-button>
         </div>
-        <el-tabs v-if="models==='details' && PowerShow" @tab-click="changeTabs">
+        <el-tabs v-if="models === 'details' && PowerShow" @tab-click="changeTabs">
             <!--基础设置-->
             <el-tab-pane :label="$t(`schoolManages.redactSet`)">
-                <div class="redactbox" v-show="models==='details' && PowerShow">
+                <div class="redactbox" v-show="models === 'details' && PowerShow">
                     <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-form-item :label="$t(`schoolManages.basicSet.name`) + ':'" class="school-form-name">
                                 <el-input v-model="nowPitchdata.name"></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">
-                                    <el-image style="width: 100%; height:125px" :src="nowPitchdata.picture" fit="contain"></el-image>
+                            <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">
+                                    <el-image style="width: 100%; height:125px" :src="nowPitchdata.picture"
+                                        fit="contain"></el-image>
                                     <div class="changebadge">
-                                        <el-button>{{$t(`schoolManages.basicSet.badgeChange`)}}</el-button>
+                                        <el-button>{{ $t(`schoolManages.basicSet.badgeChange`) }}</el-button>
                                     </div>
                                 </el-upload>
                             </el-form-item>
@@ -151,9 +172,11 @@
                                 <el-checkbox v-model="nowPitchdata.period[3].value" label="职高"></el-checkbox>
                                 <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-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-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`)">
@@ -161,13 +184,17 @@
                                     </el-option>
                                 </el-select>
                             </el-form-item> -->
-                            <el-form-item :label="$t(`schoolManages.basicSet.brevityCode`)+':'" class="school-form-code">
-                                <el-input disabled :placeholder="nowPitchdata.id" v-if="nowPitchdata.id !==null" />
-                                <el-input disabled :placeholder="$t(`schoolManages.basicSet.notCode`)" v-else="nowPitchdata.id ==null" />
+                            <el-form-item :label="$t(`schoolManages.basicSet.brevityCode`) + ':'"
+                                class="school-form-code">
+                                <el-input disabled :placeholder="nowPitchdata.id" v-if="nowPitchdata.id !== null" />
+                                <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-option v-for="item in areaSelect.data" :key="item.name" :label="item.name" :value="item.id">
+                                <el-select v-model="areaSelect.Selectvalue"
+                                    :placeholder="$t(`schoolManages.basicSet.region`)">
+                                    <el-option v-for="item in areaSelect.data" :key="item.name" :label="item.name"
+                                        :value="item.id">
                                     </el-option>
                                 </el-select>
                             </el-form-item>
@@ -177,15 +204,17 @@
                             <!-- <el-form-item :label="$t(`schoolManages.basicSet.location`)+':'" class="school-form-site">
                                 <el-input disabled :placeholder="nowPitchdata.address" />
                             </el-form-item> -->
-                            <el-form-item :label="$t(`schoolManages.basicSet.spacesize`)+':'" class="school-form-size">
+                            <el-form-item :label="$t(`schoolManages.basicSet.spacesize`) + ':'"
+                                class="school-form-size">
                                 <el-input-number v-model="nowPitchdata.size" :min="1" :max="1000" />GB
                             </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-button @click="schoolClose">{{$t(`commonMsg.closes`)}}</el-button>
+                                <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>
                     </div>
@@ -349,8 +378,8 @@ export default {
             nowPitchdata.value.areaId = data.areaId
             data.assists.length
                 ? data.assists.forEach((element) => {
-                      adminvalue.value.push(element.tmdId)
-                  })
+                    adminvalue.value.push(element.tmdId)
+                })
                 : ''
             let token = JSON.parse(localStorage.getItem('id_token'))
             uploadHeader.value['x-auth-authtoken'] = token
@@ -530,7 +559,7 @@ export default {
         function updateSuccess() {
             loading.value = true
             setTimeout(() => {
-                ;(models.value = 'default'), (tableData.value = []), getAllschool()
+                ; (models.value = 'default'), (tableData.value = []), getAllschool()
             }, 2000)
         }
         //地区选择close btn
@@ -657,11 +686,12 @@ export default {
 }
 </script>
 <style scoped>
-.schoolbox {
+.schoolboxtad {
     width: 100%;
     margin: 0 auto;
     line-height: 80px;
 }
+
 .select-List {
     line-height: 60px;
     text-align: left;
@@ -669,18 +699,21 @@ export default {
     width: 75%;
     float: left;
 }
+
 .school-list {
     width: 96%;
     max-height: 74vh;
     margin: 0 auto;
     /* overflow-y: auto; */
 }
+
 /*编辑页面样式*/
 .redactbox {
     width: 100%;
     height: 87vh;
     background-color: #fff;
 }
+
 .backbtn {
     text-align: left;
     position: absolute;
@@ -689,28 +722,35 @@ export default {
     z-index: 999;
     line-height: 40px;
 }
+
 .school-formbox {
     width: 85%;
     margin: 0 auto;
     padding: 1%;
 }
+
 .upload-demo-redact {
     width: 100%;
     height: 125px;
 }
+
 .school-form-name {
     width: 50%;
 }
+
 .school-form-area {
     width: 35%;
 }
+
 .school-form-badge,
 .school-form-code {
     width: 24%;
 }
+
 .school-form-grading {
     width: 80%;
 }
+
 .changebadge {
     width: 100%;
     height: 125px;
@@ -719,20 +759,25 @@ export default {
     left: 0px;
     opacity: 0;
 }
+
 .school-form-site {
     width: 35%;
 }
+
 .school-form-size {
     width: 21%;
     color: #bdc3c7;
 }
+
 .school-form-admin {
     width: 35%;
     text-align: left;
 }
+
 .school-form-state {
     width: 15%;
 }
+
 .school-admin-check {
     width: 2em;
     height: 2em;
@@ -740,16 +785,19 @@ export default {
     fill: currentColor;
     overflow: hidden;
 }
+
 .province-box,
 .city-box,
 .dist-box,
 .close-box {
     display: inline-block;
 }
+
 .city-box,
 .dist-box {
     margin-left: 1%;
 }
+
 /*btn*/
 .boxselect {
     width: 20%;
@@ -757,6 +805,7 @@ export default {
     margin-top: 0.5%;
     text-align: right;
 }
+
 .created-areaicon {
     width: 1.3em;
     height: 1.3em;
@@ -765,6 +814,7 @@ export default {
     overflow: hidden;
     margin-top: -135px;
 }
+
 .closebtnIcon {
     width: 1.8em;
     height: 1.8em;
@@ -773,20 +823,25 @@ export default {
     overflow: hidden;
     margin-left: 8px;
 }
+
 .closebtnIcon:hover {
     cursor: pointer;
 }
+
 .schoolDeatils {
     position: relative;
     background: #e9eef3;
 }
+
 .changebtn {
     display: inline-block;
     /* float: right; */
 }
+
 .changebtn-title {
     font-size: 12px;
 }
+
 .changebtn-areaicon {
     width: 0.9em;
     height: 0.9em;
@@ -794,6 +849,7 @@ export default {
     fill: currentColor;
     margin-right: 3px;
 }
+
 .back-icon {
     width: 0.9em;
     height: 0.9em;
@@ -801,6 +857,7 @@ export default {
     fill: currentColor;
     margin-right: 3px;
 }
+
 .created-icon {
     width: 1.3em;
     height: 1.3em;
@@ -809,6 +866,7 @@ export default {
     overflow: hidden;
     margin-right: 5px;
 }
+
 .school-analyse {
     width: 1.8em;
     height: 1.8em;
@@ -817,6 +875,7 @@ export default {
     overflow: hidden;
     cursor: pointer;
 }
+
 .have-modules {
     display: flex;
     justify-content: space-between;
@@ -824,57 +883,71 @@ export default {
 }
 </style>
 <style>
-.schoolbox .el-cascader {
+.schoolboxtad .el-cascader {
     width: 20%;
 }
+
 .school-form-badge .el-form-item__label {
     line-height: 107px;
 }
+
 .school-form-badge .el-form-item__content {
     border: 1px solid #ccc;
     position: relative;
 }
+
 .changebadge .el-button {
     width: 100%;
     height: 100%;
     font-size: 18px;
     color: #fff;
 }
+
 .changebadge .el-button span {
     border: 1px solid #ccc;
     background-color: #409eff;
     padding: 5px;
     border-radius: 10px;
 }
+
 .changebadge:hover {
     opacity: 0.8;
 }
+
 .school-form-code .el-input__inner {
     text-align: center;
 }
+
 .school-form-admin .el-select {
     width: 100%;
 }
+
 .school-form-badge .el-image__inner {
     width: 100%;
     height: 85%;
     margin-top: 10%;
 }
+
 .school-form-grading .el-form-item__content {
     text-align: left;
 }
+
 .el-select-dropdown__item {
     padding: 0 12px 0 20px;
 }
+
 .school-formbox .el-form-item__content {
     text-align: left;
 }
+
 .school-form-area .el-select {
     width: 100%;
 }
+
 .school-list .el-table__header-wrapper {
     line-height: 60px;
 }
+
 .schoolDeatils .el-tabs__header {
     height: 45px;
     line-height: 45px;
@@ -884,16 +957,20 @@ export default {
     background-color: #fff;
     margin: 0px 0px 1px;
 }
+
 .schoolDeatils .el-tabs__content {
     padding: 0px;
 }
+
 .backbtn .changebtn {
     padding: 8px 15px;
 }
+
 .upload-demo-redact .el-upload {
     width: 100%;
     height: 125px;
 }
+
 .school-form-grading .el-radio__input.is-checked .el-radio__inner::after {
     content: '';
     width: 10px;
@@ -911,16 +988,19 @@ export default {
     border-radius: 0px;
     background: none;
 }
+
 .schoolDeatils .el-tabs__nav-wrap::after {
     width: 0%;
 }
-.el-upload-dragger {
-}
+
+.el-upload-dragger {}
+
 @media screen and (max-width: 1920px) {
     .school-formbox .school-form-badge {
         width: 17.5%;
     }
 }
+
 @media screen and (max-width: 1400px) {
     .school-formbox .school-form-badge {
         width: 24%;

Dosya farkı çok büyük olduğundan ihmal edildi
+ 250 - 92
TEAMModelBI/ClientApp/src/view/participation/setAbility.vue


+ 212 - 68
TEAMModelBI/ClientApp/src/view/schoolServe/school.vue

@@ -1,36 +1,45 @@
 <template>
     <!--学校列表-->
-    <div class="schoolbox" v-show="models==='default'">
+    <div class="schoolboxea" v-show="models === 'default'">
         <div class="select-List">
             <div class="province-box">
-                <span>{{$t(`areaManages.selector.provinceName`)}}:</span>
-                <el-select v-model="provinceOptions.provinceValue" :placeholder="$t(`areaManages.selector.provinceDefault`)" @change="areaSelctChange(provinceOptions.provinceValue,'province')">
-                    <el-option v-for="item in provinceOptions.optionInfo" :key="item.code" :label="item.name" :value="item.name">
+                <!-- <span>{{$t(`areaManages.selector.provinceName`)}}:</span> -->
+                <el-select v-model="provinceOptions.provinceValue"
+                    :placeholder="$t(`areaManages.selector.provinceDefault`)"
+                    @change="areaSelctChange(provinceOptions.provinceValue, 'province')">
+                    <el-option v-for="item in provinceOptions.optionInfo" :key="item.code" :label="item.name"
+                        :value="item.name">
                     </el-option>
                 </el-select>
             </div>
             <div class="city-box">
-                <span>{{$t(`areaManages.selector.cityName`)}}:</span>
-                <el-select v-model="cityOptions.cityValue" :placeholder="$t(`areaManages.selector.cityDefault`)" @change="areaSelctChange(cityOptions.cityValue,'city')">
-                    <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name" :value="item.name">
+                <!-- <span>{{$t(`areaManages.selector.cityName`)}}:</span> -->
+                <el-select v-model="cityOptions.cityValue" :placeholder="$t(`areaManages.selector.cityDefault`)"
+                    @change="areaSelctChange(cityOptions.cityValue, 'city')">
+                    <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name"
+                        :value="item.name">
                     </el-option>
                 </el-select>
             </div>
             <div class="dist-box">
-                <span>{{$t(`areaManages.selector.areaName`)}}:</span>
-                <el-select v-model="distOptions.distValue" filterable allow-create default-first-option :placeholder="$t(`areaManages.selector.areaDefault`)" @change="areaSelctChange(distOptions.distValue,'dist')">
-                    <el-option v-for="item in distOptions.distInfo" :key="item.code" :label="item.name" :value="item.name">
+                <!-- <span>{{$t(`areaManages.selector.areaName`)}}:</span> -->
+                <el-select v-model="distOptions.distValue" filterable allow-create default-first-option
+                    :placeholder="$t(`areaManages.selector.areaDefault`)"
+                    @change="areaSelctChange(distOptions.distValue, 'dist')">
+                    <el-option v-for="item in distOptions.distInfo" :key="item.code" :label="item.name"
+                        :value="item.name">
                     </el-option>
                 </el-select>
             </div>
-            <div class="close-box" v-show="provinceOptions.provinceValue || cityOptions.cityValue ||distOptions.distValue">
+            <div class="close-box"
+                v-show="provinceOptions.provinceValue || cityOptions.cityValue || distOptions.distValue">
                 <svg class="closebtnIcon" aria-hidden="true" @click="closeSelectarea">
                     <use xlink:href="#icon-quxiao"></use>
                 </svg>
             </div>
         </div>
         <div class="boxselect" v-if="PowerShow">
-            <el-button size="small" @click="createdSchoolbtn">
+            <el-button size="small" @click="createdSchoolbtn" type="primary">
                 <svg class="created-icon" aria-hidden="true">
                     <use xlink:href="#icon-chuangjianx"></use>
                 </svg>
@@ -38,8 +47,10 @@
             </el-button>
         </div>
         <div class="school-list">
-            <el-table :data="tableData" style="width: 100%" height="75vh" v-loading="loading" element-loading-text="加载中...">
-                <el-table-column prop="index" :label="$t(`schoolManages.tables.serialnum`)" type="index" sortable align="center" />
+            <el-table :data="tableData" style="width: 100%" height="75vh" v-loading="loading"
+                element-loading-text="加载中...">
+                <el-table-column prop="index" :label="$t(`schoolManages.tables.serialnum`)" type="index" sortable
+                    align="center" />
                 <el-table-column :label="$t(`schoolManages.tables.badge`)" width="150" align="center">
                     <template #default="scope">
                         <el-image style="width: 70px; height: 70px" :src="scope.row.picture" fit="fill"></el-image>
@@ -53,9 +64,14 @@
                 </el-table-column> -->
                 <el-table-column :label="$t(`schoolManages.tables.scale`)" class="school-table-edition" align="center">
                     <template #default="scope">
-                        <el-image style="width: 80px; height: 80px" :src="imgData.basics" fit="fill" v-if="scope.row.scale ===0"></el-image>
-                        <el-image style="width: 80px; height: 80px" :src="imgData.standard" fit="fill" v-else-if="scope.row.scale ===500 && scope.row.hard.length ===0 && scope.row.serial.length ===0 && scope.row.service.length ===0"></el-image>
-                        <el-image style="width: 80px; height: 80px" :src="imgData.specialty" fit="fill" v-else-if="scope.row.scale ===500 && (scope.row.hard.length !=0 || scope.row.serial.length !=0 || scope.row.service.length !=0)"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.basics" fit="fill"
+                            v-if="scope.row.scale === 0"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.standard" fit="fill"
+                            v-else-if="scope.row.scale === 500 && scope.row.hard.length === 0 && scope.row.serial.length === 0 && scope.row.service.length === 0">
+                        </el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.specialty" fit="fill"
+                            v-else-if="scope.row.scale === 500 && (scope.row.hard.length != 0 || scope.row.serial.length != 0 || scope.row.service.length != 0)">
+                        </el-image>
                     </template>
                 </el-table-column>
                 <el-table-column prop="id" :label="$t(`schoolManages.tables.brevityCode`)" align="center" />
@@ -65,7 +81,7 @@
                             <svg class="created-icon" aria-hidden="true">
                                 <use xlink:href="#icon-shuju"></use>
                             </svg>
-                            {{scope.row.lessonCount}}
+                            {{ scope.row.lessonCount }}
                         </div>
                         <div v-else>暂无</div>
                     </template>
@@ -76,7 +92,7 @@
                 <el-table-column prop="size" :label="$t(`schoolManages.tables.spacesize`)" align="center" />
                 <el-table-column :label="$t(`schoolManages.tables.assis`)" align="center">
                     <template #default="scope">
-                        <div v-if="scope.row.assisName">{{scope.row.assisName}}</div>
+                        <div v-if="scope.row.assisName">{{ scope.row.assisName }}</div>
                         <div v-else>暂无</div>
                     </template>
                 </el-table-column>
@@ -103,8 +119,11 @@
                 <!-- <el-table-column prop="state" label="状态" width="110" align="center" /> -->
                 <el-table-column :label="$t(`schoolManages.tables.operate`)" align="center" v-if="PowerShow">
                     <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="danger" size="small" @click="removeSchool(scope.row,scope.$index)">删除</el-button>
+                        <el-button type="primary" size="small" @click.prevent="deleteRow(scope.$index, scope.row)">
+                            {{ $t(`schoolManages.tables.operatecontent`) }}</el-button>
+                        <el-button class="deletebtns" type="danger" size="small"
+                            @click="removeSchool(scope.row, scope.$index)">删 除
+                        </el-button>
                     </template>
                 </el-table-column>
             </el-table>
@@ -113,12 +132,13 @@
     <!--学校列表end-->
     <!--编辑学校页面-->
     <div class="schoolDeatils">
-        <div class="backbtn" v-if="models==='details' && PowerShow">
-            <el-button class="changebtn" v-if="store.state.changbtnShow && changebtns" @click="getSetschool()" size="small">
+        <div class="backbtn" v-if="models === 'details' && PowerShow">
+            <el-button class="changebtn" v-if="store.state.changbtnShow && changebtns" @click="getSetschool()"
+                size="small">
                 <svg class="changebtn-areaicon" aria-hidden="true">
                     <use xlink:href="#icon-wenjian"></use>
                 </svg>
-                <span class="changebtn-title">{{$t(`schoolManages.gradSet.save`)}}</span>
+                <span class="changebtn-title">{{ $t(`schoolManages.gradSet.save`) }}</span>
             </el-button>
             <el-button type="primary" size="small" @click="schoolClose">
                 <svg class="back-icon" aria-hidden="true">
@@ -127,20 +147,31 @@
                 返回
             </el-button>
         </div>
-        <el-tabs v-if="models==='details' && PowerShow" @tab-click="changeTabs">
+        <el-tabs v-if="models === 'details' && PowerShow" @tab-click="changeTabs">
             <!--基础设置-->
             <el-tab-pane :label="$t(`schoolManages.redactSet`)">
-                <div class="redactbox" v-show="models==='details' && PowerShow">
+                <div class="redactbox" v-show="models === 'details' && PowerShow" v-loading="loadingSchoolUpdate" element-loading-background="rgba(0, 0, 0, 0.3)" element-loading-text="正在修改学校基础信息,请稍等...">
                     <div class="school-formbox">
+                        <!-- <p class="school-update-header">
+                            <div class="iconsdiv">
+                                 <svg class="schoolIcons" aria-hidden="true">
+                                    <use xlink:href="#icon-xuexiao"></use>
+                                 </svg>
+                            </div>
+                            <div class="school-update-title"><span>学校基础信息</span></div>
+                        </p> -->
                         <el-form ref="form" :model="nowPitchdata" label-width="120px">
-                            <el-form-item :label="$t(`schoolManages.basicSet.name`)+':'" class="school-form-name">
+                            <el-form-item :label="$t(`schoolManages.basicSet.name`)" class="school-form-name">
                                 <el-input v-model="nowPitchdata.name"></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">
-                                    <el-image style="width: 100%; height:125px" :src="nowPitchdata.picture" fit="contain"></el-image>
+                            <el-form-item label="学校徽章" 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">
+                                    <el-image :src="nowPitchdata.picture"
+                                        fit="contain"></el-image>
                                     <div class="changebadge">
-                                        <el-button>{{$t(`schoolManages.basicSet.badgeChange`)}}</el-button>
+                                        <el-button>{{ $t(`schoolManages.basicSet.badgeChange`) }}</el-button>
                                     </div>
                                 </el-upload>
                             </el-form-item>
@@ -151,13 +182,19 @@
                                 <el-checkbox v-model="nowPitchdata.period[3].value" label="职高"></el-checkbox>
                                 <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-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-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`)">
-                                    <el-option v-for="item in adminoptions" :key="item.name" :label="item.mobile+'——'+item.name" :value="item.tmdId ===null ? '':item.tmdId" :disabled="!item.tmdId">
+                            <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`)">
+                                    <el-option v-for="item in adminoptions" :key="item.name"
+                                        :label="item.mobile + '——' + item.name"
+                                        :value="item.tmdId === null ? '' : item.tmdId" :disabled="!item.tmdId">
                                         <!-- <span style="float: left">{{ item.mobile }}-{{item.name}}</span>
                             <i style="float: right;color: var(--el-text-color-secondary);font-size: 13px;" v-show="item.isexist === false">
                                 <svg class="school-admin-check" aria-hidden="true">
@@ -167,31 +204,39 @@
                                     </el-option>
                                 </el-select>
                             </el-form-item>
-                            <el-form-item :label="$t(`schoolManages.basicSet.brevityCode`)+':'" class="school-form-code">
-                                <el-input disabled :placeholder="nowPitchdata.id" v-if="nowPitchdata.id !==null" />
-                                <el-input disabled :placeholder="$t(`schoolManages.basicSet.notCode`)" v-else="nowPitchdata.id ==null" />
+                            <el-form-item :label="$t(`schoolManages.basicSet.brevityCode`)"
+                                class="school-form-code">
+                                <el-input disabled :placeholder="nowPitchdata.id" v-if="nowPitchdata.id !== null" />
+                                <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-option v-for="item in areaSelect.data" :key="item.name" :label="item.name" :value="item.id">
+                                <el-select v-model="areaSelect.Selectvalue"
+                                    :placeholder="$t(`schoolManages.basicSet.region`)">
+                                    <el-option v-for="item in areaSelect.data" :key="item.name" :label="item.name"
+                                        :value="item.id">
                                     </el-option>
                                 </el-select>
                             </el-form-item>
-                            <el-form-item :label="$t(`schoolManages.basicSet.scale`)+':'" class="school-form-size">
-                                <el-input-number v-model="nowPitchdata.scale" :min="0" :step="100" />人
+                            <el-form-item :label="$t(`schoolManages.basicSet.scale`)" class="school-form-size">
+                                <!-- <el-input-number v-model="nowPitchdata.scale" :min="0" :step="100" /><span>人</span> -->
+                                <el-slider v-model="nowPitchdata.scale" :step="100" show-stops show-input :min='0' :max='1000' />
                             </el-form-item>
                             <!-- <el-form-item :label="$t(`schoolManages.basicSet.location`)+':'" class="school-form-site">
                                 <el-input disabled :placeholder="nowPitchdata.address" />
                             </el-form-item> -->
-                            <el-form-item :label="$t(`schoolManages.basicSet.spacesize`)+':'" class="school-form-size">
-                                <el-input-number v-model="nowPitchdata.size" :min="1" :max="1000" />GB
+                            <el-form-item :label="$t(`schoolManages.basicSet.spacesize`)"
+                                class="school-form-size">
+                                <!-- <el-input-number v-model="nowPitchdata.size" :min="1" :max="1000" /><span>GB</span> -->
+                                <el-slider v-model="nowPitchdata.size" :step="100" show-stops show-input :min='0' :max='1000' />
                             </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-button @click="schoolClose">{{$t(`commonMsg.closes`)}}</el-button>
+                            <el-form-item class="updatebtn">
+                                <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>
                     </div>
@@ -314,6 +359,7 @@ export default {
             { id: 5, name: '卷卡合一阅卷系统', icon: '#icon-pingtai_kaoshi', key: 'VABAJ6NV' },
             { id: 6, name: '教研中心模组', icon: '#icon-jiaoyan', key: 'VLY6J6N6' },
         ])
+        let loadingSchoolUpdate=ref(false)
         provinceOptions.value.optionInfo = optionsData
         console.log(store.state.point)
         //所有学校列表
@@ -376,8 +422,8 @@ export default {
             nowPitchdata.value.areaId = data.areaId
             data.assists.length
                 ? data.assists.forEach((element) => {
-                      adminvalue.value.push(element.tmdId)
-                  })
+                    adminvalue.value.push(element.tmdId)
+                })
                 : ''
             let token = JSON.parse(localStorage.getItem('id_token'))
             uploadHeader.value['x-auth-authtoken'] = token
@@ -493,6 +539,11 @@ export default {
         }
         // 确认修改学校信息
         function updateSchoolinfo() {
+            const loadingUpdate = ElLoading.service({
+                lock: true,
+                text: '正在修改基础数据,请稍后...',
+                background: 'rgba(0, 0, 0, 0.7)',
+            })
             let user = JSON.parse(localStorage.getItem('userData'))
             //修改表单
             let assistData = adminvalue.value
@@ -517,6 +568,7 @@ export default {
             console.log(updateForm, '学校信息')
             proxy.$api.updateSchoolinfo(updateForm).then((res) => {
                 console.log(res, '修改学校的返回')
+                loadingUpdate.close()
                 res.state === 200
                     ? (ElMessage.success(proxy.$t(`commonMsg.schoolUpdateSuccess`), schoolJoinarea(), schoolClose()), updateSuccess())
                     : ElMessage.error(proxy.$t(`commonMsg.schoolUpdateError`))
@@ -557,7 +609,7 @@ export default {
         function updateSuccess() {
             loading.value = true
             setTimeout(() => {
-                ;(models.value = 'default'), (tableData.value = []), getAllschool()
+                ; (models.value = 'default'), (tableData.value = []), getAllschool()
             }, 2000)
         }
         //地区选择close btn
@@ -677,35 +729,39 @@ export default {
             skipAnalyse,
             schooldataSort,
             removeSchool,
+            loadingSchoolUpdate
         }
     },
 }
 </script>
 <style scoped>
-.schoolbox {
+.schoolboxea {
     width: 100%;
     margin: 0 auto;
     line-height: 80px;
 }
+
 .select-List {
     line-height: 60px;
     text-align: left;
     padding: 1% 2%;
-    width: 75%;
+    width: 80%;
     float: left;
 }
+
 .school-list {
     width: 96%;
     max-height: 74vh;
     margin: 0 auto;
     /* overflow-y: auto; */
 }
+
 /*编辑页面样式*/
 .redactbox {
     width: 100%;
     height: 87vh;
-    background-color: #fff;
 }
+
 .backbtn {
     text-align: left;
     position: absolute;
@@ -714,28 +770,38 @@ export default {
     z-index: 999;
     line-height: 40px;
 }
+
 .school-formbox {
-    width: 85%;
-    margin: 0 auto;
-    padding: 1%;
+    width: 98%;
+    padding: 1% 1%;
+    margin:1%;
+    border:1px solid #ccc;
+    border-radius: 10px;
+    background:#fff;
 }
+
 .upload-demo-redact {
     width: 100%;
     height: 125px;
 }
+
 .school-form-name {
-    width: 50%;
+    width: 31%;
 }
+
 .school-form-area {
-    width: 35%;
+    width: 31%;
 }
+
 .school-form-badge,
 .school-form-code {
     width: 24%;
 }
+
 .school-form-grading {
     width: 80%;
 }
+
 .changebadge {
     width: 100%;
     height: 125px;
@@ -744,20 +810,25 @@ export default {
     left: 0px;
     opacity: 0;
 }
+
 .school-form-site {
-    width: 35%;
+    width: 31%;
 }
+
 .school-form-size {
-    width: 35%;
+    width: 31%;
     color: #bdc3c7;
 }
+
 .school-form-admin {
-    width: 35%;
+    width: 31%;
     text-align: left;
 }
+
 .school-form-state {
     width: 15%;
 }
+
 .school-admin-check {
     width: 2em;
     height: 2em;
@@ -765,23 +836,27 @@ export default {
     fill: currentColor;
     overflow: hidden;
 }
+
 .province-box,
 .city-box,
 .dist-box,
 .close-box {
     display: inline-block;
 }
+
 .city-box,
 .dist-box {
     margin-left: 1%;
 }
+
 /*btn*/
 .boxselect {
-    width: 20%;
+    width: 15%;
     display: inline-block;
     margin-top: 0.5%;
     text-align: right;
 }
+
 .created-areaicon {
     width: 1.3em;
     height: 1.3em;
@@ -790,6 +865,7 @@ export default {
     overflow: hidden;
     margin-top: -135px;
 }
+
 .closebtnIcon {
     width: 1.8em;
     height: 1.8em;
@@ -798,20 +874,25 @@ export default {
     overflow: hidden;
     margin-left: 8px;
 }
+
 .closebtnIcon:hover {
     cursor: pointer;
 }
+
 .schoolDeatils {
     position: relative;
     background: #e9eef3;
 }
+
 .changebtn {
     display: inline-block;
     /* float: right; */
 }
+
 .changebtn-title {
     font-size: 12px;
 }
+
 .changebtn-areaicon {
     width: 0.9em;
     height: 0.9em;
@@ -819,6 +900,7 @@ export default {
     fill: currentColor;
     margin-right: 3px;
 }
+
 .back-icon {
     width: 0.9em;
     height: 0.9em;
@@ -826,6 +908,7 @@ export default {
     fill: currentColor;
     margin-right: 3px;
 }
+
 .created-icon {
     width: 1.3em;
     height: 1.3em;
@@ -834,6 +917,7 @@ export default {
     overflow: hidden;
     margin-right: 5px;
 }
+
 .school-analyse {
     width: 1.8em;
     height: 1.8em;
@@ -842,64 +926,106 @@ export default {
     overflow: hidden;
     cursor: pointer;
 }
+
 .have-modules {
     display: flex;
     justify-content: space-between;
     overflow-x: auto;
 }
+.schoolIcons{
+    width: 1.5em;
+    height: 1.5em;
+    fill: currentColor;
+    overflow: hidden;
+    line-height: 1.2em;
+    margin-left: 2px;
+    margin-right:5px;
+}
+.iconsdiv,.school-update-title{
+    display: inline-block;
+    vertical-align: top;
+    font-weight: bold;
+}
+.school-update-header{
+    font-size: 22px;
+    font-weight: 400;
+    line-height: 30px;
+    text-align: left;
+    position: relative;
+    padding-left:30px;
+}
+.school-update-title{
+    margin-top:5px;
+}
+.updatebtn{
+    margin-top:5%;
+}
 </style>
 <style>
-.schoolbox .el-cascader {
+.schoolboxea .el-cascader {
     width: 20%;
 }
+
 .school-form-badge .el-form-item__label {
     line-height: 107px;
 }
+
 .school-form-badge .el-form-item__content {
     border: 1px solid #ccc;
     position: relative;
 }
+
 .changebadge .el-button {
     width: 100%;
     height: 100%;
     font-size: 18px;
     color: #fff;
 }
+
 .changebadge .el-button span {
     border: 1px solid #ccc;
     background-color: #409eff;
     padding: 5px;
     border-radius: 10px;
 }
+
 .changebadge:hover {
     opacity: 0.8;
 }
+
 .school-form-code .el-input__inner {
     text-align: center;
 }
+
 .school-form-admin .el-select {
     width: 100%;
 }
+
 .school-form-badge .el-image__inner {
     width: 100%;
-    height: 85%;
-    margin-top: 10%;
+    height: 100%;
 }
+
 .school-form-grading .el-form-item__content {
     text-align: left;
 }
+
 .el-select-dropdown__item {
     padding: 0 12px 0 20px;
 }
+
 .school-formbox .el-form-item__content {
     text-align: left;
 }
+
 .school-form-area .el-select {
     width: 100%;
 }
+
 .school-list .el-table__header-wrapper {
     line-height: 60px;
 }
+
 .schoolDeatils .el-tabs__header {
     height: 45px;
     line-height: 45px;
@@ -909,16 +1035,20 @@ export default {
     background-color: #fff;
     margin: 0px 0px 1px;
 }
+
 .schoolDeatils .el-tabs__content {
     padding: 0px;
 }
+
 .backbtn .changebtn {
     padding: 8px 15px;
 }
+
 .upload-demo-redact .el-upload {
     width: 100%;
     height: 125px;
 }
+
 .school-form-grading .el-radio__input.is-checked .el-radio__inner::after {
     content: '';
     width: 10px;
@@ -936,19 +1066,33 @@ export default {
     border-radius: 0px;
     background: none;
 }
+
 .schoolDeatils .el-tabs__nav-wrap::after {
     width: 0%;
 }
-.el-upload-dragger {
+.school-formbox .el-form-item__label{
+    padding: 0 31px 0 0;
+    font-weight: 700;
+    font-size:14px;
+}
+.upload-demo-redact .el-image{
+    width:100%;
+    height:125px;
 }
 @media screen and (max-width: 1920px) {
     .school-formbox .school-form-badge {
         width: 17.5%;
     }
 }
+
 @media screen and (max-width: 1400px) {
     .school-formbox .school-form-badge {
         width: 24%;
     }
+
+    .deletebtns {
+        margin-left: 0px !important;
+        margin-top: 5px;
+    }
 }
 </style>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 434 - 182
TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue


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

@@ -1,13 +1,14 @@
 <template>
     <div class="school-analyse">
-        <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+        <!-- <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
             <el-tab-pane label="数据分析" name="first">
                 <Schoolanalyse></Schoolanalyse>
             </el-tab-pane>
             <el-tab-pane label="学校列表" name="second">
                 <SchoolManage></SchoolManage>
             </el-tab-pane>
-        </el-tabs>
+        </el-tabs> -->
+        <Schoolanalyse></Schoolanalyse>
     </div>
 </template>
 <script>
@@ -29,7 +30,7 @@ export default {
 .school-analyse {
     width: 100%;
     line-height: 20px;
-    padding: 0% 1%;
+    padding: 1%;
 }
 </style>
 <style>

+ 47 - 13
TEAMModelBI/ClientApp/src/view/systemConfig/index.vue

@@ -3,25 +3,28 @@
         <div class="systembox-tabs">
             <el-tabs v-model="activeName" class="demo-tabs">
                 <el-tab-pane label="站点配置" name="websites">
-                    <div v-if="modelShow=='choice'">
+                    <div v-if="modelShow == 'choice'">
                         <p class="titles">选择站点:</p>
                         <div class="choicebox">
                             <div class="choicebox-frame">
                                 <div class="particularsbox" v-for="item in siteLists" @click="changeSite(item)">
                                     <div class="particularsbox-img">
-                                        <el-image style="width: 200px; height: 300px" :src="item.img" fit="fill" />
+                                        <el-image :src="item.img" fit="fill" />
+                                    </div>
+                                    <div class="particularsbox-name"><span>{{ item.nickName }}</span></div>
+                                    <div class="now-pitch" v-if="nowcurrentSysConfig.site === item.site">
+                                        <span>当前站点</span>
                                     </div>
-                                    <div class="particularsbox-name"><span>{{item.nickName}}</span></div>
-                                    <div class="now-pitch" v-if="nowcurrentSysConfig.site === item.site"><span>当前站点</span></div>
                                 </div>
                             </div>
                         </div>
                     </div>
-                    <Website v-else-if="modelShow=='details'" :siteValue="siteValue" @changemodels="backisinfo" @state="backState"></Website>
-                    <div class="addSitebtn" @click="dialogVisible=true" v-if="modelShow=='choice'">
+                    <Website v-else-if="modelShow == 'details'" :siteValue="siteValue" @changemodels="backisinfo"
+                        @state="backState"></Website>
+                    <div class="addSitebtn" @click="dialogVisible = true" v-if="modelShow == 'choice'">
                         <el-button type="success" size="small">新增站点</el-button>
                     </div>
-                    <div class="cutSitebtn" @click="cutsiteSHow=true" v-if="modelShow=='choice'">
+                    <div class="cutSitebtn" @click="cutsiteSHow = true" v-if="modelShow == 'choice'">
                         <el-button type="primary" size="small">切换站点</el-button>
                     </div>
                 </el-tab-pane>
@@ -111,16 +114,19 @@
     </div>
     <div class="cut-site">
         <el-dialog v-model="cutsiteSHow" title="切换站点" width="60%">
-            <div class="nowtitle"><span>当前站点:</span>{{nowcurrentSysConfig.site}}<span class="site-nickname">别名:</span>{{nowcurrentSysConfig.nickName}}</div>
+            <div class="nowtitle"><span>当前站点:</span>{{ nowcurrentSysConfig.site }}<span
+                    class="site-nickname">别名:</span>{{ nowcurrentSysConfig.nickName }}</div>
             <div class="choicebox">
                 <div class="cut-choicebox-frame">
-                    <div class="particularsbox" v-for="(item,index) in siteLists" @click="cutsites(item,index)">
+                    <div class="particularsbox" v-for="(item, index) in siteLists" @click="cutsites(item, index)">
                         <div class="particularsbox-img">
-                            <el-image style="width: 100px; height: 150px" :src="item.img" fit="fill" />
+                            <el-image :src="item.img" fit="fill" />
                         </div>
-                        <div class="cut-particularsbox-name"><span>{{item.nickName}}</span></div>
+                        <div class="cut-particularsbox-name"><span>{{ item.nickName }}</span></div>
                         <div class="pitchs" v-if="nowcurrentSysConfig.site === item.site"><span>当前站点</span></div>
-                        <div class="pitch-site" v-if="pitchNum===index && nowcurrentSysConfig.site !== item.site"><span>选中站点</span></div>
+                        <div class="pitch-site" v-if="pitchNum === index && nowcurrentSysConfig.site !== item.site">
+                            <span>选中站点</span>
+                        </div>
                     </div>
                 </div>
             </div>
@@ -296,9 +302,11 @@ export default {
     line-height: 20px;
     position: relative;
 }
+
 .systembox-tabs {
     width: 100%;
 }
+
 .choicebox {
     width: 100%;
     height: 100%;
@@ -309,6 +317,7 @@ export default {
     align-items: center;
     overflow-x: auto;
 }
+
 .choicebox-frame {
     width: 70%;
     height: 70vh;
@@ -317,6 +326,7 @@ export default {
     justify-content: space-around;
     align-items: center;
 }
+
 .cut-choicebox-frame {
     width: 100%;
     height: 55vh;
@@ -325,8 +335,9 @@ export default {
     justify-content: space-around;
     align-items: center;
 }
+
 .particularsbox {
-    width: 20%;
+    width: 22%;
     height: 70%;
     text-align: center;
     border: 1px solid #ccc;
@@ -336,63 +347,76 @@ export default {
     position: relative;
     overflow: hidden;
 }
+
 .particularsbox-img {
     width: 100%;
     height: 70%;
     display: block;
 }
+
 .particularsbox-img {
     margin-top: 20%;
 }
+
 .particularsbox-name {
     font-size: 16px;
     font-weight: 600;
     margin-top: 10%;
 }
+
 .cut-particularsbox-name {
     font-size: 16px;
     font-weight: 600;
     line-height: 20px;
 }
+
 .particularsbox:hover {
     transform: translateY(-15px);
     box-shadow: 0px 5px 8px #ccc;
     background: #fff;
 }
+
 .titles {
     font-size: 18px;
     font-weight: 600;
     margin-top: 1.5%;
 }
+
 .created-site {
     width: 100%;
     /* height: 50vh; */
     line-height: 20px;
     overflow: hidden;
 }
+
 .created-site-form {
     width: 95%;
     text-align: left;
 }
+
 .database-add {
     width: 100%;
     padding: 1%;
     border: 1px solid #ccc;
     border-radius: 5px;
 }
+
 .addSitebtn {
     position: absolute;
     top: 3%;
     right: 1%;
 }
+
 .cutSitebtn {
     position: absolute;
     top: 3%;
     left: 1%;
 }
+
 .cut-site {
     width: 100%;
 }
+
 .pitch-site {
     height: 20px;
     line-height: 18px;
@@ -403,6 +427,7 @@ export default {
     top: 4%;
     color: #fff;
 }
+
 .pitchs {
     height: 20px;
     line-height: 18px;
@@ -413,15 +438,18 @@ export default {
     top: 4%;
     color: #fff;
 }
+
 .nowtitle {
     font-size: 14px;
     text-align: left;
     line-height: 18px;
     padding-left: 1%;
 }
+
 .site-nickname {
     margin-left: 5%;
 }
+
 .now-pitch {
     height: 24px;
     line-height: 24px;
@@ -443,25 +471,31 @@ export default {
     margin-bottom: 5px;
     background: #fff;
 }
+
 .systembox .el-tabs__nav-wrap {
     padding-left: 15px;
 }
+
 .backbtn .el-button--small {
     height: 30px;
     padding: 5px 15px;
 }
+
 .created-site .el-dialog__header,
 .cut-site .el-dialog__header {
     line-height: 20px;
 }
+
 .created-site .el-dialog,
 .cut-site .el-dialog {
     height: 80vh;
     overflow: auto;
 }
+
 .cut-site .el-dialog__footer {
     line-height: 20px;
 }
+
 .cut-site .el-dialog {
     background-color: #e9eef3;
 }

+ 133 - 52
TEAMModelBI/ClientApp/src/view/teachermanage/school.vue

@@ -1,29 +1,38 @@
 <template>
     <!--学校列表-->
-    <div class="schoolbox" v-show="models==='default'">
+    <div class="schoolboxeu" v-show="models === 'default'">
         <div class="select-List">
             <div class="province-box">
-                <span>{{$t(`areaManages.selector.provinceName`)}}:</span>
-                <el-select v-model="provinceOptions.provinceValue" :placeholder="$t(`areaManages.selector.provinceDefault`)" @change="areaSelctChange(provinceOptions.provinceValue,'province')">
-                    <el-option v-for="item in provinceOptions.optionInfo" :key="item.code" :label="item.name" :value="item.name">
+                <span>{{ $t(`areaManages.selector.provinceName`) }}:</span>
+                <el-select v-model="provinceOptions.provinceValue"
+                    :placeholder="$t(`areaManages.selector.provinceDefault`)"
+                    @change="areaSelctChange(provinceOptions.provinceValue, 'province')">
+                    <el-option v-for="item in provinceOptions.optionInfo" :key="item.code" :label="item.name"
+                        :value="item.name">
                     </el-option>
                 </el-select>
             </div>
             <div class="city-box">
-                <span>{{$t(`areaManages.selector.cityName`)}}:</span>
-                <el-select v-model="cityOptions.cityValue" :placeholder="$t(`areaManages.selector.cityDefault`)" @change="areaSelctChange(cityOptions.cityValue,'city')">
-                    <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name" :value="item.name">
+                <span>{{ $t(`areaManages.selector.cityName`) }}:</span>
+                <el-select v-model="cityOptions.cityValue" :placeholder="$t(`areaManages.selector.cityDefault`)"
+                    @change="areaSelctChange(cityOptions.cityValue, 'city')">
+                    <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name"
+                        :value="item.name">
                     </el-option>
                 </el-select>
             </div>
             <div class="dist-box">
-                <span>{{$t(`areaManages.selector.areaName`)}}:</span>
-                <el-select v-model="distOptions.distValue" filterable allow-create default-first-option :placeholder="$t(`areaManages.selector.areaDefault`)" @change="areaSelctChange(distOptions.distValue,'dist')">
-                    <el-option v-for="item in distOptions.distInfo" :key="item.code" :label="item.name" :value="item.name">
+                <span>{{ $t(`areaManages.selector.areaName`) }}:</span>
+                <el-select v-model="distOptions.distValue" filterable allow-create default-first-option
+                    :placeholder="$t(`areaManages.selector.areaDefault`)"
+                    @change="areaSelctChange(distOptions.distValue, 'dist')">
+                    <el-option v-for="item in distOptions.distInfo" :key="item.code" :label="item.name"
+                        :value="item.name">
                     </el-option>
                 </el-select>
             </div>
-            <div class="close-box" v-show="provinceOptions.provinceValue || cityOptions.cityValue ||distOptions.distValue">
+            <div class="close-box"
+                v-show="provinceOptions.provinceValue || cityOptions.cityValue || distOptions.distValue">
                 <svg class="closebtnIcon" aria-hidden="true" @click="closeSelectarea">
                     <use xlink:href="#icon-quxiao"></use>
                 </svg>
@@ -42,12 +51,14 @@
                         </svg>
                     </span>
                 </div>
-                <span class="text">{{$t(`schoolManages.createdtitle`)}}</span>
+                <span class="text">{{ $t(`schoolManages.createdtitle`) }}</span>
             </a>
         </div>
         <div class="school-list">
-            <el-table :data="tableData" style="width: 100%" height="75vh" v-loading="loading" element-loading-text="加载中...">
-                <el-table-column prop="index" :label="$t(`schoolManages.tables.serialnum`)" type="index" sortable align="center" />
+            <el-table :data="tableData" style="width: 100%" height="75vh" v-loading="loading"
+                element-loading-text="加载中...">
+                <el-table-column prop="index" :label="$t(`schoolManages.tables.serialnum`)" type="index" sortable
+                    align="center" />
                 <el-table-column :label="$t(`schoolManages.tables.badge`)" width="150" align="center">
                     <template #default="scope">
                         <el-image style="width: 70px; height: 70px" :src="scope.row.picture" fit="fill"></el-image>
@@ -61,9 +72,14 @@
                 </el-table-column> -->
                 <el-table-column :label="$t(`schoolManages.tables.scale`)" class="school-table-edition" align="center">
                     <template #default="scope">
-                        <el-image style="width: 80px; height: 80px" :src="imgData.basics" fit="fill" v-if="scope.row.scale ===0"></el-image>
-                        <el-image style="width: 80px; height: 80px" :src="imgData.standard" fit="fill" v-else-if="scope.row.scale ===500 && scope.row.hard ===0 && scope.row.serial ===0 && scope.row.service ===0"></el-image>
-                        <el-image style="width: 80px; height: 80px" :src="imgData.specialty" fit="fill" v-else-if="scope.row.scale ===500 && (scope.row.hard !=0 || scope.row.serial !=0 || scope.row.service !=0)"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.basics" fit="fill"
+                            v-if="scope.row.scale === 0"></el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.standard" fit="fill"
+                            v-else-if="scope.row.scale === 500 && scope.row.hard === 0 && scope.row.serial === 0 && scope.row.service === 0">
+                        </el-image>
+                        <el-image style="width: 80px; height: 80px" :src="imgData.specialty" fit="fill"
+                            v-else-if="scope.row.scale === 500 && (scope.row.hard != 0 || scope.row.serial != 0 || scope.row.service != 0)">
+                        </el-image>
                     </template>
                 </el-table-column>
                 <el-table-column prop="id" :label="$t(`schoolManages.tables.brevityCode`)" align="center" />
@@ -73,14 +89,15 @@
                 <el-table-column prop="size" :label="$t(`schoolManages.tables.spacesize`)" align="center" />
                 <el-table-column :label="$t(`schoolManages.tables.assis`)" align="center">
                     <template #default="scope">
-                        <div v-if="scope.row.assisName">{{scope.row.assisName}}</div>
+                        <div v-if="scope.row.assisName">{{ scope.row.assisName }}</div>
                         <div v-else>暂无</div>
                     </template>
                 </el-table-column>
                 <!-- <el-table-column prop="state" label="状态" width="110" align="center" /> -->
                 <el-table-column :label="$t(`schoolManages.tables.operate`)" align="center" v-if="PowerShow">
                     <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)">
+                            {{ $t(`schoolManages.tables.operatecontent`) }}</el-button>
                     </template>
                 </el-table-column>
             </el-table>
@@ -88,30 +105,33 @@
     </div>
     <!--学校列表end-->
     <!--编辑学校页面-->
-    <div class="backbtn" v-if="models==='details' && PowerShow">
+    <div class="backbtn" v-if="models === 'details' && PowerShow">
         <el-button type="primary" icon="el-icon-back" @click="schoolClose">返回</el-button>
         <el-button class="changebtn" v-if="store.state.changbtnShow && changebtns" @click="getSetschool()">
             <svg class="changebtn-areaicon" aria-hidden="true">
                 <use xlink:href="#icon-wenjian"></use>
             </svg>
-            <span class="changebtn-title">{{$t(`schoolManages.gradSet.save`)}}</span>
+            <span class="changebtn-title">{{ $t(`schoolManages.gradSet.save`) }}</span>
         </el-button>
     </div>
     <div class="schoolDeatils">
-        <el-tabs type="border-card" v-if="models==='details' && PowerShow" @tab-click="changeTabs">
+        <el-tabs type="border-card" v-if="models === 'details' && PowerShow" @tab-click="changeTabs">
             <!--基础设置-->
             <el-tab-pane :label="$t(`schoolManages.redactSet`)">
-                <div class="redactbox" v-show="models==='details' && PowerShow">
+                <div class="redactbox" v-show="models === 'details' && PowerShow">
                     <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-form-item :label="$t(`schoolManages.basicSet.name`) + ':'" class="school-form-name">
                                 <el-input v-model="nowPitchdata.name"></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">
-                                    <el-image style="width: 100%; height:125px" :src="nowPitchdata.picture" fit="contain"></el-image>
+                            <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">
+                                    <el-image style="width: 100%; height:125px" :src="nowPitchdata.picture"
+                                        fit="contain"></el-image>
                                     <div class="changebadge">
-                                        <el-button>{{$t(`schoolManages.basicSet.badgeChange`)}}</el-button>
+                                        <el-button>{{ $t(`schoolManages.basicSet.badgeChange`) }}</el-button>
                                     </div>
                                 </el-upload>
                             </el-form-item>
@@ -122,13 +142,19 @@
                                 <el-checkbox v-model="nowPitchdata.period[3].value" label="职高"></el-checkbox>
                                 <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-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-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`)">
-                                    <el-option v-for="item in adminoptions" :key="item.name" :label="item.mobile+'——'+item.name" :value="item.tmdId ===null ? '':item.tmdId" :disabled="!item.tmdId">
+                            <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`)">
+                                    <el-option v-for="item in adminoptions" :key="item.name"
+                                        :label="item.mobile + '——' + item.name"
+                                        :value="item.tmdId === null ? '' : item.tmdId" :disabled="!item.tmdId">
                                         <!-- <span style="float: left">{{ item.mobile }}-{{item.name}}</span>
                             <i style="float: right;color: var(--el-text-color-secondary);font-size: 13px;" v-show="item.isexist === false">
                                 <svg class="school-admin-check" aria-hidden="true">
@@ -138,31 +164,37 @@
                                     </el-option>
                                 </el-select>
                             </el-form-item>
-                            <el-form-item :label="$t(`schoolManages.basicSet.brevityCode`)+':'" class="school-form-code">
-                                <el-input disabled :placeholder="nowPitchdata.id" v-if="nowPitchdata.id !==null" />
-                                <el-input disabled :placeholder="$t(`schoolManages.basicSet.notCode`)" v-else="nowPitchdata.id ==null" />
+                            <el-form-item :label="$t(`schoolManages.basicSet.brevityCode`) + ':'"
+                                class="school-form-code">
+                                <el-input disabled :placeholder="nowPitchdata.id" v-if="nowPitchdata.id !== null" />
+                                <el-input disabled :placeholder="$t(`schoolManages.basicSet.notCode`)"
+                                    v-else="nowPitchdata.id ==null" />
                             </el-form-item>
-                            <el-form-item :label="$t(`schoolManages.basicSet.region`)+':'" class="school-form-area">
-                                <el-select v-model="areaSelect.Selectvalue" :placeholder="$t(`schoolManages.basicSet.region`)">
-                                    <el-option v-for="item in areaSelect.data" :key="item.name" :label="item.name" :value="item.id">
+                            <el-form-item :label="$t(`schoolManages.basicSet.region`) + ':'" class="school-form-area">
+                                <el-select v-model="areaSelect.Selectvalue"
+                                    :placeholder="$t(`schoolManages.basicSet.region`)">
+                                    <el-option v-for="item in areaSelect.data" :key="item.name" :label="item.name"
+                                        :value="item.id">
                                     </el-option>
                                 </el-select>
                             </el-form-item>
-                            <el-form-item :label="$t(`schoolManages.basicSet.scale`)+':'" class="school-form-size">
+                            <el-form-item :label="$t(`schoolManages.basicSet.scale`) + ':'" class="school-form-size">
                                 <el-input-number v-model="nowPitchdata.scale" :min="0" :step="100" />
                             </el-form-item>
-                            <el-form-item :label="$t(`schoolManages.basicSet.location`)+':'" class="school-form-site">
+                            <el-form-item :label="$t(`schoolManages.basicSet.location`) + ':'" class="school-form-site">
                                 <el-input disabled :placeholder="nowPitchdata.address" />
                             </el-form-item>
-                            <el-form-item :label="$t(`schoolManages.basicSet.spacesize`)+':'" class="school-form-size">
+                            <el-form-item :label="$t(`schoolManages.basicSet.spacesize`) + ':'"
+                                class="school-form-size">
                                 <el-input-number v-model="nowPitchdata.size" :min="1" :max="1000" />
                             </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-button @click="schoolClose">{{$t(`commonMsg.closes`)}}</el-button>
+                                <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>
                     </div>
@@ -329,8 +361,8 @@ export default {
             nowPitchdata.value.areaId = data.areaId
             data.assists.length
                 ? data.assists.forEach((element) => {
-                      adminvalue.value.push(element.tmdId)
-                  })
+                    adminvalue.value.push(element.tmdId)
+                })
                 : ''
             let token = JSON.parse(localStorage.getItem('id_token'))
             uploadHeader.value['x-auth-authtoken'] = token
@@ -510,7 +542,7 @@ export default {
         function updateSuccess() {
             loading.value = true
             setTimeout(() => {
-                ;(models.value = 'default'), (tableData.value = []), getAllschool()
+                ; (models.value = 'default'), (tableData.value = []), getAllschool()
             }, 2000)
         }
         //地区选择close btn
@@ -610,11 +642,12 @@ export default {
 }
 </script>
 <style scoped>
-.schoolbox {
+.schoolboxeu {
     width: 100%;
     margin: 0 auto;
     line-height: 80px;
 }
+
 .select-List {
     line-height: 60px;
     text-align: left;
@@ -622,43 +655,53 @@ export default {
     width: 75%;
     float: left;
 }
+
 .school-list {
     width: 96%;
     max-height: 74vh;
     margin: 0 auto;
     /* overflow-y: auto; */
 }
+
 /*编辑页面样式*/
 .redactbox {
     width: 100%;
 }
+
 .backbtn {
     width: 100%;
     text-align: left;
     line-height: 20px;
 }
+
 .school-formbox {
     width: 85%;
     margin: 0 auto;
     padding: 1%;
 }
+
 .upload-demo-redact {
     width: 100%;
     height: 125px;
 }
+
 .school-form-name {
     width: 50%;
 }
+
 .school-form-area {
     width: 35%;
 }
+
 .school-form-badge,
 .school-form-code {
     width: 24%;
 }
+
 .school-form-grading {
     width: 80%;
 }
+
 .changebadge {
     width: 100%;
     height: 125px;
@@ -667,19 +710,24 @@ export default {
     left: 0px;
     opacity: 0;
 }
+
 .school-form-site {
     width: 35%;
 }
+
 .school-form-size {
     width: 21%;
 }
+
 .school-form-admin {
     width: 35%;
     text-align: left;
 }
+
 .school-form-state {
     width: 15%;
 }
+
 .school-admin-check {
     width: 2em;
     height: 2em;
@@ -687,16 +735,19 @@ export default {
     fill: currentColor;
     overflow: hidden;
 }
+
 .province-box,
 .city-box,
 .dist-box,
 .close-box {
     display: inline-block;
 }
+
 .city-box,
 .dist-box {
     margin-left: 1%;
 }
+
 /*btn*/
 .boxselect {
     width: 60px;
@@ -705,9 +756,11 @@ export default {
     margin-top: 1%;
     margin-left: 15%;
 }
+
 .boxselect:hover {
     cursor: pointer;
 }
+
 .boxselect a {
     text-decoration: none;
     color: #fff;
@@ -742,6 +795,7 @@ export default {
     line-height: 180px;
     text-align: center;
 }
+
 .boxselect a:hover .layer span:nth-child(1) {
     opacity: 0.3;
 }
@@ -833,6 +887,7 @@ export default {
     bottom: -25px;
     opacity: 1;
 }
+
 .created-areaicon {
     width: 1.3em;
     height: 1.3em;
@@ -841,6 +896,7 @@ export default {
     overflow: hidden;
     margin-top: -135px;
 }
+
 .closebtnIcon {
     width: 1.8em;
     height: 1.8em;
@@ -849,20 +905,25 @@ export default {
     overflow: hidden;
     margin-left: 8px;
 }
+
 .closebtnIcon:hover {
     cursor: pointer;
 }
+
 .schoolDeatils {
     margin-top: 0.5%;
     position: relative;
 }
+
 .changebtn {
     display: inline-block;
     float: right;
 }
+
 .changebtn-title {
     font-size: 12px;
 }
+
 .changebtn-areaicon {
     width: 0.9em;
     height: 0.9em;
@@ -872,70 +933,88 @@ export default {
 }
 </style>
 <style>
-.schoolbox .el-cascader {
+.schoolboxeu .el-cascader {
     width: 20%;
 }
+
 .school-form-badge .el-form-item__label {
     line-height: 107px;
 }
+
 .school-form-badge .el-form-item__content {
     border: 1px solid #ccc;
     position: relative;
 }
+
 .changebadge .el-button {
     width: 100%;
     height: 100%;
     font-size: 18px;
     color: #fff;
 }
+
 .changebadge .el-button span {
     border: 1px solid #ccc;
     background-color: #409eff;
     padding: 5px;
     border-radius: 10px;
 }
+
 .changebadge:hover {
     opacity: 0.8;
 }
+
 .school-form-code .el-input__inner {
     text-align: center;
 }
+
 .school-form-admin .el-select {
     width: 100%;
 }
+
 .school-form-badge .el-image__inner {
     width: 100%;
     height: 85%;
     margin-top: 10%;
 }
+
 .school-form-grading .el-form-item__content {
     text-align: left;
 }
+
 .el-select-dropdown__item {
     padding: 0 12px 0 20px;
 }
+
 .school-formbox .el-form-item__content {
     text-align: left;
 }
+
 .school-form-area .el-select {
     width: 100%;
 }
+
 .school-list .el-table__header-wrapper {
     line-height: 60px;
 }
+
 .schoolDeatils .el-tabs__header {
     line-height: 40px;
 }
+
 .schoolDeatils .el-tabs__content {
     padding: 0px;
 }
+
 .backbtn .changebtn {
     padding: 8px 15px;
 }
+
 .upload-demo-redact .el-upload {
     width: 100%;
     height: 125px;
 }
+
 .school-form-grading .el-radio__input.is-checked .el-radio__inner::after {
     content: '';
     width: 10px;
@@ -953,13 +1032,15 @@ export default {
     border-radius: 0px;
     background: none;
 }
-.el-upload-dragger {
-}
+
+.el-upload-dragger {}
+
 @media screen and (max-width: 1920px) {
     .school-formbox .school-form-badge {
         width: 17.5%;
     }
 }
+
 @media screen and (max-width: 1400px) {
     .school-formbox .school-form-badge {
         width: 24%;

Dosya farkı çok büyük olduğundan ihmal edildi
+ 401 - 101
TEAMModelBI/ClientApp/src/view/teachermanage/traitmanage.vue


+ 90 - 0
TEAMModelBI/Controllers/BIHome/AnalyseFileController.cs

@@ -0,0 +1,90 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Extension;
+
+namespace TEAMModelBI.Controllers.BIHome
+{
+    [Route("analyse")]
+    [ApiController]
+    public class AnalyseFileController : ControllerBase
+    {
+        private readonly IWebHostEnvironment _environment; //读取文件流
+
+        public AnalyseFileController(IWebHostEnvironment environment) 
+        {
+            _environment = environment;
+        }
+
+        [HttpPost("get-visitjson")]
+        public async Task<IActionResult> GetVisitJson() 
+        {
+            var path = $"{_environment.ContentRootPath}/JsonFile/TempFile/PT1H.json";
+            StreamReader streamReader = new StreamReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
+            List<object> objs = new(); 
+            StringBuilder visits = new();
+            string text;
+            while ((text = streamReader.ReadLine()) != null) 
+            {
+                objs.Add(text.ToString());
+                visits.Append($"{text},");
+            }
+
+            streamReader.Close();
+
+            string input = visits.ToString();
+            List<AGInfo> aGInfos = input.ToObject<List<AGInfo>>();
+
+            //var temp = visits.Split("||");
+
+            //var temp1 = string.Join("||");
+
+            return Ok(new { state = 200, aGInfos, objs, visits });
+        }
+
+
+
+        public record AGInfo 
+        {
+            public string resourceId { get; set; }
+
+            public string operationName { get; set; }
+            public string time { get; set; }
+            public string category { get; set; }
+            public Properties properties { get; set; }
+        }
+
+        public record Properties 
+        {
+            public string instanceId { get; set; }
+            public string clientIp { get; set; }
+            public string clientPort { get; set; }
+            public string requestUri { get; set; }
+            public string ruleSetType { get; set; }
+            public string ruleSetVersion { get; set; }
+            public string ruleId { get; set;}
+            public string ruleGroup { get; set; }
+            public string message { get; set; }
+            public string action { get; set; }
+            public string site { get; set; }
+            public Datails datails { get; set; }
+            public string hostname { get; set; }
+            public string transactionId { get; set; }
+        }
+
+        public record Datails 
+        {
+            public string message { get; set; }
+            public string data { get; set; }
+            public string file { get; set; }
+            public string line { get; set; }
+
+        }
+
+    }
+}

+ 75 - 85
TEAMModelBI/Controllers/BIHome/OnLineController.cs

@@ -103,19 +103,24 @@ namespace TEAMModelBI.Controllers.BIHome
         /// </summary>
         /// <returns></returns>
         [HttpPost("get-trend")]
-        public async Task<IActionResult> GetTrend() 
+        public async Task<IActionResult> GetTrend(JsonElement jsonElement) 
         {
+            jsonElement.TryGetProperty("hour", out JsonElement hour);
             var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin");
-            DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+            DateTimeOffset dateTime =  DateTimeOffset.UtcNow;
+            if (!string.IsNullOrEmpty($"{hour}")) 
+            {
+                DateTimeOffset.UtcNow.AddHours(hour.GetInt32());
+            }
             var (daySt, dayEt) = TimeHelper.GetStartOrEnd(dateTime);  //今天开始时间    13位
             var (strDaySt, strDayEt) = TimeHelper.GetUnixToDate(daySt, dayEt, "yyyyMMddHH");
             var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
 
-            daySt.ToString("yyyyMMddHH");
-            Dictionary<int, int> allDays = new();  //所有在线人数
-            Dictionary<int, int> tchDays = new();  //教师在线人数
-            Dictionary<int, int> stuDays = new();  //学生在线人数
-            Dictionary<int, int> tmdDays = new();  //醍摩豆账户学生
+            //daySt.ToString("yyyyMMddHH");
+            Dictionary<long, int> allDays = new();  //所有在线人数
+            Dictionary<long, int> tchDays = new();  //教师在线人数
+            Dictionary<long, int> stuDays = new();  //学生在线人数
+            Dictionary<long, int> tmdDays = new();  //醍摩豆账户学生
 
             SortedSetEntry[] tchDay = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:teacher:{dateDay}");
             if (tchDay.Length > 0)
@@ -124,12 +129,13 @@ namespace TEAMModelBI.Controllers.BIHome
                 {
                     int val = ((int)item.Score);
                     int key = ((int)item.Element);
-                    var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));                
-                    tchDays.Add(hour, val);
-                    if (allDays.ContainsKey(hour))
-                        allDays[hour] = (allDays[hour] + val);
+                    var utcTo = new DateTimeOffset(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, hour.GetInt32() + key, 0, 0)).Hour;
+                    //var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
+                    tchDays.Add(utcTo, val);
+                    if (allDays.ContainsKey(utcTo))
+                        allDays[utcTo] = (allDays[utcTo] + val);
                     else
-                        allDays.Add(hour, val);
+                        allDays.Add(utcTo, val);
                 }
             }
             else
@@ -142,12 +148,13 @@ namespace TEAMModelBI.Controllers.BIHome
                     foreach (var item in hourLoginsTch)
                     {
                         await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:teacher:{dateDay}", $"{item.Hour}", item.Teacher);//存一天24小时
-                        var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {item.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
-                        tchDays.Add(hour, item.Teacher);
-                        if (allDays.ContainsKey(hour))
-                            allDays[hour] = (allDays[hour] + item.Teacher);
+                        var utcTo = new DateTimeOffset(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, hour.GetInt32() + item.Hour, 0, 0)).Hour;
+                        //var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {item.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
+                        tchDays.Add(utcTo, item.Teacher);
+                        if (allDays.ContainsKey(utcTo))
+                            allDays[utcTo] = (allDays[utcTo] + item.Teacher);
                         else
-                            allDays.Add(hour, item.Teacher);
+                            allDays.Add(utcTo, item.Teacher);
                     }
                 }
             }
@@ -159,12 +166,13 @@ namespace TEAMModelBI.Controllers.BIHome
                 {
                     int val = (int)item.Score;
                     int key = (int)item.Element;
-                    var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
-                    stuDays.Add(hour, val);
-                    if (allDays.ContainsKey(hour))
-                        allDays[hour] = (allDays[hour] + val);
+                    var utcTo = new DateTimeOffset(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, hour.GetInt32() + key, 0, 0)).Hour;
+                    //var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
+                    stuDays.Add(utcTo, val);
+                    if (allDays.ContainsKey(utcTo))
+                        allDays[utcTo] = (allDays[utcTo] + val);
                     else
-                        allDays.Add(hour, val);
+                        allDays.Add(utcTo, val);
                 }
             }
             else
@@ -178,12 +186,13 @@ namespace TEAMModelBI.Controllers.BIHome
                     foreach (var item in hourLoginsStu)
                     {
                         await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:student:{dateDay}", $"{item.Hour}", item.Student);//存一天24小时
-                        var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {item.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
-                        stuDays.Add(hour, item.Student);
-                        if (allDays.ContainsKey(hour))
-                            allDays[hour] = (allDays[hour] + item.Student);
+                        var utcTo = new DateTimeOffset(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, hour.GetInt32() + item.Hour, 0, 0)).Hour;
+                        //var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {item.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
+                        stuDays.Add(utcTo, item.Student);
+                        if (allDays.ContainsKey(utcTo))
+                            allDays[utcTo] = (allDays[utcTo] + item.Student);
                         else
-                            allDays.Add(hour, item.Student);
+                            allDays.Add(utcTo, item.Student);
                     }
                 }
             }
@@ -195,12 +204,13 @@ namespace TEAMModelBI.Controllers.BIHome
                 {
                     int val = (int)item.Score;
                     int key = (int)item.Element;
-                    var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
-                    tmdDays.Add(hour, val);
-                    if (allDays.ContainsKey(hour))
-                        allDays[hour] = (allDays[hour] + val);
+                    var utcTo = new DateTimeOffset(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, hour.GetInt32() + key, 00, 00)).Hour;
+                    //var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
+                    tmdDays.Add(utcTo, val);
+                    if (allDays.ContainsKey(utcTo))
+                        allDays[utcTo] = (allDays[utcTo] + val);
                     else
-                        allDays.Add(hour, val);
+                        allDays.Add(utcTo, val);
                 }
             }
             else
@@ -214,12 +224,13 @@ namespace TEAMModelBI.Controllers.BIHome
                     foreach (var item in hourLoginsTmd)
                     {
                         await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:tmduser:{dateDay}", $"{item.Hour}", item.TmdUser);//存一天24小时
-                        var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {item.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
-                        tmdDays.Add(hour, item.TmdUser);
-                        if (allDays.ContainsKey(hour))
-                            allDays[hour] = (allDays[hour] + item.TmdUser);
+                        var utcTo = new DateTimeOffset(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, hour.GetInt32() + item.Hour, 00, 00)).Hour;
+                        //var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {item.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
+                        tmdDays.Add(utcTo, item.TmdUser);
+                        if (allDays.ContainsKey(utcTo))
+                            allDays[utcTo] = (allDays[utcTo] + item.TmdUser);
                         else
-                            allDays.Add(hour, item.TmdUser);
+                            allDays.Add(utcTo, item.TmdUser);
                     }
                 }
             }
@@ -241,36 +252,35 @@ namespace TEAMModelBI.Controllers.BIHome
             int day = dateTime.Day;      //当天
             int hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {dateTime.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));   //当前小时
 
-            Dictionary<int, int> scLessCnt = new();  //学校课例
-            Dictionary<int, int> tchLessCnt = new();   //教师课例
-            Dictionary<int, int> yesterdayCnt = new();  //昨天24小时课例
-
             var (daySt, dayEt) = TimeHelper.GetStartOrEnd(dateTime);  //今天开始时间    13位
             var (lastDayS, lastdayE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year}-{dateTime.Month}-{dateTime.Day - 1}"));   //昨天开始时间
 
-            List<RecLesn> scRecLesn = new(); //学校课例
-            List<RecLesn> tchRecLesn = new(); //个人课例
-            List<RecLesn> allRecLesn = new();  //昨天所有课例
+            Dictionary<int, int> sdOpenLesn = new();  //今日开课
+            Dictionary<int, int> sdUpdLesn = new();  //今日上传课例
+            Dictionary<int, int> ydOpenLesn = new();  //昨日开课
+            Dictionary<int, int> ydUpdLesn = new();  //昨日上传课例
+
+            List<RecLesn> sameDayLesn = new();   //今天课例
+            List<RecLesn> yesterDayLesn = new();   //昨日课例
             string lesnSql = $"select c.id,c.name,c.code,c.school,c.scope,c.startTime  from c where c.pk='LessonRecord' and c.startTime >={daySt} and c.startTime <= {dayEt}";
             await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<RecLesn>(queryText: lesnSql, requestOptions: new QueryRequestOptions() { }))
             {
-                scRecLesn.Add(item);
+                sameDayLesn.Add(item);
             }
-
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<RecLesn>(queryText: lesnSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("LessonRecord") }))
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<RecLesn>(queryText: lesnSql, requestOptions: new QueryRequestOptions() { }))
             {
-                tchRecLesn.Add(item);
+                sameDayLesn.Add(item);
             }
 
-            string allLesnSql = $"select c.id,c.name,c.code,c.school,c.scope,c.startTime  from c where c.pk='LessonRecord' and c.startTime >={lastDayS} and c.startTime <= {lastdayE}";
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<RecLesn>(queryText: allLesnSql, requestOptions: new QueryRequestOptions() { }))
+            string yesterDayLesnSql = $"select c.id,c.name,c.code,c.school,c.scope,c.startTime  from c where c.pk='LessonRecord' and c.startTime >={lastDayS} and c.startTime <= {lastdayE}";
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<RecLesn>(queryText: yesterDayLesnSql, requestOptions: new QueryRequestOptions() { }))
             {
-                allRecLesn.Add(item);
+                yesterDayLesn.Add(item);
             }
 
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<RecLesn>(queryText: allLesnSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("LessonRecord") }))
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<RecLesn>(queryText: yesterDayLesnSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("LessonRecord") }))
             {
-                allRecLesn.Add(item);
+                yesterDayLesn.Add(item);
             }
 
             for (int i = 0; i < 24; i++)
@@ -280,46 +290,25 @@ namespace TEAMModelBI.Controllers.BIHome
                     DateTimeOffset timeHour = new DateTime(year, month, day, i, 0, 0);
                     var (hourS, hourE) = TimeHelper.GetStartOrEnd(timeHour, type: "hour");
 
-                    var scLesn = scRecLesn.Where(item => item.startTime >= hourS && item.startTime <= hourE).ToList();
-                    scLessCnt.Add(i, scLesn.Count());
+                    var openLesn = sameDayLesn.Where(item => item.startTime >= hourS && item.startTime <= hourE && item.upload == 0);
+                    sdOpenLesn.Add(i, openLesn.Count());
+
+                    var UpdLesn = sameDayLesn.Where(item => item.startTime >= hourS && item.startTime <= hourE && item.upload == 1);
+                    sdUpdLesn.Add(i, openLesn.Count());
 
-                    var tchLesn = tchRecLesn.Where(item => item.startTime >= hourS && item.startTime <= hourE).ToList();
-                    tchLessCnt.Add(i, tchLesn.Count());
                 }
 
                 DateTimeOffset yesterday = new DateTime(year, month, day - 1, i, 0, 0);
                 var (yHourS, yHourE) = TimeHelper.GetStartOrEnd(yesterday, type: "hour");
 
-                var allLesn = allRecLesn.Where(item => item.startTime >= yHourS && item.startTime <= yHourE).ToList();
-                yesterdayCnt.Add(i, allLesn.Count());
-            }
+                var yOpenLesn = yesterDayLesn.Where(item => item.startTime >= yHourS && item.startTime <= yHourE && item.upload == 0).ToList();
+                ydOpenLesn.Add(i, yOpenLesn.Count);
 
-            ////通过循环实时查询课例统计
-            //for (int i = 0; i < 24; i++)
-            //{
-            //    if (hour >= i)
-            //    {
-            //        DateTimeOffset timeHour = new DateTime(year, month, day, i, 0, 0);
-            //        var (hourS, hourE) = TimeHelper.GetStartOrEnd(timeHour, type: "hour");
-            //        await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<int>(queryText: $"select value(count(c.id)) from c where c.pk='LessonRecord' and c.startTime >={hourS} and c.startTime <= {hourE}", requestOptions: new QueryRequestOptions() { }))
-            //        {
-            //            scLessCnt.Add(i, item);
-            //        }
-
-            //        await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<int>(queryText: $"select value(count(c.id)) from c where c.startTime >={hourS} and c.startTime <= {hourE}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("LessonRecord") }))
-            //        {
-            //            tchLessCnt.Add(i, item);
-            //        }
-            //    }
-
-            //    DateTimeOffset yesterday = new DateTime(year, month, day - 1, i, 0, 0);
-            //    var (yHourS, yHourE) = TimeHelper.GetStartOrEnd(yesterday, type: "hour");
-            //    string sql = $"select value(count(c.id)) from c where c.pk='LessonRecord' and c.startTime >= {yHourS} and c.startTime <= {yHourE}";
-            //    int hourLessCnt = await CommonFind.GetSqlValueCount(cosmosClient, new List<string> { "School", "Teacher" }, sql);
-            //    yesterdayCnt.Add(i, hourLessCnt);
-            //}
+                var yUpdLesn = yesterDayLesn.Where(item => item.startTime >= yHourS && item.startTime <= yHourE && item.upload == 1).ToList();
+                ydUpdLesn.Add(i, yUpdLesn.Count);
+            }
 
-            return Ok(new { state = 200, scLessCnt = scLessCnt.ToList(), tchLessCnt = tchLessCnt.ToList(), yesterdayCnt = yesterdayCnt.ToList() });
+            return Ok(new { state = 200, sdOpenLesn = sdOpenLesn.ToList(), sdUpdLesn = sdUpdLesn.ToList(), ydOpenLesn = ydOpenLesn.ToList(), ydUpdLesn = ydUpdLesn.ToList() });
         }
 
         /// <summary>
@@ -405,6 +394,7 @@ namespace TEAMModelBI.Controllers.BIHome
             public string school { get; set; }
             public string scope{get;set;}
             public long startTime { get; set; }
+            public int upload { get; set; }
         }
     }
 }

+ 32 - 6
TEAMModelBI/Controllers/BISchool/AreaRelevantController.cs

@@ -47,10 +47,17 @@ namespace TEAMModelBI.Controllers.BISchool
         {
             try
             {
-                if (!jsonElement.TryGetProperty("areaId", out JsonElement _areaId)) return BadRequest();
+                jsonElement.TryGetProperty("areaId", out JsonElement _areaId);
+                jsonElement.TryGetProperty("isManyArea", out JsonElement isManyArea);
                 var cosmosClient = _azureCosmos.GetCosmosClient();
                 List<JoinAreaSchool> joinAreaSchools = new List<JoinAreaSchool>();
                 string slqtxt = $"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period FROM c WHERE c.areaId='{_areaId}'";
+
+                if (!string.IsNullOrEmpty($"{isManyArea}"))
+                {
+                    slqtxt = $"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period FROM c join m in c.manyAreas where m.areaId='{_areaId}' or c.areaId='{_areaId}'";
+                }
+
                 await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: slqtxt,requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")})) 
                 {
                     using var json = await JsonDocument.ParseAsync(item.ContentStream);
@@ -69,6 +76,12 @@ namespace TEAMModelBI.Controllers.BISchool
                                 picture = obj.GetProperty("picture").GetString(),
                                 period = obj.GetProperty("period").ToObject<List<Period>>().Select(x => x.name).ToList()
                             };
+
+                            try
+                            {
+                                joinAreaSchool.manyAreas = obj.GetProperty("manyAreas").ToObject<List<ManyArea>>();
+                            }
+                            catch { }
                             joinAreaSchools.Add(joinAreaSchool);
                         }                    
                     }
@@ -95,16 +108,29 @@ namespace TEAMModelBI.Controllers.BISchool
         {
             try
             {
-                //if (!jsonElement.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
                 if (!jsonElement.TryGetProperty("schoolId", out JsonElement schoolId)) return BadRequest();
+                jsonElement.TryGetProperty("areaId", out JsonElement areaId);
+                jsonElement.TryGetProperty("standard", out JsonElement standard);
+                jsonElement.TryGetProperty("isDefault", out JsonElement isDefault);
 
                 var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
 
                 var cosmosClient = _azureCosmos.GetCosmosClient();
                 School tempSchool = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{schoolId}", new PartitionKey("Base"));
-
-                tempSchool.areaId = null;
-                tempSchool.standard = null;
+                if (string.IsNullOrEmpty($"{isDefault}"))
+                {
+                    tempSchool.areaId = null;
+                    tempSchool.standard = null;
+                    var temp = tempSchool.manyAreas.Find(ma => ma.areaId == $"{areaId}");
+                    if (temp != null)
+                        tempSchool.manyAreas.Remove(temp);
+                }
+                else
+                {
+                    var temp = tempSchool.manyAreas.Find(ma => ma.areaId == $"{areaId}");
+                    if (temp == null)
+                        tempSchool.manyAreas.Add(new ManyArea { areaId = $"{areaId}", standard = $"{standard}" });
+                }
 
                 School school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(tempSchool, tempSchool.id, new PartitionKey("Base"));
 
@@ -141,7 +167,7 @@ namespace TEAMModelBI.Controllers.BISchool
 
             public string dist { get; set; }
 
-
+            public List<ManyArea> manyAreas { get; set; } = new List<ManyArea>();
         }
 
     }

+ 133 - 117
TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs

@@ -141,141 +141,154 @@ namespace TEAMModelBI.Controllers.BISchool
                     var cosmosClient = _azureCosmos.GetCosmosClient();
                     foreach (BISchool bischool in foundSchools.biSchools)
                     {
-                        string tempTmdId = null;
-                        HttpClient httpClient = _http.CreateClient();
-                        string url = _configuration.GetValue<string>("HaBookAuth:CoreId:userinfo");
-                        List<string> mobile = new List<string>() { bischool.admin };
-                        HttpResponseMessage responseMessage = await httpClient.PostAsJsonAsync(url, mobile);
-                        if (responseMessage.StatusCode == HttpStatusCode.OK)
+                        List<string> scName = new();
+                        await foreach (var item in  cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText: $"select value(c.name) from c where c.name='{bischool.name}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
                         {
-                            string temp = responseMessage.Content.ReadAsStringAsync().Result;
-                            List<JsonElement> json_id = temp.ToObject<List<JsonElement>>();
-                            foreach (var item in json_id)
+                            scName.Add(item);
+                        }
+                        if (scName.Count <= 0)
+                        {
+                            string tempTmdId = null;
+                            HttpClient httpClient = _http.CreateClient();
+                            string url = _configuration.GetValue<string>("HaBookAuth:CoreId:userinfo");
+                            List<string> mobile = new List<string>() { bischool.admin };
+                            HttpResponseMessage responseMessage = await httpClient.PostAsJsonAsync(url, mobile);
+                            if (responseMessage.StatusCode == HttpStatusCode.OK)
                             {
-                                tempTmdId = item.GetProperty("id").ToString();
+                                string temp = responseMessage.Content.ReadAsStringAsync().Result;
+                                List<JsonElement> json_id = temp.ToObject<List<JsonElement>>();
+                                foreach (var item in json_id)
+                                {
+                                    tempTmdId = item.GetProperty("id").ToString();
+                                }
                             }
-                        }
 
-                        string tmdId = !string.IsNullOrEmpty(tempTmdId) ? tempTmdId : bischool.admin;
+                            string tmdId = !string.IsNullOrEmpty(tempTmdId) ? tempTmdId : bischool.admin;
 
-                        CreateSchoolInfo createSchoolInfo = new CreateSchoolInfo()
-                        {
-                            province = bischool.province,
-                            id = "",
-                            name = bischool.name,
-                            city = bischool.city,
-                            aname = "",
-                            createCount = 0,
-                        };
-
-                        //生成学校ID
-                        bool tempStaus = true;
-                        do
-                        {
-                            createSchoolInfo = await SchoolCode.GenerateSchoolCode(createSchoolInfo, _dingDing, _environment);
-                            var schoolStatu = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{createSchoolInfo.id}", new PartitionKey($"Base"));
-                            if (schoolStatu.Status != 200) tempStaus = false;
-                            else createSchoolInfo.createCount = createSchoolInfo.createCount >= 3 ? createSchoolInfo.createCount = 3 : createSchoolInfo.createCount += 1;
-                        } while (tempStaus);
-
-                        if (createSchoolInfo.id != null)
-                        {
-                            string campusId = Guid.NewGuid().ToString();
-                            School upSchool = new School
+                            CreateSchoolInfo createSchoolInfo = new CreateSchoolInfo()
                             {
-                                id = createSchoolInfo.id,
-                                name = bischool.name,
-                                size = bischool.size == 0 ? 100 : bischool.size,
-                                code = "Base",
-                                campuses = new List<Campus> { new Campus { name = bischool.name, id = campusId } },
-                                region = bischool.region,
                                 province = bischool.province,
+                                id = "",
+                                name = bischool.name,
                                 city = bischool.city,
-                                dist = bischool.dist,
-                                address = bischool.address,
-                                picture = "https://teammodelstorage.blob.core.chinacloudapi.cn/0-public/school/bbf54fb3-3fc8-43ae-a358-107281c174cc.png",
-                                timeZone = new TEAMModelOS.SDK.Models.TimeZone { label = "(UTC+08:00) 北京,重庆,香港特别行政区,乌鲁木齐", value = "+08:00" },
-                                type = bischool.type,
-                                pk = "School",
-                                ttl = -1,
-                                areaId = string.IsNullOrEmpty(bischool.areaId) ? "" : bischool.areaId,
-                                schoolCode = createSchoolInfo.id,
-                                period = PresetSchoolPeriod(bischool.period, foundSchools.lang, campusId),
-                                scale = bischool.size >= 300 ? 500 : 0,
-                                createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()                                
+                                aname = "",
+                                createCount = 0,
                             };
 
-                            stringBuilder.Append($"创建学校:{upSchool.name}【{upSchool.id}】");
-                            //创建学校
-                            await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<School>(upSchool, new PartitionKey(upSchool.code));
-                            Teacher teacher = null;
-                            try
+                            //生成学校ID
+                            bool tempStaus = true;
+                            do
                             {
-                                //查询该教师是否存在
-                                teacher = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>($"{tmdId}", new PartitionKey("Base"));
-                            }
-                            catch
-                            {
-                            }
-                            if (teacher != 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, tmdId, new PartitionKey("Base"));
-                                SchoolTeacher schoolTeacher = new SchoolTeacher
-                                {
-                                    id = tmdId,
-                                    code = $"Teacher-{createSchoolInfo.id}",
-                                    roles = new List<string> { "admin", "teacher" },
-                                    job = "管理员",
-                                    name = teacher.name,
-                                    picture = teacher.picture,
-                                    status = "join",
-                                    createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
-                                    pk = "Teacher",
-                                    ttl = -1
-                                };
-                                stringBuilder.Append($"教师信息:{schoolTeacher.name}【{schoolTeacher.id}】,教师权限:{string.Join(",", schoolTeacher.roles)}");
-                                await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey(teacher.code));
-                                await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<SchoolTeacher>(schoolTeacher, new PartitionKey(schoolTeacher.code));
-                            }
-                            else
+                                createSchoolInfo = await SchoolCode.GenerateSchoolCode(createSchoolInfo, _dingDing, _environment);
+                                var schoolStatu = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{createSchoolInfo.id}", new PartitionKey($"Base"));
+                                if (schoolStatu.Status != 200) tempStaus = false;
+                                else createSchoolInfo.createCount = createSchoolInfo.createCount >= 3 ? createSchoolInfo.createCount = 3 : createSchoolInfo.createCount += 1;
+                            } while (tempStaus);
+
+                            if (createSchoolInfo.id != null)
                             {
-                                //不存在 新建教师和新建要管理的学校信息
-                                Teacher addteacher = new Teacher
+                                string campusId = Guid.NewGuid().ToString();
+                                School upSchool = new School
                                 {
-                                    id = tmdId,
-                                    pk = "Base",
+                                    id = createSchoolInfo.id,
+                                    name = bischool.name,
+                                    size = bischool.size == 0 ? 100 : bischool.size,
                                     code = "Base",
-                                    name = $"{bischool.name}-管理员"?.ToString(),
-                                    picture = "",
-                                    //创建账号并第一次登录IES5则默认赠送1G
-                                    size = 1,
-                                    defaultSchool = createSchoolInfo.id,
-                                    createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
-                                    schools = new List<Teacher.TeacherSchool>() { new Teacher.TeacherSchool { schoolId = createSchoolInfo.id, name = bischool.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() } }
+                                    campuses = new List<Campus> { new Campus { name = bischool.name, id = campusId } },
+                                    region = bischool.region,
+                                    province = bischool.province,
+                                    city = bischool.city,
+                                    dist = bischool.dist,
+                                    address = bischool.address,
+                                    picture = "https://teammodelstorage.blob.core.chinacloudapi.cn/0-public/school/bbf54fb3-3fc8-43ae-a358-107281c174cc.png",
+                                    timeZone = new TEAMModelOS.SDK.Models.TimeZone { label = "(UTC+08:00) 北京,重庆,香港特别行政区,乌鲁木齐", value = "+08:00" },
+                                    type = string.IsNullOrEmpty(bischool.type.ToString()) ? 1 : bischool.type,
+                                    pk = "School",
+                                    ttl = -1,
+                                    areaId = string.IsNullOrEmpty(bischool.areaId) ? "" : bischool.areaId,
+                                    standard = string.IsNullOrEmpty(bischool.standard) ? "" : bischool.standard,
+                                    schoolCode = createSchoolInfo.id,
+                                    period = PresetSchoolPeriod(bischool.period, foundSchools.lang, campusId),
+                                    scale = bischool.size >= 300 ? 500 : 0,
+                                    createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
                                 };
 
-                                stringBuilder.Append($"没有该教师信息创建的教师信息:{addteacher.name}【{addteacher.id}】");
-                                await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(addteacher, new PartitionKey("Base"));
-                                SchoolTeacher schoolTeacher = new SchoolTeacher
+                                stringBuilder.Append($"创建学校:{upSchool.name}【{upSchool.id}】");
+                                //创建学校
+                                await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<School>(upSchool, new PartitionKey(upSchool.code));
+                                Teacher teacher = null;
+                                try
                                 {
-                                    id = tmdId,
-                                    code = $"Teacher-{createSchoolInfo.id}",
-                                    roles = new List<string> { "admin", "teacher" },
-                                    job = "管理员",
-                                    name = $"{tmdId}-管理员",
-                                    picture = "",
-                                    status = "join",
-                                    createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
-                                    pk = "Teacher",
-                                    ttl = -1
-                                };
+                                    //查询该教师是否存在
+                                    teacher = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>($"{tmdId}", new PartitionKey("Base"));
+                                }
+                                catch
+                                {
+                                }
+                                if (teacher != 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, tmdId, new PartitionKey("Base"));
+                                    SchoolTeacher schoolTeacher = new SchoolTeacher
+                                    {
+                                        id = tmdId,
+                                        code = $"Teacher-{createSchoolInfo.id}",
+                                        roles = new List<string> { "admin", "teacher" },
+                                        job = "管理员",
+                                        name = teacher.name,
+                                        picture = teacher.picture,
+                                        status = "join",
+                                        createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                                        pk = "Teacher",
+                                        ttl = -1
+                                    };
+                                    stringBuilder.Append($"教师信息:{schoolTeacher.name}【{schoolTeacher.id}】,教师权限:{string.Join(",", schoolTeacher.roles)}");
+                                    await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey(teacher.code));
+                                    await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<SchoolTeacher>(schoolTeacher, new PartitionKey(schoolTeacher.code));
+                                }
+                                else
+                                {
+                                    //不存在 新建教师和新建要管理的学校信息
+                                    Teacher addteacher = new Teacher
+                                    {
+                                        id = tmdId,
+                                        pk = "Base",
+                                        code = "Base",
+                                        name = $"{bischool.name}-管理员"?.ToString(),
+                                        picture = "",
+                                        //创建账号并第一次登录IES5则默认赠送1G
+                                        size = 1,
+                                        defaultSchool = createSchoolInfo.id,
+                                        createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                                        schools = new List<Teacher.TeacherSchool>() { new Teacher.TeacherSchool { schoolId = createSchoolInfo.id, name = bischool.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() } }
+                                    };
 
-                                stringBuilder.Append($"教师权限:{string.Join(",", schoolTeacher.roles)}");
-                                await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<SchoolTeacher>(schoolTeacher, new PartitionKey(schoolTeacher.code));
+                                    stringBuilder.Append($"没有该教师信息创建的教师信息:{addteacher.name}【{addteacher.id}】");
+                                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(addteacher, new PartitionKey("Base"));
+                                    SchoolTeacher schoolTeacher = new SchoolTeacher
+                                    {
+                                        id = tmdId,
+                                        code = $"Teacher-{createSchoolInfo.id}",
+                                        roles = new List<string> { "admin", "teacher" },
+                                        job = "管理员",
+                                        name = $"{tmdId}-管理员",
+                                        picture = "",
+                                        status = "join",
+                                        createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                                        pk = "Teacher",
+                                        ttl = -1
+                                    };
+
+                                    stringBuilder.Append($"教师权限:{string.Join(",", schoolTeacher.roles)}");
+                                    await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<SchoolTeacher>(schoolTeacher, new PartitionKey(schoolTeacher.code));
+                                }
                             }
                         }
+                        else 
+                        {
+                            schools.Add(bischool);
+                        }
                     }
                 }
                 else return Ok(new { state = 1, message = "创校信息为空" });
@@ -284,7 +297,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 await _azureStorage.SaveBILog("school-batchAdd", stringBuilder?.ToString(), _dingDing, httpContext: HttpContext);
 
                 if (schools.Count > 0)
-                    return Ok(new { state = 201, message = "已有部分学校批量创建成功;学校编号已经重复!请检查学校编号!", schools });
+                    return Ok(new { state = 201, message = "已有部分学校批量创建成功;学校已经重复!请检查学校信息!", schools });
                 else
                     return Ok(new { state = 200, message = "批量创校已全部完成" });
             }
@@ -1015,7 +1028,6 @@ namespace TEAMModelBI.Controllers.BISchool
             /// 县,区,郡
             /// </summary>
             public string dist { get; set; }
-
             /// <summary>
             /// 学校详细地址
             /// </summary>
@@ -1028,6 +1040,10 @@ namespace TEAMModelBI.Controllers.BISchool
             /// 区域ID
             /// </summary>
             public string areaId { get; set; }
+            /// <summary>
+            /// 区域标准
+            /// </summary>
+            public string standard { get; set; }
         }
 
         public record Exist()

+ 112 - 17
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -57,12 +57,16 @@ namespace TEAMModelBI.Controllers.BISchool
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-notarea")]
-        public async Task<IActionResult> GetNotAreaSchool()
+        public async Task<IActionResult> GetNotAreaSchool(JsonElement jsonElement)
         {
             try
             {
+                jsonElement.TryGetProperty("areaId", out JsonElement areaId);
                 var cosmosClient = _azureCosmos.GetCosmosClient();
-                string sqltxt = $"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period FROM c WHERE c.standard=null";
+                string sqltxt = "SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period,c.manyAreas FROM c WHERE c.standard=null or c.areaId=null";
+                if (!string.IsNullOrEmpty($"{areaId}"))
+                    sqltxt = $"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period,c.manyAreas FROM c join m in c.manyAreas WHERE c.areaId!='{areaId}' or m.areaId!='{areaId}'";
+
                 List<NotAreaSchool> notAreaSchools = new List<NotAreaSchool>();
                 await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: sqltxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
                 {
@@ -81,12 +85,19 @@ namespace TEAMModelBI.Controllers.BISchool
                                 period = obj.GetProperty("period").ToObject<List<Period>>().Select(x => x.name).ToList(),
                                 province = obj.GetProperty("province").GetString(),
                                 city = obj.GetProperty("city").GetString(),
-                                dist = obj.GetProperty("dist").GetString(),
+                                dist = obj.GetProperty("dist").GetString()
                             };
+                            try
+                            {
+                                notAreaSchool.manyAreas = obj.GetProperty("manyAreas").ToObject<List<ManyArea>>();
+                            }
+                            catch { }
                             notAreaSchools.Add(notAreaSchool);
                         }
                     }
                 }
+                //if (!string.IsNullOrEmpty($"{areaId}"))                    
+                //    notAreaSchools = notAreaSchools.Select(na => new NotAreaSchool { id = na.id, name = na.name, schoolCode = na.schoolCode, picture = na.picture, period = na.period, province = na.province, city = na.city = na.city, dist = na.dist,  manyAreas =  new List<ManyArea> { na.manyAreas.Find(m => m.areaId != $"{areaId}") } }).ToList();
 
                 return Ok(new { state = 200, notAreaSchools });
             }
@@ -112,6 +123,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 if (!jsonElement.TryGetProperty("standard", out JsonElement standard)) return BadRequest();
                 if (!jsonElement.TryGetProperty("schoolCode", out JsonElement _schoolCode)) return BadRequest();
                 if (!jsonElement.TryGetProperty("areaId", out JsonElement _areaId)) return BadRequest();
+                jsonElement.TryGetProperty("isDefault", out JsonElement isDefault);
 
                 var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
 
@@ -126,8 +138,20 @@ namespace TEAMModelBI.Controllers.BISchool
                         School school = await cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(tempCode, new PartitionKey("Base"));
                         if (school != null)
                         {
-                            school.standard = $"{standard}";
-                            school.areaId = $"{_areaId}";
+                            if (string.IsNullOrEmpty($"{isDefault}"))
+                            {
+                                school.standard = $"{standard}";
+                                school.areaId = $"{_areaId}";
+                                var marea = school.manyAreas.Find(ma => ma.areaId == $"{_areaId}" && ma.standard == $"{standard}");
+                                if (marea == null)
+                                    school.manyAreas.Add(new ManyArea { areaId = $"{_areaId}", standard = $"{standard}" });
+                            }
+                            else 
+                            {
+                                var marea = school.manyAreas.Find(ma => ma.areaId == $"{_areaId}" && ma.standard == $"{standard}");
+                                if (marea == null)
+                                    school.manyAreas.Add(new ManyArea { areaId = $"{_areaId}", standard = $"{standard}" });
+                            }
                             await cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey(school.code));
                         }
                     }
@@ -675,13 +699,83 @@ namespace TEAMModelBI.Controllers.BISchool
             }
             catch (Exception ex)
             {
-
                 await _dingDing.SendBotMsg($"BI,{_option.Location}  /batchschool/set-schoolme \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
                 return BadRequest();
             }
 
         }
 
+        /// <summary>
+        /// 删除学校、学校相关的教师、学生
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [AuthToken(Roles = "admin,rdc")]
+        [HttpPost("set-del")]
+        public async Task<IActionResult> DelSchool(JsonElement jsonElement)
+        {
+            try
+            {
+                if (!jsonElement.TryGetProperty("schoolId", out JsonElement schoolId)) return BadRequest();
+                string _auth = HttpContext.GetXAuth("AuthToken");
+                var (tmdId, tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(_auth, _option);
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                StringBuilder msg = new();
+                List<DelSchoolRel> delSchoolRels = new();
+
+                List<string> scTchIds = new();
+                List<string> scStuIds = new();
+                string scTecSql = $"select value(c.id) from c where ARRAY_LENGTH(c.roles) > 0 and c.status = 'join'";
+                await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText: scTecSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{schoolId}") }))
+                {
+                    scTchIds.Add(item);
+                }
+
+                string scStuSql = $"select value(c.id) from c";
+                await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText: scStuSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{schoolId}") }))
+                {
+                    scStuIds.Add(item);
+                }
+
+                var response = await cosmosClient.GetContainer("TEAMModelOS", "School").DeleteItemStreamAsync($"{schoolId}", new PartitionKey($"Base"));
+                if (response.Status == 204)
+                    msg.AppendLine($"{tmdName}【{tmdId}】删除学校,删除状态:{response.Status},删除ID:{schoolId}");
+                else
+                    delSchoolRels.Add(new DelSchoolRel() { id = $"{schoolId}", code = "Base", type = 1, status = response.Status });
+
+                foreach (var item in scTchIds)
+                {
+                    var tchRespnse = await cosmosClient.GetContainer("TEAMModelOS", "School").DeleteItemStreamAsync($"{item}", new PartitionKey($"Teacher-{schoolId}"));
+                    if (tchRespnse.Status == 204)
+                        msg.AppendLine($"删除教师,删除状态:{tchRespnse.Status},删除ID:{item}");
+                    else
+                        delSchoolRels.Add(new DelSchoolRel() { id = $"{item}", code = $"Teacher-{schoolId}", type = 2, status = response.Status });
+                }
+                
+                foreach (var item in scStuIds)
+                {
+                    var stuRespnse = await cosmosClient.GetContainer("TEAMModelOS", "Student").DeleteItemStreamAsync($"{item}", new PartitionKey($"Base-{schoolId}"));
+                    if (stuRespnse.Status == 204)
+                        msg.AppendLine($"删除学生,删除状态:{stuRespnse.Status},删除ID:{item}");
+                    else
+                        delSchoolRels.Add(new DelSchoolRel() { id = $"{item}", code = $"Base-{schoolId}", type = 3, status = response.Status });
+                }
+
+                //保存操作记录
+                await _azureStorage.SaveBILog("set-del", msg.ToString(), _dingDing, httpContext: HttpContext);
+                if (delSchoolRels.Count > 0)
+                    return Ok(new { state = 201, delSchoolRels });
+                else
+                    return Ok(new { state = 200 });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location}  /batchschool/set-del \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
         /// <summary>
         /// 通过学校Id查询详情   数据管理工具——查询工具
         /// </summary>
@@ -877,20 +971,14 @@ namespace TEAMModelBI.Controllers.BISchool
         public record NotAreaSchool
         {
             public string id { get; set; }
-
             public string name { get; set; }
-
             public string schoolCode { get; set; }
-
             public string picture { get; set; }
-
             public List<string> period { get; set; }
-
             public string province { get; set; }
-
             public string city { get; set; }
-
             public string dist { get; set; }
+            public List<ManyArea> manyAreas { get; set; } = new List<ManyArea>();
         }
 
         /// <summary>
@@ -899,9 +987,7 @@ namespace TEAMModelBI.Controllers.BISchool
         public record SchoolSpace
         {
             public string id { get; set; }
-
             public string name { get; set; }
-
             public Space space { get; set; }
 
         }
@@ -914,16 +1000,25 @@ namespace TEAMModelBI.Controllers.BISchool
             /// 已使用空间
             /// </summary>
             public long useSize { get; set; }
-
             /// <summary>
             /// 分配教师空间
             /// </summary>
             public long tSize { get; set; }
-
             /// <summary>
             /// 空间类型
             /// </summary>
             public Dictionary<string, double?> catalogSize { get; set; }
         }
+
+        public record DelSchoolRel
+        {
+            public string id { get; set; }
+            public string code { get; set; }
+            /// <summary>
+            /// 未删除的类型 1 学校 2教师  3学生
+            /// </summary>
+            public int type { get; set; }
+            public int status { get; set; }
+        }
     }
 }

+ 25 - 13
TEAMModelBI/Controllers/BITest/Ies5TestController.cs

@@ -1,4 +1,5 @@
-using Microsoft.AspNetCore.Hosting;
+using Azure.Messaging.ServiceBus;
+using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Configuration;
@@ -13,7 +14,9 @@ using TEAMModelBI.Tool;
 using TEAMModelOS.Models;
 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.Service;
 using static TEAMModelOS.SDK.Models.Teacher;
 
@@ -26,6 +29,7 @@ namespace TEAMModelBI.Controllers.BITest
 
         private readonly AzureCosmosFactory _azureCosmos;
         private readonly AzureRedisFactory _azureRedis;
+        private readonly AzureServiceBusFactory _serviceBus;
         private readonly DingDing _dingDing;
         private readonly Option _option;
         private readonly AzureStorageFactory _azureStorage;
@@ -49,21 +53,29 @@ namespace TEAMModelBI.Controllers.BITest
         }
 
         [HttpPost("get-datetime")]
-        public async Task<IActionResult> GetDateTime() 
+        public async Task<IActionResult> GetDateTime()
         {
-           var dateHours =  DateTimeOffset.UtcNow.Hour;
-           var dateHours1 = DateTime.Now.Hour;
-           var dateHours2 = DateTimeOffset.Now.Hour;
-           var dateDays = DateTimeOffset.UtcNow.Month;
+            var dateHours = DateTimeOffset.UtcNow.Hour;
+            var dateHours1 = DateTime.Now.Hour;
+            var dateHours2 = DateTimeOffset.Now.Hour;
+            var dateDays = DateTimeOffset.UtcNow.Month;
 
-           var dateDay = DateTimeOffset.UtcNow.ToString("yyyyMMdd");
-           var dateMonth = DateTimeOffset.UtcNow.ToString("yyyyMM");
-           long expire = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds();
-           long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+            var dateDay = DateTimeOffset.UtcNow.ToString("yyyyMMdd");
+            var dateMonth = DateTimeOffset.UtcNow.ToString("yyyyMM");
+            long expire = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds();
+            long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
             var cosmosClient = _azureCosmos.GetCosmosClient();
-           List<LoginInfo> loginInfos = new() { new LoginInfo (){ time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),ip="172.54.81.101",expire = expire } };
-            var tets = await LoginService.DoLoginInfo(loginInfos: loginInfos, school: "hbcn", scope: "teacher", id: "1636016499", ip: "172.168.52.102", _azureRedis, _azureStorage, expire: 1);
-           return Ok(new { state = 200, dateHours, dateHours1, dateHours2, dateDay,dateDays, dateMonth, });
+
+            //在线记录
+            List<LoginInfo> loginInfos = new() { new LoginInfo() { time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), ip = "172.54.81.101", expire = expire } };
+            //var tets = await LoginService.DoLoginInfo(loginInfos: loginInfos, school: "hbcn", scope: "teacher", id: "1636016499", ip: "172.168.52.102", _azureRedis, _azureStorage, expire: 1);
+
+            OnLinRec olrec = new() { id = "1636016499", scope = Constant.ScopeTeacher, ip = "172.168.52.102", school = "hbcn", expire = 1 };
+            var messageBatchCopyFile = new ServiceBusMessage(olrec.ToJsonString());
+            messageBatchCopyFile.ApplicationProperties.Add("name", "OnLinRecord");   //Function名称
+            var onlinRecTask = _configuration.GetValue<string>("Azue:ServiceBus:OnlinRecord");
+            await _serviceBus.GetServiceBusClient().SendMessageAsync(onlinRecTask, messageBatchCopyFile);
+            return Ok(new { state = 200, dateHours, dateHours1, dateHours2, dateDay, dateDays, dateMonth, });
         }
 
         public async Task<IActionResult> GetRedisToTable(JsonElement jsonElement)

Dosya farkı çok büyük olduğundan ihmal edildi
+ 4761 - 0
TEAMModelBI/JsonFile/TempFile/PT1H.json


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

@@ -1,6 +1,7 @@
 using Azure.Cosmos;
 using Azure.Storage.Blobs.Models;
 using HTEXLib.COMM.Helpers;
+using Microsoft.Azure.Cosmos.Table;
 using Microsoft.Azure.Functions.Worker;
 using Microsoft.Azure.Functions.Worker.Http;
 using System;
@@ -12,9 +13,13 @@ using System.Reflection;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
+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;
 
 namespace TEAMModelOS.FunctionV4.HttpTrigger
 {
@@ -39,7 +44,8 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
         /// <param name="log"></param>
         /// <returns></returns>
         [Function("system-info-function")]
-        public async Task<HttpResponseData> SystemInfo([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequestData req) {
+        public async Task<HttpResponseData> SystemInfo([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequestData req)
+        {
             var response = req.CreateResponse(HttpStatusCode.OK);
             Type attr = this.GetType();
             string currentDirectory = Path.GetDirectoryName(attr.Assembly.Location);
@@ -63,7 +69,7 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
             await response.WriteAsJsonAsync(new { version, description, nowtime });
             return response;
 
-           
+
         }
         /// <summary>
         /// 数据推送接口
@@ -99,7 +105,8 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
                         items.Add(item);
                     }
 
-                    items.ForEach(item => {
+                    items.ForEach(item =>
+                    {
                         //修改知识点
                         if (!string.IsNullOrEmpty(on._new))
                         {
@@ -127,8 +134,8 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
                             {
                                 var blob = JsonDocument.Parse(blobDownloadResult.Content);
                                 itemBlob = blob.RootElement.ToObject<ItemBlob>();
-                                itemBlob.exercise.knowledge=item.knowledge;
-                                await _azureStorage.UploadFileByContainer($"{school}", itemBlob.ToJsonString(), "item", $"{item.id}/{item.id}.json", true) ;
+                                itemBlob.exercise.knowledge = item.knowledge;
+                                await _azureStorage.UploadFileByContainer($"{school}", itemBlob.ToJsonString(), "item", $"{item.id}/{item.id}.json", true);
                             }
                         }
                         catch (Exception ex)
@@ -142,5 +149,338 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
             await response.WriteAsJsonAsync(new { data = json });
             return response;
         }
+
+        /// <summary>
+        /// 在线人数记录
+        /// </summary>
+        /// <param name="msg"></param>
+        /// <returns></returns>
+        [Function("online-record")]
+        public async Task<HttpResponseData> OnlineRecord([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;
+            try
+            {
+                string school = null;
+                string scope = null;
+                string id = null;
+                string ip = null;
+                int expire = 1;
+
+                if (json.TryGetProperty("school", out JsonElement _school))
+                    school = _school.GetString();
+
+                if (json.TryGetProperty("scope", out JsonElement _scope))
+                    scope = _scope.GetString();
+
+                if (json.TryGetProperty("id", out JsonElement _id))
+                    id = _id.GetString();
+
+                if (json.TryGetProperty("ip", out JsonElement _ip))
+                    ip = _ip.GetString();
+                if (json.TryGetProperty("expire", out JsonElement _expire))
+                    expire = _expire.GetInt32();
+
+                var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin");
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+
+                DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+                var dateHour = dateTime.ToString("yyyyMMddHH"); //获取当天的小时
+                var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
+                var dateMonth = dateTime.ToString("yyyyMM");//获取当月的日期
+                var currentHour = dateTime.Hour;   //当前小时
+                var currentDay = dateTime.Day;   //当前天
+                long Expire = dateTime.AddHours(expire).ToUnixTimeMilliseconds();  //token到期时间
+                long now = dateTime.ToUnixTimeMilliseconds();   //当前时间戳
+                DateTime hour = DateTime.UtcNow.AddHours(25);   //25小时到期
+                DateTime month = DateTime.UtcNow.AddDays(32);   //一个月到期
+                var delTbHour = dateTime.AddHours(-168).ToString("yyyyMMddHH");   //168小时前
+                var delTbDay = dateTime.AddDays(-180).ToString("yyyyMMdd");   //180天前            
+
+                switch (scope)
+                {
+                    case "teacher":
+                        try
+                        {
+                            Teacher teacher = await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
+                            teacher.loginInfos = new List<LoginInfo>() { new LoginInfo { expire = Expire, ip = ip, time = now } };
+                            await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey("Base"));
+                        }
+                        catch { }
+                        break;
+                    case "student":
+                        try
+                        {
+                            Student student = await cosmosClient.GetContainer("TEAMModelOS", Constant.Student).ReadItemAsync<Student>(id, new PartitionKey($"Base-{school}"));
+                            student.loginInfos = new List<LoginInfo>() { new LoginInfo { expire = Expire, ip = ip, time = now } };
+                            await cosmosClient.GetContainer("TEAMModelOS", Constant.Student).ReplaceItemAsync<Student>(student, student.id, new PartitionKey("Base"));
+                        }
+                        catch { }
+                        break;
+                    case "tmduser":
+                        try
+                        {
+                            TmdUser tmdUser = await cosmosClient.GetContainer("TEAMModelOS", Constant.Student).ReadItemAsync<TmdUser>(id, new PartitionKey("Base"));
+                            tmdUser.loginInfos = new List<LoginInfo>() { new LoginInfo { expire = Expire, ip = ip, time = now } };
+                            await cosmosClient.GetContainer("TEAMModelOS", Constant.Student).ReplaceItemAsync<TmdUser>(tmdUser, tmdUser.id, new PartitionKey("Base"));
+                        }
+                        catch { }
+                        break;
+                }
+
+                await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateDay}", $"{currentHour}", 1);//一天24小时  小时为单位
+                await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateMonth}", $"{currentDay}", 1); //一天的累计   天为单位
+
+                var resDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateDay}");
+                if (resDay == null)
+                    await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateDay}", hour);  //设置到期时间
+                var rspMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateMonth}");
+                if (rspMonth == null)
+                    await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateMonth}", month);  //设置到期时间
+
+                //保存当前小时统计
+                var dayCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateDay}");
+                if (dayCnt != null && dayCnt.Length > 0)
+                {
+                    List<HourLogin> hourLogins = new();
+                    foreach (var dCnt in dayCnt)
+                    {
+                        if (((int)dCnt.Element) == currentHour)
+                        {
+                            var tphourLogins = await table.QueryWhereString<HourLogin>($"PartitionKey eq 'HourLogin' and RowKey eq '{dateHour}'");
+                            if (tphourLogins.Count > 0)
+                            {
+                                foreach (var hourLogin in tphourLogins)
+                                {
+                                    if (scope.Equals("teacher"))
+                                        hourLogin.Teacher = (int)dCnt.Score;
+                                    else if (scope.Equals("student"))
+                                        hourLogin.Student = (int)dCnt.Score;
+                                    else
+                                        hourLogin.TmdUser = (int)dCnt.Score;
+                                    hourLogins.Add(hourLogin);
+                                }
+                            }
+                            else
+                            {
+                                HourLogin hourLogin = new() { PartitionKey = $"HourLogin", RowKey = dateHour, Hour = currentHour };
+                                if (scope.Equals("teacher"))
+                                {
+                                    hourLogin.Teacher = 1;
+                                    hourLogin.Student = 0;
+                                    hourLogin.TmdUser = 0;
+                                }
+                                else if (scope.Equals("student"))
+                                {
+                                    hourLogin.Teacher = 0;
+                                    hourLogin.Student = 1;
+                                    hourLogin.TmdUser = 0;
+                                }
+                                else
+                                {
+                                    hourLogin.Teacher = 0;
+                                    hourLogin.Student = 0;
+                                    hourLogin.TmdUser = 1;
+                                }
+                                hourLogins.Add(hourLogin);
+                            }
+                        }
+                    }
+                    await table.SaveOrUpdateAll(hourLogins);  //保存和更新保存当前小时登录次数
+                }
+                //保存当前的统计数据
+                var monthCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateMonth}");
+                if (monthCnt != null && monthCnt.Length > 0)
+                {
+                    List<DayLogin> dayLogins = new();
+                    foreach (var mCnt in monthCnt)
+                    {
+                        if (((int)mCnt.Element) == currentDay)
+                        {
+                            //保存当天的峰值
+                            var tbDays = await table.QueryWhereString<DayLogin>($"PartitionKey eq 'DayLogin' and RowKey eq '{dateDay}'");
+                            if (tbDays.Count > 0)
+                            {
+                                foreach (var dayLogin in tbDays)
+                                {
+                                    if (scope.Equals("teacher"))
+                                        dayLogin.Teacher = (int)mCnt.Score;
+                                    else if (scope.Equals("student"))
+                                        dayLogin.Student = (int)mCnt.Score;
+                                    else
+                                        dayLogin.TmdUser = (int)mCnt.Score;
+                                    dayLogins.Add(dayLogin);
+                                }
+                            }
+                            else
+                            {
+                                //保存当月每天的峰值
+                                DayLogin dayLogin = new() { PartitionKey = $"DayLogin", RowKey = dateDay, Day = currentDay };
+                                if (scope.Equals("teacher"))
+                                {
+                                    dayLogin.Teacher = 1;
+                                    dayLogin.Student = 0;
+                                    dayLogin.TmdUser = 0;
+                                }
+                                else if (scope.Equals("student"))
+                                {
+                                    dayLogin.Teacher = 0;
+                                    dayLogin.Student = 1;
+                                    dayLogin.TmdUser = 0;
+                                }
+                                else
+                                {
+                                    dayLogin.Teacher = 0;
+                                    dayLogin.Student = 0;
+                                    dayLogin.TmdUser = 1;
+                                }
+                                dayLogins.Add(dayLogin);
+                            }
+                        }
+                    }
+                    await table.SaveOrUpdateAll(dayLogins);// 保存当月每天在线数据
+                }
+
+                string tbHourSql = $"PartitionKey eq 'HourLogin' and RowKey le '{delTbHour}'";
+                await table.DeleteStringWhere<BIOptLog>(rowKey: tbHourSql);  //删除168小时前的数据
+
+                string tbDaySql = $"PartitionKey eq 'DayLogin' and RowKey le '{delTbDay}'";
+                await table.DeleteStringWhere<BIOptLog>(rowKey: tbDaySql);   //删除180天前的数据
+
+                if (!string.IsNullOrWhiteSpace(school))
+                {
+                    await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateDay}", $"{currentHour}", 1);//当天当前小时在线人加1
+                    await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateMonth}", $"{currentDay}", 1); //当天的在线加1
+
+                    var reScDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateDay}");
+                    if (reScDay == null)
+                        await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateDay}", hour);  //设置到期时间
+                    var reScMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateMonth}");
+                    if (reScMonth == null)
+                        await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateMonth}", month);  //设置到期时间
+
+                    //保存学校当天每小时的
+                    var scDayCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateDay}");
+                    if (scDayCnt != null && scDayCnt.Length > 0)
+                    {
+                        List<HourLoginSchool> hourLoginSchools = new();
+                        foreach (var scDCnt in scDayCnt)
+                        {
+                            if (((int)scDCnt.Element) == currentHour)
+                            {
+                                var tmpHour = await table.QueryWhereString<HourLoginSchool>($"PartitionKey eq 'HourLogin-{school}' and RowKey eq '{dateHour}'");
+                                if (tmpHour.Count > 0)
+                                {
+                                    foreach (var hLoginSc in tmpHour)
+                                    {
+                                        if (scope.Equals("teacher"))
+                                            hLoginSc.Teacher = (int)scDCnt.Score;
+                                        else if (scope.Equals("student"))
+                                            hLoginSc.Student = (int)scDCnt.Score;
+                                        else
+                                            hLoginSc.TmdUser = (int)scDCnt.Score;
+                                        hourLoginSchools.Add(hLoginSc);
+                                    }
+                                }
+                                else
+                                {
+                                    //学校小时峰值
+                                    HourLoginSchool hourLoginSc = new() { PartitionKey = $"HourLogin-{school}", RowKey = dateHour, Hour = currentHour, School = school };
+                                    if (scope.Equals("teacher"))
+                                    {
+                                        hourLoginSc.Teacher = 1;
+                                        hourLoginSc.Student = 0;
+                                        hourLoginSc.TmdUser = 0;
+                                    }
+                                    else if (scope.Equals("student"))
+                                    {
+                                        hourLoginSc.Teacher = 0;
+                                        hourLoginSc.Student = 1;
+                                        hourLoginSc.TmdUser = 0;
+                                    }
+                                    else
+                                    {
+                                        hourLoginSc.Teacher = 0;
+                                        hourLoginSc.Student = 0;
+                                        hourLoginSc.TmdUser = 1;
+                                    }
+                                    hourLoginSchools.Add(hourLoginSc);
+                                }
+                            }
+                        }
+                        await table.SaveOrUpdateAll(hourLoginSchools);
+                    }
+                    //学校天峰值
+                    var scMonthCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateMonth}");
+                    if (scMonthCnt != null && scMonthCnt.Length > 0)
+                    {
+                        List<DayLoginSchool> DayLoginSchools = new();
+                        foreach (var scMCnt in scMonthCnt)
+                        {
+                            if (((int)scMCnt.Element) == currentDay)
+                            {
+                                var tempDays = await table.QueryWhereString<DayLoginSchool>($"PartitionKey eq 'DayLogin-{school}' and RowKey eq '{dateDay}'");
+                                if (tempDays.Count > 0)
+                                {
+                                    foreach (var dLoginSc in tempDays)
+                                    {
+                                        if (scope.Equals("teacher"))
+                                            dLoginSc.Teacher = (int)scMCnt.Score;
+                                        else if (scope.Equals("student"))
+                                            dLoginSc.Student = (int)scMCnt.Score;
+                                        else
+                                            dLoginSc.TmdUser = (int)scMCnt.Score;
+                                        DayLoginSchools.Add(dLoginSc);
+                                    }
+                                }
+                                else
+                                {
+                                    //学校天峰值
+                                    DayLoginSchool dayLoginSc = new() { PartitionKey = $"DayLogin-{school}", RowKey = dateDay, Day = currentDay, School = school };
+                                    if (scope.Equals("teacher"))
+                                    {
+                                        dayLoginSc.Teacher = 1;
+                                        dayLoginSc.Student = 0;
+                                        dayLoginSc.TmdUser = 0;
+                                    }
+                                    else if (scope.Equals("student"))
+                                    {
+                                        dayLoginSc.Teacher = 0;
+                                        dayLoginSc.Student = 1;
+                                        dayLoginSc.TmdUser = 0;
+                                    }
+                                    else
+                                    {
+                                        dayLoginSc.Teacher = 0;
+                                        dayLoginSc.Student = 0;
+                                        dayLoginSc.TmdUser = 1;
+                                    }
+
+                                    DayLoginSchools.Add(dayLoginSc);
+                                }
+                            }
+                        }
+                        await table.SaveOrUpdateAll(DayLoginSchools);//保存学校当月在线数据
+                    }
+
+                    string tbScHourSql = $"PartitionKey eq 'HourLogin-{school}' and RowKey le '{delTbHour}'";
+                    await table.DeleteStringWhere<BIOptLog>(rowKey: tbHourSql); //删除学校168小时前的数据
+
+                    string tbScDaySql = $"PartitionKey eq 'DayLogin-{school}' and RowKey le '{delTbDay}'";
+                    await table.DeleteStringWhere<BIOptLog>(rowKey: tbDaySql); //删除学校180天前的数据
+                }
+
+                await response.WriteAsJsonAsync(new { data = json });
+                return response;
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-online-record 人数记录异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                await response.WriteAsJsonAsync(new { data = json });
+                return response;
+            }
+        }
     }
 }

+ 25 - 0
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -995,6 +995,31 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                         lessonRecord.clientInteractionAverge = lessonBase.summary.clientInteractionAverge;
                                         lessonRecord.examCount = lessonBase.summary.examCount;
                                         lessonRecord.totalInteractPoint = lessonBase.summary.totalInteractPoint;
+                                        if (!string.IsNullOrWhiteSpace(lessonRecord.school)) {
+                                            lessonBase.student.ForEach(x => {
+                                                if (string.IsNullOrWhiteSpace(x.school))
+                                                {
+                                                    x.school = lessonRecord.school;
+                                                }
+                                            });
+                                        }
+                                        LessonStudentRecord lessonStudentRecord = new LessonStudentRecord
+                                        {
+                                            clientSummaryList = lessonBase.report.clientSummaryList,
+                                            students = lessonBase.student,
+                                            name = lessonRecord.name,
+                                            school = lessonRecord.school,
+                                            id = lessonRecord.id,
+                                            scope = lessonRecord.scope,
+                                            tmdid = lessonRecord.tmdid,
+                                            code = "LessonStudentRecord",
+                                            pk = "LessonStudentRecord",
+                                            courseId =lessonRecord.courseId,
+                                            groupIds= lessonRecord.groupIds,
+                                            periodId = lessonRecord.periodId,
+                                            subjectId = lessonRecord.subjectId,
+                                        };
+                                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS,Constant.Student).UpsertItemAsync<LessonStudentRecord>(lessonStudentRecord, new PartitionKey("LessonStudentRecord"));
                                     }
                                     //有上传 base.josn.
                                     lessonRecord.upload =1;

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

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

+ 39 - 0
TEAMModelOS.SDK/Helper/Common/ReflectorExtensions/ReflectorExtensions.cs

@@ -53,6 +53,14 @@ namespace TEAMModelOS.SDK.Helper.Common.ReflectorExtensions
                 foreach (var model in ScanModel)
                 {
                     Assembly assembly = Assembly.LoadFrom(currentDirectory + "\\" + model + ".dll");
+                    var TypeInModelS = assembly.GetTypes().SelectMany(x => x.GetMethods()).GroupBy(z=>z.Name).ToList();
+                    TypeInModelS.ForEach(x => {
+                        if (x.Key.Equals("GetTeacherInfo"))
+                        {
+                            var at = x.ToList().SelectMany(z => z.GetCustomAttributes()).Where(m=>m.GetType().Equals(attr));
+                            string ke = x.Key;
+                        }
+                    });
                     var  TypeInModel = assembly.GetTypes().Select(x => x.GetMethods()).SelectMany(y => y).Select(z=>z.GetCustomAttribute(attr,true)).Where(n=>n!=null);
                     attributes.AddRange(TypeInModel);
                 }
@@ -60,6 +68,37 @@ namespace TEAMModelOS.SDK.Helper.Common.ReflectorExtensions
             return attributes;
         }
 
+        /// <summary>
+        /// 获取T类型的属性标记的类的方法集合
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <returns></returns>
+        public static List<Attribute> GetMethodCustomAttribute<T,V>(string[] ScanModel)
+        {
+            Type attrT = typeof(T);
+            Type attrV = typeof(V);
+            string currentDirectory = Path.GetDirectoryName(attrT.Assembly.Location);
+            List<Attribute> attributes = new List<Attribute>();
+            if (ScanModel != null)
+            {
+                foreach (var model in ScanModel)
+                {
+                    Assembly assembly = Assembly.LoadFrom(currentDirectory + "\\" + model + ".dll");
+                    var TypeInModelS = assembly.GetTypes().SelectMany(x => x.GetMethods()).GroupBy(z => z.Name).ToList();
+                  //  var TypeInModelSS = assembly.GetTypes().SelectMany(x => x.GetMethods()).Where(x=>);
+                    TypeInModelS.ForEach(x => {
+                        if (x.Key.Equals("GetTeacherInfo"))
+                        {
+                            var at = x.ToList().SelectMany(z => z.GetCustomAttributes()).Where(m => m.GetType().Equals(attrT));
+                            string ke = x.Key;
+                        }
+                    });
+                    var TypeInModel = assembly.GetTypes().Select(x => x.GetMethods()).SelectMany(y => y).Select(z => z.GetCustomAttribute(attrT, true)).Where(n => n != null);
+                    attributes.AddRange(TypeInModel);
+                }
+            }
+            return attributes;
+        }
         /// <summary>
         /// 获取T类型属性标记的类集合
         /// </summary>

+ 21 - 46
TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs

@@ -254,7 +254,7 @@ namespace TEAMModelOS.SDK.Models
         /// <summary>
         /// 
         /// </summary>
-        public List<StudentItem> student { get; set; }
+        public List<LessonStudent> student { get; set; }
     }
     public class Summary
     {
@@ -365,50 +365,24 @@ namespace TEAMModelOS.SDK.Models
 
     public class ClientSummaryList
     {
-        /// <summary>
-        /// 
-        /// </summary>
-        public string groupName { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public double groupScore { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public int groupTaskCompleteCount { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        //public double attendState { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public double score { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public int taskCompleteCount { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public List<double> examScoreList { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public double interactScore { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public List<string> answerList { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public int seatID { get; set; }
-        /// <summary>
-        /// 李镇希
-        /// </summary>
-        public string name { get; set; }
+        public string groupName { get; set; }//組名
+        public double groupScore { get; set; }//組記分
+
+        public int groupTaskCompleteCount { get; set; }//組任務數完成數
+        //public int attendState { get; set; } //出席狀態
+
+        public double score { get; set; }//個人記分
+        public int taskCompleteCount { get; set; }//任務完成數
+
+        public List<double> examScoreList { get; set; } = new List<double>();//課堂測驗分數Array
+
+        public double tnteractScore { get; set; }//互動總得分
+
+        public List<string> answerLis { get; set; } = new List<string>(); //逐題回答內容Array
+
+        public int seatID { get; set; } //座位號
+
+        public string name { get; set; }//學生姓名
     }
 
     public class Report
@@ -424,8 +398,9 @@ namespace TEAMModelOS.SDK.Models
         
     }
 
-    public class StudentItem
+    public class LessonStudent
     {
+        public string school { get; set; }//学校编码
         /// <summary>
         /// 学生id
         /// </summary>

+ 39 - 2
TEAMModelOS.SDK/Models/Cosmos/Common/LessonStudentRecord.cs

@@ -17,9 +17,46 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
         public LessonStudentRecord() {
             pk = "LessonStudentRecord";
         } 
+        /// <summary>
+        /// 课程
+        /// </summary>
         public string courseId { get; set; }
+        /// <summary>
+        /// 学段
+        /// </summary>
         public string periodId { get; set; }
-        public List<string> studentId { get; set; } = new List<string>();
-        public List<double> score { get; set; } = new List<double>();
+
+        /// <summary>
+        ///  不填 科目id,由课程id获取
+        /// </summary>
+        public string subjectId { get; set; }
+        /// <summary>
+        /// 名单信息
+        /// </summary>
+        public List<string> groupIds { get; set; } = new List<string>();
+        /// <summary>
+        /// 学生
+        /// </summary>
+        public List<LessonStudent> students { get; set; } = new List<LessonStudent>();
+        /// <summary>
+        /// 学生互动信息
+        /// </summary>
+        public List<ClientSummaryList> clientSummaryList { get; set; } = new List<ClientSummaryList>();
+        /// <summary>
+        ///必填 教师醍摩豆id
+        /// </summary>
+        public string tmdid { get; set; }
+        /// <summary>
+        ///必填 课堂名称
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        ///必填 scope==school必填 | string | 学校id
+        /// </summary>
+        public string school { get; set; }
+        /// <summary>
+        ///必填  private/school|
+        /// </summary>
+        public string scope { get; set; }
     }
 }

+ 12 - 0
TEAMModelOS.SDK/Models/Cosmos/School/School.cs

@@ -85,6 +85,10 @@ namespace TEAMModelOS.SDK.Models
         /// 创建时间  十位 时间戳
         /// </summary>
         public long createTime { get; set; }
+        /// <summary>
+        /// 存多个区域
+        /// </summary>
+        public List<ManyArea> manyAreas { get; set; }
     }
     /// <summary>
     /// 课表计划
@@ -118,4 +122,12 @@ namespace TEAMModelOS.SDK.Models
         public string value { get; set; } = null;
 
     }
+    /// <summary>
+    /// 存区域
+    /// </summary>
+    public class ManyArea 
+    {
+        public string areaId { get; set; }
+        public string standard { get; set; }
+    }
 }

+ 44 - 0
TEAMModelOS.SDK/Models/Cosmos/Teacher/OnLinRec.cs

@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static TEAMModelOS.SDK.Models.Teacher;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.Teacher
+{
+    /// <summary>
+    /// 存储登录记录试题存储中间实体
+    /// </summary>
+    public class OnLinRec
+    {
+        /// <summary>
+        /// 登录者的ID
+        /// </summary>
+        public string id { get; set; }
+        /// <summary>
+        /// 登录类型Teacher Student  TmdUser
+        /// </summary>
+        public string scope { get; set; }
+        /// <summary>
+        /// 登陆者的IP地址
+        /// </summary>
+        public string ip { get; set; }
+        /// <summary>
+        /// 学校ID
+        /// </summary>
+        public string school { get; set; }
+        /// <summary>
+        /// 到期时间 小时
+        /// </summary>
+        public int expire { get; set; } = 1;
+        /// <summary>
+        /// 上次登录地址
+        /// </summary>
+        public string region { get; set; } = null;
+        ///// <summary>
+        ///// 保留一条登录信息
+        ///// </summary>
+        //public List<LoginInfo> loginInfos { get; set; }
+    }
+}

+ 8 - 3
TEAMModelOS.SDK/Models/Service/Common/TeacherService.cs

@@ -29,7 +29,7 @@ namespace TEAMModelOS.Services
 {
     public static class TeacherService
     {
-        public static async Task<TeacherInfo> TeacherInfo(AzureCosmosFactory _azureCosmos, Teacher teacher, string name, string picture, string id, AzureStorageFactory _azureStorage, Option _option,AzureRedisFactory _azureRedis,string ip)
+        public static async Task<TeacherInfo> TeacherInfo(AzureCosmosFactory _azureCosmos, Teacher teacher, string name, string picture, string id, AzureStorageFactory _azureStorage, Option _option,AzureRedisFactory _azureRedis,string ip, HttpTrigger _httpTrigger)
         {
             List<object> schools = new List<object>();
             List<AreaDto> areas = new List<AreaDto>();
@@ -219,6 +219,7 @@ namespace TEAMModelOS.Services
                         teacher.defaultSchool = null;
                     }
                 }
+                await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
                 //預設學校ID
                 defaultschool = teacher.defaultSchool;
             }
@@ -278,9 +279,13 @@ namespace TEAMModelOS.Services
             var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, standard: areaa != null ? areaa.standard : "", roles: roles.ToArray(), expire: 1);
 
             //用户在线记录
-            teacher.loginInfos = await LoginService.DoLoginInfo(teacher.loginInfos, defaultschool, Constant.ScopeTeacher, id, ip, _azureRedis, _azureStorage, expire: 1);
+            try
+            {
+                _ = _httpTrigger.RequestHttpTrigger(new { school = defaultschool, scope = $"{Constant.ScopeTeacher}", id=$"{id}", ip=$"{ip}", expire=1 }, _option.Location, "online-record");
+            }
+            catch { }
 
-            await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
+           
             //取得Teacher Blob 容器位置及SAS 
             await _azureStorage.GetBlobContainerClient(id).CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
             var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(id, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete);

+ 2 - 2
TEAMModelOS.SDK/Models/Table/OpenApi.cs

@@ -21,7 +21,7 @@ namespace TEAMModelOS.SDK.Models
     /// 限流方案  漏斗、令牌桶、sentinel
     /// 平台开放的OpenAIPs
     /// </summary>
-    [TableName(Name = "OpenApi")]
+    [TableName(Name = "IESOpenApi")]
     public class OpenApi : TableEntity
     {
         public OpenApi() {
@@ -72,7 +72,7 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         ///public decimal cost { get; set; }
     }
-    [TableName(Name = "OpenApi")]
+    [TableName(Name = "IESOpenApi")]
     public class Webhook : TableEntity
     {
         public Webhook()

+ 111 - 66
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -347,20 +347,28 @@ const LANG_EN_US = {
         filter6: 'Bound',
         filter7: 'Serial No. Filtering',
         search: 'Search',
-        classroom: 'CLassroom:',
+        classroom: 'Classroom:',
         expiredData: 'Expiry Date:',
         hadExp: '(Expired)',
         useInfo: 'Use Status:',
-        unband: 'Unbind',
+        unband: 'Unbind Device',
         cancel: 'Cancel',
         select: 'Select',
         hasSelected: 'Selected',
         sltTips: 'Please select serial number',
         band: 'Bind',
-        attr1: 'Sokrates Lesson Observation',
-        attr2: 'Distance Classroom Service',
-        attr3: 'Recording System',
-        unbandTitle: 'Unbound Serial No.',
+        attr1: 'Sokrates App',
+        attr2: 'Sokrates Video',
+        attr3: 'Sokrates Report',
+        attr4: 'Sokrates Screen Video',
+        attr5: 'AI Terminal',
+        attr6: 'Distance Smarter Classroom Service System',
+        attr7: 'IRS Disabled',
+        attr8: 'AI Camera',
+        attr9: 'AI Text Analysis',
+        attr10: 'DLO Participant No.',
+        attr11: 'Group No.',
+        unbandTitle: 'Unbind Serial No.',
         unbandCont: 'Are you sure to unbind the serial no. of the current classroom?',
         scaleLabel: 'School Scale Authorization',
         scaleInfo: 'Online Capacity',
@@ -374,6 +382,42 @@ const LANG_EN_US = {
         toAuth: 'Go to Authorize',
         periodInfo1: 'No. of school systems school purchased',
         periodInfo2: 'No. of colleges school purchased',
+        searchSerial:'Search serial number',
+        noDeviceName:'No device name yet',
+        noClassId:'No bound classroom',
+        rltClass:'Bind to a classroom',
+        unrltClass:'Unbind Classroom',
+        unbdDeviceCont:'Confirm to unbind this device?',
+        unbdOk:'Unbind successfully',
+        unbdErr1:'Device ID error',
+        unbdErr2:'Serial number abnormal',
+        unMatchRoom:'Not matched to a classroom',
+        deviceName:'Device Name:',  
+        bandOk:'Bound successfully',
+        bandErr:'Failed to bind',
+        unbdRoomCt:'Are you sure to unbind this classroom?',
+        unbdOk:'Unbind successfully',
+        unbdErr:'Failed to unbind',
+        pdName1:'學情分析模組',
+        pdName2:'智慧學校管理服務',
+        pdName3:'卷卡合一閱卷系統',
+        pdName4:'AClass ONE智慧學伴',
+        pdName5:'數據儲存服務空間',
+        pdName6:'Haboard醍摩豆智慧大屏',  
+        serialLabel:'序列号:',
+        authDate:'有效期:',
+        fuAuth:'功能权限:',
+        IRSnumber:'IRS链接数:',
+        bandDeviceNO:'可绑定硬件数:',
+        svcName:'服务名称:',
+        authType:'授权方式:',
+        authType1:'新约',
+        authType2:'续约',
+        authNumber:'购买数量:',
+        text1:'設備名稱:',
+        text2:'硬件:',
+        text3:'服務類型:',
+        text4:'智慧教室:',
     },
     // 班级管理
     classMgmt: {
@@ -780,7 +824,7 @@ const LANG_EN_US = {
         nicknameTips: "Please enter the student's nickname",
         evRcd: 'Assessment',
         gradeErr: 'Failed to obtain grade data',
-        rcdExpired:'到期',
+        rcdExpired:'expired',
 
         //ManageClass.vue
         stuMgt: 'Student Management',
@@ -875,7 +919,7 @@ const LANG_EN_US = {
         timeSetTitle: 'Schedule Settings',
         job: 'Title',
         teaName: 'Name',
-        listName: 'List Name',
+        listName: 'Name',
         stuCount: 'Student Number',
         code: 'Class ID',
         nameWarning: 'Please enter list name',
@@ -1106,9 +1150,6 @@ const LANG_EN_US = {
         paperTagPlace: 'Manual input to create new tabs',
         useTip: 'Please keep at least one use of the test question',
         editor: {
-            canvasTip:'空白畫闆',
-            canvasStemTip:'帶題幹畫闆',
-            addTextDot:'添加著重號',
             imagePasteTip: 'You can open the TM Teaching Assistant to get a better picture/text paste experience.',
             uploadVideo: 'Upload Local Video',
             uploadAudio: 'Upload Local Audio',
@@ -1229,7 +1270,7 @@ const LANG_EN_US = {
             modalTip: 'Friendly Reminder',
             unSaveTip: 'Are you sure you want to quit saving the current question and leave?',
             answerTitle: 'Reference Answer',
-            contentRelate: 'Link Content'
+            contentRelate: 'Linked Content'
         },
         exerciseList: {
             confirmDelete: 'Are you sure you want to delete the test question?',
@@ -1827,7 +1868,7 @@ const LANG_EN_US = {
         offline: {
             activity: "研修活動",
             info: "詳細資訊",
-            creator: "建者",
+            creator: "建者",
             noPeople: "無",
             joinNum: "參與人數",
             actTime: "活動時間",
@@ -2021,7 +2062,7 @@ const LANG_EN_US = {
     // 知识点管理
     knowledge: {
         title: 'Key Concept Management',
-        colorTip: '* Green indicates the selected key concept, the blue indicates key concept related to the key concept set',
+        colorTip: '* Green indicates the selected key concept. Blue indicates key concept already added to the key concept set',
         subject: 'Subject',
         label: 'Name',
         blockP: 'Please enter the key concept set name',
@@ -2089,7 +2130,7 @@ const LANG_EN_US = {
     },
     // 活动模块
     learnActivity: {
-        noStartTimeTip:'不設置則默認為立即發佈',
+        noStartTimeTip:'If not set, the default is to start immediately',
         school: 'School',
         area: 'District',
         noFound: "Can't find the current activity!",
@@ -2273,6 +2314,7 @@ const LANG_EN_US = {
             zeroScore1: '0 point',
             stuAns: '【Student Response】',
             mark: 'Annotate',
+            reMark:'Re-annotate',
             quAns: '【Answer】',
             question: '【Question】',
             noAnswer: 'No answer set',
@@ -2361,8 +2403,8 @@ const LANG_EN_US = {
             crtTips2: '2. For more detailed data analysis, please go to Learning Analysis.',
             crtErr: 'Failed to load data',
             noSeeRpt: 'Students have not yet answered and cannot view their individual reports',
-            noSeeRpt1: '評測進行中,無法查看學生報告',
-            noSeeRpt2: '尚未完成當前學生的評分,無法查看學生報告',
+            noSeeRpt1: 'Assessment in progress, unable to view student reports',
+            noSeeRpt2: "Student reports are not available for viewing as the current student's grading has not been completed",
             crtRateTitle: 'Correct Rate Statistics',
             crtLabel: 'Correct',
             wrongLabel: 'Incorrect',
@@ -2598,21 +2640,21 @@ const LANG_EN_US = {
     },
     // 课堂记录
     lessonRecord: {
-        overdue:'到期',
-        customSetting: '自定義設置',
-        open: '開啟',
-        close: '關閉',
-        condTip: '默認課堂記錄僅保留7天(被收藏的課例除外),若開啟自定義設置,則需要您設置保留期限以及保留條件',
-        daySetting: '課例保留時間設置',
-        expire: '課堂記錄保留期限',
-        day: '',
-        condTip2: '符合以下條件的課堂記錄,將會進行保留,不會被繫統自動清除',
-        advanced: '進階設置',
-        over: '大於等於',
-        less: '小於等於',
-        point: '',
-        unit: '',
-        setting: '課堂記錄設置',
+        overdue:'expired',
+        customSetting: 'Custom Setting',
+        open: 'Open',
+        close: 'Close',
+        condTip: 'Lesson records are kept for 7 days only by default (except for collected ones). If you use custom setting, you will need to set a retention period and retention conditions.',
+        daySetting: 'Retention Period Setting',
+        expire: 'Retention Period',
+        day: ' days',
+        condTip2: 'Lesson records that meet the following criteria will be retained and will not be automatically erased by the system',
+        advanced: 'Advanced Settings',
+        over: 'Greater than or equal to',
+        less: 'Less than or equal to',
+        point: 'point',
+        unit: '',
+        setting: 'Lesson Record Setting',
         all: 'All',
         cate: 'Category',
         range: 'Time',
@@ -3018,12 +3060,12 @@ const LANG_EN_US = {
             title: 'Smart Campus Big Data',
             block1: 'Teaching & Research',
             block2: 'Classroom IoT',
-            block3: 'Moral Education Evaluation',
+            block3: 'Multivariate Assessment',
             block4: 'Learning Status Analysis',
-            block5: '教學看闆',
-            block6: '德育看闆',
-            block7: '體育看闆',
-            block8: '藝術看闆',
+            block5: 'Teaching Board',
+            block6: 'Moral Education Board',
+            block7: 'Physical Education Board',
+            block8: 'Art Board',
             comingSoon: 'Coming Soon',
             loading: 'Loading',
             quit: 'Exit',
@@ -3220,9 +3262,9 @@ const LANG_EN_US = {
         tab1: 'Basic Information',
         tab2: 'Student List',
         tab3: 'Location Settings',
-        tab4: 'Linked Hiteach',
+        tab4: 'Linked HiTeach',
         classAttr: 'Classroom Attribute',
-        relationHi: 'Associated HiTeach Devices',
+        relationHi: 'Linked HiTeach Devices',
         hiFilter1: 'Show all versions of HiTeach',
         hiFilter2: 'Show Hiteach Standard version only',
         hiFilter3: 'Show Hiteach Pro version only',
@@ -3230,7 +3272,7 @@ const LANG_EN_US = {
         single: 'Single ',
         mach: 'Mass',
         expireLabel: 'Serial Number Expiration Date',
-        related: 'Already Associated',
+        related: 'Already Linked',
         noEnable: 'This serial number is not yet used',
         onClassStu: 'There is no fixed student list in a dedicated subject classrooms!',
         classNoErr: 'The class ID cannot be empty!',
@@ -3300,6 +3342,7 @@ const LANG_EN_US = {
         updOk: 'Modified successfully',
         updErr: 'Failed to modify',
         warmTips: 'Reminder',
+        mobileTips:'In order to make better use of the system, it is recommended to use the PC IES5 device!',
         noStuContent: 'The school has not imported any student account, do you want to go to Student Management to import student accounts?',
         setIrsWarning: 'Please set IRS number',
         setNoWarning: 'Please set seat number'
@@ -3524,8 +3567,8 @@ const LANG_EN_US = {
         unedit: '取消編輯',
         delModal1: '您確定刪除',
         delModal2: '嗎?',
-        delModal3: '刪除成功',
-        delModal4: '刪除失敗',
+        delModal3: 'Delete successfully',
+        delModal4: 'Failed to delete',
         delModal5: '已取消刪除',
         keepModal1: '儲存成功',
         keepModal2: '儲存失敗',
@@ -3609,7 +3652,7 @@ const LANG_EN_US = {
         sltPdFirst: 'Please select school system first',
         sltGdFirst: 'Please select grade level first',
         noClass: 'This grade has no class yet',
-        noRelClass: 'Unrelated Classes',
+        noRelClass: 'No linked classes',
         resetPw: 'Reset Password',
         semYear: 'Semester:',
         delOk: 'Deleted successfully',
@@ -3619,7 +3662,7 @@ const LANG_EN_US = {
         adminClass: 'Admin Class',
         teachClass: 'Customized Class',
         stuMgt: 'Student Management',
-        filterNoClass: 'Filter students who are not associated with any classes',
+        filterNoClass: 'Filter students who are not linked with any classes',
         updClass: 'Change Class',
         sltStuLabel: 'Selected Student:',
         classLabel: 'Class:',
@@ -3693,7 +3736,7 @@ const LANG_EN_US = {
         idWarning: 'Warning: Account/student ID is repeated in Excel!',
         idFormatWarning: 'Error:Student account format is a 4-12 digit number',
         gradeWarning: 'Warning: Error in grade',
-        setNoErr: "錯誤:座位號與當前班級已導入的學生重復",
+        setNoErr: "Error: The seat number is duplicated with a student already imported in this class.",
         downloadText: '(Download List Sample)',
         idRepErr: 'Account already exists, will overwrite the original account',
         stuYearErr: "Student's academic year data is incorrect",
@@ -3731,15 +3774,15 @@ const LANG_EN_US = {
             survey: 'Survey',
             homework: 'Homework',
             title: {
-                classRecord: "老師發佈的課堂記錄",
-                activity: "老師發佈的活動",
-                notice1: "班級公告",
-                notice2: "課程公告",
-                exam: "評測成績分析",
-                homework: "作業評分",
-                classScore: "課例記分",
+                classRecord: "Lesson records posted by teachers",
+                activity: "Activities started by teachers",
+                notice1: "Class Announcement",
+                notice2: "Course Announcement",
+                exam: "Assessment Grade Analysis",
+                homework: "Homework Rating",
+                classScore: "Lesson Point",
             },
-            toLook: "現在去看",
+            toLook: "See now",
         },
         public: {
             noData: 'No data yet',
@@ -3762,7 +3805,7 @@ const LANG_EN_US = {
             hour: "H",
             minute: "M",
             mustFile: "Must Upload",
-            uploadTime: "上傳時間",
+            uploadTime: "Upload Time",
         },
         type: {
             home: "Home",
@@ -4214,7 +4257,6 @@ const LANG_EN_US = {
                 againPractice: "Practice Again",
                 finish: 'Completed',
                 showAns: 'Show the answer',
-                showPage: "查看題號",
                 hideAns: 'Hide the answer',
                 hint: 'Key Hint',
                 previous: 'Previous Question',
@@ -4249,7 +4291,6 @@ const LANG_EN_US = {
                 correction: 'Correct Answer',
                 queNo: 'Question:',
                 myAns: 'My Answer:',
-                reAns:'New Answer:',
                 noExam: "No question yet",
                 wrongSub: "Incorrect",
                 rightSub: "Correct",
@@ -4558,9 +4599,9 @@ const LANG_EN_US = {
             wrongNum: "No. of Incorrect",
         },
         myAchievement: {
-            examAch: "評量成績",
-            hwAch: "作業成績",
-            cusAch: "老師給分",
+            examAch: "Assessment Results",
+            hwAch: "Homework Results",
+            cusAch: "Teacher's Score",
             examMode: "Assessment Mode",
             examIn: "Source",
             name: "Name",
@@ -4849,10 +4890,12 @@ const LANG_EN_US = {
     // 系统相关
     system: {
         wechatTip: '關注醍摩豆微信公眾號咨詢',
+        wechatTipTw: "TEAM Model Facebook Page",
         preview: 'Preview',
         title: 'TEAM Model Cloud',
         hostTitle: {
-            jinniu: '成都市金牛區研修平台'
+            jinniu: '成都市金牛區研修平台',
+            scyx: 'Research Platform',
         },
         loading: 'Loading',
         authErr: 'Insufficient authorization!',
@@ -4918,7 +4961,7 @@ const LANG_EN_US = {
             discuss: 'Discussion Center',
             policy: 'Policy Document',
             research: 'Lesson',
-            toSokrates:'蘇格拉底',
+            toSokrates:'Sokrates',
             researchBoard: 'Data Board',
             cusVideos: 'Lesson Data',
             cusVideoMgt: 'Records',
@@ -5123,7 +5166,7 @@ const LANG_EN_US = {
         tips2: 'List',
         tips3: 'Download File',
         tips4: 'Preview File',
-        tips5: 'Related Key Concept',
+        tips5: 'Associated Key Concept',
         tips6: 'Rename',
         tips7: 'Delete',
         tips8: 'Your browser does not support the video tag',
@@ -5136,7 +5179,7 @@ const LANG_EN_US = {
         props7: 'Not enough storage space!',
         uploadText: 'Tap or drag to upload',
         resTips: 'HiTeach generates teaching materials that only support HTEX format previews',
-        space: '可用空間:',
+        space: 'Available Space:',
         calcing: 'Calculating...',
         blobFull: '(Full)',
         otherType: 'Other types',
@@ -5163,7 +5206,7 @@ const LANG_EN_US = {
         startDown: 'Start Downloading',
         videoTips: 'Friendly reminder: Only MP4 format is supported for online video playing! ',
         spaceTips: 'School Available Space = Total School Space - Space Allocated To Teachers',
-        common: 'General',
+        common: 'General (unassociated school sysyem resources)',
         renameTitle: 'Rename',
         fileName: 'File Name:',
         sltPeriod: 'Please select at least one school system',
@@ -5450,7 +5493,7 @@ const LANG_EN_US = {
         importTips7: '5. note: Note about the teacher, optional',
         importTips8: "Tip: If the imported teacher's user ID, cell phone, or email has already registered a TEAM Model account, the system will automatically invite the teacher to join the school.",
         importTips9: 'Select or drag files to this area to import',
-        impText: '無效數據(沒有名字):',
+        impText: 'Invalid Data (No name):',
         impText1: 'No. of imported:',
         impText2: 'No. of only name is imported:',
         impText3: 'No. of auto-invite by system:',
@@ -5464,6 +5507,7 @@ const LANG_EN_US = {
         impTd3: 'Email',
         impTd4: 'User ID',
         impTd5: 'Note',
+        expTd:'Status',
         joinTips1: 'Note: If a teacher is imported into the school by name only, the teacher can be bound/modified to join the school after comparing with the current teacher account in the school.',
         joinTips2: 'Binding teachers who have not yet joined school:',
         hasLeader: 'This teacher is already a section chief',
@@ -5855,7 +5899,7 @@ const LANG_EN_US = {
             all: '全部',
             trainTypeLabel: '活動類型:',
             search: '搜索',
-            toCreate: '建研修',
+            toCreate: '建研修',
             areaLabel: '區級',
             schoolLabel: '校級',
             presenter: '主講人:',
@@ -6052,6 +6096,7 @@ const LANG_EN_US = {
         uploadVideoLimit: 'Only one video can be uploaded at most!',
         videoFormatError: 'The video format is incorrect! Please reselect!',
         audioFormatError: 'The audio format is incorrect! Please reselect!',
+        maxFileSize: "Upload file size cannot exceed 100MB!",
         fileReadFail: 'There is test data reading failure!',
         uploadLoading: 'Uploading...',
         standrad: 'Capability Point Version',

+ 56 - 10
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -351,15 +351,23 @@ const LANG_ZH_CN = {
         expiredData: '到期日:',
         hadExp: '(已到期)',
         useInfo: '使用状况:',
-        unband: '解绑',
+        unband: '解绑设备',
         cancel: '取消',
         select: '选择',
         hasSelected: '已选中',
         sltTips: '请选择序列号',
         band: '绑定',
-        attr1: '苏格拉底议课',
-        attr2: '远距教室服务',
-        attr3: '录播系统',
+        attr1: '苏格拉底APP',
+        attr2: '苏格拉底影片',
+        attr3: '苏格拉底报告',
+        attr4: '苏格拉底桌面',
+        attr5: 'ezStation',
+        attr6: '远距教室服务',
+        attr7: 'IRS禁用',
+        attr8: 'AI摄影机',
+        attr9: 'AI文句分析',
+        attr10: '议课人数',
+        attr11: '分组数',
         unbandTitle: '解绑序列号',
         unbandCont: '确认解绑当前教室的序列号吗?',
         scaleLabel: '学校规模授权',
@@ -374,6 +382,42 @@ const LANG_ZH_CN = {
         toAuth: '前往授权',
         periodInfo1: '学校学段数量',
         periodInfo2: '学校学院数量',
+        searchSerial:'搜索序列号',
+        noDeviceName:'暂无设备名称',
+        noClassId:'未关联教室',
+        rltClass:'关联教室',
+        unrltClass:'解绑教室',
+        unbdDeviceCont:'确认解绑当前设备吗?',
+        unbdOk:'解绑成功',
+        unbdErr1:'设备ID错误',
+        unbdErr2:'序列号异常',
+        unMatchRoom:'未匹配到教室',
+        deviceName:'设备名称:',  
+        bandOk:'绑定成功',
+        bandErr:'绑定失败',
+        unbdRoomCt:'确定解绑当前教室吗?',
+        unbdOk:'解绑成功',
+        unbdErr:'解绑失败',
+        pdName1:'学情分析模组',
+        pdName2:'智慧学校管理服务',
+        pdName3:'卷卡合一阅卷系统',
+        pdName4:'AClass ONE智慧学伴',
+        pdName5:'数据储存服务空间',
+        pdName6:'Haboard醍摩豆智慧大屏',
+        serialLabel:'序列号:',
+        authDate:'有效期:',
+        fuAuth:'功能权限:',
+        IRSnumber:'IRS链接数:',
+        bandDeviceNO:'可绑定硬件数:',
+        svcName:'服务名称:',
+        authType:'授权方式:',
+        authType1:'新约',
+        authType2:'续约',
+        authNumber:'购买数量:',
+        text1:'设备名称:',
+        text2:'硬件:',
+        text3:'服务类型:',
+        text4:'智慧教室:',
     },
     // 班级管理
     classMgmt: {
@@ -1106,9 +1150,6 @@ const LANG_ZH_CN = {
         paperTagPlace: '选择标签或者手动输入后回车创建新标签',
         useTip: '请至少保留一种试题用途',
         editor: {
-            canvasTip:'空白画板',
-            canvasStemTip:'带题干画板',
-            addTextDot:'添加着重号',
             imagePasteTip: '检测到您粘贴的内容包含图片信息,为了更好的使用体验,建议您开启醍摩豆阅卷助手',
             uploadVideo: '上传本地视频',
             uploadAudio: '上传本地音频',
@@ -2273,6 +2314,7 @@ const LANG_ZH_CN = {
             zeroScore1: '0分',
             stuAns: '【学 生 作 答】',
             mark: '批注',
+            reMark:'重新批注',
             quAns: '【答ㅤ案】',
             question: '【题  目】',
             noAnswer: '未设置答案',
@@ -3300,6 +3342,7 @@ const LANG_ZH_CN = {
         updOk: '修改成功',
         updErr: '修改失败',
         warmTips: '温馨提示',
+        mobileTips:'为了您更好的使用体验,建议使用PC端访问IES5云平台!',
         noStuContent: '学校暂未导入学生账号,是否前往学生管理汇入学生账号?',
         setIrsWarning: '请设置IRS编号',
         setNoWarning: '请设置座号'
@@ -4214,7 +4257,6 @@ const LANG_ZH_CN = {
                 againPractice: "再次练习",
                 finish: '已完成',
                 showAns: '显示答案',
-                showPage: "查看题号",
                 hideAns: '隐藏答案',
                 hint: '重点提示',
                 previous: '上一题',
@@ -4249,7 +4291,6 @@ const LANG_ZH_CN = {
                 correction: '正解',
                 queNo: '题目:',
                 myAns: '我的作答:',
-                reAns:'重新作答:',
                 noExam: "暂没有试题",
                 wrongSub: "错题",
                 rightSub: "正确题目",
@@ -4849,10 +4890,12 @@ const LANG_ZH_CN = {
     // 系统相关
     system: {
         wechatTip: '关注醍摩豆微信公众号咨询',
+        wechatTipTw: '扫描二维码添加LINE好友',
         preview: 'Beta',
         title: '醍摩豆云平台',
         hostTitle: {
-            jinniu: '成都市金牛区研修平台'
+            jinniu: '成都市金牛区研修平台',
+            scyx: '研修平台',
         },
         loading: '加载中',
         authErr: '权限不足!',
@@ -5464,6 +5507,7 @@ const LANG_ZH_CN = {
         impTd3: '邮箱',
         impTd4: '醍摩豆ID',
         impTd5: '备注',
+        expTd:'状态',
         joinTips1: '温馨提示:学校存在仅导入名字的老师,如果对应当前老师账号,可以进行绑定修改教师加入学校的状态。如果当前老师账号不为学校导入对应的老师可以不用进行绑定。',
         joinTips2: '绑定学校尚未加入的老师:',
         hasLeader: '当前老师已经是组长了',
@@ -5749,6 +5793,7 @@ const LANG_ZH_CN = {
         ql_text13: '返回',
         ql_text14: '连线题',
         ql_text15: '改错题',
+
         baseExport: {
             title: '选择要导出的表格',
             checkAll: '全选',
@@ -6052,6 +6097,7 @@ const LANG_ZH_CN = {
         uploadVideoLimit: '最多只能上传一个视频!',
         videoFormatError: '视频格式不正确!请重新选择!',
         audioFormatError: '音频格式不正确!请重新选择!',
+        maxFileSize: "上传文件大小不能超过100M!",
         fileReadFail: '有试题数据读取失败!',
         uploadLoading: '上传中...',
         standrad: '能力点版本',

Dosya farkı çok büyük olduğundan ihmal edildi
+ 133 - 88
TEAMModelOS/ClientApp/public/lang/zh-TW.js


+ 0 - 85
TEAMModelOS/ClientApp/src/App.vue

@@ -1,85 +0,0 @@
-<template>
-    <div id="app" data-html2canvas-ignore>
-        <div v-if="hasAccess"
-             id="nav">
-            <router-link to="/">Ho11111me</router-link> |
-            <router-link to="/protected">Protected</router-link> |
-            <a v-if="oidcIsAuthenticated" href @click.prevent="signOut">Sign out</a>
-            <a v-else href @click.prevent="authenticateOidc">Sign in</a>
-        </div>
-        <router-view />
-    </div>
-</template>
-
-<script>
-    import { mapGetters, mapActions } from 'vuex'
-    export default {
-        name: 'App',
-        computed: {
-            ...mapGetters('oidcStore', [
-                'oidcIsAuthenticated'
-            ]),
-            hasAccess: function() {
-                return this.oidcIsAuthenticated || this.$route.meta.isPublic
-            }
-        },
-        methods: {
-            ...mapActions('oidcStore', [
-                'authenticateOidc',
-                'removeOidcUser',
-                'signOutOidc'
-            ]),
-            userLoaded: function(e) {
-                console.log('I am listening to the user loaded event in vuex-oidc', e.detail)
-            },
-            oidcError: function(e) {
-                console.log('I am listening to the oidc error event in vuex-oidc', e.detail)
-            },
-            signOut: function() {
-                this.signOutOidc().then(() => {
-                    this.$router.push('/')
-                })
-                // this.removeOidcUser().then(() => {
-                //    this.$router.push('/')
-                // })
-            }
-        },
-        mounted() {
-            window.addEventListener('vuexoidc:userLoaded', this.userLoaded)
-            window.addEventListener('vuexoidc:oidcError', this.oidcError)
-        },
-        created() {
-            
-        },
-        destroyed() {
-            window.removeEventListener('vuexoidc:userLoaded', this.userLoaded)
-            window.removeEventListener('vuexoidc:oidcError', this.oidcError)
-        }
-    }
-</script>
-
-<style>
-	html,body{
-		font-family:'ALI' !important;
-	}
-    #app {
-        /* font-family: 'Avenir', Helvetica, Arial, sans-serif; */
-        -webkit-font-smoothing: antialiased;
-        -moz-osx-font-smoothing: grayscale;
-        text-align: center;
-        color: #2c3e50;
-    }
-
-    #nav {
-        padding: 30px;
-    }
-
-        #nav a {
-            font-weight: bold;
-            color: #2c3e50;
-        }
-
-            #nav a.router-link-exact-active {
-                color: #42b983;
-            }
-</style>

+ 4 - 1
TEAMModelOS/ClientApp/src/api/lessonRecord.js

@@ -41,5 +41,8 @@ export default {
 	getIntroLessons: function (data) {
 	    return post('/common/lesson-record/get-other-lesson-record', data)
 	}, 
-	
+	// 根据id 查询课堂记录
+    getLessonInfo: function (data) {
+        return post("/common/lesson-record/get-lesson-record-id", data)
+    },
 }

+ 9 - 3
TEAMModelOS/ClientApp/src/api/serviceDriveAuth.js

@@ -2,8 +2,14 @@ import { fetch, post } from '@/api/http'
 
 
 export default {
-    getSchoolProduct: function (data) {        
-        return post('/school/init/get-school-product', {'school_code': data} )
-       
+    getSchoolProduct: function (data) {
+        return post('/school/init/get-school-product', { 'school_code': data })
+    },
+    unbandSerial: function (data) {
+        return post('/school/init/unbind-serial', data)
+    },
+    classroomBand: function (data) {
+        return post('/school/classroom/hiteach-link-unlink', data)
     }
+    
 }

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

@@ -339,4 +339,8 @@ export default {
     getHwAch: function(data) {
         return post("/student/stu-hw-score", data)
     },
+    // 获取所有名单
+    getAllGrouplist: function(data) {
+        return post("/grouplist/get-student-joined-grouplist", data)
+    },
 }

BIN
TEAMModelOS/ClientApp/src/assets/image/qrcode_tw.png


+ 5 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/classmate-commentPages.less

@@ -92,6 +92,11 @@
       width: 75%;
       // margin-top: 38px;
 
+      .remarks {
+        font-size: 16px;
+        font-weight: bold;
+      }
+
       @media screen and (max-width: 991px) {
         padding: 20px 20px 100px 50px !important;
       }

+ 16 - 1
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/course-content.less

@@ -3,7 +3,7 @@
 .course-content {
     position: relative;
     float: right;
-    width: 70%;
+    width: 75%;
     padding: 2%;
     height: auto;
 
@@ -205,3 +205,18 @@
         }
     } */
 }
+
+@media screen and (max-width: 1280px) {
+    .course-content {
+        width: 67%;
+    }
+}
+
+@media screen and (max-width: 1024px) {
+    .course-content {
+        width: 100%;
+    }
+}
+.no-bar {
+    width: 100%;
+}

+ 64 - 30
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/course-list.less

@@ -1,42 +1,50 @@
 @import "color.less";
 
-.course-list {
-    .list{
-        width: 30%;
-
-        .tag-style {
-            border: 1px solid;
-            padding: 0 5px;
-            border-radius: 3px;
-            margin-right: 10px;
-        }
+// .course-list {
+.list {
+    // .list{
+    width: 25%;
+
+    .tag-style {
+        border: 1px solid;
+        padding: 0 5px;
+        border-radius: 3px;
+        margin-right: 10px;
     }
-    .tableViewBtn,.listViewBtn{
+
+    // }
+    .tableViewBtn,
+    .listViewBtn {
         display: inline-block;
         position: fixed;
-        right:20px;
-        top:-50px;
-        z-index:999;
-        
-        &:hover{
+        right: 20px;
+        top: -50px;
+        z-index: 999;
+
+        &:hover {
             color: @primary;
-            cursor:pointer
+            cursor: pointer
         }
     }
-    .chooseView{
+
+    .chooseView {
         color: @primary;
     }
-    .listViewBtn{
-        right:50px;
+
+    .listViewBtn {
+        right: 50px;
     }
-    .listViewBtn{
+
+    .listViewBtn {
         display: inline-block;
         position: absolute;
     }
+
     .addCourseIcon {
         font-size: 60px;
         margin: 10px;
     }
+
     .typeMark {
         text-align: center;
         background-color: @primary;
@@ -44,30 +52,32 @@
         font-size: 14px;
         padding: 1px 10px;
         border-radius: 10px;
-        margin-right:10px;
+        margin-right: 10px;
         margin-top: 3px;
     }
+
     .list-block {
         margin-top: 10px;
 
-        .list-table{
+        .list-table {
             margin: 0 10px;
 
-            .table-item{
+            .table-item {
                 cursor: pointer;
             }
 
-            .list-name{
+            .list-name {
                 font-weight: bold;
                 font-size: 16px;
                 margin-top: 5px;
             }
         }
 
-        .list-item-no{
+        .list-item-no {
             text-align: center;
         }
     }
+
     .list-item {
         height: auto;
         padding-left: 3%;
@@ -87,7 +97,7 @@
             width: 100% !important;
             padding: 15px 30px 15px 30px;
 
-            & > span{
+            &>span {
                 float: right;
             }
 
@@ -110,27 +120,31 @@
             // padding: 10px 20px 10px 30px;
             margin-top: 15px;
 
-            & > p{
+            &>p {
                 margin-bottom: 5px;
             }
         }
     }
+
     .ivu-tabs-tabpane {
         padding-bottom: 100px;
         height: 92vh;
         overflow: auto;
     }
+
     .courseTable {
         margin: 20px;
 
         .table-time {
             font-size: 8px;
         }
+
         .courseName {
             font-size: 12px;
             color: #515a6e;
-            font-weight:bolder;
+            font-weight: bolder;
         }
+
         .list-item-typeMark {
             width: auto;
             text-align: center;
@@ -140,11 +154,13 @@
             margin-top: 3px;
         }
     }
+
     .table-item-selected {
         font-weight: bolder !important;
         color: @secondary;
         // background-color: #d4ede1;
     }
+
     .table-item-selected {
         .list-item-typeMark {
             text-align: center;
@@ -157,8 +173,26 @@
     }
 }
 
-@media screen and (max-width: 768px) {
+/* @media screen and (max-width: 768px) {
     .course-list .list {
       width: 100%;
     }
+} */
+
+@media screen and (max-width: 1280px) {
+    .list {
+        width: 33%;
+    }
+}
+
+@media screen and (max-width: 1024px) {
+    .list {
+        width: 40%;
+    }
+}
+
+@media screen and (max-width: 768px) {
+    .list {
+        width: 100%;
+    }
 }

+ 9 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/homework.less

@@ -125,12 +125,21 @@
     }
 
     .homework-detail {
+        .answer-title {
+            font-weight: bold;
+            font-size: 20px;
+            margin-top: 10px;
+        }
         .file-show{
             background-color: #f1f1f1;
             border-radius: 5px;
             padding: 20px 25px;
             margin-top: 10px;
 
+            .answer-show img {
+                max-width: 50% !important;
+            }
+
             & > p{
                 font-size: 18px;
                 font-weight: bold;

+ 1 - 1
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-view.css

@@ -1,5 +1,5 @@
 .lesson-test {
-    height: 90vh;
+    /* height: 90vh; */
     padding-top: calc(1% + 15px);
 }
 .lesson-test .ivu-tabs-nav {

+ 32 - 34
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -132,7 +132,7 @@ export default {
         return {
             isLoading: false,
             systemLevel: this.$t('system.basic'),
-            isLock: false,
+            isLock: true,
             isShowAreaSelect: true,
             openNames: [],
             activeName: '',
@@ -144,7 +144,7 @@ export default {
                     opacity: 0
                 }
             },
-            isCollapsed: true,
+            isCollapsed: false,
             menuTree: [],
             isShowLogo: true,
             hasAnalysisAuth: false
@@ -157,11 +157,6 @@ export default {
         mouseLeave() {
             if (!this.isLock) this.isCollapsed = true
         },
-        //根据域名判断菜单是否显示
-        checkHost() {
-            let host = window.location.host
-            return host !== 'jinniu.teammodel.cn'
-        },
         initMenu() {
             //判断当前学校是否购买服务 暂未提供字段
             // this.schoolMenu = 
@@ -175,7 +170,7 @@ export default {
             if (this.$store.state.userInfo.hasSchool) {
                 let prodInfo = this.$store.state.user?.schoolProfile?.svcStatus || {}
                 //如果没有购买服务则为基础版、标准版、专业版
-                let serviceList = this.$GLOBAL.PROD_CODE.filter(item => item.type === 'service')
+                let serviceList = this.$GLOBAL.PROD_CODE().filter(item => item.type === 'service')
                 let count = 0
                 serviceList.forEach(item => {
                     if (prodInfo[item.code]) count++
@@ -252,6 +247,15 @@ export default {
                 }
             }
         },
+        IES5Menu() {
+            return !this.$jsFn.checkJinNiu() && !this.$jsFn.checkTrain()
+        },
+        jinniuMenu() {
+            return this.$jsFn.checkJinNiu()
+        },
+        trainMenu() {
+            return this.$jsFn.checkTrain()
+        },
         schoolMenu() {
             let data = !this.$store.state.userInfo.schoolPay ? [
                 //数据看板
@@ -264,7 +268,7 @@ export default {
                     permission: 'dashboard-read',
                     menuName: 'Dashboard',
                     child: [],
-                    isShow: this.checkHost()
+                    isShow: this.IES5Menu
                 },
                 // 学校管理
                 {
@@ -274,7 +278,7 @@ export default {
                     subName: 'schoolMgt',
                     role: 'admin',
                     permission: 'schoolSetting-read|teacher-read|student-read|classroom-read|auth-read|course-read',
-                    isShow: this.checkHost(),
+                    isShow: this.IES5Menu,
                     child: [
                         // 基础设置
                         {
@@ -307,7 +311,7 @@ export default {
                             role: 'admin',
                             permission: 'student-upd|student-read',
                             menuName: 'studentAccount',
-                            isShow: true && this.checkHost()
+                            isShow: this.IES5Menu
                         },
                         // 课程管理
                         {
@@ -318,7 +322,7 @@ export default {
                             role: 'admin',
                             permission: 'course-read|course-upd',
                             menuName: 'NewCusMgt',
-                            isShow: true && this.checkHost()
+                            isShow: this.IES5Menu
                         },
                         // 教室管理
                         {
@@ -329,7 +333,7 @@ export default {
                             role: 'admin',
                             permission: 'classroom-upd|classroom-read',
                             menuName: 'classroom',
-                            isShow: true && this.checkHost()
+                            isShow: this.IES5Menu
                         },
                         // 学校公告
                         {
@@ -340,7 +344,7 @@ export default {
                             role: 'admin',
                             permission: 'notify-upd',
                             menuName: 'schoolNotify',
-                            isShow: true && this.checkHost()
+                            isShow: this.IES5Menu
                         },
                         // 授权管理
                         {
@@ -351,8 +355,8 @@ export default {
                             role: 'admin',
                             permission: 'auth-read|auth-upd',
                             menuName: 'auth',
-                            isShow: this.checkHost()
-                            // isShow: this.$store.state.config.srvAdrType != 'product' && this.checkHost()
+                            isShow: this.IES5Menu
+                            // isShow: this.$store.state.config.srvAdrType != 'product' && this.$jsFn.checkJinNiu()
                         }
                     ]
                 },
@@ -364,7 +368,7 @@ export default {
                     subName: 'schoolRes',
                     role: 'admin|teacher',
                     permission: '',
-                    isShow: true && this.checkHost(),
+                    isShow: this.IES5Menu,
                     child: [
                         // 校本课纲
                         {
@@ -421,7 +425,7 @@ export default {
                     role: 'admin',
                     permission: 'schoolAc-read|schoolAc-upd',
                     subName: 'scAc',
-                    isShow: true && this.checkHost(),
+                    isShow: this.IES5Menu,
                     child: [{
                         icon: 'iconfont icon-test',
                         name: this.$t('system.menu.scEv'),
@@ -463,7 +467,7 @@ export default {
                     tag: this.$t('system.preview'),
                     permission: 'research-read|research-upd',
                     subName: 'research',
-                    isShow: this.checkHost(),
+                    isShow: this.IES5Menu,
                     child: [
                         {
                             icon: 'iconfont icon-course-videos',
@@ -589,7 +593,7 @@ export default {
                     permission: 'analysis-read',
                     menuName: 'totalIndex',
                     child: [],
-                    isShow: true && this.checkHost()
+                    isShow: this.IES5Menu
                 },
                 //开放平台
                 // {
@@ -601,7 +605,7 @@ export default {
                 //     permission: '',
                 //     menuName: 'OpenPlat',
                 //     child: [],
-                //     isShow: process.env.NODE_ENV == 'development' && this.checkHost()
+                //     isShow: process.env.NODE_ENV == 'development' && this.$jsFn.checkJinNiu()
                 // },
                 //三方平台
                 {
@@ -613,7 +617,7 @@ export default {
                     permission: '',
                     menuName: 'mgtPlatform',
                     child: [],
-                    isShow: this.checkHost()
+                    isShow: this.IES5Menu
                 }
             ] : []
             return data
@@ -725,7 +729,7 @@ export default {
                     permission: '',
                     child: [],
                     menuName: 'classmgt',
-                    isShow: this.$store.state.userInfo.hasSchool && this.isHeadmaster && this.checkHost()
+                    isShow: this.$store.state.userInfo.hasSchool && this.isHeadmaster && this.IES5Menu
                 },
                 // 我的课程
                 {
@@ -737,7 +741,7 @@ export default {
                     permission: '',
                     child: [],
                     menuName: 'myCourse',
-                    isShow: true && this.checkHost(),
+                    isShow: this.IES5Menu,
                     info: this.$t('tip.myCus')
                 },
                 // 我的资源
@@ -748,7 +752,7 @@ export default {
                     role: 'teacher',
                     permission: '',
                     subName: 'cusContent',
-                    isShow: true && this.checkHost(),
+                    isShow: this.IES5Menu,
                     child: [{
                         icon: 'iconfont icon-syllabus',
                         name: this.$t('system.menu.prtSyllabus'),
@@ -789,7 +793,7 @@ export default {
                     role: 'teacher|admin',
                     permission: '',
                     subName: 'stuAc',
-                    isShow: true && this.checkHost(),
+                    isShow: this.IES5Menu,
                     child: [{
                         icon: 'iconfont icon-test',
                         name: this.$t('system.menu.prtEv'),
@@ -864,7 +868,7 @@ export default {
                     permission: '',
                     child: [],
                     menuName: 'taskList',
-                    isShow: this.$store.state.userInfo.hasSchool && this.checkHost(),
+                    isShow: this.$store.state.userInfo.hasSchool && this.IES5Menu,
                     info: this.$t('tip.task')
                 }
             ]
@@ -878,13 +882,13 @@ export default {
             cloudSetting = JSON.parse(cloudSetting)
             if (cloudSetting.menuStatus == 'close') {
                 this.isCollapsed = true
+                this.isLock = false
             }
             this.isShowLogo = cloudSetting.logoStatus === 'open'
         }
         this.$EventBus.$off('onGlobalLoading')
         this.$EventBus.$on('onGlobalLoading', val => {
             this.getSystemLevel()
-            this.initMenu()
         })
     },
     mounted() {
@@ -893,13 +897,11 @@ export default {
             this.isShowLogo = val === 'open'
         })
         this.getSystemLevel()
-        this.initMenu()
     },
     watch: {
         $route: {
             handler(val, oldval) {
                 this.getSystemLevel()
-                this.initMenu()
                 let metaName = val.meta.activeName
                 this.activeName = metaName
                 this.openNames = []
@@ -933,10 +935,6 @@ export default {
         },
         '$i18n.locale'(n, o) {
             this.getSystemLevel()
-            this.initMenu()
-        },
-        hasAnalysisAuth() {
-            this.initMenu()
         }
     }
 

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

@@ -27,7 +27,7 @@
                     </DropdownItem>
                     <DropdownItem class="drop-item" @click.native="toSettings('0')" v-if="curPlatform === 'school'">
                         <Icon type="ios-settings" class="drop-item-icon" />
-                        {{$t('user.systemSet')}}
+                        {{$t('settings.setting_title2')}}
                     </DropdownItem>
                     <DropdownItem @click.native="onQuit">
                         <Icon type="md-power" class="drop-item-icon" />

+ 0 - 1
TEAMModelOS/ClientApp/src/components/app-root.vue

@@ -34,7 +34,6 @@ export default {
     watch: {
         '$i18n.locale': {
             handler(n, o) {
-                // let host = 'https://jinniu.teammodel.cn/'
                 let host = window.location.host
                 let hostList = this.$GLOBAL.HOST_LIST()
                 let cur = hostList.find(item => {

+ 10 - 3
TEAMModelOS/ClientApp/src/components/dashboard/art/BaseLessonLineBar.vue

@@ -6,10 +6,12 @@ export default {
   data() {
     return {
       option: null,
+      legendData:[],
     }
   },
   methods: {
     doRender(data) {
+      let that = this
       let myChart = this.$echarts.init(document.getElementById('ArtLessonLineBar'))
       this.option = {
         title: {
@@ -38,7 +40,7 @@ export default {
           containLabel: true
         },
         legend: {
-          data: ['东坡小学', '青羊区'],
+          data: that.legendData,
           right: 100,
           top: 12,
           textStyle: {
@@ -98,7 +100,7 @@ export default {
         ],
         series: [
           {
-            name: '东坡小学',
+            name: that.legendData[0],
             type: 'line',
             symbolSize: '10',
             zlevel: 3,
@@ -127,7 +129,7 @@ export default {
             data: data.map(i => i.schoolRate),
           },
           {
-            name: '青羊区',
+            name: that.legendData[1],
             type: 'line',
             symbolSize: '10',
             zlevel: 3,
@@ -168,6 +170,11 @@ export default {
       handler(n, o) {
         if (n) {
           this.$nextTick(() => {
+            if(this.$store.state.dashboard.classType === 'all'){
+              this.legendData = ['紫藤小学', '高新区']
+            }else{
+              this.legendData = ['本班', '紫藤小学']
+            }
             this.doRender(n.lessonData)
           })
         }

+ 239 - 0
TEAMModelOS/ClientApp/src/components/dashboard/art/BaseStuLineBar.vue

@@ -0,0 +1,239 @@
+<template>
+  <div id="ArtStuLineBar" class="art-echart"></div>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      option: null,
+    }
+  },
+  methods: {
+    doRender(data) {
+      let myChart = this.$echarts.init(document.getElementById('ArtStuLineBar'))
+      this.option = {
+        title: {
+          textStyle: {
+            align: 'center',
+            color: '#fff',
+            fontSize: 20,
+          },
+          top: '5%',
+          left: 'center',
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: { // 坐标轴指示器,坐标轴触发有效
+            type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
+          }
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'shadow'
+          },
+        },
+        grid: {
+          left: '2%',
+          right: '4%',
+          bottom: '8%',
+          top: '16%',
+          containLabel: true
+        },
+        legend: {
+          data: ['得分', '班级平均分'],
+          right: 100,
+          top: 12,
+          textStyle: {
+            color: "#fff"
+          },
+          itemWidth: 12,
+          itemHeight: 10,
+        },
+        dataZoom: [{
+          show: true,
+          height: 10,
+          start:40,
+          end:60,
+          xAxisIndex: [0],
+          bottom: 10,
+          handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
+          handleSize: '110%',
+          handleStyle: {
+            color: "#5B3AAE",
+          },
+          textStyle: {
+            color: "rgba(204,187,225,0.5)",
+          },
+          fillerColor: "rgba(67,55,160,0.4)",
+          borderColor: "rgba(204,187,225,0.5)",
+
+        }, {
+          type: "inside",
+          show: true,
+          height: 15,
+          start: 1,
+          end: 35
+        }],
+        xAxis: {
+          type: 'category',
+          data: data.map(i => i.className),
+          axisLine: {
+            lineStyle: {
+              color: '#eee'
+            }
+          },
+          axisLabel: {
+            interval: 0,
+            margin: 20,
+            color: '#05D5FF',
+            textStyle: {
+              fontSize: 11,
+            },
+          },
+        },
+        yAxis: [
+          {
+            type: 'value',
+            nameTextStyle: {
+              color: '#A2A5AA',
+              fontSize: 10
+            },
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: 'rgba(255,255,255,0.3)'
+              }
+            },
+            axisLine: {
+              lineStyle: {
+                color: '#6C6F79' //改轴颜色
+              }
+            },
+            axisLabel: {}
+          },
+          {
+            type: 'value',
+            min: 0,
+            max: 100,
+            interval: 20,
+            nameTextStyle: {
+              color: '#A2A5AA',
+              fontSize: 10
+            },
+            splitLine: {
+              lineStyle: {
+                color: 'rgba(255,255,255,0.1)' //改轴颜色
+              }
+            },
+            axisTick: {
+              show: false
+            },
+            axisLine: {
+              lineStyle: {
+                color: '#6C6F79' //改轴颜色
+              }
+            },
+            axisLabel: {
+              formatter: '{value}%',
+              textStyle: {
+                color: '#A2A5AA', //改轴数值颜色
+                fontSize: 10
+              }
+            }
+          }
+        ],
+        series: [
+          {
+            name: '得分',
+            type: 'bar',
+            yAxis: 0,
+            barWidth: '10%',
+            itemStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: '#fccb05'
+                }, {
+                  offset: 1,
+                  color: '#f5804d'
+                }]),
+                barBorderRadius: 12,
+              },
+            },
+            markPoint: {
+                data: [{
+                        type: 'max',
+                        name: `最高分`,
+                        itemStyle: {
+                            color:'#2ccc44'
+                        },
+                        label: {
+                            color:'#fff'
+                        }
+                    },
+                    {
+                        type: 'min',
+                        name: `最低分`,
+                        itemStyle: {
+                            color:'#ff3976'
+                        },
+                        label: {
+                            color:'#fff'
+                        }
+                    }
+                ]
+            },
+            data: data.map(i => i.hScore),
+          },
+          {
+            name: '班级平均分',
+            type: 'bar',
+            yAxis: 0,
+            barWidth: '10%',
+            itemStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: '#8bd46e'
+                }, {
+                  offset: 1,
+                  color: '#09bcb7'
+                }]),
+                barBorderRadius: 11,
+              }
+            },
+            data: data.map(i => i.average)
+          }]
+      };
+      myChart.clear()
+      myChart.setOption(this.option)
+      window.addEventListener('resize', function () {
+        myChart.resize()
+      })
+    }
+  },
+  watch: {
+    '$store.state.dashboard.artDashboard': {
+      deep: true,
+      immediate: true,
+      handler(n, o) {
+        if (n) {
+          this.$nextTick(() => {
+            this.doRender(n.classData)
+          })
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style>
+.art-echart {
+  width: 100%;
+  height: 100%;
+  margin: 0 auto;
+  display: block;
+}
+</style>

+ 9 - 10
TEAMModelOS/ClientApp/src/components/dashboard/art/LeftTop.vue

@@ -78,15 +78,15 @@ export default {
       handler(n, o) {
         if (n) {
           this.$nextTick(() => {
-			let staticNums = n.staticData
-			this.titleItem[0].number = staticNums.total
-			this.titleItem[1].number = staticNums.join
-			this.titleItem[2].number = staticNums.hScore
-			this.titleItem[3].number = staticNums.lScore
-			this.titleItem[4].number = staticNums.average
-			this.titleItem[5].number = staticNums.goodRate
-			this.titleItem[6].number = staticNums.normalRate
-			this.titleItem[7].number = staticNums.standard
+            let staticNums = n.staticData
+            this.titleItem[0].number = staticNums.total
+            this.titleItem[1].number = staticNums.join
+            this.titleItem[2].number = staticNums.hScore
+            this.titleItem[3].number = staticNums.lScore
+            this.titleItem[4].number = staticNums.average
+            this.titleItem[5].number = staticNums.goodRate
+            this.titleItem[6].number = staticNums.normalRate
+            this.titleItem[7].number = staticNums.standard
           })
         }
       }
@@ -137,7 +137,6 @@ export default {
     flex-wrap: wrap;
     justify-content: space-between;
 
-
     .ranking {
       padding: 10px;
       width: 59%;

+ 6 - 3
TEAMModelOS/ClientApp/src/components/dashboard/art/RightTop.vue

@@ -2,20 +2,23 @@
   <div id="bottomLeft">
 	  <p class="dashboard-block-title">
 	  	<Icon type="md-pulse" />
-	  	<span>各班级测评情况统计</span>
+	  	<span>{{ $store.state.dashboard.classType === 'all' ? '各班级测评情况统计' : '班级测评情况统计' }}</span>
 		<dv-decoration-1 class="dv-dec-3" />
 	  </p>
     <div class="bg-color-black">
-        <BaseClassLineBar/>
+        <BaseClassLineBar v-if="$store.state.dashboard.classType === 'all'"/>
+        <BaseStuLineBar v-else/>
     </div>
   </div>
 </template>
 
 <script>
 import BaseClassLineBar from '@/components/dashboard/art/BaseClassLineBar.vue'
+import BaseStuLineBar from '@/components/dashboard/art/BaseStuLineBar.vue'
 export default {
   components: {
-    BaseClassLineBar
+    BaseClassLineBar,
+    BaseStuLineBar
   }
 }
 </script>

+ 17 - 1
TEAMModelOS/ClientApp/src/components/homework/BaseHwTable.less

@@ -26,12 +26,15 @@
 }
 
 .score-modal {
+
 	
 	.score-wrap{
 		display: flex;
 		
 		.left{
 			width: 700px;
+
+            
 			
 			.preview-bar{
 				display: flex;
@@ -247,10 +250,23 @@
 
     .download-title {
         color: @second-textColor;
-		margin-bottom: 10px;
+		margin-bottom: 20px;
 		margin-left: 5px;
 		font-weight: bold;
 		font-size: 16px;
+        display: flex;
+        justify-content:space-between;
+        align-items:center;
+
+        .title{
+            margin-right: 10px;
+            padding-bottom: 3px;
+            cursor: pointer;
+        }
+
+        .title-active{
+            border-bottom: 2px solid #1CC0F3;
+        }
 		
 		.btn-download{
 			display: inline-block;

Dosya farkı çok büyük olduğundan ihmal edildi
+ 780 - 685
TEAMModelOS/ClientApp/src/components/homework/BaseHwTable.vue


+ 64 - 36
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ClassRecord.less

@@ -16,11 +16,13 @@
         .cur-page-tag {
             opacity: 0;
         }
-        .course-cur-img{
+
+        .course-cur-img {
             height: 100%;
         }
     }
 }
+
 .cur-page-tag {
     position: absolute;
     left: 5px;
@@ -30,7 +32,7 @@
     font-size: 18px;
     line-height: 30px;
     display: block;
-    background: rgba(255,153,0,0.9);
+    background: rgba(255, 153, 0, 0.9);
     border-radius: 50%;
     text-align: center;
     opacity: 1;
@@ -53,6 +55,7 @@
     transition: opacity 1.2s;
     border-right: 2px solid black;
 }
+
 .record-info {
     background-color: #f9f9f9;
     width: 100%;
@@ -65,11 +68,11 @@
         display: flex;
         justify-content: space-between;
 
-        & > div > p {
+        &>div>p {
             margin-bottom: 5px;
         }
     }
-    
+
     .testTitle {
         background-color: rgb(255, 255, 255);
         // color: #24b880;
@@ -81,7 +84,7 @@
         border-bottom: 1px solid rgba(0, 0, 0, 0.1);
         z-index: 10;
 
-        .logoutIcon{
+        .logoutIcon {
             cursor: pointer;
             margin-right: 10px;
         }
@@ -94,7 +97,7 @@
         width: 100%;
     }
 
-    .video-player-box{
+    .video-player-box {
         width: 50%;
         justify-content: center;
         height: 450px;
@@ -104,13 +107,13 @@
         background-color: #fff;
     }
 
-    .message-area{
+    .message-area {
         position: relative;
         height: 815px;
         padding: 10px;
         margin-bottom: 20px;
 
-        .filter-type{
+        .filter-type {
             position: absolute;
             right: 0;
             top: 10px;
@@ -122,11 +125,11 @@
             flex-direction: column;
             background-color: #F1F1F1;
 
-            span{
+            span {
                 border: none;
                 padding: 0px;
                 font-size: 32px;
-                
+
                 &:hover {
                     cursor: pointer;
                     color: #24b880;
@@ -138,17 +141,17 @@
             }
         }
 
-        .message-box{
+        .message-box {
             display: flex;
             border-bottom: 1px #ccc solid;
 
-            .message-page{
+            .message-page {
                 width: 10%;
                 padding: 10px 15px;
                 padding-bottom: 0;
                 // border-right: 1px #ccc dashed;
 
-                img{
+                img {
                     margin-top: 5px;
                 }
 
@@ -169,7 +172,7 @@
                 }
             }
 
-            .message-record{
+            .message-record {
                 padding: 10px 15px;
                 padding-bottom: 0;
                 width: 87%;
@@ -208,8 +211,8 @@
                         border-radius: 4px;
                         position: relative;
                         // width: 85%;
-                    
-                        &::before{
+
+                        &::before {
                             content: "";
                             position: absolute;
                             top: 3px;
@@ -222,8 +225,8 @@
                             border-color: transparent #d4ede1 transparent transparent;
                         }
 
-                        .message-text{
-                            img{
+                        .message-text {
+                            img {
                                 max-width: 80%;
                             }
 
@@ -237,11 +240,13 @@
                                 display: flex;
                                 flex-direction: column;
                                 justify-content: center;
+
                                 .student-no {
                                     font-size: 40px;
                                     color: black;
                                     font-weight: 600;
                                 }
+
                                 .student-name {
                                     color: #007cff;
                                     font-weight: 800;
@@ -265,14 +270,14 @@
                         left: 55px;
                     }
                 }
-                
+
                 .teacher-item {
                     display: block;
                     // padding-right: 5%;
                     text-align: right !important;
                     position: relative;
                     margin-bottom: 50px;
-                    
+
                     .message-avatar {
                         border-radius: 50%;
                         float: left;
@@ -300,8 +305,8 @@
                         border-radius: 4px;
                         position: relative;
                         // width: 85%;
-                    
-                        &::before{
+
+                        &::before {
                             content: "";
                             position: absolute;
                             top: 3px;
@@ -314,8 +319,8 @@
                             border-color: transparent transparent transparent #ffecc2;
                         }
 
-                        .message-text{
-                            img{
+                        .message-text {
+                            img {
                                 max-width: 80%;
                             }
 
@@ -329,11 +334,13 @@
                                 display: flex;
                                 flex-direction: column;
                                 justify-content: center;
+
                                 .student-no {
                                     font-size: 40px;
                                     color: black;
                                     font-weight: 600;
                                 }
+
                                 .student-name {
                                     color: #007cff;
                                     font-weight: 800;
@@ -358,7 +365,7 @@
                     }
                 }
 
-                .teacher-client-icon{
+                .teacher-client-icon {
                     font-size: 30px;
                     padding: 5px;
                     color: #ffffff;
@@ -368,7 +375,7 @@
                     float: left;
                 }
 
-                .student-client-icon{
+                .student-client-icon {
                     font-size: 30px;
                     padding: 5px;
                     color: #ffffff;
@@ -378,15 +385,17 @@
                     margin-left: 15px;
                 }
 
-                .event-item{
+                .event-item {
                     border: 1px dashed transparent;
                     margin-bottom: 15px;
                     padding: 5px 5px;
                 }
-                .event-item:hover{
+
+                .event-item:hover {
                     border: 1px dashed #e0e0e0;
                 }
-                .student-event{
+
+                .student-event {
                     display: flex;
                     justify-content: end;
                 }
@@ -407,8 +416,8 @@
             font-weight: bold;
         }
     }
-    
-    .title-rect-name > span{
+
+    .title-rect-name>span {
         background-color: #24B880;
         font-size: 12px;
         padding: 3px;
@@ -417,19 +426,21 @@
         color: #fff;
         cursor: pointer;
     }
-    
-    .e-note-tag{
+
+    .e-note-tag {
         font-size: 16px;
         padding: 2px 5px;
         margin-left: 30px;
         vertical-align: top;
         cursor: pointer;
         user-select: none;
-        &:hover{
+
+        &:hover {
             color: #24b880;
         }
     }
 }
+
 .image-viewer {
     background-color: rgba(0, 0, 0, 0.8);
     z-index: 9999;
@@ -450,7 +461,7 @@
         margin: 5% auto;
         border: none;
     }
-    
+
     .close-icon {
         position: absolute;
         right: 15px;
@@ -461,10 +472,27 @@
     }
 }
 
-.no-video-tips{
+.no-video-tips {
     position: absolute;
     top: 0px;
     left: 0px;
     color: #ff9900;
     width: 100%;
 }
+
+@media screen and (max-width: 768px) {
+    .class-content {
+        flex-direction: column;
+
+        .courseware-wrap,
+        .video-player-box {
+            width: 100%;
+        }
+
+        .video-player-box {
+            margin-top: 10px;
+            margin-left: 0;
+            height: auto;
+        }
+    }
+}

+ 12 - 10
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ClassRecord.vue

@@ -16,16 +16,18 @@
                             <Icon type="ios-contact-outline" style="font-weight: bold;" class="base-info-icon" />{{ $t('studentWeb.baseInfo.teacher') }}
                             <span class="base-info-text">{{ recordInfo.tmdname }}</span>
                         </p>
-                        <p style="margin-left: 20px;">
-                            <svg-icon class="base-info-icon" icon-class="course" />{{ $t('studentWeb.baseInfo.subjectName') }}
-                            <span class="base-info-text">{{ courseNow.name }}</span>
-                        </p>
-                        <p style="margin-left: 20px;">
-                            <Icon custom="iconfont icon-mingdan" class="base-info-icon" />{{ $t('studentWeb.baseInfo.stuList') }}
-                            <template v-if="courseNow.className.length">
-                                <span class="base-info-text" v-for="(item, index) in courseNow.className" :key="index" style="margin-right: 10px;">{{ item.name }}</span>
-                            </template>
-                        </p>
+                        <template v-if="courseNow">
+                            <p style="margin-left: 20px;">
+                                <svg-icon class="base-info-icon" icon-class="course" />{{ $t('studentWeb.baseInfo.subjectName') }}
+                                <span class="base-info-text">{{ courseNow.name }}</span>
+                            </p>
+                            <p style="margin-left: 20px;">
+                                <Icon custom="iconfont icon-mingdan" class="base-info-icon" />{{ $t('studentWeb.baseInfo.stuList') }}
+                                <template v-if="courseNow.className.length">
+                                    <span class="base-info-text" v-for="(item, index) in courseNow.className" :key="index" style="margin-right: 10px;">{{ item.name }}</span>
+                                </template>
+                            </p>
+                        </template>
                         <p style="margin-left: 20px;">
                             <Icon type="md-timer" class="base-info-icon" />{{ $t('studentWeb.baseInfo.duration') }}:
                             <span class="base-info-text">{{ recordInfo.time }}</span>

+ 1 - 1
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/DataCount.vue

@@ -41,7 +41,7 @@ export default {
         return {
             attentColor: ['', '#19be6b', '#EB3941', '#EB3941', '#EB3941', '#EB3941'],
             colorList: ['#19be6b', '#2d8cf0', '#2db7f5', '#2db7f5', '#2db7f5', '#19be6b', '#2db7f5', '#2db7f5', '#2db7f5', '#ed4014'],
-            attendType: false,
+            attendType: 2, //新加入的会没有该学生的信息,即nowStuInfo = undefined
             dataList: [
                 {
                     label: this.$t("studentWeb.hiteachNote.dataCount.getCount"),

+ 2 - 2
TEAMModelOS/ClientApp/src/components/student-web/EventView/BillBoardandLightBox.vue

@@ -6,10 +6,10 @@
         <div class="dec">
             <p><span v-html="activityData.description"></span></p>
         </div>
-        <div class="title-rect-group" v-if="this.$store.getters.getItemTitle.eventType  === 'Vote'">
+        <div class="title-rect-group" v-if="this.$store.getters.getItemTitle.type  === 'Vote'">
             <h2 class="title-rect-name">{{$t("studentWeb.vote.voteRecord")}}</h2>
         </div>
-        <div class="dec" v-if="this.$store.getters.getItemTitle.eventType == 'Vote'">
+        <div class="dec" v-if="this.$store.getters.getItemTitle.type == 'Vote'">
             <Table v-if="showTable" border :columns="voteColums" :data="voteColumsData"></Table>
             <span v-else>{{ $t("studentWeb.public.noData") }}</span>
         </div>

+ 4 - 5
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/ClassmateCommentPages.vue

@@ -103,7 +103,7 @@
                         <div v-if="nowStudentHw.answer" style="margin-top: 10px;">
                             <div class="remarks">{{ $t("studentWeb.exam.answer") }}:</div>
                             <div class="file-show">
-                                <p>{{ nowStudentHw.answer }}</p>
+                                <p v-html="nowStudentHw.answer"></p>
                             </div>
                             <!-- <Input v-special-char v-model="nowStudentHw.answer" disabled type="textarea" /> -->
                         </div>
@@ -259,7 +259,7 @@ export default {
         this.homeWork = this.$route.params.homework ? this.$route.params.homework : JSON.parse(localStorage.getItem("homework")) */
     },
     mounted () {
-        console.log(this.students);
+        // console.log(this.students);
         this.getStudentList()
     },
     methods: {
@@ -286,7 +286,7 @@ export default {
                             }
                         }) */
                         if(this.students.length) {
-                            console.log(this.students.length);
+                            // console.log(this.students.length);
                             // this.students[0]._highlight = true
                             // this.starNum = this.students[0].star
                             this.nowStudent = this.students[0]
@@ -319,7 +319,6 @@ export default {
         // 获取同学
         getAllComment() {
             this.starNum = 0
-                    console.log("默认一位学生");
             let params = {
                 opt: "ReadAllComment",
                 id: this.homeWork.id,
@@ -337,7 +336,7 @@ export default {
                     this.getBlobSas()
                 }
                 if(res.comments.length) {
-                    console.log(res.comments.find(item => {return item.userid === this.userInfo.sub}));
+                    // console.log(res.comments.find(item => {return item.userid === this.userInfo.sub}));
                     let com = res.comments.find(item => {return item.userid === this.userInfo.sub})
                     if(com) {
                         this.starNum = com.star

+ 12 - 4
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Homework.vue

@@ -88,13 +88,13 @@
                                 </div>
                             </div> -->
                             <div v-if="answerList.answer" style="margin-bottom: 15px;">
-                                <p>{{ $t("studentWeb.homework.content") }}:</p>
+                                <p class="answer-title">{{ $t("studentWeb.homework.content") }}:</p>
                                 <div class="file-show">
-                                    <p>{{ answerList.answer }}</p>
+                                    <p v-html="answerList.answer" class="answer-show"></p>
                                 </div>
                             </div>
                             <div v-if="answerList.content.length">
-                                <p>{{ $t("studentWeb.homework.attachment") }}:</p>
+                                <p class="answer-title">{{ $t("studentWeb.homework.attachment") }}:</p>
                                 <Table :columns="fileCol" :data="answerList.content">
                                     <template slot-scope="{row}" slot="action">
                                         <Icon type="md-download" size="20" @click="loadAttach(row)" :title="$t('studentWeb.homework.upload')" />
@@ -190,7 +190,8 @@
                                 <p>{{ $t("studentWeb.homework.answerArea") }}:</p>
                                 <div>
                                     <div>
-                                        <Input v-special-char v-model="hwText" type="textarea" :rows="4" :placeholder="$t('studentWeb.homework.placeholder1')" />
+                                        <Compose ref="compose" :itemInfo="homeworkInfo" :close="false" :textData="hwText" :index="0" @dataGet="getComposeAns"></Compose>
+                                        <!-- <Input v-special-char v-model="hwText" type="textarea" :rows="4" :placeholder="$t('studentWeb.homework.placeholder1')" /> -->
                                     </div>
                                 </div>
                             </div>
@@ -239,6 +240,7 @@ import BlobTool from "@/utils/blobTool.js"
 import { mapGetters, mapState } from 'vuex';
 import Loading from '@/common/Loading.vue';
 import ClassmateCommentPages from './ClassmateCommentPages.vue';
+import Compose from './composePaperHw.vue';
 
 export default {
     name: "Howework",
@@ -248,6 +250,7 @@ export default {
         EventBasicInfo,
         Loading,
         ClassmateCommentPages,
+        Compose,
     },
     created() {
         this.openLightBox = false;
@@ -485,6 +488,7 @@ export default {
                             this.isfinishedUpload = true
                             this.uploadList = []
                             this.hwText = null
+                            this.$refs.compose.initEditor()
                             this.$Message.success(this.$t("studentWeb.homework.uploadSuccess"))
                             this.getAnswer(this.homeworkInfo)
                         }
@@ -632,6 +636,10 @@ export default {
         closeImg() {
             this.openLightBox = false;
         },
+        //獲取富文本返回數據
+        getComposeAns(data) {
+            this.hwText = data
+        },
     },
     computed: {
         ...mapGetters(["getItemTitle"]),

+ 21 - 2
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/HomeworkFeedback.vue

@@ -26,6 +26,10 @@
                                 <strong>{{ $t("studentWeb.homework.comment") }}</strong>
                                 {{ item.replies[0].comment }}
                             </p>
+                            <div v-if="item.mark" style="display: flex;">
+                                <p>{{ $t("studentWeb.exam.report.mark") }}:</p>
+                                <img :src="item.mark" alt="" @click="onPreview(item.mark)" style="cursor: pointer;">
+                            </div>
                             <div class="timeRate">
                                 <div>
                                     <span>{{ $t("studentWeb.homework.grade") }}:</span>
@@ -146,7 +150,7 @@ export default {
                 userType: roles,
                 userSchool: this.userInfo.azp
             }
-            this.$api.studentWeb.getAllComment(params).then(res => {
+            this.$api.studentWeb.getAllComment(params).then(async res => {
                 if(res.record) {
                     this.score = res.record.score < 0 ? 0 : res.record.score
                 }
@@ -155,7 +159,19 @@ export default {
                 // }
                 if(res.comments.length) {
                     this.studentList = res.comments.filter(item => {return item.identity == "student"})
-                    this.teacherList = res.comments.filter(item => {return item.identity == "teacher"})
+                    this.teacherList = res.comments.filter(item => {
+                        item.mark = null
+                        return item.identity == "teacher"
+                    })
+                    if(this.teacherList.length) {
+                        let sas = await this.$tools.getBlobSas(params.code)
+                        let url = `${sas.url}/${sas.name}/homework/${this.homeWork.id}/${this.userInfo.sub}/mark/teacherMark.png?${sas.sas}`
+                        this.$tools.getImgsBase64ByUrls([url]).then(res => {
+                            this.teacherList[0].mark = res[0]
+                        }).catch(err => {
+                            this.teacherList[0].mark = null
+                        })
+                    }
                 }
             })
         },
@@ -170,6 +186,9 @@ export default {
             var S = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()) + " "
             return Y + M + D + H + Min;
         },
+        onPreview(url) {
+            this.$hevueImgPreview(url)
+        },
     },
     computed: {
         ...mapState({

+ 28 - 4
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReport.vue

@@ -364,7 +364,7 @@
                 </div>
             </div>
             <div class="qcontent img-question" ref="qcontent" v-if="paperData.length && examInfo.qamode">
-                <SubjectMould :subjectList="showPaperData" :imgList="imgList" />
+                <SubjectMould :subjectList="showPaperData" :imgList="imgList" :testState="testState" />
             </div>
         </div>
         <!-- 补救资源 -->
@@ -506,6 +506,15 @@
                 this.previewFile = {}
             },
             showTest() {
+                let textArr = {
+                    scope: this.getItemTitle.scope,
+                    cntr: this.getItemTitle.scope === 'school' ? this.getItemTitle.school : this.getItemTitle.creatorId,
+                    examId: this.getItemTitle.id,
+                    subjectId: this.examInfo.subject.id,
+                    stuId: this.$store.state.userInfo.sub
+                }
+                this.$store.commit("setComposeData", textArr)
+                localStorage.setItem("composeData", encodeURIComponent(JSON.stringify(textArr)))
                 this.$router.push({
                     name: "examView/evaluation",
                     /* params: {
@@ -777,10 +786,25 @@
                         code: codes.scope === 'school' ? codes.school : codes.creatorId,
                         blob: data
                     }
-                    let blob = await this.formUrl(code)
+                    let sas = await this.$tools.getBlobSas(code.code)
+                    let blob = `${sas.url}/${code.code}/exam/${code.blob}`
                     code.blob = blob
-                    datas = await this.$evTools.getComposeItem(code)
-                    return datas
+                    let videoBlob = `${blob}?${sas.sas}`
+                    // datas = await this.$evTools.getComposeItem(code)
+                    let fullUrl = code.blob.replace("/ans.json", "")
+                    let newData = await this.$jsFn.handleStudentAnswer(videoBlob, fullUrl, sas.sas)
+                    /* datas.forEach(item => {
+                        
+                        
+                        let newItem = []
+                        if(item.length) {
+                            newItem[0] = this.$editorTools.getMideaFullPath(item[0], videoBlob, '?' + sas.sas)
+                        } else {
+                            newItem = item
+                        }
+                        newData.push(newItem)
+                    }) */
+                    return newData
                 } else {
                     return []
                 }

+ 3 - 3
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/ScoreBarChart.vue

@@ -2,8 +2,8 @@
     <div class="score-bar-chart">
         <!-- <h4>{{ $t("studentWeb.exam.chart.scoreDistribution") }}</h4> -->
         
-        <div class="no-data">
-            <p class="no-data-title">{{ $t("studentWeb.exam.chart.scoreDistribution") }}</p>
+        <div class="no-data-stu">
+            <p class="no-data-stu-title">{{ $t("studentWeb.exam.chart.scoreDistribution") }}</p>
         </div>
         <div class="attendance">
             {{ $t("studentWeb.exam.chart.participant") }}
@@ -134,7 +134,7 @@ export default {
     color: rgba(0, 0, 0, 0.726);
 }
 
-.score-bar-chart .no-data .no-data-title {
+.score-bar-chart .no-data-stu .no-data-stu-title {
     color: #484848;
     font-weight: bolder;
 }

+ 13 - 3
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue

@@ -431,6 +431,7 @@
             this.showMessageNum = 0;
             // this.papers = this.$route.params.papers
             if(!Object.keys(this.getItemTitle).length) {
+                this.$store.commit("setComposeData", JSON.parse(decodeURIComponent(localStorage.getItem("composeData"))));
                 this.$store.commit("ChangeItemName", JSON.parse(decodeURIComponent(localStorage.getItem("Item"))));
                 this.$store.commit("setUserInfo", JSON.parse(decodeURIComponent(sessionStorage.getItem("userInfo"))));
                 this.$store.commit("SetExamInfo", JSON.parse(decodeURIComponent(localStorage.getItem("examInfo"))));
@@ -788,11 +789,13 @@
             openWarmMessage(showMessageNum) {
                 if (showMessageNum == 1) {
                     if(this.isWrong) {
-                        this.showMessageNum = 4
+                        // this.showMessageNum = 4
+                        this.showMessageNum = 7
+                        this.quitTest()
                     } else {
                         this.showMessageNum = showMessageNum
+                        this.WarmMessageisOpen = true
                     }
-                    this.WarmMessageisOpen = true
                 } else if (showMessageNum == 2) {
                     this.WarmMessageisOpen = true
                     for (var i = 0; i <= this.examInfo.length; i++) {
@@ -865,12 +868,19 @@
                 this.WarmMessageisOpen = false
                 if (this.checkers.length) {
                     this.isLoading = true;
+                    let answer = []
+                    this.checkers.forEach(item => {
+                        if(item.length) {
+                            item[0] = this.$editorTools.getRelativeSrcPath(item[0])
+                        }
+                        answer.push(item)
+                    })
                     // 选了个人课程:scope == 'private'
                     // 选了标准课程:scope == 'school'
                     let codes = this.getItemTitle.scope == 'school' ? this.getItemTitle.school : this.getItemTitle.creatorId
                     let req = {
                         id: this.getItemTitle.id,
-                        answer: this.checkers,
+                        answer,
                         studentId: this.getStuUserInfo.studentId,
                         classIds: this.getItemTitle.classIds,
                         subjectId: this.getExamInfo.subject.id,

+ 13 - 3
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/SubjectMould.vue

@@ -30,12 +30,12 @@
             <vuescroll>
                 <div v-for="(exam, indexs) in subjectList" :key="indexs" style="margin-bottom: 40px;">
                     <div>
-                        <div style="float: right;">
+                        <div style="float: right;" v-if="testState === 3 && getItemTitle.progress === 'finish'">
                             <span style="font-size: 20px; color:#00ad6c;">{{ exam.getScore }}</span>
                                 / <span style="font-size: 12px;">{{ exam.score }}{{ $t("studentWeb.exam.score111") }}</span>
                         </div>
                         <div style="display: flex; font-size: 16px; margin-bottom: 10px;">
-                            <span style="margin-right: 10px;">
+                            <span style="margin-right: 10px;" v-if="testState === 3 && getItemTitle.progress === 'finish'">
                                 <Icon type="md-close-circle" color="#FF5508" size="25"
                                     v-show="exam.getScore != exam.score"
                                 />
@@ -136,6 +136,7 @@
 </template>
 
 <script>
+import { mapGetters } from 'vuex'
 export default {
     props: {
         subjectList: {
@@ -149,7 +150,13 @@ export default {
             default: () => {
                 return []
             }
-        }
+        },
+        testState: {
+            type: Number,
+            default: () => {
+                return 0
+            }
+        },
     },
     data () {
         return {
@@ -173,6 +180,9 @@ export default {
                 }
             }
         },
+    },
+    computed: {
+        ...mapGetters(['getItemTitle'])
     }
 }
 </script>

+ 269 - 221
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/composePaper.vue

@@ -1,254 +1,302 @@
 <template>
-    <div class="content">
-        <div class="editor-wrap" v-show="!isConnector">
-            <div id="textArea"></div>
-        </div>
-        <div class="connector-wrap" v-if="isConnector">
-            <div v-if="answerImg">
-                <!-- <img :src="answerImg" alt=""> -->
-                <span v-html="answerImg"></span>
-            </div>
-            <p v-if="answerImg" style="font-weight: bold; margin-bottom: 20px">
-                {{ $t("studentWeb.exam.testpop.reAns") }}
-            </p>
-            <BaseCanvas :vm="vm" :bgImg="markBg" :isStudent="markStatus" @onCloseModal="closeModal" @onSaveCanvas="saveMark"></BaseCanvas>
-        </div>
-        <Modal v-model="markStatus" fullscreen :title="$t('studentWeb.exam.answer')" footer-hide ref="compose">
-            <BaseCanvas v-if="markStatus" :vm="vm" :bgImg="markBg" :isStudent="markStatus" @onCloseModal="closeModal" @onSaveCanvas="saveMark"></BaseCanvas>
-        </Modal>
-        <iframe class="frame" id="answerIframe" :srcdoc="itemInfo.question"></iframe>
+  <div class="content">
+    <div class="editor-wrap" v-show="!isConnector">
+      <div id="textArea"></div>
     </div>
+    <div class="connector-wrap" v-if="isConnector">
+      <div v-if="answerImg">
+        <!-- <img :src="answerImg" alt=""> -->
+        <span v-html="answerImg"></span>
+      </div>
+      <p v-if="answerImg" style="font-weight: bold; margin-bottom: 20px">
+        {{ $t("studentWeb.exam.testpop.reAns") }}
+      </p>
+      <BaseCanvas :vm="vm" :bgImg="markBg" :isStudent="markStatus" @onCloseModal="closeModal" @onSaveCanvas="saveMark"></BaseCanvas>
+    </div>
+    <Modal v-model="markStatus" fullscreen :title="$t('studentWeb.exam.answer')" footer-hide ref="compose">
+      <BaseCanvas v-if="markStatus" :vm="vm" :bgImg="markBg" :isStudent="markStatus" @onCloseModal="closeModal" @onSaveCanvas="saveMark"></BaseCanvas>
+    </Modal>
+    <iframe class="frame" id="answerIframe" :srcdoc="itemInfo.question"></iframe>
+  </div>
 </template>
 <script>
+import BlobTool from "@/utils/blobTool.js"
+import { mapGetters } from 'vuex';
 import html2canvas from "html2canvas"
 import E from "wangeditor"
 import { editor_tw_config } from "@/utils/editorLangTw.js"
 import { editor_en_config } from "@/utils/editorLangEn.js"
 import i18next from "i18next"
 export default {
-    components: {},
-    props: {
-        index: {
-            type: Number,
-            default: -1,
-        },
-        textData: {
-            type: Array,
-            default: () => {
-                return []
-            },
-        },
-        itemInfo: {
-            type: Object,
-            default: () => {
-                return {}
-            },
-        },
-        close: {
-            type: Boolean,
-            default: false,
-        },
+  components: {},
+  props: {
+    index: {
+      type: Number,
+      default: -1,
+    },
+    textData: {
+      type: Array,
+      default: () => {
+        return []
+      },
+    },
+    itemInfo: {
+      type: Object,
+      default: () => {
+        return {}
+      },
     },
-    data(vm) {
-        return {
-            answerImg: null,
-            vm: vm,
-            tabName: "exercise",
-            editorContent: "",
-            examInfo: [],
-            editor: null,
-            markStatus: false,
-            markBg: "",
+    close: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data(vm) {
+    return {
+      answerImg: null,
+      vm: vm,
+      tabName: "exercise",
+      editorContent: "",
+      examInfo: [],
+      editor: null,
+      markStatus: false,
+      markBg: "",
+    }
+  },
+  methods: {
+    async getInfo() {
+      // console.error(this.markBg)
+      this.markBg = ""
+      this.examInfo = []
+      this.initEditor()
+      // console.error(this.textData)
+      this.answerImg = null
+      if (this.textData.length > 0) {
+        this.examInfo = [...this.textData]
+        if (this.isConnector) {
+          this.answerImg = this.textData[0]
+        } else {
+          this.answerImg = null
+          this.editor.txt.html(this.examInfo[0])
+        }
+      }
+      setTimeout(() => {
+        if (this.isConnector) {
+          this.markStuAnswer()
         }
+      }, 100)
     },
-    methods: {
-        async getInfo() {
-            // console.error(this.markBg)
-            this.markBg = ""
-            this.examInfo = []
-            this.initEditor()
-            // console.error(this.textData)
-            this.answerImg = null
-            if (this.textData.length > 0) {
-                this.examInfo = [...this.textData]
-                if (this.isConnector) {
-                    this.answerImg = this.textData[0]
-                } else {
-                    this.answerImg = null
-                    this.editor.txt.html(this.examInfo[0])
-                }
-            }
-            setTimeout(() => {
-                if (this.isConnector) {
-                    this.markStuAnswer()
-                }
-            }, 100)
-        },
-        closeModal() {
-            this.markStatus = false
-            this.markBg = ""
-        },
-        saveMark(data) {
-            if (data) {
-                data.height = 400
-                data.width = 400
-                let params = `<img src="${data.base64}" />`
-                let img = document.createElement("img")
-                img.src = data.base64
-                if (this.isConnector) {
-                    this.answerImg = params
-                    this.markBg = ""
-                    setTimeout(() => {
-                        this.markStuAnswer()
-                    }, 100)
-                    this.$emit("dataGet", params, this.index)
-                    this.$Message.success(this.$t("settings.submitSucTips"))
-                } else {
-                    this.editor.txt.html(img.outerHTML)
-                }
-                this.markStatus = false
-            }
-        },
-        initEditor() {
-            this.editorContent = ""
-            this.editor = new E("#textArea")
-            this.editor.config.onchange = (html) => {
-                this.editorContent = html
-            }
-            this.editor.config.showFullScreen = false
-            this.editor.config.menus = [
-                "link", // 插入链接
-                "justify", // 对齐方式
-                "image", // 插入图片
-            ]
-            this.editor.config.zIndex = 1
-            this.editor.config.placeholder = this.$t(
-                "studentWeb.exam.inputAnswers"
-            )
-            this.editor.config.height = 300
-            this.editor.config.showLinkImg = false
-            this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片不建议使用这种,我只是图个方便
-            this.$editorTools.addCanvas(this, this.editor)
-            this.editor.config.menus.push("connector")
-            this.$editorTools.addStuBgBtn(this, this.editor)
-            // if (this.itemInfo.type == 'correct' || this.itemInfo.type == 'connector') {
-            //     this.editor.config.menus.push('connector')
-            //     this.$editorTools.addStuBgBtn(this, this.editor)
-            // } else {
-            //     this.$editorTools.addCanvas(this, this.editor)
-            // }
-            let curLang = localStorage.getItem("local") || "zh-cn"
-            if (curLang === "zh-tw") {
-                // 自定义语言
-                this.editor.config.languages["tw"] = editor_tw_config
-                // 选择语言
-                this.editor.config.lang = "tw"
-                // 引入 i18next 插件
-                this.editor.i18next = i18next
-            }
-            if (curLang === "en-us") {
-                // 自定义语言
-                this.editor.config.languages["en"] = editor_en_config
-                // 选择语言
-                this.editor.config.lang = "en"
-                // 引入 i18next 插件
-                this.editor.i18next = i18next
-            }
-            this.editor.create()
-            if (this.close) {
-                this.editor.disable()
-            }
-            this.editor.txt.clear()
-            if (this.examInfo.length > 0) {
-                this.editor.txt.html(this.examInfo[0])
-            }
-        },
-        markStuAnswer() {
-            let answerIframe = ""
-            answerIframe = document.getElementById("answerIframe")
-            answerIframe.contentWindow.document.body.style.width = "fit-content"
-            answerIframe.contentWindow.document.body.style.minWidth = "600px"
-            answerIframe.contentWindow.document.body.style.backgroundColor =
-                "#f5f5f5"
-            console.log(
-                document.getElementById("answerIframe").contentWindow.document
-            )
-            let iframe = document
-                .getElementById("answerIframe")
-                .contentWindow.document.getElementsByTagName("p")
-
-            if (iframe.length > 0) {
-                for (let i = 0; i < iframe.length - 1; i++) {
-                    iframe[i].style.lineHeight = "50px"
-                    iframe[i].style.paddingBottom = "30px"
-                }
-                iframe[iframe.length - 1].style.paddingBottom = "100px"
-                iframe[iframe.length - 1].style.lineHeight = "50px"
-            }
-            html2canvas(answerIframe.contentWindow.document.body).then(
-                (canvas) => {
-                    if (!this.isConnector) {
-                        this.markStatus = true
-                    }
-                    this.markBg = canvas.toDataURL("image/png")
-                }
-            )
-        },
+    closeModal() {
+      this.markStatus = false
+      this.markBg = ""
     },
-    mounted() {
-        this.initEditor()
-        this.getInfo()
-        // 监听富文本画板功能
-        this.$EventBus.$off("onStuCanvas")
-        this.$EventBus.$on("onStuCanvas", (editor) => {
-            this.markBg = ""
+    saveMark(data) {
+      if (data) {
+        data.height = 400
+        data.width = 400
+        let params = `<img src="${data.base64}" />`
+        let img = document.createElement("img")
+        img.src = data.base64
+        if (this.isConnector) {
+          this.answerImg = params
+          this.markBg = ""
+          setTimeout(() => {
             this.markStuAnswer()
+          }, 100)
+          this.$emit("dataGet", params, this.index)
+          this.$Message.success(this.$t("settings.submitSucTips"))
+        } else {
+          this.editor.txt.html(img.outerHTML)
+        }
+        this.markStatus = false
+      }
+    },
+    initEditor() {
+      this.editorContent = ""
+      this.editor = new E("#textArea")
+      this.editor.config.onchange = (html) => {
+        this.editorContent = html
+      }
+      this.editor.config.showFullScreen = false
+      this.editor.config.menus = [
+        "link", // 插入链接
+        "justify", // 对齐方式
+        "image", // 插入图片
+        "video"
+      ]
+      this.editor.config.zIndex = 1
+      this.editor.config.placeholder = this.$t(
+        "studentWeb.exam.inputAnswers"
+      )
+      this.editor.config.height = 300
+      this.editor.config.showLinkImg = false
+      this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片不建议使用这种,我只是图个方便
+      this.$editorTools.addAudio(this, this.editor, 'simple')
+      this.$editorTools.addVideoUpload(this, this.editor, 'simple')
+      this.$editorTools.addCanvas(this, this.editor)
+      this.$editorTools.addStuBgBtn(this, this.editor)
+      // if (this.itemInfo.type == 'correct' || this.itemInfo.type == 'connector') {
+      //     this.editor.config.menus.push('connector')
+      //     this.$editorTools.addStuBgBtn(this, this.editor)
+      // } else {
+      //     this.$editorTools.addCanvas(this, this.editor)
+      // }
+      let curLang = localStorage.getItem("local") || "zh-cn"
+      if (curLang === "zh-tw") {
+        // 自定义语言
+        this.editor.config.languages["tw"] = editor_tw_config
+        // 选择语言
+        this.editor.config.lang = "tw"
+        // 引入 i18next 插件
+        this.editor.i18next = i18next
+      }
+      if (curLang === "en-us") {
+        // 自定义语言
+        this.editor.config.languages["en"] = editor_en_config
+        // 选择语言
+        this.editor.config.lang = "en"
+        // 引入 i18next 插件
+        this.editor.i18next = i18next
+      }
+      this.editor.create()
+      if (this.close) {
+        this.editor.disable()
+      }
+      this.editor.txt.clear()
+      if (this.examInfo.length > 0) {
+        this.editor.txt.html(this.examInfo[0])
+      }
+    },
+    markStuAnswer() {
+      let answerIframe = ""
+      answerIframe = document.getElementById("answerIframe")
+      answerIframe.contentWindow.document.body.style.width = "fit-content"
+      answerIframe.contentWindow.document.body.style.minWidth = "600px"
+      answerIframe.contentWindow.document.body.style.backgroundColor =
+        "#f5f5f5"
+      console.log(
+        document.getElementById("answerIframe").contentWindow.document
+      )
+      let iframe = document
+        .getElementById("answerIframe")
+        .contentWindow.document.getElementsByTagName("p")
+
+      if (iframe.length > 0) {
+        for (let i = 0; i < iframe.length - 1; i++) {
+          iframe[i].style.lineHeight = "50px"
+          iframe[i].style.paddingBottom = "30px"
+        }
+        iframe[iframe.length - 1].style.paddingBottom = "100px"
+        iframe[iframe.length - 1].style.lineHeight = "50px"
+      }
+      html2canvas(answerIframe.contentWindow.document.body).then(
+        (canvas) => {
+          if (!this.isConnector) {
+            this.markStatus = true
+          }
+          this.markBg = canvas.toDataURL("image/png")
+        }
+      )
+    },
+    /* 上传文件到BLOB */
+    doUploadFile(file) {
+      return new Promise(async (r, j) => {
+        this.$Spin.show();
+        let { scope, cntr, examId, subjectId, stuId } = this.getComposeData
+        const sasData = scope === 'school' ? await this.$tools.getSchoolSas(cntr) : await this.$api.blob.blobSasRCW({ name: cntr, role: 'teacher' })
+        let sas = scope === 'school' ? sasData.sas : ('?' + sasData.sas)
+        let containerClient = new BlobTool(sasData.url, sasData.name, sas, scope)
+        containerClient.upload(file, {
+          path: `exam/${examId}/${subjectId}/${stuId}`,
+          checkSize: false
+        }).then(res => {
+          let fileFullPath = res.url + sas
+          this.$Spin.hide();
+          r(fileFullPath)
+        }).catch(err => {
+          console.log(err);
+          j(err)
         })
+      })
+
+    },
+  },
+  mounted() {
+    this.initEditor()
+    this.getInfo()
+    // 监听富文本画板功能
+    this.$EventBus.$off("onStuCanvas")
+    this.$EventBus.$on("onStuCanvas", (editor) => {
+      this.markBg = ""
+      this.markStuAnswer()
+    })
+    /* 富文本上传音视频 */
+    this.$EventBus.$off("selectFileFinish")
+    this.$EventBus.$on("selectFileFinish", (fileObj) => {
+      this.doUploadFile(fileObj.file).then(fileFullPath => {
+        if (fileObj.type === 'audio') {
+          this.editor.selection.getSelectionStartElem().elems[0].innerHTML += `<span><span>&nbsp;&nbsp;</span><span class="richText-audio" contenteditable="false" >
+					<span class="audio-info">
+						<i class="ivu-icon ivu-icon-ios-musical-notes" style="font-size: 24px;margin:0 10px"></i>
+						<span class="audio-name">${fileObj.file.name}</span>
+					</span>
+					<audio src="${fileFullPath}"  id="audio" controls="controls" controlsList="nodownload"></audio>
+				</span><span>&nbsp;</span></span>`
+        } else if (fileObj.type === 'video') {
+          this.editor.selection.getSelectionStartElem().elems[0].innerHTML += `<span><span>&nbsp;</span><video src="${fileFullPath}" class="richText-video" width="300" preload controls="controls"></video><span>&nbsp;</span></span>`
+        }
+        this.editor.change.emit()
+      })
+    })
+
+  },
+  computed: {
+    isConnector() {
+      return (
+        this.itemInfo.type == "connector" ||
+        this.itemInfo.type == "correct"
+      )
     },
-    computed: {
-        isConnector() {
-            return (
-                this.itemInfo.type == "connector" ||
-                this.itemInfo.type == "correct"
-            )
-        },
+    ...mapGetters([
+      "getComposeData",
+    ]),
+  },
+  watch: {
+    index() {
+      this.getInfo()
+      deep: true
+      immediate: true
     },
-    watch: {
-        index() {
-            this.getInfo()
-            deep: true
-            immediate: true
-        },
-        editorContent() {
-            if(!this.isConnector) {
-                this.$emit("dataGet", this.editorContent, this.index)
-            }
-        },
+    editorContent() {
+      if (!this.isConnector) {
+        this.$emit("dataGet", this.editorContent, this.index)
+      }
     },
+  },
 }
 </script>
 <style scoped>
 .content {
-    width: 100%;
-    height: 100%;
+  width: 100%;
+  height: 100%;
 }
 .connector-wrap /deep/ .demo {
-    justify-content: flex-start !important;
+  justify-content: flex-start !important;
 }
 .textArea {
-    width: 100%;
-    height: 100%;
+  width: 100%;
+  height: 100%;
 }
 .frame {
-    /*height: 100px;*/
-    border: none;
-    position: fixed;
-    height: 0.1px;
-    width: 50%;
-    /*margin-left:10px;*/
-    /*line-height: 50px;*/
+  /*height: 100px;*/
+  border: none;
+  position: fixed;
+  height: 0.1px;
+  width: 50%;
+  /*margin-left:10px;*/
+  /*line-height: 50px;*/
 }
 .canvas-tools {
-    bottom: -50px;
+  bottom: -50px;
 }
 </style>

+ 201 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/composePaperHw.vue

@@ -0,0 +1,201 @@
+<template>
+    <div class="content">
+        <div class="editor-wrap">
+            <div id="textArea"></div>
+        </div>
+        <Modal v-model="markStatus" fullscreen :title="$t('studentWeb.exam.answer')" footer-hide ref="compose">
+            <BaseCanvas v-if="markStatus" :vm="vm" :bgImg="markBg" :isStudent="markStatus" @onCloseModal="closeModal" @onSaveCanvas="saveMark"></BaseCanvas>
+        </Modal>
+        <iframe class="frame" id="answerIframe" :srcdoc="itemInfo.description"></iframe>
+    </div>
+</template>
+<script>
+import { mapGetters } from "vuex"
+import html2canvas from "html2canvas"
+import E from "wangeditor"
+import { editor_tw_config } from "@/utils/editorLangTw.js"
+import { editor_en_config } from "@/utils/editorLangEn.js"
+import i18next from "i18next"
+export default {
+    components: {},
+    props: {
+        index: {
+            type: Number,
+            default: -1,
+        },
+        textData: {
+            type: String,
+            default: () => {
+                return ""
+            },
+        },
+        itemInfo: {
+            type: Object,
+            default: () => {
+                return {}
+            },
+        },
+        close: {
+            type: Boolean,
+            default: false,
+        },
+    },
+    data(vm) {
+        return {
+            answerImg: null,
+            vm: vm,
+            tabName: "exercise",
+            editorContent: "",
+            examInfo: "",
+            editor: null,
+            markStatus: false,
+            markBg: "",
+        }
+    },
+    methods: {
+        async getInfo() {
+            // console.error(this.markBg)
+            this.markBg = ""
+            this.examInfo = ""
+            this.initEditor()
+            // console.error(this.textData)
+            this.answerImg = null
+            if (this.textData) {
+                this.examInfo = this.textData
+                    this.answerImg = null
+                    this.editor.txt.html(this.examInfo)
+            }
+        },
+        closeModal() {
+            this.markStatus = false
+            this.markBg = ""
+        },
+        saveMark(data) {
+            if (data) {
+                data.height = 400
+                data.width = 400
+                let img = document.createElement("img")
+                img.src = data.base64
+                    this.editor.txt.html(img.outerHTML)
+                this.markStatus = false
+            }
+        },
+        initEditor() {
+            this.editorContent = ""
+            this.editor = new E("#textArea")
+            this.editor.config.onchange = (html) => {
+                this.editorContent = html
+            }
+            this.editor.config.showFullScreen = false
+            this.editor.config.menus = [
+                "link", // 插入链接
+                "justify", // 对齐方式
+                "image", // 插入图片
+            ]
+            this.editor.config.zIndex = 1
+            this.editor.config.placeholder = this.$t(
+                "studentWeb.exam.inputAnswers"
+            )
+            this.editor.config.height = 300
+            this.editor.config.showLinkImg = false
+            this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片不建议使用这种,我只是图个方便
+            this.$editorTools.addCanvas(this, this.editor)
+            // this.$editorTools.addStuBgBtn(this, this.editor)
+            let curLang = localStorage.getItem("local") || "zh-cn"
+            if (curLang === "zh-tw") {
+                // 自定义语言
+                this.editor.config.languages["tw"] = editor_tw_config
+                // 选择语言
+                this.editor.config.lang = "tw"
+                // 引入 i18next 插件
+                this.editor.i18next = i18next
+            }
+            if (curLang === "en-us") {
+                // 自定义语言
+                this.editor.config.languages["en"] = editor_en_config
+                // 选择语言
+                this.editor.config.lang = "en"
+                // 引入 i18next 插件
+                this.editor.i18next = i18next
+            }
+            this.editor.create()
+            if (this.close) {
+                this.editor.disable()
+            }
+            this.editor.txt.clear()
+            if (this.examInfo.length > 0) {
+                this.editor.txt.html(this.examInfo)
+            }
+        },
+        markStuAnswer() {
+            let answerIframe = ""
+            answerIframe = document.getElementById("answerIframe")
+            answerIframe.contentWindow.document.body.style.width = "fit-content"
+            answerIframe.contentWindow.document.body.style.minWidth = "600px"
+            answerIframe.contentWindow.document.body.style.backgroundColor = "#f5f5f5"
+            let iframe = document.getElementById("answerIframe").contentWindow.document.getElementsByTagName("p")
+
+            if (iframe.length > 0) {
+                for (let i = 0; i < iframe.length - 1; i++) {
+                    iframe[i].style.lineHeight = "50px"
+                    iframe[i].style.paddingBottom = "30px"
+                }
+                iframe[iframe.length - 1].style.paddingBottom = "100px"
+                iframe[iframe.length - 1].style.lineHeight = "50px"
+            }
+            html2canvas(answerIframe.contentWindow.document.body).then((canvas) => {
+                this.markStatus = true
+                this.markBg = canvas.toDataURL("image/png")
+            })
+        },
+    },
+    mounted() {
+        this.initEditor()
+        this.getInfo()
+        // 监听富文本画板功能
+        this.$EventBus.$off("onStuCanvas")
+        this.$EventBus.$on("onStuCanvas", (editor) => {
+            this.markBg = ""
+            this.markStuAnswer()
+        })
+    },
+    computed: {
+        ...mapGetters(["getComposeData"]),
+    },
+    watch: {
+        index() {
+            this.getInfo()
+            deep: true
+            immediate: true
+        },
+        editorContent() {
+            this.$emit("dataGet", this.editorContent)
+        },
+    },
+}
+</script>
+<style scoped>
+.content {
+    width: 100%;
+    height: 100%;
+}
+.connector-wrap /deep/ .demo {
+    justify-content: flex-start !important;
+}
+.textArea {
+    width: 100%;
+    height: 100%;
+}
+.frame {
+    /*height: 100px;*/
+    border: none;
+    position: fixed;
+    height: 0.1px;
+    width: 50%;
+    /*margin-left:10px;*/
+    /*line-height: 50px;*/
+}
+.canvas-tools {
+    bottom: -50px;
+}
+</style>

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

@@ -1,8 +1,8 @@
 <template>
     <div>
         <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
-        <div class="event-list" v-show="getSidebarisOpen">
-            <div class="list">
+        <!-- <div class="event-list"> -->
+            <div class="list" v-show="getSidebarisOpen">
                 <!--活動搜尋與篩選區域-->
                 <div class="event-selector-block">
                     <div class="search">
@@ -315,7 +315,7 @@
                     <div class="list-end"></div>
                 </div>
             </div>
-        </div>
+        <!-- </div> -->
         <div class="eventContentArea-view" :class="{'no-bar': !getSidebarisOpen}">
             <!--<VoteHint v-if="this.$store.getters.getisVoteResulthover==true"/>-->
             <template v-if="nowActivity">

+ 25 - 3
TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/ClassPoint.vue

@@ -4,6 +4,10 @@
             {{ $t("studentWeb.home.title.classScore") }}
         </div>
         <div id="classPoint"></div>
+        <div v-show="!nowRadar.length" class="no-data">
+            <img src="../noData.png" alt="">
+            <p>{{ $t("studentWeb.public.noData") }}</p>
+        </div>
         <div class="typeAll">
             <div class="typeDef" @click="changeType(false)">
                 <span :class="{'activeBg': !type}"></span>
@@ -23,10 +27,13 @@ export default {
     data() {
         return {
             type: false, //个人的类型
-            school: ["数学", "语文", "英语", "化学", "生物", "物理", "地理"],
-            private: ["个人", "培训课", "健身课", "鉴赏课", "解剖课", "盆栽课", "人文历史概述"],
+            // school: ["数学", "语文", "英语", "化学", "生物", "物理", "地理"],
+            school: [],
+            // privates: ["个人", "培训课", "健身课", "鉴赏课", "解剖课", "盆栽课", "人文历史概述"],
+            privates: [],
             schoolData: ['87', '75', '100', '12', '46', 97, 57],
             privateData: ['55', '99', '12', '74', '88', 37, 67],
+            nowRadar: [],
         }
     },
     methods: {
@@ -82,7 +89,7 @@ export default {
                     // name:'作业次数',
                     nameLocation: 'end',
                     type: 'category',
-                    data: this.type ? this.private : this.school,
+                    data: this.type ? this.privates : this.school,
                     axisLine: {
                         lineStyle: {
                             color: "#AAA"
@@ -117,10 +124,12 @@ export default {
         },
         changeType(type) {
             this.type = type
+            this.nowRadar = type ? this.privates : this.school
             this.setEcharts()
         },
     },
     mounted () {
+        this.nowRadar = this.school
         this.setEcharts()
     }
 }
@@ -161,5 +170,18 @@ export default {
             // color: white;
         }
     }
+    .no-data {
+        background-color: #fff;
+        // width: 100%;
+        height: 235px;
+        position: absolute;
+        top: 30px;
+        text-align: center;
+        // padding-top: 35px;
+
+        img {
+            width: 50%;
+        }
+    }
 }
 </style>

+ 3 - 3
TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/ExamPerform.vue

@@ -8,7 +8,7 @@
         </template>
         <div v-show="!nowRadar.length" class="no-data">
             <img src="../noData.png" alt="">
-            <p>暂没有数据</p>
+            <p>{{ $t("studentWeb.public.noData") }}</p>
         </div>
         <div class="typeAll">
             <div class="typeDef" @click="changeType(false)">
@@ -136,7 +136,7 @@ export default {
                             name: item.name
                         })
                         let average = Number((item.total / item.num * 100).toFixed(0))
-                        console.log(item.total, item.num, average);
+                        // console.log(item.total, item.num, average);
                         this.schoolData[0].value.push(average)
                     })
                     examArr.privates.forEach(item => {
@@ -145,7 +145,7 @@ export default {
                             name: item.name
                         })
                         let average = Number((item.total / item.num * 100).toFixed(0))
-                        console.log(item.total, item.num, average);
+                        // console.log(item.total, item.num, average);
                         this.privateData[0].value.push(average)
                     })
                     this.nowRadar = this.school

+ 19 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/HomeworkPoint.vue

@@ -4,6 +4,10 @@
             {{ $t("studentWeb.home.title.homework") }}
         </div>
         <div id="homeworkPoint"></div>
+        <div v-show="!hwAch.length" class="no-data">
+            <img src="../noData.png" alt="">
+            <p>{{ $t("studentWeb.public.noData") }}</p>
+        </div>
     </div>
 </template>
 
@@ -260,4 +264,19 @@ export default {
     width: 100%;
     height: 253px;
 }
+.homework-echarts {
+    .no-data {
+        background-color: #fff;
+        // width: 100%;
+        height: 235px;
+        position: absolute;
+        top: 30px;
+        text-align: center;
+        padding-top: 35px;
+
+        img {
+            width: 50%;
+        }
+    }
+}
 </style>

+ 14 - 11
TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseListView.vue

@@ -3,11 +3,14 @@
     <div class="courselist-view">
         <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
         <!-- 列表 -->
-        <div class="course-list"
-            :class="{ courselistEn: getCurrentLaguage == 'en-us', 'hide-sidebar': !getSidebarisOpen}"
-        >
-            <div class="list">
-                <ul class="list-block">
+        <!-- <div class="course-list"
+            
+        > -->
+            <div class="list"
+                v-show="getSidebarisOpen"
+            >
+                <!-- :class="{ courselistEn: getCurrentLaguage == 'en-us', 'hide-sidebar': !getSidebarisOpen}" -->
+                <!-- <ul class="list-block"> -->
                     <Tabs :value="onlyStu ? (getMycID.addSuccess == true ? 'tab2' : 'tab1') : 'tab2' ">
                         <!-- 表定课程 -->
                         <TabPane :label="$t('studentWeb.defaultClass')"
@@ -118,12 +121,12 @@
                             </div>
                         </TabPane>
                     </Tabs>
-                </ul>
+                <!-- </ul> -->
             </div>
-        </div>
+        <!-- </div> -->
         <!-- 基本信息 -->
         <div class="course-content"
-            :class="{ courseContentEn: getCurrentLaguage == 'en-us', 'course-content-span': !getSidebarisOpen }"
+            :class="{ courseContentEn: getCurrentLaguage == 'en-us', 'no-bar': !getSidebarisOpen }"
             v-if="showInfo"
         >
             <h2>
@@ -951,7 +954,7 @@ export default {
                 this.needParam.classes = this.courseNow.classId
             }
             // 螢幕寬度<767px時,直接關掉sidebar
-            if (window.innerWidth <= 991) {
+            if (window.innerWidth <= 1024) {
                 this.$store.commit("ToggleSidebar", false);
             }
             this.showInfo = true
@@ -1142,7 +1145,7 @@ export default {
             this.nickName = this.stuList[value].find((item) => {
                 return item.id === this.$store.state.userInfo.sub
             })
-            console.log(this.nickName);
+            // console.log(this.nickName);
             this.nickName.scope = this.classList[value].scope
             this.nickName.cId = this.classList[value].id
         },
@@ -1354,7 +1357,7 @@ export default {
     }
 }
 
-.list-block{
+.list{
     .ivu-tabs-nav {
         float: left !important;
 

+ 1 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseView/SchoolReport.vue

@@ -188,6 +188,7 @@ export default {
     methods: {
         getReportList(classInfo) {
             this.showSchoolRep = []
+            this.schoolRep = []
             console.log(classInfo);
             let cId = classInfo.classId.concat(classInfo.stuList)
             let param = {

+ 25 - 7
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewnnnnew.less

@@ -1,6 +1,6 @@
 .home-view {
     padding: 0.5rem 1.7rem;
-    
+
     .home-card {
         margin-top: 15px;
         box-shadow: 0px 2px 13px rgba(0, 0, 0, 0.1);
@@ -24,6 +24,7 @@
             margin-right: 20px;
         }
     }
+
     .home-head {
         margin-top: 15px;
         // display: flex;
@@ -54,7 +55,7 @@
     }
 
     .no-data-notice {
-        
+
         text-align: center;
         min-height: 212px;
         // padding-top: 40px;
@@ -69,18 +70,18 @@
         justify-content: space-between;
         margin-bottom: 20px;
 
-        & > div > p:first-child {
+        &>div>p:first-child {
             margin-bottom: 5px;
         }
 
-        & > div:first-child {
-            & > p:first-child {
+        &>div:first-child {
+            &>p:first-child {
                 font-size: 18px;
                 font-weight: bold;
             }
         }
 
-        & > div:last-child{
+        &>div:last-child {
             text-align: right;
         }
 
@@ -88,10 +89,27 @@
             width: 50%;
         }
     }
+
+    .list-new {
+        .list-new-test {
+            display: flex;
+            justify-content: center;
+            flex-direction: column;
+        }
+
+        .list-new-img {
+            width: 20%;
+            margin-right: 5px;
+
+            &>img {
+                width: 100%;
+            }
+        }
+    }
 }
 
 @media screen and (max-width: 520px) {
     .home-view .home-list-title {
         display: block;
     }
-}
+}

+ 182 - 43
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewnnnnew.vue

@@ -2,17 +2,17 @@
     <div class="home-view">
         <Loading v-show="isLoading" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
         <div class="home-head home-card">
-        <Row :gutter="30">
-            <Col :xs="24" :sm="12" :md="12" :lg="8">
-                <ExamPerform />
-            </Col>
-            <Col :xs="24" :sm="12" :md="12" :lg="8">
-                <HomeworkPoint />
-            </Col>
-            <Col :xs="24" :sm="12" :md="12" :lg="8">
-                <ClassPoint />
-            </Col>
-        </Row>
+            <Row :gutter="30">
+                <Col :xs="24" :sm="12" :md="12" :lg="8">
+                    <ExamPerform />
+                </Col>
+                <Col :xs="24" :sm="12" :md="12" :lg="8">
+                    <HomeworkPoint />
+                </Col>
+                <Col :xs="24" :sm="12" :md="12" :lg="8">
+                    <ClassPoint />
+                </Col>
+            </Row>
         </div>
         <Row :gutter="30">
             <Col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
@@ -20,9 +20,9 @@
                     <p class="home-title-name">{{ $t("studentWeb.home.title.classRecord") }}</p>
                     <div v-if="classRecord.length" style="height: 455px;">
                         <vuescroll>
-                            <div v-for="(classRecord, cIndex) in classRecord" :key="cIndex" class="list-new">
-                                <div class="list-new-icon">
-                                    <img src="./noData.png" alt="">
+                            <div v-for="(classRecord, cIndex) in classRecord" :key="cIndex" class="list-new" @click="toRecord(classRecord)">
+                                <div class="list-new-img">
+                                    <img :src="classRecord.CoverImage ? classRecord.CoverImage : './noData.png'" alt="">
                                 </div>
                                 <div class="list-new-test">
                                     <p>{{ classRecord.name }}</p>
@@ -213,7 +213,9 @@
 import ExamPerform from './ChartHome/ExamPerform.vue';
 import HomeworkPoint from './ChartHome/HomeworkPoint.vue';
 import ClassPoint from './ChartHome/ClassPoint.vue';
+
 import { mapState } from 'vuex';
+import BlobTool from "@/utils/blobTool.js"
 
 export default {
     name: "HomeViewnnnnew",
@@ -240,6 +242,11 @@ export default {
                 survey: 0,
             },
             examAch: [],
+            groups: {
+                school: [],
+                private: [],
+            },
+            sasInfo: undefined,
         }
     },
     mounted () {
@@ -247,7 +254,7 @@ export default {
         this.$emit("onNavNo", this.MyNo)
         this.$emit("onNavName", this.MyName)
         this.getNotice()
-        this.getClaRecord()
+        this.getGroupList()
         this.getActivity()
     },
     methods: {
@@ -280,34 +287,157 @@ export default {
                 }, */
             ]
         },
-        getClaRecord() {
-            this.classRecord = [
-                /* {
-                    name: "罗老师的课堂记录",
-                    startTime: "2022-04-29",
-                    time: "00:10:58",
-                },
-                {
-                    name: "罗老师的课堂记录",
-                    startTime: "2022-04-29",
-                    time: "00:10:58",
-                },
-                {
-                    name: "罗老师的课堂记录",
-                    startTime: "2022-04-29",
-                    time: "00:10:58",
-                },
-                {
-                    name: "罗老师的课堂记录",
-                    startTime: "2022-04-29",
-                    time: "00:10:58",
-                },
-                {
-                    name: "罗老师的课堂记录",
-                    startTime: "2022-04-29",
-                    time: "00:10:58",
-                }, */
-            ]
+        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) {
+                        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)
+                            }
+                        })
+                        this.getSchool("school", this.groups.school)
+                    }
+                }).finally(() => {
+                    // resolve(groups)
+                })
+            // })
+        },
+        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,
+                    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 = ""
+                            }
+                            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
+                })
+            }
+        },
+        // 查找活动的视频和文件
+        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 => {
+                })
+            })
+        },
+        getSas(info) {
+            return new Promise(async (r, j) => {
+                let code = info
+                let sasInfo = await this.$tools.getBlobSas(code)
+                r(sasInfo)
+            })
         },
         getActivity(time) {
             this.isLoading = true
@@ -477,6 +607,15 @@ export default {
                 query: {aId: item.id}
             })
         },
+        toRecord(item) {
+            this.$router.push({
+                name: "stuClassRec",
+                params: {
+                    record: item,
+                    // courseNow: this.courseNow
+                }
+            })
+        },
     },
     computed: {
         ...mapState({

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

@@ -3,7 +3,7 @@
         <Loading v-show="isLoading" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
         <div class="home-view">
             <Row :gutter="30">
-                <i-col :xs="24" :sm="24" :md="12" :lg="7">
+                <i-col :xs="24" :sm="24" :md="24" :lg="12" :xl="7">
                     <!-- 加入课程 -->
                     <Card :bordered="true" class="barCard">
                         <p slot="title" style="font-weight: bolder">
@@ -72,7 +72,7 @@
                         </div>
                     </Card>
                 </i-col>
-                <i-col :xs="24" :sm="24" :md="12" :lg="9">
+                <i-col :xs="24" :sm="24" :md="24" :lg="12" :xl="9">
                     <!-- 评测、作业 -->
                     <Card class="barCard" :bordered="true">
                         <div slot="title" style="font-weight: bolder">
@@ -86,7 +86,7 @@
                         <hwMissionListCard :testData="examandHw" :choDate="choDate ? choDate : ''" @choiceDate="choiceDate" />
                     </Card>
                 </i-col>
-                <i-col :xs="24" :sm="24" :md="12" :lg="8">
+                <i-col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
                     <!-- 活动完成率 -->
                     <Card class="barCard" :bordered="true">
                         <p slot="title" style="font-weight: bolder">

+ 2 - 0
TEAMModelOS/ClientApp/src/components/student-web/achievement/MyAchievement.vue

@@ -374,6 +374,7 @@ export default {
     mounted () {
         document.getElementsByClassName("ivu-table-body")[0].addEventListener("scroll", this.examScroll)
         document.getElementsByClassName("ivu-table-body")[1].addEventListener("scroll", this.hwScroll)
+        this.isLoading = true
         this.getRecordList()
         this.getExamList()
         this.getHwList()
@@ -664,6 +665,7 @@ export default {
         searchExam() {
             this.continuationTokenExam = null
             this.examRep = []
+            this.isLoading = true
             this.getExamList()
         },
     },

+ 30 - 30
TEAMModelOS/ClientApp/src/router/routes.js

@@ -1169,14 +1169,14 @@ export const routes = [{
 		}
 	},
 	// 购买记录
-	{
-		path: 'prodRecord',
-		name: 'prodRecord',
-		component: resolve => require(['@/view/auth/ProdRecord.vue'], resolve),
-		meta: {
-			activeName: 'ProdRecord'
-		}
-	},
+	// {
+	// 	path: 'prodRecord',
+	// 	name: 'prodRecord',
+	// 	component: resolve => require(['@/view/auth/ProdRecord.vue'], resolve),
+	// 	meta: {
+	// 		activeName: 'ProdRecord'
+	// 	}
+	// },
 	// 未授权页面
 	{
 		path: 'unauth',
@@ -1191,30 +1191,30 @@ export const routes = [{
 		path: 'auth',
 		name: 'auth',
 		component: resolve => require(['@/view/auth/Index.vue'], resolve),
-		redirect: '/home/auth/product',
+		// redirect: '/home/auth',
 		meta: {
 			activeName: 'auth'
 		},
-		children: [
-			//教室序列号
-			{
-				name: 'serial',
-				path: '/home/auth/serial',
-				meta: {
-					activeName: 'auth'
-				},
-				component: resolve => require(['@/view/auth/Serial.vue'], resolve),
-			},
-			//产品模块授权
-			{
-				name: 'product',
-				path: '/home/auth/product',
-				meta: {
-					activeName: 'auth'
-				},
-				component: resolve => require(['@/view/auth/Product.vue'], resolve),
-			}
-		]
+		// children: [
+		// 	//教室序列号
+		// 	{
+		// 		name: 'serial',
+		// 		path: '/home/auth/serial',
+		// 		meta: {
+		// 			activeName: 'auth'
+		// 		},
+		// 		component: resolve => require(['@/view/auth/Serial.vue'], resolve),
+		// 	},
+		// 	//产品模块授权
+		// 	{
+		// 		name: 'service',
+		// 		path: '/home/auth/product',
+		// 		meta: {
+		// 			activeName: 'auth'
+		// 		},
+		// 		component: resolve => require(['@/view/auth/Product.vue'], resolve),
+		// 	}
+		// ]
 	}
 	]
 },
@@ -1223,7 +1223,7 @@ export const routes = [{
 	name: 'studentWeb',
 	path: '/studentWeb',
 	redirect: '/studentWeb/homeView',
-	component: resolve => require(['@/view/student-web/App'], resolve),
+	component: resolve => require(['@/view/student-web/AppNew'], resolve),
 	meta: {
 		// 暫時連其他權限也可以登入 日後要改成只有學生
 		middleware: ['login', 'role:student'], // 强制登录(会自动跳转到登录页),角色为管理员或教师

+ 141 - 130
TEAMModelOS/ClientApp/src/static/Global.js

@@ -15,7 +15,7 @@ const CONTENT_TYPES = {
 	'audio': ['MP3', 'OGG', 'WAV', 'APE', 'CDA', 'AU', 'MIDI', 'MAC', 'AAC']
 }
 /* 需要监听关闭和刷新的路由名单 */
-const WATCH_ROUTE_CLOSE = ['newPrivateExercise','newSchoolExercise','newSchoolPaper','newPrivatePaper']
+const WATCH_ROUTE_CLOSE = ['newPrivateExercise', 'newSchoolExercise', 'newSchoolPaper', 'newPrivatePaper']
 //单位对应域名
 const HOST_LIST = () => {
 	return [
@@ -25,96 +25,107 @@ const HOST_LIST = () => {
 			router: 'jinniu',
 			isShowTMD: false,
 			title: i18n.t('system.hostTitle.jinniu'),
-			icon:'https://teammodeltest.blob.core.chinacloudapi.cn/0-public/logo/logo-%E9%87%91%E7%89%9B.png'
+			icon: 'https://teammodeltest.blob.core.chinacloudapi.cn/0-public/logo/logo-%E9%87%91%E7%89%9B.png'
+		},
+		{
+			info: '研修平台',
+			host: 'scyx.teammodel.cn',
+			router: 'jinniu', //目前需求和金牛相同则共同使用金牛的登录页
+			isShowTMD: false,
+			title: i18n.t('system.hostTitle.scyx'),
+			icon: '/favicon.ico'
 		},
 		{
 			info: '醍摩豆 IES5',
 			host: 'www.teammodel.cn',
 			router: 'login',
 			isShowTMD: true,
-			title: i18n.t('system.hostTitle.jinniu'),
-			icon:'/favicon.ico'
+			title: i18n.t('system.title'),
+			icon: '/favicon.ico'
 		}
 	]
 }
 
-const PROD_CODE = [
-	{
-		type:'serial',
-		code:'3222NIYD',
-		name:'ezStation 2',
-	},
-	{
-		type:'serial',
-		code:'J223IZ6M',
-		name:'HiTeach STD',
-	},
-	{
-		type:'serial',
-		code:'3222C6D2',
-		name:'HiTeach TBL',
-	},
-	{
-		type:'serial',
-		code:'J223IZAM',
-		name:'HiTeach PRO',
-	},
-	{
-		type:'serial',
-		code:'J2236ZCX',
-		name:'HiTeach Lite',
-	},
-	{
-		type:'serial',
-		code:'3222DNG2',
-		name:'HiTeach Mobile',
-	},
-	{
-		type:'serial',
-		code:'3222IAVN',
-		name:'HiTeach Premium',
-	},
-	{
-		type:'serial',
-		code:'BYJ6LZ6Z',
-		name:'HiTeach5',
-	},
-	{
-		type:'service',
-		code:'YMPCVCIM',
-		name:'學情分析模組',
-	},
-	{
-		type:'service',
-		code:'IPDYZYLC',
-		name:'智慧學校管理服務',
-	},
-	{
-		type:'service',
-		code:'VABAJ6NV',
-		name:'卷卡合一閱卷系統',
-	},
-	{
-		type:'service',
-		code:'YMPCVCIM',
-		name:'學情分析模組',
-	},
-	{
-		type:'quantity',
-		code:'3CLYJ6NP',
-		name:'AClass ONE智慧學伴',
-	},
-	{
-		type:'quantity',
-		code:'IPALJ6NY',
-		name:'數據儲存服務空間',
-	},
-	{
-		type:'hardware',
-		code:'0VPBDZPG',
-		name:'Haboard醍摩豆智慧大屏',
-	}
-]
+const PROD_CODE = () => {
+	return [
+		{
+			type: 'serial',
+			code: '3222NIYD',
+			name: 'ezStation 2',
+		},
+		{
+			type: 'serial',
+			code: 'J223IZ6M',
+			name: 'HiTeach STD',
+		},
+		{
+			type: 'serial',
+			code: '3222C6D2',
+			name: 'HiTeach TBL',
+		},
+		{
+			type: 'serial',
+			code: 'J223IZAM',
+			name: 'HiTeach PRO',
+		},
+		{
+			type: 'serial',
+			code: 'J2236ZCX',
+			name: 'HiTeach Lite',
+		},
+		{
+			type: 'serial',
+			code: '3222DNG2',
+			name: 'HiTeach Mobile',
+		},
+		{
+			type: 'serial',
+			code: '3222IAVN',
+			name: 'HiTeach Premium',
+		},
+		{
+			type: 'serial',
+			code: 'BYJ6LZ6Z',
+			name: 'HiTeach5',
+		},
+		//學情分析模組
+		{
+			type: 'service',
+			code: 'YMPCVCIM',
+			name: i18n.t('auth.pdName1'),
+		},
+		//智慧學校管理服務
+		{
+			type: 'service',
+			code: 'IPDYZYLC',
+			name: i18n.t('auth.pdName2'),
+		},
+		//卷卡合一閱卷系統
+		{
+			type: 'service',
+			code: 'VABAJ6NV',
+			name: i18n.t('auth.pdName3'),
+		},
+		// 可上线人数(AClass ONE智慧學伴)
+		{
+			type: 'quantity',
+			code: '3CLYJ6NP',
+			name: i18n.t('auth.pdName4'),
+		},
+		// 數據儲存服務空間
+		{
+			type: 'quantity',
+			code: 'IPALJ6NY',
+			name: i18n.t('auth.pdName5'),
+		},
+		// Haboard醍摩豆智慧大屏
+		{
+			type: 'hardware',
+			code: '0VPBDZPG',
+			name: i18n.t('auth.pdName6'),
+		}
+	]
+}
 
 
 
@@ -326,67 +337,67 @@ const TRAIN_TYPE = () => {
 // PgJump, 跳頁
 // ActEnd, 結束
 // PgIdList, 依照最後的頁面狀態排序出所有 pageid
-const HI_TEACH_EVENT = ()=>{
+const HI_TEACH_EVENT = () => {
 	return {
-		EzsStartRecord:{
-			text:'开始',
-			type:'tag',
-			relation:''
+		EzsStartRecord: {
+			text: '开始',
+			type: 'tag',
+			relation: ''
 		},
-		PopQuesLoad:{
-			text:'互动问答',
-			type:'fn',
-			relation:'irs'
+		PopQuesLoad: {
+			text: '互动问答',
+			type: 'fn',
+			relation: 'irs'
 		},
-		ReAtmpAnsStrt:{
-			text:'二次作答',
-			type:'fn',
-			relation:'irs'
+		ReAtmpAnsStrt: {
+			text: '二次作答',
+			type: 'fn',
+			relation: 'irs'
 		},
-		FastPgPush:{
-			text:'页面推送',
-			type:'fn',
-			relation:'push'
+		FastPgPush: {
+			text: '页面推送',
+			type: 'fn',
+			relation: 'push'
 		},
-		WrkSpaceEnd:{
-			text:'作品收集',
-			type:'fn',
-			relation:'task'
+		WrkSpaceEnd: {
+			text: '作品收集',
+			type: 'fn',
+			relation: 'task'
 		},
-		WrkCmp:{
-			text:'作品贴上',
-			type:'tag',
-			relation:''
+		WrkCmp: {
+			text: '作品贴上',
+			type: 'tag',
+			relation: ''
 		},
-		BuzrAns:{
-			text:'抢权',
-			type:'fn',
-			relation:'irs'
+		BuzrAns: {
+			text: '抢权',
+			type: 'fn',
+			relation: 'irs'
 		},
-		SPQStrt:{
-			text:'测验模式',
-			type:'fn',
-			relation:'exam'
+		SPQStrt: {
+			text: '测验模式',
+			type: 'fn',
+			relation: 'exam'
 		},
-		PickupResult:{
-			text:'挑人',
-			type:'fn',
-			relation:'timeline'
+		PickupResult: {
+			text: '挑人',
+			type: 'fn',
+			relation: 'timeline'
 		},
-		PgJump:{
-			text:'翻页',
-			type:'tag',
-			relation:''
+		PgJump: {
+			text: '翻页',
+			type: 'tag',
+			relation: ''
 		},
-		ActEnd:{
-			text:'结束',
-			type:'tag',
-			relation:''
+		ActEnd: {
+			text: '结束',
+			type: 'tag',
+			relation: ''
 		},
-		PgIdList:{
-			text:'页码',
-			type:'tag',
-			relation:''
+		PgIdList: {
+			text: '页码',
+			type: 'tag',
+			relation: ''
 		}
 	}
 }

+ 4 - 0
TEAMModelOS/ClientApp/src/store/module/config.js

@@ -22,6 +22,10 @@ export default {
                     station: 'product',
                     url: 'https://jinniu.teammodel.cn'
                 },
+                {
+                    station: 'product',
+                    url: 'https://scyx.teammodel.cn'
+                },
                 {
                     station: 'rc',
                     url: 'https://rc.teammodel.cn'

+ 717 - 16
TEAMModelOS/ClientApp/src/store/module/dashboard.js

@@ -1,6 +1,7 @@
 import $tools from '@/utils/public.js'
 export default {
 	state: {
+		classType:'all',
 		researchDashboard: {
 			total: [],
 			trend: [],
@@ -10,24 +11,686 @@ export default {
 			classify_sub: [],
 			exams: []
 		},
-		artDashboard: null
+		artDashboard: null,
+		musicOrigin: {
+			paperArr: [
+				['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷一</span>', "50", "16", "86", "13", "3", "0.84"],
+				['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷二</span>', "50", "16", "86", "15", "1", "0.83"],
+				['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷三</span>', "50", "16", "88", "13", "3", "0.88"],
+			],
+			//音乐试卷整体质量
+			papers: [
+				{
+					name: '高新区艺术素养测评五年级试卷一',
+					score: 50,
+					itemCount: 16,
+					useCount: 86,
+					validCount: 13,
+					invalidCount: 3,
+					difficulty: 0.84
+				},
+				{
+					name: '高新区艺术素养测评五年级试卷二',
+					score: 50,
+					itemCount: 16,
+					useCount: 86,
+					validCount: 15,
+					invalidCount: 1,
+					difficulty: 0.83
+				},
+				{
+					name: '高新区艺术素养测评五年级试卷三',
+					score: 50,
+					itemCount: 16,
+					useCount: 86,
+					validCount: 13,
+					invalidCount: 3,
+					difficulty: 0.88
+				}
+			],
+			// 测评总体情况
+			staticData: {
+				total: 263,
+				join: 260,
+				hScore: 49.76,
+				lScore: 28.42,
+				average: 42.58,
+				goodRate: '34.23',
+				normalRate: '98.85',
+				standard: 4.31
+			},
+			// 知识点得分率统计
+			knowledges: [
+				{
+					name: '戏曲',
+					level1: '审美感知',
+					level2: '音乐体裁与形式',
+					val: 96.51,
+				}, {
+					name: '民歌体裁',
+					level1: '审美感知',
+					level2: '音乐体裁与形式',
+					val: 82.18,
+				}, {
+					name: '情绪',
+					level1: '审美感知',
+					level2: '音乐情绪与情感',
+					val: 94.52,
+				}, {
+					name: '速度',
+					level1: '审美感知',
+					level2: '音乐表现要素及音乐音响材料',
+					val: 95,
+				}, {
+					name: '节拍',
+					level1: '审美感知',
+					level2: '音乐表现要素及音乐音响材料',
+					val: 91.98,
+				}, {
+					name: '音色',
+					level1: '审美感知',
+					level2: '音乐表现要素及音乐音响材料',
+					val: 88.05,
+				}, {
+					name: '中国音乐名家',
+					level1: '审美感知',
+					level2: '音乐风格与流派',
+					val: 93.02,
+				}, {
+					name: '中国音乐名曲',
+					level1: '审美感知',
+					level2: '音乐风格与流派',
+					val: 86.21,
+				}, {
+					name: '外国音乐名曲',
+					level1: '审美感知',
+					level2: '音乐风格与流派',
+					val: 83.72,
+				}, {
+					name: '外国音乐名家',
+					level1: '审美感知',
+					level2: '音乐风格与流派',
+					val: 71.59,
+				}, {
+					name: '中国民族文化',
+					level1: '文化理解',
+					level2: '音乐与民族、地域文化',
+					val: 87.21,
+				}, {
+					name: '音符',
+					level1: '艺术表现',
+					level2: '乐谱识读与运用',
+					val: 86.82,
+				}, {
+					name: '音乐记号',
+					level1: '艺术表现',
+					level2: '乐谱识读与运用',
+					val: 85.82,
+				}, {
+					name: '视谱跟唱模唱',
+					level1: '艺术表现',
+					level2: '乐谱识读与运用',
+					val: 81.92,
+				}, {
+					name: '演唱形式',
+					level1: '艺术表现',
+					level2: '演唱',
+					val: 69.37,
+				}, {
+					name: '演奏形式',
+					level1: '艺术表现',
+					level2: '演奏',
+					val: 4.65,
+				}
+			],
+			// 班级数据对比
+			classData: [
+				{
+					className: '1班',
+					total: 44,
+					join: 44,
+					hScore: 49.76,
+					average: 43.13,
+					goodRate: 34.09,
+					normalRate: 97.73,
+					standard: 3.95
+				},
+				{
+					className: '2班',
+					total: 43,
+					join: 43,
+					hScore: 49.50,
+					average: 41.58,
+					goodRate: 25.58,
+					normalRate: 100,
+					standard: 4.79
+				},
+				{
+					className: '3班',
+					total: 44,
+					join: 43,
+					hScore: 48.44,
+					average: 41.48,
+					goodRate: 27.91,
+					normalRate: 95.35,
+					standard: 4.60
+				},
+				{
+					className: '4班',
+					total: 44,
+					join: 42,
+					hScore: 49.68,
+					average: 43.58,
+					goodRate: 47.62,
+					normalRate: 100,
+					standard: 4.26
+				},
+				{
+					className: '5班',
+					total: 44,
+					join: 44,
+					hScore: 49.50,
+					average: 42.87,
+					goodRate: 34.09,
+					normalRate: 100,
+					standard: 3.44
+				},
+				{
+					className: '6班',
+					total: 44,
+					join: 44,
+					hScore: 49.62,
+					average: 42.87,
+					goodRate: 36.36,
+					normalRate: 100,
+					standard: 4.25
+				}
+			],
+			// 课堂挤占情况
+			lessonData: [
+				{
+					key: '经常',
+					schoolRate: 0,
+					areaRate: 0.24
+				},
+				{
+					key: '偶尔',
+					schoolRate: 0,
+					areaRate: 1.01
+				},
+				{
+					key: '很少',
+					schoolRate: 1.53,
+					areaRate: 3.95
+				},
+				{
+					key: '从来没有',
+					schoolRate: 98.47,
+					areaRate: 98.48
+				}
+			],
+			// 获奖情况统计
+			awardData: [
+				{
+					key: 'school',
+					country: 18,
+					province: 21,
+					city: 9,
+					area: 7,
+					school: 28
+				},
+				{
+					key: 'areaAverage',
+					country: 49,
+					province: 55,
+					city: 31,
+					area: 33,
+					school: 71
+				},
+				{
+					key: 'areaTotal',
+					country: 1754,
+					province: 1971,
+					city: 1098,
+					area: 1162,
+					school: 2564
+				}
+			]
+		},
+		paintOrigin: {
+			paperArr: [
+				['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷一</span>', "40", "16", "86", "13", "3", "0.94"],
+				['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷二</span>', "40", "16", "86", "15", "1", "0.92"],
+				['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷三</span>', "40", "16", "88", "13", "1", "0.88"],
+			],
+			//音乐试卷整体质量
+			papers: [
+				{
+					name: '高新区艺术素养测评五年级试卷一',
+					score: 50,
+					itemCount: 16,
+					useCount: 86,
+					validCount: 13,
+					invalidCount: 3,
+					difficulty: 0.84
+				},
+				{
+					name: '高新区艺术素养测评五年级试卷二',
+					score: 50,
+					itemCount: 16,
+					useCount: 86,
+					validCount: 15,
+					invalidCount: 1,
+					difficulty: 0.83
+				},
+				{
+					name: '高新区艺术素养测评五年级试卷三',
+					score: 50,
+					itemCount: 16,
+					useCount: 86,
+					validCount: 13,
+					invalidCount: 3,
+					difficulty: 0.88
+				}
+			],
+			// 测评总体情况
+			staticData: {
+				total: 263,
+				join: 260,
+				hScore: 40.00,
+				lScore: 18.00,
+				average: 36.54,
+				goodRate: '72.69',
+				normalRate: '98.08',
+				standard: 3.87
+			},
+			// 知识点得分率统计
+			knowledges: [
+				{
+					name: '民族文化',
+					level1: '文化理解',
+					level2: '美术与自然、地域',
+					val: 97.29,
+				}, {
+					name: '设计应用',
+					level1: '美术表现',
+					level2: '创作实践',
+					val: 99.08,
+				}, {
+					name: '造型表现',
+					level1: '美术表现',
+					level2: '创作实践',
+					val: 89.85,
+				}, {
+					name: '图像识读',
+					level1: '美术表现',
+					level2: '视觉形象感知',
+					val: 91.50,
+				}, {
+					name: '图像类别',
+					level1: '美术表现',
+					level2: '视觉形象感知',
+					val: 91.15,
+				}, {
+					name: '图像要素',
+					level1: '美术表现',
+					level2: '视觉形象感知',
+					val: 89.21,
+				}
+			],
+			// 班级数据对比
+			classData: [
+				{
+					className: '1班',
+					total: 44,
+					join: 44,
+					hScore: 40.00,
+					average: 36.18,
+					goodRate: 70.45,
+					normalRate: 95.45,
+					standard: 4.41
+				},
+				{
+					className: '2班',
+					total: 43,
+					join: 43,
+					hScore: 40.00,
+					average: 36.14,
+					goodRate: 72.09,
+					normalRate: 100,
+					standard: 3.51
+				},
+				{
+					className: '3班',
+					total: 44,
+					join: 43,
+					hScore: 40.00,
+					average: 35.81,
+					goodRate: 67.44,
+					normalRate: 95.35,
+					standard: 4.68
+				},
+				{
+					className: '4班',
+					total: 44,
+					join: 42,
+					hScore: 40.00,
+					average: 37.48,
+					goodRate: 76.19,
+					normalRate: 100,
+					standard: 2.86
+				},
+				{
+					className: '5班',
+					total: 44,
+					join: 44,
+					hScore: 40.00,
+					average: 36.73,
+					goodRate: 70.45,
+					normalRate: 100,
+					standard: 3.14
+				},
+				{
+					className: '6班',
+					total: 44,
+					join: 44,
+					hScore: 40.00,
+					average: 36.91,
+					goodRate: 79.55,
+					normalRate: 97.73,
+					standard: 4.03
+				}
+			],
+			// 课堂挤占情况
+			lessonData: [
+				{
+					key: '经常',
+					schoolRate: 0,
+					areaRate: 0.33
+				},
+				{
+					key: '偶尔',
+					schoolRate: 1.26,
+					areaRate: 0.38
+				},
+				{
+					key: '很少',
+					schoolRate: 0,
+					areaRate: 3.77
+				},
+				{
+					key: '从来没有',
+					schoolRate: 99.62,
+					areaRate: 94.64
+				}
+			],
+			// 获奖情况统计
+			awardData: [
+				{
+					key: 'school',
+					country: 17,
+					province: 16,
+					city: 8,
+					area: 8,
+					school: 37
+				},
+				{
+					key: 'areaAverage',
+					country: 52,
+					province: 37,
+					city: 20,
+					area: 15,
+					school: 93
+				},
+				{
+					key: 'areaTotal',
+					country: 1854,
+					province: 1314,
+					city: 715,
+					area: 524,
+					school: 3331
+				}
+			]
+		},
+		stuArr: [
+			{
+				"className": 1,
+				"name": "蒋系羽",
+				"score": 47.94
+			},
+			{
+				"className": 1,
+				"name": "刘曜绫",
+				"score": 48.82
+			},
+			{
+				"className": 1,
+				"name": "李梓洁",
+				"score": 42.48
+			},
+			{
+				"className": 1,
+				"name": "许惠雯",
+				"score": 41.4
+			},
+			{
+				"className": 1,
+				"name": "邓雅榕",
+				"score": 39.06
+			},
+			{
+				"className": 1,
+				"name": "何男勋",
+				"score": 29.5
+			},
+			{
+				"className": 1,
+				"name": "张显亮",
+				"score": 43.33
+			},
+			{
+				"className": 1,
+				"name": "张书语",
+				"score": 35.65
+			},
+			{
+				"className": 1,
+				"name": "赵清清",
+				"score": 35.18
+			},
+			{
+				"className": 1,
+				"name": "何铱菲",
+				"score": 39.02
+			},
+			{
+				"className": 1,
+				"name": "吴佳蔓",
+				"score": 41.54
+			},
+			{
+				"className": 1,
+				"name": "林娇",
+				"score": 43.39
+			},
+			{
+				"className": 1,
+				"name": "肖皓楠",
+				"score": 44.97
+			},
+			{
+				"className": 1,
+				"name": "向昶轩",
+				"score": 44.41
+			},
+			{
+				"className": 1,
+				"name": "许欣彤",
+				"score": 46.45
+			},
+			{
+				"className": 1,
+				"name": "刘煜琪",
+				"score": 41.1
+			},
+			{
+				"className": 1,
+				"name": "李俊峰",
+				"score": 37.96
+			},
+			{
+				"className": 1,
+				"name": "刘金浩",
+				"score": 42.89
+			},
+			{
+				"className": 1,
+				"name": "杨思琪",
+				"score": 49.76
+			},
+			{
+				"className": 1,
+				"name": "徐浩晨",
+				"score": 47.59
+			},
+			{
+				"className": 1,
+				"name": "杨垚",
+				"score": 47.58
+			},
+			{
+				"className": 1,
+				"name": "王泽豪",
+				"score": 39.37
+			},
+			{
+				"className": 1,
+				"name": "黄芸汐",
+				"score": 42.24
+			},
+			{
+				"className": 1,
+				"name": "刘彦希",
+				"score": 40.94
+			},
+			{
+				"className": 1,
+				"name": "潘云轩",
+				"score": 45.28
+			},
+			{
+				"className": 1,
+				"name": "张芯玉",
+				"score": 43.33
+			},
+			{
+				"className": 1,
+				"name": "符诗琪",
+				"score": 42.45
+			},
+			{
+				"className": 1,
+				"name": "刘涛瑞",
+				"score": 47.32
+			},
+			{
+				"className": 1,
+				"name": "陶思睿",
+				"score": 44.34
+			},
+			{
+				"className": 1,
+				"name": "董诚",
+				"score": 45.1
+			},
+			{
+				"className": 1,
+				"name": "周星",
+				"score": 43.32
+			},
+			{
+				"className": 1,
+				"name": "李子瀚",
+				"score": 44.66
+			},
+			{
+				"className": 1,
+				"name": "付子琪",
+				"score": 39.6
+			},
+			{
+				"className": 1,
+				"name": "王子霖",
+				"score": 42.95
+			},
+			{
+				"className": 1,
+				"name": "王欣怡",
+				"score": 37.34
+			},
+			{
+				"className": 1,
+				"name": "李昊凌",
+				"score": 45.27
+			},
+			{
+				"className": 1,
+				"name": "杨玉菁",
+				"score": 45.64
+			},
+			{
+				"className": 1,
+				"name": "范忠友",
+				"score": 44.61
+			},
+			{
+				"className": 1,
+				"name": "刘玲瑞",
+				"score": 44.78
+			},
+			{
+				"className": 1,
+				"name": "易术家",
+				"score": 44.11
+			},
+			{
+				"className": 1,
+				"name": "陈雅思",
+				"score": 46.92
+			},
+			{
+				"className": 1,
+				"name": "蒋诗灿",
+				"score": 45.61
+			},
+			{
+				"className": 1,
+				"name": "刘胜溢",
+				"score": 45.09
+			},
+			{
+				"className": 1,
+				"name": "胡馨雨",
+				"score": 47.4
+			}
+		]
 	},
 	mutations: {
 		setRearchDashboardData(state, val) {
 			state.researchDashboard = val
 		},
 		setArtDashboardData(state, val) {
-			if(val === 'music'){
+			if (val === 'music') {
 				state.artDashboard = {
 					paperArr: [
-						['<span style="color:#32c5e9;font-weight: bold;">青羊区艺术素养测评五年级试卷一</span>', "50", "16", "86", "13", "3", "0.84"],
-						['<span style="color:#32c5e9;font-weight: bold;">青羊区艺术素养测评五年级试卷二</span>', "50", "16", "86", "15", "1", "0.83"],
-						['<span style="color:#32c5e9;font-weight: bold;">青羊区艺术素养测评五年级试卷三</span>', "50", "16", "88", "13", "3", "0.88"],
+						['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷一</span>', "50", "16", "86", "13", "3", "0.84"],
+						['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷二</span>', "50", "16", "86", "15", "1", "0.83"],
+						['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷三</span>', "50", "16", "88", "13", "3", "0.88"],
 					],
 					//音乐试卷整体质量
 					papers: [
 						{
-							name: '青羊区艺术素养测评五年级试卷一',
+							name: '高新区艺术素养测评五年级试卷一',
 							score: 50,
 							itemCount: 16,
 							useCount: 86,
@@ -36,7 +699,7 @@ export default {
 							difficulty: 0.84
 						},
 						{
-							name: '青羊区艺术素养测评五年级试卷二',
+							name: '高新区艺术素养测评五年级试卷二',
 							score: 50,
 							itemCount: 16,
 							useCount: 86,
@@ -45,7 +708,7 @@ export default {
 							difficulty: 0.83
 						},
 						{
-							name: '青羊区艺术素养测评五年级试卷三',
+							name: '高新区艺术素养测评五年级试卷三',
 							score: 50,
 							itemCount: 16,
 							useCount: 86,
@@ -263,17 +926,17 @@ export default {
 						}
 					]
 				}
-			}else{
+			} else {
 				state.artDashboard = {
 					paperArr: [
-						['<span style="color:#32c5e9;font-weight: bold;">青羊区艺术素养测评五年级试卷一</span>', "40", "16", "86", "13", "3", "0.94"],
-						['<span style="color:#32c5e9;font-weight: bold;">青羊区艺术素养测评五年级试卷二</span>', "40", "16", "86", "15", "1", "0.92"],
-						['<span style="color:#32c5e9;font-weight: bold;">青羊区艺术素养测评五年级试卷三</span>', "40", "16", "88", "13", "1", "0.88"],
+						['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷一</span>', "40", "16", "86", "13", "3", "0.94"],
+						['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷二</span>', "40", "16", "86", "15", "1", "0.92"],
+						['<span style="color:#32c5e9;font-weight: bold;">高新区艺术素养测评五年级试卷三</span>', "40", "16", "88", "13", "1", "0.88"],
 					],
 					//音乐试卷整体质量
 					papers: [
 						{
-							name: '青羊区艺术素养测评五年级试卷一',
+							name: '高新区艺术素养测评五年级试卷一',
 							score: 50,
 							itemCount: 16,
 							useCount: 86,
@@ -282,7 +945,7 @@ export default {
 							difficulty: 0.84
 						},
 						{
-							name: '青羊区艺术素养测评五年级试卷二',
+							name: '高新区艺术素养测评五年级试卷二',
 							score: 50,
 							itemCount: 16,
 							useCount: 86,
@@ -291,7 +954,7 @@ export default {
 							difficulty: 0.83
 						},
 						{
-							name: '青羊区艺术素养测评五年级试卷三',
+							name: '高新区艺术素养测评五年级试卷三',
 							score: 50,
 							itemCount: 16,
 							useCount: 86,
@@ -460,7 +1123,45 @@ export default {
 					]
 				}
 			}
-		}
+		},
+		setRandomArtData(state, val) {
+			if (val.index === -1) {
+				state.artDashboard = JSON.parse(JSON.stringify(val.subject === 'music' ? state.musicOrigin : state.paintOrigin))
+				state.classType = 'all'
+			} else {
+				state.classType = 'single'
+				state.artDashboard.staticData.total = $tools.randomNum(30, 50)
+				state.artDashboard.staticData.join = state.artDashboard.staticData.total - $tools.randomNum(0, 2)
+				state.artDashboard.staticData.hScore = $tools.randomNum(40, 50)
+				state.artDashboard.staticData.lScore = $tools.randomNum(20, 30)
+				state.artDashboard.staticData.average = $tools.randomNum(30, 45)
+				state.artDashboard.staticData.goodRate = $tools.randomNum(70, 90)
+				state.artDashboard.staticData.normalRate = $tools.randomNum(90, 100)
+				state.artDashboard.paperArr.forEach(i => {
+					i[3] = $tools.randomNum(10, 20)
+				})
+				state.artDashboard.knowledges.forEach(i => {
+					i.val = $tools.randomNum(10, 90)
+				})
+				state.artDashboard.awardData[0].country = $tools.randomNum(0, 10)
+				state.artDashboard.awardData[0].province = $tools.randomNum(0, 10)
+				state.artDashboard.awardData[0].city = $tools.randomNum(0, 10)
+				state.artDashboard.awardData[0].area = $tools.randomNum(0, 10)
+				state.artDashboard.awardData[0].school = $tools.randomNum(0, 10)
+				state.artDashboard.classData = state.stuArr.map(i => {
+					return {
+						className: i.name,
+						total: 0,
+						join: 0,
+						hScore: i.score,
+						average: 36.18,
+						goodRate: 0,
+						normalRate: 0,
+						standard: 0
+					}
+				})
+			}
+		},
 	},
 
 }

+ 8 - 1
TEAMModelOS/ClientApp/src/store/module/studentWeb.js

@@ -89,6 +89,7 @@ export default {
         addSuccess: false,
         coureseMessageOpen: false, //是否打開加入課程的提示訊息
         choseDate: "",
+        composeData: undefined,
     },
 
     //定義方法
@@ -310,7 +311,10 @@ export default {
         },
         setChoseDate(state, time) {
             state.choseDate = time
-        }
+        },
+        setComposeData(state, data) {
+            state.composeData = data
+        },
     },
     getters: {
         getStuUserInfo: (state) => {
@@ -438,6 +442,9 @@ export default {
         },
         getChoseDate: (state) => {
             return state.choseDate
+        },
+        getComposeData: (state) => {
+            return state.composeData
         }
     },
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/store/module/user.js

@@ -541,7 +541,7 @@ export default {
             let svcStatus = {}
             if (data.productSum?.service) {
                 // 所有服务模组列表
-                let svcList = GLOBAL.PROD_CODE.filter(item => item.type === 'service')
+                let svcList = GLOBAL.PROD_CODE().filter(item => item.type === 'service')
                 let buyCodes = data.productSum.service.map(item => item.prodCode)
                 svcList.forEach(item => {
                     svcStatus[item.code] = buyCodes.includes(item.code)

+ 6 - 0
TEAMModelOS/ClientApp/src/utils/blobTool.js

@@ -183,6 +183,7 @@ export default class BlobTool {
     // upload(file, path, option = {}, checkSize = true, root = '/') { //原来参数格式
     upload(file, config = {}, option = {}) {
         let { path, root, checkSize, checkExist } = config
+        console.log(config)
         //验证和初始化参数
         if (!path) throw new Error('上传失败:config.path必传')
         root = root || '/'
@@ -626,7 +627,12 @@ export default class BlobTool {
         return new Promise(async (r, j) => {
             try {
                 let sizeRes = await BlobTool.getContainerSize(this.container, scope)
+                console.log(scope)
+                console.log(sizeRes)
                 if (sizeRes) {
+                    console.log(sizeRes.total)
+                    console.log(this.blobSpace * 1024 * 1024 * 1024)
+
                     r(sizeRes.total > this.blobSpace * 1024 * 1024 * 1024)
                 } else {
                     j('容器空间判断失败!')

+ 1 - 0
TEAMModelOS/ClientApp/src/utils/editorLangEn.js

@@ -1,5 +1,6 @@
 let editor_en_config = {
     wangEditor: {
+        重置: 'Reset',
         插入: 'Insert',
         默认: 'Default',
         创建: 'Create',

+ 1 - 0
TEAMModelOS/ClientApp/src/utils/editorLangTw.js

@@ -1,5 +1,6 @@
 let editor_tw_config = {
     wangEditor: {
+        重置: '重设',
         插入: '插入',
         默认: '默認',
         创建: '創建',

+ 151 - 106
TEAMModelOS/ClientApp/src/utils/editorTools.js

@@ -29,7 +29,7 @@ export default {
 	normalizeSafariSpaceSpans(htmlString) {
 		return htmlString.replace(/<span(?: class="Apple-converted-space"|)>(\s+)<\/span>/g, (fullMatch, spaces) => {
 			return spaces.length === 1 ? ' ' : Array(spaces.length + 1).join('\u00A0 ').substr(0, spaces
-			.length);
+				.length);
 		});
 	},
 	/* 粘贴文本的解析和轻量化操作 */
@@ -79,7 +79,7 @@ export default {
 	},
 	/* 粘贴事件监听 */
 	pasteEvent(e, editor) {
-		if(e.target.nodeName === 'INPUT'){
+		if (e.target.nodeName === 'INPUT') {
 			return
 		}
 		let that = this
@@ -148,7 +148,7 @@ export default {
 			}
 		}
 	},
-	initEditorLang(editor){
+	initEditorLang(editor) {
 		let curLang = localStorage.getItem('local') || 'zh-cn'
 		if (curLang === 'zh-tw') {
 			// 自定义语言
@@ -192,7 +192,7 @@ export default {
 		this.addVideoUpload(vm, editor)
 		this.addAudio(vm, editor)
 		this.addCanvas(vm, editor)
-		this.addTextDot(vm,editor)
+		this.addTextDot(vm, editor)
 		// editor.config.pasteFilterStyle = false
 		editor.config.uploadImgMaxSize = 2 * 1024 * 1024 // 2M
 		editor.config.uploadImgShowBase64 = true;
@@ -220,17 +220,25 @@ export default {
 		isOption && editor.config.menus.splice(editor.config.menus.indexOf('video'), 1)
 		let dom = editor.toolbarSelector
 		if (dom) {
-			editor.config.pasteTextHandle = function(pasteStr) {
-				return ''
-			}
-			dom.removeEventListener('paste', e => {
-				this.pasteEvent(e, editor)
-			})
-			dom.addEventListener('paste', e => {
-				this.pasteEvent(e, editor)
-			})
+			editor.config.pasteTextHandle = function (pasteStr) {
+				// 对粘贴的文本进行处理,然后返回处理后的结果
+				var newStr = pasteStr.replace(
+					/@font-face{[^>]*div.Section0{page:Section0;}/g,
+					""
+				);
+				return newStr;
+			};
+			// editor.config.pasteTextHandle = function (pasteStr) {
+			// 	return ''
+			// }
+			// dom.removeEventListener('paste', e => {
+			// 	this.pasteEvent(e, editor)
+			// })
+			// dom.addEventListener('paste', e => {
+			// 	this.pasteEvent(e, editor)
+			// })
 		} else {
-			editor.config.pasteTextHandle = function(pasteStr) {
+			editor.config.pasteTextHandle = function (pasteStr) {
 				// 对粘贴的文本进行处理,然后返回处理后的结果
 				var newStr = pasteStr.replace(
 					/@font-face{[^>]*div.Section0{page:Section0;}/g,
@@ -260,7 +268,7 @@ export default {
 			editor.i18next = i18next
 		}
 		// editor.config.pasteFilterStyle = false
-		editor.config.pasteTextHandle = function(pasteStr) {
+		editor.config.pasteTextHandle = function (pasteStr) {
 			// 对粘贴的文本进行处理,然后返回处理后的结果
 			var newStr = pasteStr.replace(
 				/@font-face{[^>]*div.Section0{page:Section0;}/g,
@@ -286,7 +294,7 @@ export default {
 		]
 	},
 	/* 添加自定义本地视频上传功能 */
-	addVideoUpload(vm, editor) {
+	addVideoUpload(vm, editor, isSimple) {
 		// 获取必要的变量,这些在下文中都会用到
 		const {
 			$,
@@ -365,12 +373,18 @@ export default {
 								if (fileList.length) {
 									if (fileList[0].type.slice(0, 5) !== 'video') {
 										Message.warning(app.$t('utils.videoFormatError'))
+									}else if(fileList[0].size > 100 * 1024 * 1024){
+										Message.warning(app.$t('utils.maxFileSize'))
 									} else {
 										// var url = window.URL.createObjectURL(`https://teammodelstorage.blob.core.chinacloudapi.cn/hbcn/item/f469d65d-b18b-273b-f137-e8aefab6990d/002N0NH6gx07LhTzM67l010412005WHv0E010.mp4?sv=2020-04-08&st=2021-03-23T02%3A28%3A01Z&se=2120-02-28T02%3A58%3A01Z&sr=b&sp=r&sig=R%2Ff7zhkh%2FKES%2BXZbc60IGyTadarW3n86poSeaA%2BIjKk%3D`);
 										// editor.selection.getSelectionStartElem().elems[0].innerHTML += '<span><span>&nbsp;</span><video src=' +
 										// 	url + ' class="richText-video" width="300" preload controls="controls"></video><span>&nbsp;</span></span>'
 										// editor.change.emit()
-										$tools.doUploadVideo(vm, fileList[0], editor)
+										if (isSimple) {
+											app.$EventBus.$emit('selectFileFinish', { file: fileList[0], type: 'video' })
+										} else {
+											$tools.doUploadVideo(vm, fileList[0], editor)
+										}
 									}
 								}
 								// 返回 true 可关闭 panel
@@ -389,10 +403,10 @@ export default {
 				return conf;
 			}
 
-			command(value) {}
+			command(value) { }
 
 			// 菜单是否需要激活
-			tryChangeActive() {}
+			tryChangeActive() { }
 		}
 
 		// 注册菜单
@@ -401,10 +415,10 @@ export default {
 
 		// 将菜单加入到 editor.config.menus 中
 		// 也可以通过配置 menus 调整菜单的顺序,参考【配置菜单】部分的文档
-		// editor.config.menus = editor.config.menus.concat(videoUpload);
+		editor.config.menus = editor.config.menus.concat(videoUpload);
 	},
 	/* 添加自定义本地音频上传功能 */
-	addAudio(vm, editor) {
+	addAudio(vm, editor, isSimple) {
 		// 获取必要的变量,这些在下文中都会用到
 		const {
 			$,
@@ -478,8 +492,14 @@ export default {
 								if (fileList.length) {
 									if (fileList[0].type.slice(0, 5) !== 'audio') {
 										Message.warning(app.$t('utils.audioFormatError'))
-									} else {
-										$tools.doUploadAudio(vm, fileList[0], editor)
+									} else if(fileList[0].size > 100 * 1024 * 1024){
+										Message.warning(app.$t('utils.maxFileSize'))
+									}  else {
+										if (isSimple) {
+											app.$EventBus.$emit('selectFileFinish', { file: fileList[0], type: 'audio' })
+										} else {
+											$tools.doUploadAudio(vm, fileList[0], editor)
+										}
 									}
 								}
 								// 返回 true 可关闭 panel
@@ -498,10 +518,10 @@ export default {
 				return conf;
 			}
 
-			command(value) {}
+			command(value) { }
 
 			// 菜单是否需要激活
-			tryChangeActive() {}
+			tryChangeActive() { }
 		}
 
 		// 注册菜单
@@ -540,7 +560,7 @@ export default {
 					onOk: () => {
 						app.$EventBus.$emit('doCanvasConfirm')
 					},
-					render(h){
+					render(h) {
 						return h('div', {
 							style: {
 								display: 'flex',
@@ -571,7 +591,7 @@ export default {
 										// let widthPercent = val.width > 800 ? '50%' : '100%'
 										editor.txt.append('<img  src=' + val.base64 +
 											' class="richText-canvas" style="max-width:100%"></img>'
-											);
+										);
 										Modal.remove()
 									},
 									onCloseModal() {
@@ -584,10 +604,10 @@ export default {
 				})
 			}
 
-			command(value) {}
+			command(value) { }
 
 			// 菜单是否需要激活
-			tryChangeActive() {}
+			tryChangeActive() { }
 		}
 
 		// 注册菜单
@@ -606,7 +626,7 @@ export default {
 			BtnMenu,
 			Panel
 		} = E;
-	
+
 		// 标题菜单的 class ,可作为 DropList 菜单的参考代码
 		class myPanel extends BtnMenu {
 			constructor(editor) {
@@ -617,7 +637,7 @@ export default {
 				);
 				super($elem, editor);
 			}
-	
+
 			clickHandler() {
 				// Modal.props.fullscreen.default = true
 				app.$EventBus.$emit('clickResource')
@@ -636,7 +656,7 @@ export default {
 								maxWidth: '1200px',
 								margin: '0 auto'
 							},
-	
+
 						}, [
 							h('div', {
 								style: {
@@ -648,10 +668,10 @@ export default {
 							}),
 							h('NewChooseContent', {
 								props: {
-									vm:vm,
-									showSyllabus:false,
-									showQuestion:false,
-									showPaper:false
+									vm: vm,
+									showSyllabus: false,
+									showQuestion: false,
+									showPaper: false
 								},
 								on: {
 									'on-file-change'(val) {
@@ -666,29 +686,29 @@ export default {
 					},
 				})
 			}
-	
-			command(value) {}
-	
+
+			command(value) { }
+
 			// 菜单是否需要激活
-			tryChangeActive() {}
+			tryChangeActive() { }
 		}
-	
+
 		// 注册菜单
 		const resourceDraw = "resource"; // 菜单 key ,各个菜单不能重复
 		editor.menus.extend("resource", myPanel);
-	
+
 		// 将菜单加入到 editor.config.menus 中
 		// 也可以通过配置 menus 调整菜单的顺序,参考【配置菜单】部分的文档
 		editor.config.menus = editor.config.menus.concat(resourceDraw);
 	},
-	
+
 	/* 添加文字下加重点功能 */
 	addTextDot(vm, editor) {
 		const {
 			$,
-			BtnMenu 
+			BtnMenu
 		} = E;
-		class TextDot extends BtnMenu{
+		class TextDot extends BtnMenu {
 			constructor(editor) {
 				const $elem = $(
 					`<div class="w-e-menu" style="color:red" title="${app.$t('evaluation.editor.addTextDot')}"><i class="icon iconfont icon-heavy" style="font-size: 20px;display: inline-block;margin-top: 3px;"></i></div>`
@@ -699,7 +719,7 @@ export default {
 			/**
 			 * 点击事件
 			 */
-			clickHandler(){
+			clickHandler() {
 				const editor = this.editor
 				const isSelectEmpty = editor.selection.isSelectionEmpty()
 				// console.log(editor)
@@ -711,16 +731,16 @@ export default {
 					editor.selection.createEmptyRange()
 					editor.selection.collapseRange()
 					editor.selection.restoreSelection()
-				}else{
+				} else {
 					let selectDom = editor.selection.getSelectionStartElem().elems[0]
 					let selectText = editor.selection.getSelectionText()
-					if(selectDom.localName === 'dot'){
+					if (selectDom.localName === 'dot') {
 						// 如果选中的文本 本身就有着重号 就去除
 						editor.cmd.do('insertHTML', selectText)
-					}else{
+					} else {
 						// 添加着重号
 						// console.log(selectText)
-						let textArr = selectText.replace(/\u200B/g,'').split('').filter(s => s && s.trim())
+						let textArr = selectText.replace(/\u200B/g, '').split('').filter(s => s && s.trim())
 						// console.log(textArr)
 						let html = ``
 						// let html = `&#8203<dot>${selectText}</dot>&#8203`
@@ -736,7 +756,7 @@ export default {
 			/**
 			 * 尝试修改菜单激活状态
 			 */
-			tryChangeActive(){
+			tryChangeActive() {
 				const editor = this.editor
 				if (editor.cmd.queryCommandState('textDot')) {
 					this.active()
@@ -745,7 +765,7 @@ export default {
 				}
 			}
 		}
-		
+
 		// 注册菜单
 		const TextDotKey = "textDot"; // 菜单 key ,各个菜单不能重复
 		editor.menus.extend("textDot", TextDot);
@@ -777,7 +797,7 @@ export default {
 				panel.create();
 			}
 
-			tryChangeActive() {}
+			tryChangeActive() { }
 		}
 
 		// 注册菜单
@@ -801,7 +821,7 @@ export default {
 			// 公式输入插件
 			constructor(editors) {
 				const $elem = $(
-					`<div class="w-e-menu" title="${ app.$t('evaluation.editor.canvasStemTip') }" style="color:red"><i class="icon iconfont icon-brush" style="font-size: 20px;"></i></div>`
+					`<div class="w-e-menu" title="${app.$t('evaluation.editor.canvasStemTip')}" style="color:red"><i class="icon iconfont icon-brush" style="font-size: 20px;"></i></div>`
 				);
 				super($elem, editors);
 			}
@@ -810,7 +830,7 @@ export default {
 				app.$EventBus.$emit('onStuCanvas', editor)
 			}
 
-			tryChangeActive() {}
+			tryChangeActive() { }
 		}
 
 		// 注册菜单
@@ -819,14 +839,39 @@ export default {
 
 		// 将菜单加入到 editor.config.menus 中
 		// 也可以通过配置 menus 调整菜单的顺序,参考【配置菜单】部分的文档
-		//editor.config.menus = editor.config.menus.concat(videoUpload);
+		editor.config.menus = editor.config.menus.concat(videoUpload);
+	},
+	/* 获取富文本中音视频相对路径 */
+	getRelativeSrcPath(richText) {
+		let videoSrcList = this.getRichTextSrc(richText, 'video')
+		let audioSrcList = this.getRichTextSrc(richText, 'audio')
+		let srcList = videoSrcList.concat(audioSrcList)
+		if (srcList.length) {
+			srcList.forEach(src => {
+				let withSas = src.split('/')[src.split('/').length - 1]
+				let j = withSas.lastIndexOf('?')
+				richText = richText.replaceAll(src, decodeURI(withSas.slice(0, j)));
+			})
+		}
+		return richText
+	},
+	/* 获取富文本中音视频完整路径 */
+	getMideaFullPath(richText, host, sas) {
+		let videoSrcList = this.getRichTextSrc(richText, 'video')
+		let audioSrcList = this.getRichTextSrc(richText, 'audio')
+		let srcList = videoSrcList.concat(audioSrcList)
+		if (srcList.length) {
+			srcList.forEach(src => {
+				let fullSrc = host + src + sas
+				richText = richText.replaceAll(`src="${src}"`, `src="${fullSrc}"`);
+			})
+		}
+		return richText
 	},
 	/* 移除上传的音视频富文本src中的HOST */
 	doRemoveMideaHost(exerciseItem) {
 		console.log('removeHost', exerciseItem.question)
-		let isSubjective = exerciseItem.type === 'complete' || exerciseItem.type === 'subjective' || exerciseItem
-			.type ===
-			'compose'
+		let isSubjective = exerciseItem.type === 'complete' || exerciseItem.type === 'subjective' || exerciseItem.type === 'compose'
 		let richTextObj = {
 			question: exerciseItem.question,
 			answer: Array.isArray(exerciseItem.answer) && exerciseItem.answer.length ? exerciseItem.answer[0] :
@@ -846,7 +891,7 @@ export default {
 						srcList.forEach(src => {
 							let withSas = src.split('/')[src.split('/').length - 1]
 							let j = withSas.lastIndexOf('?')
-							richTextObj[key] = richTextObj[key].replace(src, decodeURI(
+							richTextObj[key] = richTextObj[key].replaceAll(src, decodeURI(
 								withSas.slice(0, j)));
 						})
 						if (key === 'answer' && Array.isArray(exerciseItem.answer) && exerciseItem
@@ -896,13 +941,13 @@ export default {
 									let imgList = [];
 									let srcList = []
 									item.replace(srcReg, async (
-											match, capture
-											) => {
-											imgList.push(
-												match);
-											srcList.push(
-												capture)
-										});
+										match, capture
+									) => {
+										imgList.push(
+											match);
+										srcList.push(
+											capture)
+									});
 									// 如果富文本中有图片内容 则提取所有src的值
 									if (imgList.length) {
 										for (let j = 0; j < imgList
@@ -912,14 +957,14 @@ export default {
 											// 如果图片有被设置过宽高即有被拉伸过之后 则根据新的宽高来生成新的base64作为图片src
 											if (heightReg.test(
 												item) && widthReg
-												.test(item)) {
+													.test(item)) {
 												let srcHeight = ''
 												let srcWidth = ''
 												item.replace(
 													heightReg,
 													async (match,
 														capture
-														) => {
+													) => {
 														srcHeight
 															=
 															capture
@@ -928,17 +973,17 @@ export default {
 													widthReg,
 													async (match,
 														capture
-														) => {
+													) => {
 														srcWidth
 															=
 															capture
 													});
 												let newBase64 =
 													await this
-													.compressImg(
-														src,
-														srcWidth,
-														srcHeight)
+														.compressImg(
+															src,
+															srcWidth,
+															srcHeight)
 												item = item.replace(
 													src,
 													newBase64)
@@ -946,58 +991,58 @@ export default {
 											} else if (!heightReg
 												.test(item) &&
 												widthReg.test(item)
-												) {
+											) {
 												// 取到宽度的百分比
 												let srcWidth = ''
 												item.replace(
 													widthReg,
 													async (match,
 														capture
-														) => {
+													) => {
 														srcWidth
 															=
 															parseInt(
 																capture
-																)
+															)
 													});
 												let img =
-												new Image();
+													new Image();
 												img.src = src;
 												// 如果是宽度 则需要根据编辑器的宽度来计算出 拉伸后的高度和宽度
 												img.onload =
-											async () => {
-													let newWidth =
-														editorWidth
-														.optionWidth *
-														srcWidth *
-														0.01
-													let newHeight =
-														newWidth *
-														(img.height /
-															img
-															.width
-															)
-													let newBase64 =
-														await this
-														.compressImg(
-															src,
-															newWidth,
-															newHeight
+													async () => {
+														let newWidth =
+															editorWidth
+																.optionWidth *
+															srcWidth *
+															0.01
+														let newHeight =
+															newWidth *
+															(img.height /
+																img
+																	.width
 															)
-													item =
-														item
-														.replace(
-															src,
-															newBase64
-															)
-													r(item)
-												}
+														let newBase64 =
+															await this
+																.compressImg(
+																	src,
+																	newWidth,
+																	newHeight
+																)
+														item =
+															item
+																.replace(
+																	src,
+																	newBase64
+																)
+														r(item)
+													}
 											} else {
 												// 如果没有拉伸或者点击百分比显示 则按照原图进行压缩 宽高不变
 												let newBase64 =
 													await this
-													.compressImg(
-														src, 0, 0)
+														.compressImg(
+															src, 0, 0)
 												item = item.replace(
 													src,
 													newBase64)

+ 5 - 5
TEAMModelOS/ClientApp/src/utils/evTools.js

@@ -300,7 +300,7 @@ export default {
 								let blobUrl = src.includes(curHost) ? src.split('?')[0] : (curHost +  '/' + examContainer  + paperItem.blob +  '/' + src)
 								try{
 									let addSasUrl = await $tools.getFileSas(blobUrl)
-									richTextObj[key] = richTextObj[key].replace(`src="${ src }"`, `src="${ addSasUrl.url }"`);
+									richTextObj[key] = richTextObj[key].replaceAll(`src="${ src }"`, `src="${ addSasUrl.url }"`);
 								}catch(e){
 									j(500)
 								}
@@ -308,18 +308,18 @@ export default {
 								let blobUrl = src.includes(curHost) ? src.split('?')[0] : (curHost +  '/'  + container + '/paper/' + paperItem.name + '/' + src)
 								try{
 									let addSasUrl = await $tools.getFileSas(blobUrl)
-									richTextObj[key] = richTextObj[key].replace(`src="${ src }"`, `src="${ addSasUrl.url }"`);
+									richTextObj[key] = richTextObj[key].replaceAll(`src="${ src }"`, `src="${ addSasUrl.url }"`);
 								}catch(e){
 									j(500)
 								}
 							}else if(nodeId){
 								// 如果是在课纲读取课纲目录下的试题
-								let srcPath = exerciseItem.blob.replace(`${exerciseItem.id}.json`,'').split('?')[0]
+								let srcPath = exerciseItem.blob.replaceAll(`${exerciseItem.id}.json`,'').split('?')[0]
 								let blobUrl = exerciseItem.blob.includes(curHost) ? (srcPath + src) : (curHost + '/' + container +  srcPath + src)
 								// debugger;
 								try{
 									let addSasUrl = await $tools.getFileSas(blobUrl)
-									richTextObj[key] = richTextObj[key].replace(`src="${ src }"`, `src="${ addSasUrl.url }"`);
+									richTextObj[key] = richTextObj[key].replaceAll(`src="${ src }"`, `src="${ addSasUrl.url }"`);
 								}catch(e){
 									j(500)
 								}
@@ -327,7 +327,7 @@ export default {
 								let blobUrl = src.includes(curHost) ? src.split('?')[0] : (curHost +  '/'  + container + '/item/' + exerciseItem.id + '/' + src)
 								try{
 									let addSasUrl = await $tools.getFileSas(blobUrl)
-									richTextObj[key] = richTextObj[key].replace(`src="${ src }"`, `src="${ addSasUrl.url }"`);
+									richTextObj[key] = richTextObj[key].replaceAll(`src="${ src }"`, `src="${ addSasUrl.url }"`);
 								}catch(e){
 									j(500)
 								}

+ 49 - 1
TEAMModelOS/ClientApp/src/utils/js-fn.js

@@ -3,6 +3,8 @@ import store from '@/store'
 import {
     app
 } from '@/boot-app.js'
+import _tools from "./public.js"
+import _editorTools from "./editorTools.js"
 /*
  * 根据某个属性进行分组
  */
@@ -216,6 +218,7 @@ function timeFormat(timestamp) {
     return `${Y}/${M < 9 ? '0' + (M + 1) : M + 1}/${D} ${H < 10 ? '0' + H : H}:${MIN < 10 ? '00' : MIN}`
 }
 function dateFormat(timestamp) {
+    if (timestamp <= 0) return ''
     timestamp = timestamp < 10000000000 ? timestamp * 1000 : timestamp
     let date = new Date(timestamp)
     let Y = date.getFullYear()
@@ -364,6 +367,49 @@ function checkJinNiu() {
     let host = window.location.host
     return host == 'jinniu.teammodel.cn'
 }
+//根据域名判断菜单是否显示
+function checkTrain() {
+    let host = window.location.host
+    return host == 'scyx.teammodel.cn'
+}
+/**
+ * 统一处理学生作答数据
+ * @param {string} fullUrl ans.json完成路径含授权
+ * @param {string} richPrefix 富文本前缀(到stuId)
+ * @param {string} sas 授权(不需要“?”)
+ */
+function handleStudentAnswer(fullUrl, richPrefix, sas) {
+    return new Promise(async (r, j) => {
+        try {
+            let ansStr = await _tools.getFile(fullUrl)
+            if (ansStr) {
+                let ans = JSON.parse(ansStr)
+                ans.forEach((item, index) => {
+                    // 数据异常
+                    if (!item) {
+                        ans[index] = [app.$t('learnActivity.score.ansErr')]
+                    }
+                    // 未作答
+                    else if (!item.length) {
+                        ans[index] = [app.$t('learnActivity.score.noStuAns')]
+                    }
+                    // 处理富文本中多媒体
+                    else {
+                        item.forEach((as, ai) => {
+                            item[ai] = _editorTools.getMideaFullPath(as, richPrefix + '/', '?' + sas)
+                        })
+                        ans[index] = item
+                    }
+                })
+                r(ans)
+            } else {
+                r([])
+            }
+        } catch (e) {
+            r([])
+        }
+    })
+}
 
 export default {
     groupBy,
@@ -385,5 +431,7 @@ export default {
     dateFormat,
     timeFormat,
     getTeacherSubjects,
-    checkJinNiu
+    checkJinNiu,
+    checkTrain,
+    handleStudentAnswer
 }

+ 6 - 0
TEAMModelOS/ClientApp/src/utils/public.js

@@ -691,6 +691,11 @@ export default {
 				k]).substr(('' + o[k]).length)))
 		return fmt
 	},
+	/* 检测是否为移动端 */
+	isMobile() {
+		let flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
+		return flag;
+	},
 	/* 字节格式转换 */
 	bytesToSize(bytes) {
 		if (bytes === 0) return '0 B';
@@ -1059,6 +1064,7 @@ export default {
 					console.error(url)
 					var img = new Image();
 					img.src = url
+					img.setAttribute('crossOrigin', 'anonymous')
 					img.onload = function () {
 						var canvas = document.createElement("canvas");
 						canvas.width = img.width;

+ 0 - 0
TEAMModelOS/ClientApp/src/view/Home.vue


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor