CrazyIter_Bin 2 gadi atpakaļ
vecāks
revīzija
0ca655b2f4
100 mainītis faili ar 57247 papildinājumiem un 2538 dzēšanām
  1. 5 5
      TEAMModelAPI/Controllers/Business/CourseController.cs
  2. 1 1
      TEAMModelAPI/Controllers/Business/ExamController.cs
  3. 8 8
      TEAMModelAPI/Controllers/Business/GroupListController.cs
  4. 3 3
      TEAMModelAPI/Controllers/Business/RoomController.cs
  5. 2 2
      TEAMModelAPI/Controllers/Business/SchoolController.cs
  6. 1 1
      TEAMModelBI/ClientApp/package.json
  7. 1 1
      TEAMModelBI/ClientApp/public/index.html
  8. 82 6
      TEAMModelBI/ClientApp/src/api/index.js
  9. BIN
      TEAMModelBI/ClientApp/src/assets/img/backtop.png
  10. 54 13
      TEAMModelBI/ClientApp/src/components/AbilityTree.vue
  11. 83 0
      TEAMModelBI/ClientApp/src/components/echarts/Xline.vue
  12. 0 1
      TEAMModelBI/ClientApp/src/components/echarts/commonLine.vue
  13. 1 1
      TEAMModelBI/ClientApp/src/components/echarts/conventionPie.vue
  14. 3 1
      TEAMModelBI/ClientApp/src/main.js
  15. 41 1
      TEAMModelBI/ClientApp/src/router/index.js
  16. 37 29
      TEAMModelBI/ClientApp/src/static/regions/region_cn.json
  17. 18 30
      TEAMModelBI/ClientApp/src/static/regions/region_gl.json
  18. 5 0
      TEAMModelBI/ClientApp/src/store/index.js
  19. 47 1
      TEAMModelBI/ClientApp/src/until/common.js
  20. 5 1
      TEAMModelBI/ClientApp/src/until/http.js
  21. 84 44
      TEAMModelBI/ClientApp/src/view/areaServe/areamanage.vue
  22. 276 10
      TEAMModelBI/ClientApp/src/view/areaServe/setthird.vue
  23. 1 1
      TEAMModelBI/ClientApp/src/view/areaServe/thirdparty.vue
  24. 419 198
      TEAMModelBI/ClientApp/src/view/areamanage/statistics.vue
  25. 31 11
      TEAMModelBI/ClientApp/src/view/common/aside.vue
  26. 307 82
      TEAMModelBI/ClientApp/src/view/created/created.vue
  27. 31 24
      TEAMModelBI/ClientApp/src/view/index/index.vue
  28. 2 2
      TEAMModelBI/ClientApp/src/view/index/operateLog.vue
  29. 42850 0
      TEAMModelBI/ClientApp/src/view/index/test.json
  30. 167 0
      TEAMModelBI/ClientApp/src/view/index/test.vue
  31. 3 0
      TEAMModelBI/ClientApp/src/view/login.vue
  32. 294 0
      TEAMModelBI/ClientApp/src/view/participation/copy.vue
  33. 198 11
      TEAMModelBI/ClientApp/src/view/participation/examination.vue
  34. 440 162
      TEAMModelBI/ClientApp/src/view/participation/index.vue
  35. 829 0
      TEAMModelBI/ClientApp/src/view/participation/paper.vue
  36. 189 27
      TEAMModelBI/ClientApp/src/view/participation/setAbility.vue
  37. 72 5
      TEAMModelBI/ClientApp/src/view/participation/setPhase.vue
  38. 1135 0
      TEAMModelBI/ClientApp/src/view/product/details.vue
  39. 574 0
      TEAMModelBI/ClientApp/src/view/product/index.vue
  40. 80 0
      TEAMModelBI/ClientApp/src/view/resultpage.vue
  41. 802 271
      TEAMModelBI/ClientApp/src/view/schoolServe/school.vue
  42. 71 29
      TEAMModelBI/ClientApp/src/view/schoolServe/setSchooladmin.vue
  43. 41 16
      TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue
  44. 15 15
      TEAMModelBI/ClientApp/src/view/schoolmanage/index.vue
  45. 594 176
      TEAMModelBI/ClientApp/src/view/schoolmanage/schoolAnalyse.vue
  46. 10 8
      TEAMModelBI/ClientApp/src/view/schoolmanage/schoolManege.vue
  47. 294 134
      TEAMModelBI/ClientApp/src/view/systemConfig/correlation.vue
  48. 225 86
      TEAMModelBI/ClientApp/src/view/systemConfig/manageschool.vue
  49. 36 37
      TEAMModelBI/ClientApp/src/view/systemConfig/operate.vue
  50. 1478 0
      TEAMModelBI/ClientApp/src/view/systemConfig/pushmsg/createdpush.vue
  51. 441 0
      TEAMModelBI/ClientApp/src/view/systemConfig/pushmsg/index.vue
  52. 16 4
      TEAMModelBI/ClientApp/src/view/systemConfig/setAdmin.vue
  53. 77 11
      TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue
  54. 2 2
      TEAMModelBI/ClientApp/src/view/teachermanage/school.vue
  55. 44 15
      TEAMModelBI/ClientApp/src/view/teachermanage/traitmanage.vue
  56. 1 0
      TEAMModelBI/Controllers/BIBlob/AnalyseFileController.cs
  57. 275 0
      TEAMModelBI/Controllers/BICommon/BINoticeController.cs
  58. 106 0
      TEAMModelBI/Controllers/BICommon/BIProductUseRecordController.cs
  59. 100 0
      TEAMModelBI/Controllers/BICommon/StatsNoticeController.cs
  60. 6 6
      TEAMModelBI/Controllers/BIHome/HomeStatisController.cs
  61. 6 0
      TEAMModelBI/Controllers/BIHome/OnLineController.cs
  62. 10 20
      TEAMModelBI/Controllers/BINormal/AreaRelevantController.cs
  63. 25 60
      TEAMModelBI/Controllers/BINormal/BatchAreaController.cs
  64. 2 2
      TEAMModelBI/Controllers/BINormal/BusinessConfigController.cs
  65. 101 32
      TEAMModelBI/Controllers/BINormal/BusinessUsersController.cs
  66. 323 164
      TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs
  67. 141 214
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  68. 30 10
      TEAMModelBI/Controllers/BIServer/BiServersController.cs
  69. 131 2
      TEAMModelBI/Controllers/BISystem/CoreController.cs
  70. 374 28
      TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs
  71. 2 2
      TEAMModelBI/Controllers/BITest/Ies5TestController.cs
  72. 413 151
      TEAMModelBI/Controllers/BITest/TestController.cs
  73. 5 28
      TEAMModelBI/Controllers/Census/ActivitySticsController.cs
  74. 1 1
      TEAMModelBI/Controllers/Census/BlobLogController.cs
  75. 2 1
      TEAMModelBI/Controllers/Census/ItemSticsController.cs
  76. 1 1
      TEAMModelBI/Controllers/Census/LessonSticsController.cs
  77. 111 73
      TEAMModelBI/Controllers/Census/PaperController.cs
  78. 1 0
      TEAMModelBI/Controllers/Census/ProductStatisController.cs
  79. 959 26
      TEAMModelBI/Controllers/Census/SchoolController.cs
  80. 12 4
      TEAMModelBI/Controllers/LoginController.cs
  81. 3 29
      TEAMModelBI/Controllers/RepairApi/InitialAreaController.cs
  82. 94 0
      TEAMModelBI/Controllers/RepairApi/NormalController.cs
  83. 573 0
      TEAMModelBI/Controllers/RepairApi/SchoolRepController.cs
  84. 16 16
      TEAMModelBI/JsonFile/Preset/LangSchoolConfig.json
  85. 6 0
      TEAMModelBI/LogLang/en-us.json
  86. 4 1
      TEAMModelBI/LogLang/zh-cn.json
  87. 6 0
      TEAMModelBI/LogLang/zh-tw.json
  88. 0 1
      TEAMModelBI/Models/AssistSchool.cs
  89. 44 0
      TEAMModelBI/Models/ForeEndModel.cs
  90. 33 0
      TEAMModelBI/Models/RearEndMiddle.cs
  91. 11 5
      TEAMModelBI/Startup.cs
  92. 13 6
      TEAMModelBI/TEAMModelBI.csproj
  93. 19 10
      TEAMModelBI/Tool/CommonFind.cs
  94. 40 27
      TEAMModelBI/Tool/CosmosBank/ActivityWay.cs
  95. 1 1
      TEAMModelBI/Tool/CosmosBank/JointlySingleQuery.cs
  96. 172 117
      TEAMModelBI/Tool/CosmosBank/SchoolWay.cs
  97. 496 0
      TEAMModelBI/Tool/CosmosBank/StatsWay.cs
  98. 47 12
      TEAMModelBI/Tool/TimeHelper.cs
  99. 6 2
      TEAMModelOS.FunctionV4/CosmosDB/CommonTrigger.cs
  100. 0 0
      TEAMModelOS.FunctionV4/CosmosDB/TriggerArt.cs

+ 5 - 5
TEAMModelAPI/Controllers/Business/CourseController.cs

@@ -58,7 +58,7 @@ namespace TEAMModelAPI.Controllers
         }
         [ProducesDefaultResponseType]
         [HttpPost("get-course-list")]
-        [ApiToken(Auth = "1301", Name = "获取课程列表信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1301", Name = "获取课程列表信息", RWN = "R", Limit = false)]
         public async Task<IActionResult> GetCourseList(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -85,7 +85,7 @@ namespace TEAMModelAPI.Controllers
 
         [ProducesDefaultResponseType]
         [HttpPost("get-course-info")]
-        [ApiToken(Auth = "1302", Name = "课程详细信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1302", Name = "课程详细信息", RWN = "R", Limit = false)]
         public async Task<IActionResult> GetCourseInfo(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -111,7 +111,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-period-timetable")]
-        [ApiToken(Auth = "1303", Name = "试卷和评测的条件信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1303", Name = "试卷和评测的条件信息", RWN = "R", Limit = false)]
         public async Task<IActionResult> GetPaperExamCondition(JsonElement json)
         {
             json.TryGetProperty("periodId", out JsonElement _periodId);
@@ -132,7 +132,7 @@ namespace TEAMModelAPI.Controllers
 
         [ProducesDefaultResponseType]
         [HttpPost("upsert-course-infos")]
-        [ApiToken(Auth = "1304", Name = "课程详细信息", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1304", Name = "课程详细信息", RWN = "W", Limit = false)]
         public async Task<IActionResult> UpsertCourseInfo(CourseDtoImpt json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -244,7 +244,7 @@ namespace TEAMModelAPI.Controllers
         
         [ProducesDefaultResponseType]
         [HttpPost("upsert-course-schedule")]
-        [ApiToken(Auth = "1305", Name = "更新课程的排课信息", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1305", Name = "更新课程的排课信息", RWN = "W", Limit = false)]
         public async Task<IActionResult> UpsertCourseSchedule(ImportCourseDto json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();

+ 1 - 1
TEAMModelAPI/Controllers/Business/ExamController.cs

@@ -60,7 +60,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-paper-exam-condition")]
-        [ApiToken(Auth = "1101", Name = "试卷和评测的条件信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1101", Name = "试卷和评测的条件信息", RWN = "R", Limit = false)]
         public async Task<IActionResult> GetPaperExamCondition(JsonElement json)
         {
             json.TryGetProperty("periodId", out JsonElement _periodId);

+ 8 - 8
TEAMModelAPI/Controllers/Business/GroupListController.cs

@@ -63,7 +63,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-group-list")]
-        [ApiToken(Auth = "1201", Name = "学校名单列表", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1201", Name = "学校名单列表", RWN = "R", Limit = false)]
         public async Task<IActionResult> GetGroupList(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -159,7 +159,7 @@ namespace TEAMModelAPI.Controllers
         }
         [ProducesDefaultResponseType]
         [HttpPost("get-group-members")]
-        [ApiToken(Auth = "1202", Name = "获取名单详细信息和成员信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1202", Name = "获取名单详细信息和成员信息", RWN = "R", Limit = false)]
         public async Task<IActionResult> GetGroupMembers(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -176,7 +176,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("import-class-members")]
-        [ApiToken(Auth = "1203", Name = "导入行政班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1203", Name = "导入行政班学生", RWN = "W", Limit = false)]
         public async Task<IActionResult> ImportClassMembers(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -211,7 +211,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("update-class-members")]
-        [ApiToken(Auth = "1204", Name = "更新行政班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1204", Name = "更新行政班学生", RWN = "W", Limit = false)]
         public async Task<IActionResult> UpdateClassMembers(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -248,7 +248,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("remove-class-members")]
-        [ApiToken(Auth = "1205", Name = "移除行政班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1205", Name = "移除行政班学生", RWN = "W", Limit = false)]
         public async Task<IActionResult> RemoveClassMembers(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -290,7 +290,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("upsert-teach-groups")]
-        [ApiToken(Auth = "1206", Name = "创建或更新教学班", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1206", Name = "创建或更新教学班", RWN = "W", Limit = false)]
         public async Task<IActionResult> UpsertTeachGroups(GroupListDtoImpt json) {
             var (_, school) = HttpContext.GetApiTokenInfo();
             var groupListsDto = json.groupLists;
@@ -378,7 +378,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("import-teach-members")]
-        [ApiToken(Auth = "1207", Name = "导入教学班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1207", Name = "导入教学班学生", RWN    = "W", Limit = false)]
         public async Task<IActionResult> ImportTeachMembers(MemberImpt json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -447,7 +447,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("remove-teach-members")]
-        [ApiToken(Auth = "1208", Name = "移除教学班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1208", Name = "移除教学班学生", RWN = "W", Limit = false)]
         public async Task<IActionResult> RemoveTeachMembers(JsonElement json) {
             var (id, school) = HttpContext.GetApiTokenInfo();
             json.TryGetProperty("stuids", out JsonElement _stuids);

+ 3 - 3
TEAMModelAPI/Controllers/Business/RoomController.cs

@@ -57,7 +57,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-room-list")]
-        [ApiToken(Auth = "1401", Name = "获取物理教室列表", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1401", Name = "获取物理教室列表", RWN= "R", Limit = false)]
         public async Task<IActionResult> GetRoomList(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -88,7 +88,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-room-info")]
-        [ApiToken(Auth = "1402", Name = "获取物理教室详细信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1402", Name = "获取物理教室详细信息", RWN= "R", Limit = false)]
         public async Task<IActionResult> GetRoomInfo(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -120,7 +120,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("upsert-room-infos")]
-        [ApiToken(Auth = "1403", Name = "创建或更新教学班", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1403", Name = "创建或更新教学班", RWN= "W", Limit = false)]
         public async Task<IActionResult> UpsertRoomInfo(RoomsDto json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();

+ 2 - 2
TEAMModelAPI/Controllers/Business/SchoolController.cs

@@ -59,7 +59,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-schools")]
-        [ApiToken(Auth = "1000", Name = "合作商获取可访问的学校列表", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1000", Name = "合作商获取可访问的学校列表", RWN= "R", Limit = false)]
         public async Task<IActionResult> GetSchools() {
             var (id, _) = HttpContext.GetApiTokenInfo();
             var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOpenApi");
@@ -73,7 +73,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-school-info")]
-        [ApiToken(Auth = "1001",Name = "学校基础信息", RW = "R", Limit =false)]
+        [ApiToken(Auth = "1001",Name = "学校基础信息", RWN= "R", Limit =false)]
         public async Task<IActionResult> GetSchoolInfo()
         {
             var (id, school) = HttpContext.GetApiTokenInfo();

+ 1 - 1
TEAMModelBI/ClientApp/package.json

@@ -20,7 +20,7 @@
         "echarts": "^5.2.2",
         "echarts-liquidfill": "^3.1.0",
         "el-plus-powerful-table-ts": "^1.0.5",
-        "element-plus": "^1.1.0-beta.24",
+        "element-plus": "^2.2.22",
         "elui-china-area-dht": "^1.0.4",
         "file-saver": "^2.0.5",
         "jwt-decode": "^3.1.2",

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

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

+ 82 - 6
TEAMModelBI/ClientApp/src/api/index.js

@@ -53,6 +53,10 @@ export default {
     setisAdmin(data) {
         return post('/tabledd/set-backend', data)
     },
+    //同步某个人员信息  已完善 V2.0
+    updateAlone(data) {
+        return post('/tabledd/set-usettmdinfo', data)
+    },
     //为用户设置关联学校或删除
     setAistschool(data) {
         return post('/schoolcheck/set-aistschool', data)
@@ -113,8 +117,12 @@ export default {
         return post('/batcharea/cut-full-statndard', data)
     },
     //获取未加入区域的学校
+    // getNotjoinSchool(data) {
+    //     return post('/schoolcheck/get-notarea', data)
+    // },
+    //未加入学区 新API
     getNotjoinSchool(data) {
-        return post('/schoolcheck/get-notarea', data)
+        return post('/schoolcheck/get-nojoinsc', data)
     },
     //获取目前区域内拥有的学校
     getForareaSchool(data) {
@@ -155,11 +163,15 @@ export default {
     getSchooldata(data) {
         return post('/batchschool/get-schoolsinfo', data)
     },
+    //获取所有学校信息 V2.0
+    getSchool(data) {
+        return post('/school/get-scinfos', data)
+    },
     //进入学校管理,获取所有顾问列表(目前是说去  研发中心B)(也可替代其他 组织架构,一层人员的获取。)
     getAllassist(data) {
         return post('/dd/get-tmdandddusers', data)
     },
-    //对学校编辑提交更改 ***   Headers[x-auth-authtoken]   接口已对接
+    //对学校编辑提交更改 ***   Headers[x-auth-authtoken]   接口已对接  已完善V2.0
     updateSchoolinfo(data) {
         return post('/batchschool/upd-schoolassist', data)
     },
@@ -199,6 +211,10 @@ export default {
     getsimpleSchool(data) {
         return post('/schoolcheck/get-scsimple', data)
     },
+    //获取所有学校(所有)
+    getallSchool(data) {
+        return post('/batchschool/get-allscinfo', data)
+    },
 
     //首页dashboard数据接口
     //获取各城市的学校数量(bar)
@@ -389,7 +405,26 @@ export default {
     getGradeandSubjects(data) {
         return post('/schoolcheck/get-ratio', data)
     },
-
+    //获取所有学区的数据 V2.1
+    getAllarea(data) {
+        return post('/school/get-allscstats ', data)
+    },
+    //获取某个学区内的数据 V2.1
+    getoneselfArea(data) {
+        return post('/school/get-areastats', data)
+    },
+    //获取所有学校数据 (区校掌握-学校情况)V2.1
+    acquireAllschool(data) {
+        return post('/school/get-rolestats', data)
+    },
+    //获取某个学校的详细信息 V2.1
+    schooloneDetails(data) {
+        return post('/school/get-scstats', data)
+    },
+    //获取某个学校的资源数和课堂数量
+    classroomDatas(data) {
+        return post('/school/get-leseoncnt', data)
+    },
 
 
     //顾问使用(我参与的)
@@ -405,7 +440,36 @@ export default {
     getExaminations(data) {
         return post('/paper/get-list', data)
     },
+    //根据不同学校获取 相应的sas
+    getSchoolsas(data) {
+        return post('/biservers/get-cntrkey', data)
+    },
+    //访问试卷信息
+    getExamintionpaper(url) {
+        return fetch(url, '')
+    },
+    //获取所有学校进行筛选(试卷拷贝功能)
+    getschoolIntegration(data) {
+        return post('/schoolcheck/get-schools', data)
+    },
+    //拷贝试卷
+    copypaperTo(data) {
+        return post('/paper/copy-infos', data)
+    },
 
+
+    //消息通知(端外通知)
+    informSearch(data) {
+        return post('/notice/get-info', data)
+    },
+    //发送端外通知(消息通知)
+    sendMsgs(data) {
+        return post('notice/push-info', data)
+    },
+    //获取消息列表
+    getMsglist(data) {
+        return post('/notice/get-infos', data)
+    },
     //第三方相关API(BI)
     //创建or保存 第三方信息
     // setThirdparty(data) {
@@ -453,6 +517,18 @@ export default {
     getschoolCorrelation(data) {
         return post('/bizconfig/get-schools', data)
     },
+    //根据企业ID获取 用户列表
+    getUserarr(data) {
+        return post('/bizuser/get-bizid', data)
+    },
+    //根据手机号查询企业用户
+    searchphoneUser(data) {
+        return post('/bizuser/get-mobileuser', data)
+    },
+    //关联用户到企业
+    getCorrelationUser(data) {
+        return post('/bizuser/rel-biz', data)
+    },
 
 
     //获取地址location
@@ -464,12 +540,12 @@ export default {
         return fetch('https://devapi.qweather.com/v7/weather/now?location=' + location + '&key=' + key)
     },
 
-    //创建学校 BB验证数据,以及BB搜索学校信息
+    //创建学校 BB验证数据,以及BB搜索学校信息s
     verifyDatainbb(data) {
-        return post('https://bb-rc.teammodel.net/ies5/search-cs-school', data)
+        return post('https://bb.teammodel.net/ies5/search-cs-school', data)
     },
     //创建学校成功,数据回传BB
     successBack(data) {
-        return post('https://bb-rc.teammodel.net/ies5/create-cs-school', data)
+        return post('https://bb.teammodel.net/ies5/create-cs-school ', data)
     }
 }

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


+ 54 - 13
TEAMModelBI/ClientApp/src/components/AbilityTree.vue

@@ -9,7 +9,7 @@
           </svg>
         </div>
       </div>
-      <el-tree ref='treeRef' :data="tree" :props="defaultProps" node-key="id" :highlight-current="true" :current-node-key="pitchNow" default-expand-all :expand-on-click-node="false" :render-content="renderContent" @node-click="handleNodeClick" />
+      <el-tree ref='treeRef' :data="tree" :props="defaultProps" node-key="id" :highlight-current="true" :current-node-key="pitchNow" default-expand-all :expand-on-click-node="false" :render-content="treeShows ? renderContent:inoperableRender" @node-click="handleNodeClick" />
     </div>
     <div class="right-box">
       <div class="resource">
@@ -17,13 +17,13 @@
         <div class="changebtn" v-show="uploadList.length !==0" @click="changes">
           <el-button type="primary" size="small ">{{$t(`schoolManages.gradSet.save`)}}</el-button>
         </div>
-        <div class="resourceadd-box" v-if="PowerShow.roles.includes('admin')">
+        <div class="resourceadd-box" v-if="PowerShow.roles.includes('admin') && treeShows">
           <el-dropdown>
             <span class="el-dropdown-link">
               {{$t(`abilityManages.addresource`)}}
-              <el-icon class="el-icon--right">
+              <!-- <el-icon class="el-icon--right">
                 <arrow-down />
-              </el-icon>
+              </el-icon> -->
             </span>
             <template #dropdown>
               <el-dropdown-menu>
@@ -54,7 +54,7 @@
 									<Icon type="md-eye" />
 									<span>{{ $t('syllabus.preview') }}</span>
 								</div> -->
-            <div class="resource-tool" @click="deleteResource(item,index)">
+            <div class="resource-tool" @click="deleteResource(item,index)" v-show="treeShows">
               <i class="el-icon-delete-solid"></i>
               <span>删除</span>
             </div>
@@ -158,6 +158,7 @@ export default {
   setup (props, context) {
     let curNode = ref(null)
     let PowerShow = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
+    let treeShows = ref(true)
     const store = useStore()
     let { proxy } = getCurrentInstance()
     let defaultProps = {
@@ -278,14 +279,12 @@ export default {
           {
             class: 'tree-node-tools',
           },
-          h(
-            'a',
-            {
-              onClick: (e) => {
-                e.stopPropagation()
-                append(data)
-              },
+          h('a', {
+            onClick: (e) => {
+              e.stopPropagation()
+              append(data)
             },
+          },
             <i class="el-icon-plus"></i>
           ),
           h(
@@ -298,6 +297,44 @@ export default {
         )
       )
     }
+    function inoperableRender (h, { node, data }) {
+      return h(
+        'span',
+        {
+          class: 'custom-tree-node',
+          title: data.title,
+        },
+        h('span', null, data.title),
+        h(
+          'i',
+          data.rnodes && data.rnodes.length ? { class: 'tree-icon' } : { class: 'tree-none' },
+          <svg class="treeResource" aria-hidden="true">
+            <use xlink:href="#icon-ziyuan"></use>
+          </svg>
+        ),
+        h(
+          'span',
+          {
+            class: 'tree-node-tools',
+          },
+          // h('a', {
+          //   onClick: (e) => {
+          //     e.stopPropagation()
+          //     append(data)
+          //   },
+          // },
+          //   <i class="el-icon-plus"></i>
+          // ),
+          // h(
+          //   'a',
+          //   {
+          //     onClick: () => remove(node, data),
+          //   },
+          //   <i class="el-icon-minus"></i>
+          // )
+        )
+      )
+    }
     function getSuffix (name) {
       return name.substr(name.lastIndexOf('.') + 1)
     }
@@ -552,6 +589,7 @@ export default {
             fileList.value.id = nweProps.defaultinfo
             // curNode.value = nweProps.tree[0].rnodes
             console.log(nweProps)
+            nweProps.areaId === "bde5c011-2ae4-461a-b46c-5483ba72ae45" ? treeShows.value = false : treeShows.value = true
             nweProps.tree.length !== 0 && nweProps.tree[0].rnodes ? (curNode.value = nweProps.tree[0].rnodes) : (curNode.value = [])
           }
         })
@@ -598,7 +636,9 @@ export default {
       videobox,
       srcList,
       users,
-      PowerShow
+      PowerShow,
+      treeShows,
+      inoperableRender
     }
   },
 }
@@ -692,6 +732,7 @@ export default {
   border: 1px dashed #ccc;
   border-radius: 5px;
   padding: 5px;
+  padding-top: 10px;
 }
 .chapter::before,
 .resource::before {

+ 83 - 0
TEAMModelBI/ClientApp/src/components/echarts/Xline.vue

@@ -0,0 +1,83 @@
+<template>
+  <div ref="myEcharts" :style="{ height, width }"></div>
+</template>
+<script>
+import { ref, onMounted, nextTick, watch, getCurrentInstance } from 'vue'
+import * as echarts from 'echarts'
+export default {
+  props: {
+    width: {
+      type: String,
+      default: '100%',
+    },
+    height: {
+      type: String,
+      default: '100%',
+    },
+    lineData: {
+      type: Array,
+      default: () => { },
+    },
+    title: {
+      type: String,
+      default: '',
+    },
+  },
+  setup (props) {
+    const myEcharts = ref(null)
+    let { proxy } = getCurrentInstance()
+    const chart = new InitChart(props, myEcharts)
+    onMounted(() => {
+      chart.init(props.lineData, proxy)
+    })
+    watch(
+      props,
+      (nweProps) => {
+        nextTick(() => {
+          nweProps ? chart.init(props.lineData, proxy) : ''
+        })
+      },
+      { immediate: true, deep: true }
+    )
+    return {
+      myEcharts,
+    }
+  },
+}
+class InitChart {
+  constructor(props, myEcharts) {
+    this.props = props
+    this.myEcharts = myEcharts
+    this.state = {
+      chart: null,
+    }
+  }
+  init (datas, proxy) {
+    console.log(datas, 'Xline调用')
+    this.state.chart && this.destory()
+    this.state.chart = echarts.init(this.myEcharts.value)
+    this.state.chart.setOption({
+      title: datas.title ? datas.title : {},
+      backgroundColor: datas.backgroundColor ? datas.backgroundColor : '',
+      grid: datas.grid ? datas.grid : '',
+      // legend: datas.legend ? datas.legend : {},
+      xAxis: datas.xAxis ? datas.xAxis : {},
+      yAxis: datas.yAxis ? datas.yAxis : {},
+      dataZoom: datas.dataZoom ? datas.dataZoom : '',
+      series: datas.series ? datas.series : [],
+    })
+    window.addEventListener('resize', () => {
+      this.state.chart.resize()
+    })
+  }
+  destory () {
+    this.state.chart.dispose()
+    window.removeEventListener('resize', () => {
+      console.log('事件移除')
+    })
+  }
+}
+</script>
+<style lang="less">
+</style>
+

+ 0 - 1
TEAMModelBI/ClientApp/src/components/echarts/commonLine.vue

@@ -59,7 +59,6 @@ class InitChart {
     this.state.chart.setOption({
       title: datas.title ? datas.title : {},
       backgroundColor: datas.backgroundColor ? datas.backgroundColor : '',
-
       grid: datas.grid ? datas.grid : '',
       legend: datas.legend ? datas.legend : {},
       tooltip: {

+ 1 - 1
TEAMModelBI/ClientApp/src/components/echarts/conventionPie.vue

@@ -64,7 +64,7 @@ class InitChart {
       legend: datas.legend ? datas.legend : '',
       tooltip: {
         trigger: 'item',
-        formatter: '{a} <br/>{b}: {c} ({d}%)',
+        formatter: '{a} <br/>{b}: {c}({d}%)',
       },
       series: datas.series ? datas.series : '',
     })

+ 3 - 1
TEAMModelBI/ClientApp/src/main.js

@@ -15,13 +15,15 @@ import Export2Excel from "@/until/excel/Export2Excel";
 import i18n from './language/i18n'
 import CScrollbar from 'c-scrollbar';
 import PersonalPhoto from './components/public/personalPhoto/index.vue'
+import zhCn from "element-plus/lib/locale/lang/zh-cn";
+import 'dayjs/locale/zh-cn';
 
 const app = createApp(App)
 app.config.globalProperties.$api = axios
 app.config.globalProperties.$access = inspect
 app.config.globalProperties.$common = common
 app.use(router)
-app.use(ElementPlus)
+app.use(ElementPlus, { locale: zhCn })
 app.use(store)
 app.use(powerfulTable)
 app.use(ElIcon)

+ 41 - 1
TEAMModelBI/ClientApp/src/router/index.js

@@ -11,6 +11,12 @@ const routes = [{
         roles: "all",
         component: () => require.ensure([], (require) => require(`@/view/login.vue`))
     },
+    {
+        path: "/test",
+        name: "test",
+        roles: "all",
+        component: () => require.ensure([], (require) => require(`@/view/index/test.vue`))
+    },
     // {
     //     path: "/dashboard",
     //     name: "dashboard",
@@ -46,6 +52,15 @@ const routes = [{
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/teachermanage/manage.vue`))
             },
+            //产品分析
+            {
+                name: "analysis",
+                path: "analysis",
+                permission: "teacher-read|teacher-upd",
+                roles: ['admin'],
+                isShow: true,
+                component: () => require.ensure([], (require) => require(`@/view/product/index.vue`))
+            },
             //区校管理(学区管理)--研发部
             {
                 name: "areaManagement",
@@ -109,6 +124,7 @@ const routes = [{
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/index/operateLog.vue`))
             },
+            //api查看
             {
                 name: "apistatistics",
                 path: "apistatistics",
@@ -117,6 +133,24 @@ const routes = [{
                 isShow: true,
                 component: () => require.ensure([], (require) => require(`@/view/systemConfig/apimanage.vue`))
             },
+            //消息推送模块
+            {
+                name: 'pushmsg',
+                path: 'pushmsg',
+                permission: "",
+                roles: ['admin'],
+                isShow: true,
+                component: () => require.ensure([], (require) => require(`@/view/systemConfig/pushmsg/index.vue`))
+            },
+            //创建消息推送页面
+            {
+                name: 'createdpush',
+                path: 'createdpush',
+                permission: "",
+                roles: ['admin'],
+                isShow: true,
+                component: () => require.ensure([], (require) => require(`@/view/systemConfig/pushmsg/createdpush.vue`))
+            },
             //单个学校数据统计
             {
                 name: "analyse",
@@ -182,6 +216,12 @@ const routes = [{
             },
         ]
     },
+    //消息通知跳转页面
+    {
+        path: "/resultPage",
+        name: "resultPage",
+        component: () => require.ensure([], (require) => require(`@/view/resultpage.vue`))
+    },
     {
         path: "/404",
         name: "404",
@@ -214,7 +254,7 @@ const router = createRouter({
 });
 router.beforeEach((to, from, next) => {
     console.log(to, 'router')
-    if (to.path === '/login') return next()
+    if (to.path === '/login' || to.path === '/resultPage') return next()
     if (to.path === '/login-thirdparty') return next()
     let thirdUser = localStorage.getItem('thirdUser')
     if (to.path === '/thirdpartys' && thirdUser) return next()

+ 37 - 29
TEAMModelBI/ClientApp/src/static/regions/region_cn.json

@@ -11107,62 +11107,70 @@
 	"code": "810000",
 	"name": "香港特别行政区",
 	"children": [{
-		"code": "810100",
-		"name": "直辖市",
+		"code": "810300",
+		"name": "香港岛区",
 		"children": [{
 			"code": "810101",
 			"name": "中西区"
 		}, {
 			"code": "810102",
 			"name": "东区"
-		}, {
-			"code": "810103",
-			"name": "九龙城区"
-		}, {
-			"code": "810104",
-			"name": "观塘区"
 		}, {
 			"code": "810105",
 			"name": "南区"
-		}, {
-			"code": "810106",
-			"name": "深水埗区"
 		}, {
 			"code": "810107",
 			"name": "湾仔区"
-		}, {
-			"code": "810108",
-			"name": "黄大仙区"
-		}, {
-			"code": "810109",
-			"name": "油尖旺区"
 		}, {
 			"code": "810110",
-			"name": "离岛区"
+			"name": "离岛区"			
+		}]
+	}, {
+		"code": "810200",
+		"name": "九龙半岛区",
+		"children": [{
+			"code": "810210",
+			"name": "九龙城区"
 		}, {
-			"code": "810111",
-			"name": "葵青区"
+			"code": "810211",
+			"name": "观塘区"
 		}, {
-			"code": "810112",
-			"name": "北区"
+			"code": "810212",
+			"name": "深水埗区"
 		}, {
-			"code": "810113",
+			"code": "810204",
 			"name": "西贡区"
 		}, {
-			"code": "810114",
-			"name": "沙田区"
+			"code": "810214",
+			"name": "油尖旺区"
 		}, {
-			"code": "810115",
+			"code": "810108",
+			"name": "黄大仙区"
+		}]
+	}, {
+		"code": "810100",
+		"name": "新界区",
+		"children": [{
+			"code": "810108",
 			"name": "屯门区"
 		}, {
-			"code": "810116",
+			"code": "810105",
+			"name": "沙田区"
+		}, {
+			"code": "810102",
+			"name": "葵青区"
+		}, {
+			"code": "810106",
 			"name": "大埔区"
 		}, {
-			"code": "810117",
+			"code": "810107",
 			"name": "荃湾区"
 		}, {
-			"code": "810118",
+			"code": "810109",
 			"name": "元朗区"
+		}, {
+			"code": "810103",
+			"name": "北区"
 		}]
 	}]
 }, {

+ 18 - 30
TEAMModelBI/ClientApp/src/static/regions/region_gl.json

@@ -244,6 +244,10 @@
           {
             "code": "6601",
             "name": "中區"
+          },
+		  {
+            "code": "6629",
+            "name": "東區"
           },
           {
             "code": "6602",
@@ -350,16 +354,8 @@
             "name": "外埔區"
           },
           {
-            "code": "33",
+            "code": "6628",
             "name": "大安區"
-          },
-          {
-            "code": "06",
-            "name": "臺中市1"
-          },
-          {
-            "code": "19",
-            "name": "臺中市2"
           }
         ]
       },
@@ -514,14 +510,6 @@
           {
             "code": "6737",
             "name": "安定區"
-          },
-          {
-            "code": "11",
-            "name": "臺南市1"
-          },
-          {
-            "code": "21",
-            "name": "臺南市2"
           }
         ]
       },
@@ -680,14 +668,6 @@
           {
             "code": "6438",
             "name": "那瑪夏區"
-          },
-          {
-            "code": "12",
-            "name": "高雄市1"
-          },
-          {
-            "code": "50",
-            "name": "高雄市2"
           }
         ]
       },
@@ -927,7 +907,7 @@
           },
           {
             "code": "0708",
-            "name": "北鎮"
+            "name": "北鎮"
           },
           {
             "code": "0709",
@@ -996,6 +976,10 @@
           {
             "code": "0725",
             "name": "溪州鄉"
+          },
+		  {
+            "code": "0726",
+            "name": "秀水鄉"
           }
         ]
       },
@@ -1063,11 +1047,11 @@
         "children": [
           {
             "code": "0901",
-            "name": "六市"
+            "name": "六市"
           },
           {
             "code": "0902",
-            "name": "南鎮"
+            "name": "南鎮"
           },
           {
             "code": "0903",
@@ -1153,7 +1137,7 @@
           },
           {
             "code": "1002",
-            "name": "子市"
+            "name": "子市"
           },
           {
             "code": "1003",
@@ -1534,6 +1518,10 @@
           {
             "code": "1415",
             "name": "達仁鄉"
+          },
+		  {
+            "code": "1416",
+            "name": "蘭嶼鄉"
           }
         ]
       },
@@ -1651,7 +1639,7 @@
   },
   {
     "code": "NZ",
-    "name": "西蘭"
+    "name": "西蘭"
   },
   {
     "code": "AR",

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

@@ -22,6 +22,7 @@ export default createStore({
         areaClickschool: {},
         areaClickCounselor: '',
         areaClickRoles: '',
+        msgData: {}
     },
     mutations: {
         //修改组织架构
@@ -94,6 +95,10 @@ export default createStore({
         //学区点击人员查看详情 (传输身份)
         clickRoles(state, value) {
             state.areaClickRoles = value
+        },
+        //复用消息
+        copyMsgs(state, value) {
+            state.msgData = value
         }
     },
     actions: {},

+ 47 - 1
TEAMModelBI/ClientApp/src/until/common.js

@@ -88,7 +88,6 @@ export default {
         }
         var strDate = state !== 'all' ? Y + M + D : Y + M + D + h + m + s;
         return strDate; //2020-07-30 01:05:54
-
     },
     toCode(str) { //加密字符串
         //定义密钥,36个字母和数字
@@ -127,5 +126,52 @@ export default {
         }
         b = eval("String.fromCharCode(" + s.join(',') + ")");
         return b; //返回被解密的字符串
+    },
+    //检查是否为空对象
+    isEmpty(obj) {
+        Reflect.ownKeys(obj).length === 0 && obj.constructor === Object;
+    },
+    //计算两天之间相差多少天 格式(2022-11-03)
+    dayDiff(date1, date2) {
+        Math.ceil(Math.abs(date1.getTime() - date2.getTime()) / 86400000);
+    },
+    //把数字转换成汉字
+    toChinesNum(num) {
+        let changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
+        let unit = ['', '十', '百', '千', '万']
+        num = parseInt(num)
+        let getWan = (temp) => {
+            let strArr = temp.toString().split('').reverse()
+            let newNum = ''
+            let newArr = []
+            strArr.forEach((item, index) => {
+                newArr.unshift(item === '0' ? changeNum[item] : changeNum[item] + unit[index])
+            })
+            let numArr = []
+            newArr.forEach((m, n) => {
+                if (m !== '零') numArr.push(n)
+            })
+            if (newArr.length > 1) {
+                newArr.forEach((m, n) => {
+                    if (newArr[newArr.length - 1] === '零') {
+                        if (n <= numArr[numArr.length - 1]) {
+                            newNum += m
+                        }
+                    } else {
+                        newNum += m
+                    }
+                })
+            } else {
+                newNum = newArr[0]
+            }
+
+            return newNum
+        }
+        let overWan = Math.floor(num / 10000)
+        let noWan = num % 10000
+        if (noWan.toString().length < 4) {
+            noWan = '0' + noWan
+        }
+        return overWan ? getWan(overWan) + '万' + getWan(noWan) : getWan(num)
     }
 }

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

@@ -6,6 +6,7 @@ axios.interceptors.request.use(
     config => {
         // const token = getCookie('名称');
         config.data = JSON.stringify(config.data);
+        console.log(config, '访问内容')
         if (config.url.indexOf('biabilitymgmt') != -1 ||
             config.url.indexOf('biabilitytask') != -1 ||
             config.url.indexOf('area') != -1 ||
@@ -17,7 +18,10 @@ axios.interceptors.request.use(
             config.url.indexOf('syscfg') != -1 ||
             config.url.indexOf('biservers') != -1 ||
             config.url.indexOf('business') != -1 ||
-            config.url.indexOf('bizconfig') != -1
+            config.url.indexOf('bizconfig') != -1 ||
+            config.url.indexOf('paper') != -1 ||
+            config.url.indexOf('notice') != -1 ||
+            config.url.indexOf('bizuser') != -1
         ) {
             config.headers = {
                 'Content-Type': 'application/json',

+ 84 - 44
TEAMModelBI/ClientApp/src/view/areaServe/areamanage.vue

@@ -11,14 +11,14 @@
         <div class="select-box-items">
           <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')" size="small">
+            <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')" size="small">
+            <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>
@@ -30,7 +30,7 @@
           </div>
         </div>
         <div class="areasearch-box">
-          <el-input v-model="areaValues" placeholder="搜索 学区名称" class="input-with-select" size="small" clearable>
+          <el-input v-model="areaValues" placeholder="搜索 学区名称" class="input-with-select" clearable>
             <template #prepend>
               <svg class="addrelevancy-icon" aria-hidden="true">
                 <use xlink:href="#icon-sousuo3-copy"></use>
@@ -61,7 +61,7 @@
                     </div>
                     <span class="text">{{$t(`areaManages.found.creation`)}}</span>
                 </a> -->
-        <el-button size="small" color="#81ecec" type="primary" @click="createArea">
+        <el-button type="primary" @click="createArea">
           <svg class="created-icon" aria-hidden="true">
             <use xlink:href="#icon-chuangjiandizhisuoyin"></use>
           </svg>
@@ -112,7 +112,7 @@
                 <div class="haveSchool-title">
                   <div>{{ $t(`areaManages.operational.areaAddSchool.schooltitle`) }}</div>
                   <div class="search-school">
-                    <el-input v-model="schoolSeach" placeholder="输入学校名称搜索" size="small" clearable>
+                    <el-input v-model="schoolSeach" placeholder="输入学校名称搜索" clearable>
                       <!-- <template #prepend>
                         <svg class="addrelevancy-icon" aria-hidden="true">
                           <use xlink:href="#icon-sousuo3-copy"></use>
@@ -125,7 +125,8 @@
                 <ul>
                   <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 :src="item.picture" fit="fill"> </el-image>
+                      <el-image :src="item.picture" fit="fill" v-if="item.picture"> </el-image>
+                      <div class="notimages" v-else>暂无图片</div>
                     </div>
                     <div class="list-school-name">
                       <div>
@@ -189,11 +190,12 @@
                   {{ $t(`areaManages.operational.areaAddSchool.tabletitle`) }}
                 </div>
                 <div :class="[!PowerShow ? 'subjoin':'','schoolRight-table']">
-                  <el-table :data="tableDatas" style="width: 100%" height="535">
+                  <el-table :data="tableDatas" style="width: 100%" height="535" empty-text="暂无数据">
                     <el-table-column prop="index" :label="$t(`areaManages.operational.areaAddSchool.tables.serialnum`)" type="index" />
                     <el-table-column :label="$t(`areaManages.operational.areaAddSchool.tables.badge`)" align="center">
                       <template #default="scope">
-                        <el-image :src="scope.row.picture" fit="fill"></el-image>
+                        <el-image :src="scope.row.picture" fit="fill" v-if="scope.row.picture"></el-image>
+                        <div class="notimages nottables" v-else>暂无图片</div>
                       </template>
                     </el-table-column>
                     <el-table-column prop="name" :label="$t(`areaManages.operational.areaAddSchool.tables.name`)" align="center" />
@@ -289,7 +291,7 @@
                         <div class="hint"><span>请输入用户</span><span class="emphasize">手机号、醍摩豆账号</span><span>等相关信息进行搜索</span></div>
                         <div class="search-box">
                           <!-- <input class="search-txt" type="text" id="serachname" :value="filterText" placeholder="搜索相关人名" @oninput="personnelSearch()" @compositionend="personnelSearch()"> -->
-                          <el-input v-model="adminfilter" placeholder="Please input" class="search-txt" />
+                          <el-input v-model="adminfilter" placeholder="" class="search-txt" />
                           <svg class="serachbox-empty" aria-hidden="true" v-if="adminfilter !==''" @click="adminfilter=''">
                             <use xlink:href="#icon-qingkong"></use>
                           </svg>
@@ -301,7 +303,7 @@
                           <p>未搜索到相关用户信息,请检验后重新输入搜索</p>
                         </div>
                         <div class="submitbtn">
-                          <el-button type="primary" size="small" @click=serachPersonnel(adminfilter) class="anewbox-btn blue">搜索人员</el-button>
+                          <el-button type="primary" @click=serachPersonnel(adminfilter) class="anewbox-btn blue">搜索人员</el-button>
                         </div>
                       </div>
                       <div class="admin-text-box" v-else-if="searchState ===true">
@@ -327,8 +329,10 @@
                   <div class="managelist">
                   </div>
                   <div class="backadds">
-                    <el-button size="small" type="primary" @click="adminOrsearch='search',adminIndex=-1" :icon="Search">
-                      <!-- <el-icon><Back /></el-icon> -->
+                    <el-button size="small" type="primary" @click="adminOrsearch='search',adminIndex=-1">
+                      <el-icon>
+                        <Back />
+                      </el-icon>
                       添加管理员
                     </el-button>
                   </div>
@@ -597,7 +601,7 @@ import { useRouter } from 'vue-router'
 import Ability from '@/components/Ability.vue'
 import option from '@/static/region.json'
 import loadingsz from '@/components/loading/partial.vue'
-import { CopyDocument, ArrowRight, ArrowLeft, Search } from '@element-plus/icons-vue'
+import { CopyDocument, ArrowRight, ArrowLeft, Search, Back } from '@element-plus/icons-vue'
 import useClipboard from 'vue-clipboard3'
 import jwt_decode from 'jwt-decode'
 const optionsData = option
@@ -608,7 +612,8 @@ export default {
     CopyDocument,
     ArrowRight,
     ArrowLeft,
-    Search
+    Search,
+    Back
   },
   setup () {
     let { proxy } = getCurrentInstance()
@@ -774,17 +779,15 @@ export default {
       })
     }
     //获取当前未加入区的所有学校
-    function getNotjoin () {
+    async function getNotjoin () {
       loadingSchoolList.value = true
       console.log(currentlySelect.value.id)
-      proxy.$api
-        .getNotjoinSchool({ areaId: '' })
+      await proxy.$api
+        .getNotjoinSchool({})
         .then((res) => {
           console.log(res, '获取未加入区域的学校')
           res.state === 200
-            ? ((notjoinSchool.value = []),
-              notjoinSchool.value.push(...res.notAreaSchools), notjoinPrimitive.value.push(...res.notAreaSchools)
-                (loadingSchoolList.value = false))
+            ? (notjoinSchool.value = [], notjoinSchool.value = res.notAreaSchools, notjoinPrimitive.value = res.notAreaSchools, loadingSchoolList.value = false)
             : ''
         })
     }
@@ -799,11 +802,11 @@ export default {
         areaId: currentlySelect.value.id,
         // schoolCode: [schoolcode],
       }
-      proxy.$api.areaAddSchool(data).then((res) => {
+      proxy.$api.areaAddSchool(data).then(async (res) => {
         console.log(res, '区域加入学校返回')
         res.state === 200
           ? (ElMessage.success(proxy.$t(`commonMsg.addschoolSuccess`)), (addSchoolHint.value = false),
-            getNotjoin(),
+            await getNotjoin(), notjoinSchoolarea(),
             getAreaschool())
           : res.state === 401 ? ElMessage.error('已同步省平台,无法加入学区') : ElMessage.error(proxy.$t(`commonMsg.addschoolError`))
       })
@@ -920,12 +923,10 @@ export default {
               schoolId: datas.id,
               isDefault: states,
             }
-            proxy.$api.areaDeleSchool(data).then((res) => {
+            proxy.$api.areaDeleSchool(data).then(async (res) => {
               console.log(res, '移除返回')
-              res.state == 200
-                ? (ElMessage.success('操作成功'), getAreaschool())
-                : res.state === 401 ? ElMessage.error('已同步省平台,无法移学校') : res.state !== 200 ? (ElMessage.success('操作失败')) : '',
-                getNotjoin()
+              res.state == 200 ? (ElMessage.success('操作成功'), getAreaschool()) : res.state === 401 ? ElMessage.error('已同步省平台,无法移学校') : res.state !== 200 ? (ElMessage.success('操作失败')) : '',
+                await getNotjoin(), notjoinSchoolarea()
             })
             done()
             instance.confirmButtonLoading = false
@@ -1068,14 +1069,18 @@ export default {
       proxy.$api.areaAddadmins(data).then((res) => {
         // res.state === 200 ? (ElMessage.success('操作成功'), getAreasadmin()) : ''
         if (res.state === 200 || res.state === 201) {
-          if (res.existsArea !== null) {
-            ElMessage.warning('该管理员已是本学区管理员,请勿重复添加')
-          } else if (res.existsSc.length !== 0) {
-            ElMessage.success('操作成功')
-            stageShow.value.state = false
-            getAreasadmin()
-          } else if (res.errorSc.length !== 0) {
-            ElMessage.error('全部或部分设置学校管理员操作失败')
+          if (res.hasOwnProperty('existsArea')) {
+            if (res.existsArea !== null) {
+              ElMessage.warning('该管理员已是本学区管理员,请勿重复添加')
+            } else if (res.existsSc.length !== 0) {
+              ElMessage.success('操作成功')
+              stageShow.value.state = false
+              getAreasadmin()
+            } else if (res.errorSc.length !== 0) {
+              ElMessage.error('全部或部分设置学校管理员操作失败')
+            }
+          } else {
+            res.state === 200 ? (ElMessage.success('操作成功'), stageShow.value.state = false, getAreasadmin()) : res.state === 201 ? (ElMessage.success('部分学校操作成功'), stageShow.value.state = false, getAreasadmin()) : ''
           }
         }
       }).catch((error) => {
@@ -1124,8 +1129,7 @@ export default {
         if (i < 5) {
           nameArr !== '' ? nameArr = nameArr + ',' + removeList.value[i].name : nameArr = removeList.value[i].name
         } else {
-          nameArr = nameArr + '...等等'
-          break
+          nameArr.indexOf('...等等') !== -1 ? '' : nameArr = nameArr + '...等等'
         }
       }
       console.log(nameArr, schoolcodeArr)
@@ -1135,7 +1139,7 @@ export default {
         type: 'error',
         center: true,
       }).then(() => {
-        let data = { tmdId: adminSchoold.value.nowid, scIds: schoolcodeArr }
+        let data = { tmdId: adminSchoold.value.nowid, scIds: schoolcodeArr, rmvFromSc: true }
         proxy.$api
           .deleteSchooladmin(data)
           .then((res) => {
@@ -1210,6 +1214,7 @@ export default {
     }
     function removeSelect (value) {
       removeList.value = value
+      console.log(removeList.value, '当前准备删除的学校')
     }
     //学区个人管理员 添加未管理学校
     function addManageSchool () {
@@ -1217,19 +1222,19 @@ export default {
       let nowUser = adminSchoold.value.name
       let schoolName = ''
       for (let i in schoolList) {
-        if (i < 6) {
+        if (i < 5) {
           schoolName += schoolList[i].name + ','
         } else {
-          schoolName = schoolName + '等...'
-          break;
+          schoolName.indexOf('...等等') !== -1 ? '' : schoolName = schoolName + '...等等'
         }
       }
       let texts = '请问您是否将 ' + `${nowUser}` + ' 成为 ' + `${schoolName}` + ' 的管理员吗?'
       console.log(schoolName)
       ElMessageBox.confirm(texts, '添加管理学校', {
+        type: 'success',
+        center: true,
         confirmButtonText: '确认',
         cancelButtonText: '取消',
-        type: 'primary',
       }).then(() => {
         let schoolArr = []
         for (let i in schoolList) {
@@ -1264,7 +1269,7 @@ export default {
     function notjoinSchoolarea () {
       let values = schoolSeach.value
       let newdata = notjoinPrimitive.value.filter((item) => { return item.name.includes(values) })
-      notjoinSchool.value = newdata
+      notjoinSchool.value = JSON.parse(JSON.stringify(newdata))
     }
     watch(abilityModel, (newdata) => {
       console.log(newdata)
@@ -2205,6 +2210,23 @@ export default {
   background-color: rgba(223, 230, 233, 0.7);
   color: rgba(178, 190, 195, 1);
 }
+.notimages {
+  /* width: 65%;
+  margin: 3% 0 0 3%; */
+  width: 70px;
+  height: 70px;
+  line-height: 70px;
+  text-align: center;
+  background-color: #bdc3c7;
+  font-size: 10px;
+  color: #ecf0f1;
+  margin: 0 auto;
+}
+.nottables {
+  width: 60px !important;
+  height: 60px !important;
+  line-height: 60px !important;
+}
 </style>
 <style>
 .stagebox-table-not .el-image {
@@ -2325,7 +2347,7 @@ export default {
 }
 
 .schoolRight-table .el-image__inner {
-  width: 75%;
+  width: 80%;
 }
 .addschoolHints .el-dialog__title {
   padding-left: 15px;
@@ -2381,6 +2403,24 @@ export default {
   width: 55%;
   border-radius: 50%;
 }
+.schoolLeft .search-school .el-input__wrapper {
+  width: 100%;
+}
+.search-box .el-input__wrapper {
+  width: 100%;
+  padding: 0px;
+  /* background: #bdc3c7; */
+  background: transparent;
+  box-shadow: 0px 0px 0px 0px transparent;
+}
+.search-box .el-input__wrapper .is-focues {
+  border: 0px;
+  box-shadow: 0px 0px 0px 0px transparent;
+}
+.search-box .el-input__wrapper:hover {
+  border: 0px;
+  box-shadow: 0px 0px 0px 0px transparent;
+}
 @media screen and (max-width: 2600px) {
   .select-box-items {
     width: 25%;

+ 276 - 10
TEAMModelBI/ClientApp/src/view/areaServe/setthird.vue

@@ -27,6 +27,13 @@
                   <!-- <el-input v-model="setform.mobile" @input="saveState=true" v-if="PowerShow" /> -->
                   <el-input v-model="setform.mobile" disabled />
                 </el-form-item>
+                <el-form-item label="企业类型">
+                  <el-radio-group v-model="setType">
+                    <el-radio label="0" v-if="setform.type == '1'" disabled>非定制</el-radio>
+                    <el-radio label="0" v-else>非定制</el-radio>
+                    <el-radio label="1">定制</el-radio>
+                  </el-radio-group>
+                </el-form-item>
                 <el-form-item label="企业logo">
                   <div class="upload-logo">
                     <el-upload class="avatar-uploader" :headers="uploadHeader" accept=".png,.jpeg,.jpg" action="/blob/upload-public" :disabled='uploadState' :show-file-list="false" :before-upload="changeBadge" :on-success="success" :on-error="handleUpdErr" v-if="PowerShow">
@@ -60,9 +67,9 @@
                   <div class="tokenbox">
                     <!-- <el-input v-model="setform.token" :rows="2" type="textarea" @input="saveState=true" v-if="PowerShow" /> -->
                     <el-input v-model="setform.token" :rows="2" type="textarea" disabled />
-                  </div>
-                  <div class="generatebox-copy">
-                    <el-button type="primary" size="small" @click="copykeys(setform.token)">复制秘钥</el-button>
+                    <div class="generatebox-copy">
+                      <el-button type="primary" size="small" @click="copykeys(setform.token)">复制秘钥</el-button>
+                    </div>
                   </div>
                   <div class="generatebox" v-if="PowerShow">
                     <el-button type="primary" size="small" @click="againGenerate">重新生成秘钥</el-button>
@@ -124,6 +131,61 @@
             </div>
           </div>
         </el-tab-pane>
+        <el-tab-pane label="用户信息" name="user">
+          <div class="set-basics">
+            <p class="set-basics-title">
+            <div class="set-basics-title-name">关联用户</div>
+            <div class="set-basics-save">
+              <el-button type="primary" size="small" @click="addschoolRelevancy=true" v-if="PowerShow">
+                <svg class="addrelevancy-icon" aria-hidden="true">
+                  <use xlink:href="#icon-guanlianrenyuan"></use>
+                </svg>
+                添加关联用户
+              </el-button>
+            </div>
+            <!-- <div class="set-basics-save remove" v-if="removeArr.length !==0">
+              <el-button type="danger" size="small" @click="removeSchools('','batch')">
+                <svg class="addrelevancy-icon" aria-hidden="true">
+                  <use xlink:href="#icon-addLink-fill"></use>
+                </svg>
+                移除选中用户
+              </el-button>
+            </div> -->
+            </p>
+            <div class="relevancyschool-list">
+              <el-table :data="userData" height="65vh" style="width: 100%" empty-text="暂无关联学校" v-if="userData.length !==0" @selection-change="removeUserList">
+                <!-- <el-table-column label="状态" type="selection" /> -->
+                <el-table-column prop="index" label="编号" type="index" align="center" />
+                <el-table-column label="头像" align="center">
+                  <template #default="scope">
+                    <el-image style="width: 60px; height: 60px" :src="scope.row.picture" fit="fill" v-if="scope.row.picture"></el-image>
+                    <PersonalPhoto style="cursor: pointer;" :name="scope.row.name" v-else></PersonalPhoto>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="name" label="名称" align="center" />
+                <el-table-column label="电话号码" align="center">
+                  <template #default="scope">
+                    <div v-if="scope.row.mobile">{{scope.row.mobile}}</div>
+                    <div v-else> 暂无 </div>
+                  </template>
+                </el-table-column>
+                <el-table-column label="电子邮箱" align="center">
+                  <template #default="scope">
+                    <div v-if="scope.row.mail">{{scope.row.mail}}</div>
+                    <div v-else> 暂无 </div>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" v-if="PowerShow">
+                  <template #default="scope">
+                    <el-button class="deletebtns" type="danger" size="small" @click="removeUser(scope.row,'alone')">移除用户
+                    </el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+              <div v-else class="notdatas"><span>暂无关联用户</span></div>
+            </div>
+          </div>
+        </el-tab-pane>
       </el-tabs>
     </div>
     <!--添加关联学校弹窗-->
@@ -139,7 +201,7 @@
           </el-input>
         </div>
         <el-table ref="multipleTableRef" :data="schoolLists" style="width: 100%" height="42vh" @selection-change="handleSelectionChange" empty-text="暂无相关搜索学校">
-          <el-table-column label="校徽">
+          <el-table-column label="校徽" align="center">
             <template #default="scope">
               <el-image style="width: 40px; height: 40px" :src="scope.row.picture" fit="fill"></el-image>
             </template>
@@ -157,6 +219,58 @@
       </el-dialog>
     </div>
     <!--添加关联学校弹窗end-->
+    <!--添加关联用户弹窗-->
+    <div class="adduser-relevancy">
+      <el-dialog v-model="addschoolRelevancy" title="搜索用户列表" width="25%">
+        <div>
+          <el-input v-model="searchUser" placeholder="搜索 手机号码" class="input-with-select" size="small" clearable>
+            <template #prepend>
+              <svg class="addrelevancy-icon" aria-hidden="true">
+                <use xlink:href="#icon-sousuo3-copy"></use>
+              </svg>
+            </template>
+          </el-input>
+        </div>
+        <el-table :data="userLists" style="width: 100%" height="42vh" @selection-change="handleUser" empty-text="暂无搜索相关用户" v-loading="searchUserstate" element-loading-text="加载中...">
+          <el-table-column label="头像" align="center">
+            <template #default="scope">
+              <el-image style="width: 40px; height: 40px" :src="scope.row.picture" fit="fill" v-if="scope.row.picture"></el-image>
+              <PersonalPhoto style="cursor: pointer;" :name="scope.row.name" v-else></PersonalPhoto>
+            </template>
+          </el-table-column>
+          <el-table-column property="name" label="名称" />
+          <!-- <el-table-column property="mobile" label="手机号码" /> -->
+          <el-table-column label="手机号码" align="center">
+            <template #default="scope">
+              <div v-if="scope.row.mobile">{{scope.row.mobile}}</div>
+              <div v-else> 暂无 </div>
+            </template>
+          </el-table-column>
+          <el-table-column label="状态" type="selection" />
+        </el-table>
+        <template #footer>
+          <span class="dialog-footer">
+            <el-button @click="addschoolRelevancy = false">取消</el-button>
+            <el-button type="primary" @click="notarizebox=true">关联选中用户</el-button>
+          </span>
+        </template>
+      </el-dialog>
+    </div>
+    <!--添加关联用户弹窗end-->
+    <!--身份确认-->
+    <el-dialog v-model="notarizebox" title="选择关联身份" width="20%" class="radiusbox">
+      <el-radio-group v-model="correlationRole">
+        <el-radio label="1" size="large">任命为管理员</el-radio>
+        <el-radio label="2" size="large">普通会员</el-radio>
+      </el-radio-group>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="notarizebox = false">取消</el-button>
+          <el-button type="primary" @click="correlationUser('add')">确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    <!--身份确认end-->
   </div>
 </template>
 <script>
@@ -182,6 +296,7 @@ export default {
     let setform = ref({
       name: '',
       credit: '',
+      type: '0',
       mobile: '',
       imageUrl: '',
       email: '',
@@ -189,6 +304,7 @@ export default {
       domain: '',
       webhook: '',
     })
+    let setType = ref('0')
     let formVerify = ref({
       name: [
         { required: true, message: '企业名称不能为空', trigger: 'blur' },
@@ -204,15 +320,23 @@ export default {
     })
     let saveState = ref(false)
     let tableData = ref([])
+    let userData = ref([])
     let schoolLists = ref([])
+    let userLists = ref([])
     let original = ref([])
     let timer = ref('')
     let addschoolRelevancy = ref(false)
     let checkedSchool = ref([])
+    let checkedUser = ref([])
     let removeArr = ref([])
+    let removeUserarr = ref([])
     let serachValues = ref('')
     let uploadState = ref(false)
     let uploadHeader = ref({})
+    let searchUser = ref('')
+    let searchUserstate = ref(false)
+    let notarizebox = ref(false)
+    let correlationRole = ref('2')
     function backs () {
       context.emit('backState', 'list')
     }
@@ -272,6 +396,10 @@ export default {
       console.log(val, '选中')
       checkedSchool.value = val
     }
+    //勾选的即将关联的用户
+    function handleUser (val) {
+      checkedUser.value = val
+    }
     //企业关联学校
     function correlationSchool () {
       let schoolList = checkedSchool.value
@@ -284,6 +412,31 @@ export default {
         ElMessage.error('关联失败')
       })
     }
+    //添加或删除用户的提示
+    function operateHint (type) {
+      ElMessageBox.alert(
+        '<strong>proxy is <i>HTML</i> string</strong>',
+        'HTML String',
+        {
+          dangerouslyUseHTMLString: true,
+        }
+      )
+    }
+    //企业关联用户
+    function correlationUser (types) {
+      console.log(types, '7')
+      let userlist = checkedUser.value[0]
+      let typevalue = types
+      console.log(userlist)
+      let bizsData = { bizId: setform.value.id, name: setform.value.name, picture: setform.value.picture, role: [correlationRole.value === '1' ? 'admin' : 'read'] }
+      let data = { id: userlist.id, type: typevalue, bizs: [bizsData], userType: userlist.id.indexOf('-') == -1 ? 'tmdId' : '' }
+      proxy.$api.getCorrelationUser(data).then((res) => {
+        console.log(res, '添加角色')
+        res.state === 200 ? (ElMessage.success('关联成功'), notarizebox.value = false, details(setform.value.id), addschoolRelevancy.value = false) : ''
+      }).catch((err) => {
+        ElMessage.error('关联失败,API异常')
+      })
+    }
     //重新生成秘匙
     function againGenerate () {
       let data = { id: setform.value.id }
@@ -297,6 +450,10 @@ export default {
     function removeSchoolList (val) {
       removeArr.value = val
     }
+    //移除用户选中
+    function removeUserList (val) {
+      removeUserarr.value = val
+    }
     //企业内移除关联学校
     function removeSchools (data, type) {
       console.log(data, type, '现在的删除方式')
@@ -331,6 +488,42 @@ export default {
         })
       })
     }
+    //企业内移除用户关联
+    function removeUser (data, type) {
+      let removeList = []
+      data && type === 'alone' ? removeList.push(data) : ''
+      type === 'batch' ? removeUserarr.value.forEach((item) => { removeList.push(item) }) : ''
+      let text = ''
+      if (removeUserarr.value.length > 0 && !data) {
+        for (let i in removeUserarr.value) {
+          if (i < 6) {
+            text === '' ? text = removeUserarr.value[i].name : text = text + ',' + removeUserarr.value[i].name
+          } else {
+            text.indexOf('... 等') !== -1 ? '' : text = text + '... 等'
+          }
+        }
+      } else if (data) {
+        text = data.name
+      }
+      console.log(data, '类型')
+      ElMessageBox.confirm(`您确定要移除 ${text} 与 当前企业的关联 吗? 请慎重操作!`, '移除关联用户', {
+        confirmButtonText: proxy.$t(`commonMsg.confirm`),
+        cancelButtonText: proxy.$t(`commonMsg.closes`),
+        type: 'warning',
+        center: true,
+      }).then(() => {
+        console.log(data, '类型111')
+        let bizsData = [];
+        data.relation.forEach((item) => { item.bizId === setform.value.id ? bizsData.push(item) : '' })
+        let datainfo = { id: data.id, type: 'del', bizs: bizsData, userType: data.id.indexOf('-') == -1 ? 'tmdId' : '' }
+        proxy.$api.getCorrelationUser(datainfo).then((res) => {
+          console.log(res, '移除角色')
+          res.state === 200 ? (ElMessage.success('移除成功'), details(setform.value.id)) : ''
+        }).catch((err) => {
+          ElMessage.error('移除失败,API异常')
+        })
+      })
+    }
     function debounce (fn, wait) {
       if (timer.value !== null) {
         clearTimeout(timer.value)
@@ -345,12 +538,48 @@ export default {
       })
       schoolLists.value = newArr
     }
+    //对用户进行搜索
+    function serachUserinfo () {
+      let values = searchUser.value
+      let data = { mobile: values }
+      searchUserstate.value = true
+      proxy.$api.searchphoneUser(data).then((res) => {
+        console.log(res, '999999')
+        // res.state === 200 ? userLists.value = res.userinfos : ''
+        if (res.state === 200) {
+          if (res.bizUsers.length !== 0) {
+            userLists.value = res.bizUsers
+            userLists.value.userType = ''
+          } else if (res.coreUser !== null) {
+            userLists.value = [res.coreUser]
+            userLists.value.userType = 'tmdId'
+          }
+          if (res.bizUsers.length === 0 && res.coreUser === null) { userLists.value = [] }
+        }
+        searchUserstate.value = false
+      }).catch((error) => {
+        ElMessage.error('搜索失败,API异常')
+        searchUserstate.value = false
+      })
+    }
     //保存基础设置
     function saveSet () {
       console.log(setform.value, '保存相关')
       let datas = setform.value
       let schoolData = tableData.value
-      let saveData = { code: datas.code, id: datas.id, name: datas.name, credit: datas.credit, picture: datas.imageUrl, mobile: datas.mobile, email: datas.email, domain: datas.domain, webhook: datas.webhook, schools: schoolData }
+      let saveData = {
+        code: datas.code,
+        id: datas.id,
+        name: datas.name,
+        credit: datas.credit,
+        picture: datas.imageUrl,
+        mobile: datas.mobile,
+        email: datas.email,
+        domain: datas.domain,
+        webhook: datas.webhook,
+        schools: schoolData,
+        isCustomize: Number(setType.value)
+      }
       proxy.$api.updateThirdparty(saveData).then((res) => {
         res.state === 200 ? (ElMessage.success('保存成功'), context.emit('backState', 'list')) : ElMessage.error('保存失败')
       }).catch((error) => {
@@ -361,11 +590,22 @@ export default {
       let datas = { id: val }
       proxy.$api.getAllenterprise(datas).then((res) => {
         console.log(res, '详情')
-        res.state === 200 ? (setform.value = res.businesses[0], setform.value.imageUrl = res.businesses[0].picture, tableData.value = res.businesses[0].schools) : ''
+        res.state === 200 ? (setform.value = res.businesses[0], setform.value.imageUrl = res.businesses[0].picture, setType.value = res.businesses[0].isCustomize.toString(), setform.value.type = res.businesses[0].isCustomize.toString(), tableData.value = res.businesses[0].schools) : ''
         getschoolList(setform.value.id)
       }).catch((error) => {
         ElMessage.error('企业详情获取失败,API异常')
       })
+      getUserlist(val)
+    }
+    //获取企业用户列表
+    function getUserlist (value) {
+      let data = { id: value }
+      proxy.$api.getUserarr(data).then((res) => {
+        console.log(res, '用户list')
+        res.state === 200 ? userData.value = res.businessUsers : ''
+      }).catch((error) => {
+        ElMessage.error('企业用户列表获取失败,API异常')
+      })
     }
     //复制
     async function copykeys (value) {
@@ -391,6 +631,14 @@ export default {
         schoolLists.value = original.value
       }
     })
+    watch(searchUser, (newdata) => {
+      if (newdata.trim().length !== 0) {
+        debounce(serachUserinfo, 500)
+      } else {
+        console.log('111')
+        userLists.value = []
+      }
+    })
     uploadInt()
     return {
       activeName,
@@ -421,7 +669,20 @@ export default {
       deltelogos,
       PowerShow,
       details,
-      copykeys
+      copykeys,
+      setType,
+      userData,
+      userLists,
+      searchUser,
+      serachUserinfo,
+      handleUser,
+      searchUserstate,
+      correlationUser,
+      notarizebox,
+      correlationRole,
+      removeUser,
+      removeUserarr,
+      removeUserList
     }
   },
 }
@@ -517,7 +778,9 @@ export default {
 .generatebox {
   position: absolute;
   bottom: 5px;
-  margin-left: 2%;
+  left: 101%;
+}
+.generatebox:hover {
 }
 .generatebox-copy {
   position: absolute;
@@ -569,11 +832,14 @@ export default {
   width: 100%;
   height: 100%;
 }
-.token-box:hover .generatebox-copy {
+.tokenbox:hover .generatebox-copy {
   opacity: 1 !important;
 }
-.token-box:hover .el-textarea__inner {
+.tokenbox:hover .el-textarea__inner {
   background: rgba(189, 195, 199, 0.45);
   cursor: pointer;
 }
+.setboxs .radiusbox {
+  border-radius: 5px;
+}
 </style>

+ 1 - 1
TEAMModelBI/ClientApp/src/view/areaServe/thirdparty.vue

@@ -250,7 +250,7 @@ export default {
       timer.value = setTimeout(fn, wait)
     }
     function personnelSearch () {
-      let arr = thirdpartyArr.value
+      let arr = original.value
       let newArr = arr.filter((item) => {
         // return (item.name && item.name.includes(filterText.value)) || (item.mobile && item.mobile.includes(filterText.value)) || (item.mobile && item.mobile.tmdId.includes(filterText.value))
         return item.name.includes(serachkeys.value)

+ 419 - 198
TEAMModelBI/ClientApp/src/view/areamanage/statistics.vue

@@ -68,6 +68,9 @@
       <div class="area-listinfo" v-loading="loadingTotal.areaList" element-loading-background="rgba(0, 0, 0, 0.3)">
         <el-tabs type="border-card">
           <el-tab-pane label="学区列表">
+            <div class="areaSearch">
+              <el-input v-model="searchAreasv" placeholder="输入学区名称进行搜索" clearable />
+            </div>
             <div class="area-data">
               <div class="area-item" v-for="(item,index) in areaLists" :key="item.id">
                 <div class="area-item-list">
@@ -88,7 +91,8 @@
                 <el-table-column label="校徽" align="center">
                   <template #default="scope">
                     <div class="school-badge">
-                      <el-image :src="scope.row.picture" fit="fill" />
+                      <el-image :src="scope.row.picture" fit="fill" v-show="scope.row.picture" />
+                      <div v-show="!scope.row.picture" class="notimage">暂无图片</div>
                     </div>
                   </template>
                 </el-table-column>
@@ -244,7 +248,8 @@
             <el-table-column label="校徽" align="center">
               <template #default="scope">
                 <div class="school-badge">
-                  <el-image :src="scope.row.picture" fit="fill" />
+                  <el-image :src="scope.row.picture" fit="fill" v-if="scope.row.picture" />
+                  <div style="width: 70px;height: 70px;line-height: 70px;text-align: center;background-color: #bdc3c7;font-size: 12px;color: #ecf0f1;margin:5px" v-else>暂无图片</div>
                 </div>
               </template>
             </el-table-column>
@@ -317,7 +322,7 @@ export default {
         { id: 2, title: '学期课例数', num: 0, type: 'month' },
         { id: 3, title: '本周活动数', num: 0, type: 'month' },
         { id: 4, title: '学期活动数', num: 0, type: 'month' },
-        { id: 5, title: '累计完成研训学时', num: 0, type: 'total' },
+        { id: 5, title: '智慧教室', num: 0, type: 'total' },
         { id: 6, title: '累计课例', num: 0, type: 'total' },
         { id: 7, title: '累计资源', num: 0, type: 'total' },
         { id: 8, title: '累计活动', num: 0, type: 'total' },
@@ -327,7 +332,7 @@ export default {
         { id: 2, title: '学期课例数', num: 0, type: 'month' },
         { id: 3, title: '本周活动数', num: 0, type: 'month' },
         { id: 4, title: '学期活动数', num: 0, type: 'month' },
-        { id: 5, title: '累计完成研训学时', num: 0, type: 'total' },
+        { id: 5, title: '累计开课', num: 0, type: 'total' },
         { id: 6, title: '累计课例', num: 0, type: 'total' },
         { id: 7, title: '累计资源', num: 0, type: 'total' },
         { id: 8, title: '累计活动', num: 0, type: 'total' },
@@ -382,6 +387,9 @@ export default {
     let areaSearchValue = ref()
     let timer = ref('')
     let originalSchool = ref([])
+    //学区搜索相关数据
+    let searchAreasv = ref()
+    let searchOriginal = ref([])
     //总区域echarts需要数据
     let totalArea = ref({
       //单独的饼图
@@ -1379,6 +1387,12 @@ export default {
             color: '#333',
           },
         },
+        tooltip: {
+          trigger: 'axis',
+          formatter: function (params) {
+            return params
+          }
+        },
         series: [
           {
             name: '空间占比',
@@ -1406,67 +1420,108 @@ export default {
       //     text: '正在努力加载,请稍等...',
       //     background: 'rgba(0, 0, 0, 0.8)',
       // })
-      proxy.$api
-        .getAlldata({})
-        .then((res) => {
-          console.log(res, '全区返回')
-          if (res.state === 200) {
-            //基础数据赋值
-            activityData.value.total[0].num = res.weekLess
-            activityData.value.total[1].num = res.termLess
-            activityData.value.total[2].num = res.weekActivity
-            activityData.value.total[3].num = res.termActivity
-            activityData.value.total[4].num = res.totalTime
-            activityData.value.total[5].num = res.allLess
-            activityData.value.total[6].num = res.resourceCount
-            activityData.value.total[7].num = res.allActivity
+      //proxy.$api.getAlldata({}).then((res) => {
+      // console.log(res, '全区返回')
+      //   if (res.state === 200) {
+      //     //基础数据赋值
+      //     activityData.value.total[0].num = res.weekLess
+      //     activityData.value.total[1].num = res.termLess
+      //     activityData.value.total[2].num = res.weekActivity
+      //     activityData.value.total[3].num = res.termActivity
+      //     activityData.value.total[4].num = res.totalTime
+      //     activityData.value.total[5].num = res.allLess
+      //     activityData.value.total[6].num = res.resourceCount
+      //     activityData.value.total[7].num = res.allActivity
 
-            //处理header数据
-            // let schoolnum = 0
-            // let teachnum = 0
-            // for (let i in res.areaInfos) {
-            //   schoolnum += res.areaInfos[i].schoolCount
-            //   teachnum += res.areaInfos[i].techCount
-            // }
-            areaAspectsData.value[0].num = res.areaCount
-            areaAspectsData.value[1].num = res.scCount
-            areaAspectsData.value[2].num = res.tecCount
-            areaAspectsData.value[3].num = parseInt(res.allLess) + parseInt(res.allActivity)
-            res.allSize > 1024 ? unit.value.all = 'TB' : unit.value.all = 'GB'
-            areaAspectsData.value[4].num = res.allSize > 1024 ? (res.allSize / 1024).toFixed(1) : res.allSize
+      //     //处理header数据
+      //     // let schoolnum = 0
+      //     // let teachnum = 0
+      //     // for (let i in res.areaInfos) {
+      //     //   schoolnum += res.areaInfos[i].schoolCount
+      //     //   teachnum += res.areaInfos[i].techCount
+      //     // }
+      //     areaAspectsData.value[0].num = res.areaCount
+      //     areaAspectsData.value[1].num = res.scCount
+      //     areaAspectsData.value[2].num = res.tecCount
+      //     areaAspectsData.value[3].num = parseInt(res.allLess) + parseInt(res.allActivity)
+      //     res.allSize > 1024 ? unit.value.all = 'TB' : unit.value.all = 'GB'
+      //     areaAspectsData.value[4].num = res.allSize > 1024 ? (res.allSize / 1024).toFixed(1) : res.allSize
 
-            //新增
-            areaAspectsData.value[1].addweek = res.weekScCnt
-            areaAspectsData.value[1].addmonth = res.monthScCnt
-            areaAspectsData.value[2].addweek = res.weekTchCnt
-            areaAspectsData.value[2].addmonth = res.monthTchCnt
-            areaAspectsData.value[3].addweek = parseInt(res.weekLess) + parseInt(res.weekActivity)
-            areaAspectsData.value[3].addmonth = parseInt(res.monthLesCnt) + parseInt(res.monthActCnt)
-            //学校列表赋值
-            // areaLists.value = res.areaInfos
-            //活动占比
-            // totalArea.value.activity.series[0].data[0].value = res.activitys.Exam
-            // totalArea.value.activity.series[0].data[1].value = res.activitys.Vote
-            // totalArea.value.activity.series[0].data[2].value = res.activitys.Survey
-            // totalArea.value.activity.series[0].data[3].value = res.activitys.Homework
+      //     //新增
+      //     areaAspectsData.value[1].addweek = res.weekScCnt
+      //     areaAspectsData.value[1].addmonth = res.monthScCnt
+      //     areaAspectsData.value[2].addweek = res.weekTchCnt
+      //     areaAspectsData.value[2].addmonth = res.monthTchCnt
+      //     areaAspectsData.value[3].addweek = parseInt(res.weekLess) + parseInt(res.weekActivity)
+      //     areaAspectsData.value[3].addmonth = parseInt(res.monthLesCnt) + parseInt(res.monthActCnt)
+      //     //学校列表赋值
+      //     // areaLists.value = res.areaInfos
+      //     //活动占比
+      //     // totalArea.value.activity.series[0].data[0].value = res.activitys.Exam
+      //     // totalArea.value.activity.series[0].data[1].value = res.activitys.Vote
+      //     // totalArea.value.activity.series[0].data[2].value = res.activitys.Survey
+      //     // totalArea.value.activity.series[0].data[3].value = res.activitys.Homework
 
-            //版本占比
-            // totalArea.value.versions.series[0].data[0].value = res.basics
-            // totalArea.value.versions.series[0].data[1].value = res.standard
-            // totalArea.value.versions.series[0].data[2].value = res.major
-            versionsInfo()
-            loadingTotal.value.basics = false
-            loadingTotal.value.basics2 = false
-            loadingTotal.value.areaList = false
-            getClassData()
-            getclassification()
-            getAllList()
-            notclassify()
-          }
-        })
-        .catch((res) => {
-          ElMessage.error('全区数据获取异常')
-        })
+      //     //版本占比
+      //     // totalArea.value.versions.series[0].data[0].value = res.basics
+      //     // totalArea.value.versions.series[0].data[1].value = res.standard
+      //     // totalArea.value.versions.series[0].data[2].value = res.major
+
+      //     versionsInfo()
+      //     loadingTotal.value.basics = false
+      //     loadingTotal.value.basics2 = false
+      //     loadingTotal.value.areaList = false
+      //     // getClassData()
+      //     // getclassification()
+      //     getAllList()
+      //     notclassify()
+      //   }
+      //})
+      //.catch((res) => {
+      // ElMessage.error('全区数据获取异常')
+      //})
+      proxy.$api.getAllarea({}).then((res) => {
+        console.log(res, 'all back V2.1')
+        if (res.state === 200) {
+          versionsInfo()
+          getAllList()
+          notclassify()
+          //顶部数据
+          areaAspectsData.value[0].num = res.allScStats.areaCnt
+          areaAspectsData.value[1].num = res.allScStats.sc
+          areaAspectsData.value[2].num = res.allScStats.tch
+          areaAspectsData.value[3].num = Number(res.allScStats.lessStats.all) + Number(res.allScStats.actStats.all)
+          areaAspectsData.value[4].num = res.allScStats.size
+          //新增(周、月)
+          areaAspectsData.value[1].addweek = res.allScStats.weekSc
+          areaAspectsData.value[1].addmonth = res.allScStats.monthSc
+          areaAspectsData.value[2].addweek = res.allScStats.weekTch
+          areaAspectsData.value[2].addmonth = res.allScStats.monthTch
+          areaAspectsData.value[3].addweek = Number(res.allScStats.lessStats.week) + Number(res.allScStats.actStats.week)
+          areaAspectsData.value[3].addmonth = Number(res.allScStats.lessStats.month) + Number(res.allScStats.actStats.month)
+
+          //基础数据 左
+          activityData.value.total[0].num = res.allScStats.lessStats.week
+          activityData.value.total[1].num = res.allScStats.lessStats.term
+          activityData.value.total[2].num = res.allScStats.actStats.week
+          activityData.value.total[3].num = res.allScStats.actStats.term
+          activityData.value.total[4].num = res.allScStats.witRoom
+          activityData.value.total[5].num = res.allScStats.lessStats.all
+          activityData.value.total[6].num = res.allScStats.resourceCnt
+          activityData.value.total[7].num = res.allScStats.actStats.all
+          //基础数据  右(活动)
+          totalArea.value.activity.series[0].data[0].value = res.allScStats.actStats.exam
+          totalArea.value.activity.series[0].data[1].value = res.allScStats.actStats.vote
+          totalArea.value.activity.series[0].data[2].value = res.allScStats.actStats.survey
+          totalArea.value.activity.series[0].data[3].value = res.allScStats.actStats.homework
+          loadingTotal.value.basics = false
+          loadingTotal.value.basics2 = false
+          loadingTotal.value.areaList = false
+          getClassData(res.areaGroup)
+        }
+      }).catch((error) => {
+        ElMessage.error('全区数据获取异常')
+      })
     }
     //获取全区的版本占比(7.06调整)
     function versionsInfo () {
@@ -1493,7 +1548,7 @@ export default {
     function getAllList () {
       proxy.$api.getAreaList({}).then((res) => {
         console.log(res, 'LIST')
-        res.state === 200 ? areaLists.value = res.areaInfos : ''
+        res.state === 200 ? (areaLists.value = res.areaInfos, searchOriginal.value = res.areaInfos) : ''
       }).catch((error) => {
         ElMessage.error('学区列表API异常')
       })
@@ -1537,35 +1592,35 @@ export default {
       })
     }
     //获取全区的数据(课例活动类型)
-    function getClassData (loading) {
-      proxy.$api
-        .getClassData({})
-        .then((res) => {
-          console.log(res, '课例返回')
-          if (res.state === 200) {
-            let classPie = []
-            let activityAndclass = { classData: [], activityData: [] }
-            let nameData = []
-            for (let i in res.areaInfos) {
-              let classdata = { id: res.areaInfos[i].id, value: res.areaInfos[i].allCnt, name: res.areaInfos[i].name + '(' + res.areaInfos[i].allCnt + ')' }
-              classPie.push(classdata)
-              nameData.push(res.areaInfos[i].name)
-              activityAndclass.classData.push(res.areaInfos[i].lessCnt)
-              activityAndclass.activityData.push(res.areaInfos[i].actCnt)
-            }
-            totalArea.value.class.series[0].data = classPie
-            totalArea.value.classAndactivity.xAxis.data = nameData
-            totalArea.value.classAndactivity.series[0].data = activityAndclass.classData
-            totalArea.value.classAndactivity.series[1].data = activityAndclass.activityData
+    function getClassData (val) {
+      // proxy.$api.getClassData({}).then((res) => {
+      console.log(val, '课例返回')
+      // if (res.state === 200) {
+      let areaLists = val.sort(function (a, b) { return b.lessAct - a.lessAct })
+      let classPie = []
+      let activityAndclass = { classData: [], activityData: [] }
+      let nameData = []
+      for (let i in areaLists) {
+        let classdata = { id: areaLists[i].areaId, value: areaLists[i].lessAct, name: areaLists[i].name !== null ? areaLists[i].name + '(' + areaLists[i].lessAct + ')' : '未归区学校总计' }
+        if (i < 10) { classPie.push(classdata) }
+        areaLists[i].name !== null ? nameData.push(areaLists[i].name) : nameData.push('未归区学校总计')
+        activityAndclass.classData.push(areaLists[i].lessCnt)
+        activityAndclass.activityData.push(areaLists[i].actCnt)
+      }
 
-            loadingTotal.value.class = false
-            loadingTotal.value.classAndactivity = false
-            //getClassLivelys('')
-          }
-        })
-        .catch((res) => {
-          ElMessage.error('全区课例数据获取异常')
-        })
+      totalArea.value.class.series[0].data = classPie
+      totalArea.value.classAndactivity.xAxis.data = nameData
+      totalArea.value.classAndactivity.series[0].data = activityAndclass.classData
+      totalArea.value.classAndactivity.series[1].data = activityAndclass.activityData
+
+      loadingTotal.value.class = false
+      loadingTotal.value.classAndactivity = false
+      //getClassLivelys('')
+      // }
+      // })
+      // .catch((res) => {
+      //   ElMessage.error('全区课例数据获取异常')
+      // })
     }
     //获取课例活跃度
     function getClassLivelys (id, loading) {
@@ -1619,81 +1674,177 @@ export default {
       nowArea.value.studentCount = areaids.stuCnt
       let data = { areaId: areaids.id }
       showPattern.value = 'details'
-      proxy.$api
-        .getSchoolStatistics(data)
-        .then((res) => {
-          console.log(res, '某个学区的返回')
-          if (res.state === 200) {
-            //基础数据
-            activityData.value.oneself[0].num = res.weekLess
-            activityData.value.oneself[1].num = res.termLess
-            activityData.value.oneself[2].num = res.weekActivity + res.weekLess
-            activityData.value.oneself[3].num = res.termActivity
-            activityData.value.oneself[4].num = res.totalTime
-            activityData.value.oneself[5].num = res.allLess
-            activityData.value.oneself[6].num = 123456
-            // activityData.value.oneself[7].num = parseInt(res.examAreaCount) + parseInt(res.homeworkAreaCount) + parseInt(res.voteAreaCount) + parseInt(res.surveyAreaCount)
-            //header数量
-            nowArea.value.schoolCount = res.scCnt
-            nowArea.value.studentCount = res.stuCnt
-            nowArea.value.teacherCount = res.tchCnt
-            let teachNums = 0
-            for (let i in res.schools) {
-              teachNums += res.schools[i].teacherCount
-            }
-            aspectsData.value[0].num = res.scCnt
-            aspectsData.value[1].num = res.tchCnt
-            aspectsData.value[2].num = res.stuCnt
-            // aspectsData.value[3].num = parseInt(res.allLess) + parseInt(activityData.value.oneself[7].num)
-            aspectsData.value[0].addweek = res.weekScCnt
-            aspectsData.value[0].addmonth = res.motnhScCnt
-            aspectsData.value[1].addweek = res.weekTchCnt
-            aspectsData.value[1].addmonth = res.monthTchCnt
-            aspectsData.value[2].addweek = res.weekStuCnt
-            aspectsData.value[2].addmonth = res.monthStuCnt
-            aspectsData.value[3].addweek = parseInt(res.weekActivity) + parseInt(res.weekLess)
-            aspectsData.value[3].addmonth = parseInt(res.monthActCnt) + parseInt(res.monthLess)
-            aspectsLoading.value.headerBasics = false
-          }
-          //处理研修进度
-          let outer = [
-            { value: 0, name: '线上研修' },
-            { value: 0, name: '校本研修' },
-            { value: 0, name: '认证材料' },
-            { value: 0, name: '课堂实录' },
-          ]
-          let within = [
-            { value: 0, name: '已完成' },
-            { value: 0, name: '进行中' },
-            { value: 0, name: '未完成' },
-          ]
-          outer[0].value = res.study.onLineCount
-          outer[1].value = res.study.offlineCount
-          outer[2].value = res.study.submitCount
-          outer[3].value = res.study.classRoomCount
+      // proxy.$api.getSchoolStatistics(data).then((res) => {
+      //   console.log(res, '某个学区的返回')
+      //   if (res.state === 200) {
+      //     //基础数据
+      //     activityData.value.oneself[0].num = res.weekLess
+      //     activityData.value.oneself[1].num = res.termLess
+      //     activityData.value.oneself[2].num = res.weekActivity + res.weekLess
+      //     activityData.value.oneself[3].num = res.termActivity
+      //     activityData.value.oneself[4].num = res.totalTime
+      //     activityData.value.oneself[5].num = res.allLess
+      //     activityData.value.oneself[6].num = 123456
+      //     // activityData.value.oneself[7].num = parseInt(res.examAreaCount) + parseInt(res.homeworkAreaCount) + parseInt(res.voteAreaCount) + parseInt(res.surveyAreaCount)
+      //     //header数量
+      //     nowArea.value.schoolCount = res.scCnt
+      //     nowArea.value.studentCount = res.stuCnt
+      //     nowArea.value.teacherCount = res.tchCnt
+      //     let teachNums = 0
+      //     for (let i in res.schools) {
+      //       teachNums += res.schools[i].teacherCount
+      //     }
+      //     aspectsData.value[0].num = res.scCnt
+      //     aspectsData.value[1].num = res.tchCnt
+      //     aspectsData.value[2].num = res.stuCnt
+      //     // aspectsData.value[3].num = parseInt(res.allLess) + parseInt(activityData.value.oneself[7].num)
+      //     aspectsData.value[0].addweek = res.weekScCnt
+      //     aspectsData.value[0].addmonth = res.motnhScCnt
+      //     aspectsData.value[1].addweek = res.weekTchCnt
+      //     aspectsData.value[1].addmonth = res.monthTchCnt
+      //     aspectsData.value[2].addweek = res.weekStuCnt
+      //     aspectsData.value[2].addmonth = res.monthStuCnt
+      //     aspectsData.value[3].addweek = parseInt(res.weekActivity) + parseInt(res.weekLess)
+      //     aspectsData.value[3].addmonth = parseInt(res.monthActCnt) + parseInt(res.monthLess)
+      //     aspectsLoading.value.headerBasics = false
+      //   }
+      //   //处理研修进度
+      //   let outer = [
+      //     { value: 0, name: '线上研修' },
+      //     { value: 0, name: '校本研修' },
+      //     { value: 0, name: '认证材料' },
+      //     { value: 0, name: '课堂实录' },
+      //   ]
+      //   let within = [
+      //     { value: 0, name: '已完成' },
+      //     { value: 0, name: '进行中' },
+      //     { value: 0, name: '未完成' },
+      //   ]
+      //   outer[0].value = res.study.onLineCount
+      //   outer[1].value = res.study.offlineCount
+      //   outer[2].value = res.study.submitCount
+      //   outer[3].value = res.study.classRoomCount
 
-          within[0].value = res.study.fulfilCount
-          within[1].value = res.study.carryOnCount
-          within[2].value = res.study.noCount
+      //   within[0].value = res.study.fulfilCount
+      //   within[1].value = res.study.carryOnCount
+      //   within[2].value = res.study.noCount
 
-          console.log(outer, within)
-          areaData.value.schedule.data = within
-          areaData.value.schedule.legend.data = outer
-          areaData.value.schedule.series[0].data = within
-          areaData.value.schedule.series[1].data = outer
-          aspectsLoading.value.research = false
+      //   console.log(outer, within)
+      //   areaData.value.schedule.data = within
+      //   areaData.value.schedule.legend.data = outer
+      //   areaData.value.schedule.series[0].data = within
+      //   areaData.value.schedule.series[1].data = outer
+      //   aspectsLoading.value.research = false
 
 
-          getclassification(areaids.id)
-          getcounselor(areaids.id)
-          getClassLivelys(areaids.id)
-          employSize(areaids.id)
-          researchData(areaids.id)
-          getAreaSchool(areaids.id)
-        })
-        .catch((res) => {
-          ElMessage.error('获取学区统计数据失败')
+      //   getclassification(areaids.id)
+      //   getcounselor(areaids.id)
+      //   getClassLivelys(areaids.id)
+      //   employSize(areaids.id)
+      //   researchData(areaids.id)
+      //   getAreaSchool(areaids.id)
+      // })
+      //   .catch((res) => {
+      //     ElMessage.error('获取学区统计数据失败')
+      //   })
+
+      proxy.$api.getoneselfArea(data).then((res) => {
+        console.log(res, 'one V2')
+        //header数据
+        //  nowArea.value.schoolCount=res.schoolInfos.length
+        //  nowArea.value.studentCount=res.areaScStats.stu
+        //  nowArea.value.teacherCount=res.areaScStats.tch
+        researchData(res.schoolInfos)
+        //学区顾问
+        CounselorList.value = res.assists
+        aspectsLoading.value.counselorData = false
+        // //基本
+        aspectsData.value[0].num = res.schoolInfos.length
+        aspectsData.value[1].num = res.areaScStats.tch
+        aspectsData.value[2].num = res.areaScStats.stu
+        aspectsData.value[3].num = Number(res.areaScStats.lessStats.all) + Number(res.areaScStats.actStats.all)
+        aspectsData.value[4].num = res.areaScStats.size
+        //新增 周
+        aspectsData.value[0].addweek = res.areaScStats.weekSc
+        aspectsData.value[1].addweek = res.areaScStats.weekTch
+        aspectsData.value[2].addweek = res.areaScStats.weekStu
+        aspectsData.value[3].addweek = Number(res.areaScStats.lessStats.week) + Number(res.areaScStats.actStats.week)
+        //新增 月
+        aspectsData.value[0].addmonth = res.areaScStats.monthSc
+        aspectsData.value[1].addmonth = res.areaScStats.monthTch
+        aspectsData.value[2].addmonth = res.areaScStats.monthStu
+        aspectsData.value[3].addmonth = Number(res.areaScStats.lessStats.month) + Number(res.areaScStats.actStats.month)
+        aspectsLoading.value.headerBasics = false
+        // //基础数据 左一
+        activityData.value.oneself[0].num = res.areaScStats.lessStats.week
+        activityData.value.oneself[1].num = res.areaScStats.lessStats.term
+        activityData.value.oneself[2].num = res.areaScStats.actStats.week
+        activityData.value.oneself[3].num = res.areaScStats.actStats.term
+        activityData.value.oneself[4].num = res.areaScStats.lessStats.open
+        activityData.value.oneself[5].num = res.areaScStats.lessStats.all
+        activityData.value.oneself[6].num = res.areaScStats.resourceCnt
+        activityData.value.oneself[7].num = res.areaScStats.actStats.all
+        // //基础数据  右(活动)
+        areaData.value.research.series[0].data[0].value = res.areaScStats.actStats.exam
+        areaData.value.research.series[0].data[1].value = res.areaScStats.actStats.vote
+        areaData.value.research.series[0].data[2].value = res.areaScStats.actStats.survey
+        areaData.value.research.series[0].data[3].value = res.areaScStats.actStats.homework
+        //基础数据 右(版本占比)
+        let basicsOneself = []; let standardOneself = []; let majorOneself = [];
+        res.schoolInfos.forEach((item) => {
+          item.service.includes('YMPCVCIM') || item.service.includes('VLY6J6N6') || item.service.includes('VABAJ6NV') ? majorOneself.push(item)
+            : (item.scale === 300 && item.size === 500) || (item.size > 100 && (!item.service.includes('YMPCVCIM') && !item.service.includes('VLY6J6N6') && !item.service.includes('VABAJ6NV'))) ? standardOneself.push(item)
+              : item.scale < 300 && item.size <= 100 ? basicsOneself.push(item) : ''
         })
+        areaData.value.versions.series[0].data[0].value = basicsOneself.length
+        areaData.value.versions.series[0].data[1].value = standardOneself.length
+        areaData.value.versions.series[0].data[2].value = majorOneself.length
+        aspectsLoading.value.basics = false
+
+        //课例活跃度
+        let namedata = []
+        for (let i in res.weekLess) {
+          let num = Number(i) + Number(1)
+          namedata.push('第' + num + '周')
+        }
+        areaData.value.dynamic.series[0].data = res.weekLess
+        areaData.value.dynamic.series[1].data = res.weekLess
+        areaData.value.dynamic.xAxis.data = namedata
+        aspectsLoading.value.classWeek = false
+
+        //处理研修进度
+        let outer = [
+          { value: 0, name: '线上研修' },
+          { value: 0, name: '校本研修' },
+          { value: 0, name: '认证材料' },
+          { value: 0, name: '课堂实录' },
+        ]
+        let within = [
+          { value: 0, name: '已完成' },
+          { value: 0, name: '进行中' },
+          { value: 0, name: '未完成' },
+        ]
+        outer[0].value = res.areaScStats.srStats.online
+        outer[1].value = res.areaScStats.srStats.offline
+        outer[2].value = res.areaScStats.srStats.submit
+        outer[3].value = res.areaScStats.srStats.classRoom
+
+        within[0].value = res.areaScStats.srStats.finish
+        within[1].value = res.areaScStats.srStats.ongoing
+        within[2].value = res.areaScStats.srStats.notStarted
+        areaData.value.schedule.data = within
+        areaData.value.schedule.legend.data = outer
+        areaData.value.schedule.series[0].data = within
+        areaData.value.schedule.series[1].data = outer
+        aspectsLoading.value.research = false
+        //学区内的学校列表
+        schooltableData.value = res.schoolInfos
+        aspectsLoading.value.schoolList = false
+        //employSize(areaids.id)
+        getEmploysize(res)
+      }).catch((error) => {
+        ElMessage.error('获取学区统计数据失败')
+      })
     }
     //获取某个学区的顾问情况
     function getcounselor (val) {
@@ -1709,7 +1860,7 @@ export default {
         ElMessage.error('顾问列表获取异常')
       })
     }
-    //获取某个学区学校列表
+    //获取某个学区学校列表 和 版本占比
     function getAreaSchool (val) {
       if (!val) {
         ElMessage.error('学区ID异常,无法获取学校列表')
@@ -1765,6 +1916,8 @@ export default {
               { label: '教材', value: 'res' },
               { label: '音频', value: 'audio' },
               { label: 'HiTeach上传的数据', value: 'records' },
+              { label: '活动内容', value: 'activity' },  //活动包含(homework,survey,vote,survey)
+              { label: '德育风采', value: 'elegant' },
             ]
             for (let i in namedata) {
               let names = namedata[i].label
@@ -1782,38 +1935,72 @@ export default {
           ElMessage.error('空间内容获取失败')
         })
     }
-    //某个学区 数据占比 总数据、上周、本月
-    function researchData (areaIds) {
-      if (!areaIds) {
-        return ElMessage.error('无区域ID')
+    //获取某个学区空间使用率 V2.1
+    function getEmploysize (val) {
+      let res = val
+      //处理使用率
+      let employInfo = []
+      employInfo.push((proxy.$common.convertSize(res.useSize) / res.areaScStats.size).toFixed(2))
+      areaData.value.size.series[0].data = employInfo
+      //处理空间占比
+      let namedata = [
+        { name: '文档', title: 'doc', value: 0 },
+        { name: '图片', title: 'image', value: 0 },
+        { name: '其他', title: 'other', value: 0 },
+        { name: '视频', title: 'video', value: 0 },
+        { name: '缩略图', title: 'thum', value: 0 },
+        { name: '教材', title: 'res', value: 0 },
+        { name: '音频', title: 'audio', value: 0 },
+        { name: 'HiTeach上传的数据', title: 'records', value: 0 },
+        { name: '德育风采', title: 'elegant', value: 0 },
+      ]
+      console.log(res.typeStics, '8888888')
+      for (let i in namedata) {
+        let names = namedata[i].name
+        let titles = namedata[i].title
+        for (let e in res.typeStics) {
+          console.log(res.typeStics[e].key, '状态')
+          res.typeStics[e].key == titles ? namedata[i].value = res.typeStics[e].value : ''
+        }
       }
-      let data = { areaId: areaIds }
-      proxy.$api
-        .getResearchdata(data)
-        .then((res) => {
-          console.log(res, '学区数据占比')
-          //课例活动数据
-          let totalData = []; let lastWeek = []; let nowMonths = []
-          if (res.state === 200) {
-            res.areaSchools.forEach((item) => {
-              let names = item.name
-              totalData.push({ name: names, value: item.allCnt })
-              lastWeek.push({ name: names, value: item.weekCnt })
-              nowMonths.push({ name: names, value: item.monthCnt })
-            })
-            console.log(totalData, lastWeek, nowMonths, '查看数据')
-            totalData = (totalData.sort((a, b) => { return a.value - b.value })).slice(0, 5)
-            lastWeek = (lastWeek.sort((a, b) => { return a.value - b.value })).slice(0, 5)
-            nowMonths = (nowMonths.sort((a, b) => { return a.value - b.value })).slice(0, 5)
-            areaData.value.class.series[0].data = totalData
-            areaData.value.lastweek.series[0].data = lastWeek
-            areaData.value.monthsContrast.series[0].data = nowMonths
-          }
-          aspectsLoading.value.class = false
-        })
-        .catch((res) => {
-          ElMessage.error('API异常,学区数据占比获取失败')
-        })
+      namedata.forEach((item) => {
+        item.value = proxy.$common.convertSize(item.value)
+      })
+      areaData.value.sizeProportion.series[0].data = namedata
+      console.log(namedata, '空间占比')
+      aspectsLoading.value.size = false
+    }
+    //某个学区 数据占比 总数据、上周、本月
+    function researchData (value) {
+      // if (!areaIds) {
+      //   return ElMessage.error('无区域ID')
+      // }
+      // let data = { areaId: areaIds }
+      // proxy.$api.getResearchdata(data).then((res) => {
+      // console.log(res, '学区数据占比')
+      let areaschoolList = value
+      //课例活动数据
+      let totalData = []; let lastWeek = []; let nowMonths = []
+      // if (res.state === 200) {
+      areaschoolList.forEach((item) => {
+        let names = item.name
+        totalData.push({ name: names, value: item.less })
+        lastWeek.push({ name: names, value: item.lastWeekLess })
+        nowMonths.push({ name: names, value: item.monthLess })
+      })
+      totalData = (totalData.sort((a, b) => { return b.value - a.value })).filter((item, index) => { return index < 5 })
+      lastWeek = (lastWeek.sort((a, b) => { return b.value - a.value })).filter((item, index) => { return index < 5 })
+      nowMonths = (nowMonths.sort((a, b) => { return b.value - a.value })).filter((item, index) => { return index < 5 })
+      console.log(totalData, lastWeek, nowMonths, '查看数据')
+      areaData.value.class.series[0].data = totalData
+      areaData.value.lastweek.series[0].data = lastWeek
+      areaData.value.monthsContrast.series[0].data = nowMonths
+      // }
+      aspectsLoading.value.class = false
+      // })
+      // .catch((res) => {
+      //   ElMessage.error('API异常,学区数据占比获取失败')
+      // })
     }
     function getoption () {
       proxy.$api.getCapacity({}).then((res) => {
@@ -1839,8 +2026,8 @@ export default {
     function leaves (val) {
       // router.push('/home/campus')
       console.log(val, 3333)
-      store.commit('clickCounselor', val.tmdId)
-      store.commit('clickRoles', val.roles)
+      store.commit('clickCounselor', val.id)
+      store.commit('clickRoles', 'assist')
       router.push({ path: 'campus', query: { pattern: 'area' } })
     }
     function detailsclick (value) {
@@ -1857,13 +2044,22 @@ export default {
       timer.value = setTimeout(fn, wait)
     }
     function personnelSearch () {
-      let arr = showPattern.value === 'all' ? notClassifydata.value : schooltableData.value
+      let arr = showPattern.value === 'all' ? notClassifyoriginal.value : originalSchool.value
       let newArr = arr.filter((item) => {
         // return (item.name && item.name.includes(filterText.value)) || (item.mobile && item.mobile.includes(filterText.value)) || (item.mobile && item.mobile.tmdId.includes(filterText.value))
         return item.name.includes(areaSearchValue.value) || item.id.includes(areaSearchValue.value)
       })
       showPattern.value === 'all' ? notClassifydata.value = newArr : schooltableData.value = newArr
     }
+    //搜索学区
+    function personnelArea () {
+      let arr = searchOriginal.value
+      let newArr = arr.filter((item) => {
+        // return (item.name && item.name.includes(filterText.value)) || (item.mobile && item.mobile.includes(filterText.value)) || (item.mobile && item.mobile.tmdId.includes(filterText.value))
+        return item.name.includes(searchAreasv.value)
+      })
+      areaLists.value = newArr
+    }
     getAll()
     // getoption()
     watch(showPattern, (newValue, oldValue) => {
@@ -1876,6 +2072,13 @@ export default {
         showPattern.value === 'all' ? notClassifydata.value = notClassifyoriginal.value : schooltableData.value = originalSchool.value
       }
     })
+    watch(searchAreasv, (newdata) => {
+      if (newdata.trim().length !== 0) {
+        debounce(personnelArea, 500)
+      } else {
+        areaLists.value = searchOriginal.value
+      }
+    })
     return {
       aspectsData,
       showPattern,
@@ -1911,7 +2114,11 @@ export default {
       unit,
       notclassify,
       notClassifydata,
-      notClassifyoriginal
+      notClassifyoriginal,
+      getEmploysize,
+      searchAreasv,
+      searchOriginal,
+      personnelArea
     }
   },
 }
@@ -2274,7 +2481,7 @@ export default {
 }
 .area-listinfo {
   width: 100%;
-  height: 450px;
+  /* height: 450px; */
   background: #fff;
   padding: 1%;
   /* height: 40vh; */
@@ -2475,6 +2682,20 @@ export default {
 .sizeclass {
   width: 100% !important;
 }
+.notimage {
+  width: 70px;
+  height: 70px;
+  line-height: 70px;
+  text-align: center;
+  background-color: #bdc3c7;
+  font-size: 12px;
+  color: #ecf0f1;
+  margin: 5px;
+}
+.areaSearch {
+  width: 30%;
+  float: right;
+}
 </style>
 <style>
 .statisticsbox-all .el-loading-spinner .circular,

+ 31 - 11
TEAMModelBI/ClientApp/src/view/common/aside.vue

@@ -117,6 +117,22 @@ export default {
             isShow: true,
             sort: 5,
           },
+          {
+            name: '消息推送',
+            router: '/home/pushmsg',
+            icon: '#icon-xiaoxi',
+            permission: [],
+            isShow: true,
+            sort: 6,
+          },
+          {
+            name: '产品分析',
+            router: '/home/analysis',
+            icon: '#icon-fenxi1',
+            permission: [],
+            isShow: true,
+            sort: 7,
+          },
         ],
       },
       {
@@ -126,7 +142,7 @@ export default {
         icon: '#icon-zisunchaquyufenbu',
         permission: ['batcharea-read', 'batcharea-upd'],
         isShow: true,
-        sort: 6,
+        sort: 8,
         child: [
           {
             name: '学区管理',
@@ -134,7 +150,7 @@ export default {
             icon: '#icon-quyuguanli',
             permission: ['orgusers-read', 'orgusers-upd'],
             isShow: true,
-            sort: 7,
+            sort: 9,
           },
           {
             name: '学校管理',
@@ -142,7 +158,7 @@ export default {
             icon: '#icon-pingtai_xuexiaoguanli',
             permission: ['orgusers-read', 'orgusers-upd'],
             isShow: true,
-            sort: 8,
+            sort: 10,
           },
           {
             name: '微能力管理',
@@ -150,7 +166,7 @@ export default {
             icon: '#icon-peizhiguanli',
             permission: ['orgusers-read', 'orgusers-upd'],
             isShow: true,
-            sort: 9,
+            sort: 11,
           },
           // {
           //   name: '权限管理',
@@ -166,7 +182,7 @@ export default {
             icon: '#icon-collaboration-system',
             permission: [],
             isShow: true,
-            sort: 11,
+            sort: 12,
           },
         ],
       },
@@ -229,7 +245,7 @@ export default {
         role: ['admin', 'assist', 'leader', 'sales'],
         isShow: true,
         permission: '',
-        sort: 12,
+        sort: 13,
         child: [
           {
             name: '学区情况',
@@ -237,7 +253,7 @@ export default {
             icon: '#icon-xiangmufanwei',
             permission: [],
             isShow: true,
-            sort: 13,
+            sort: 14,
           },
           {
             name: '学校情况',
@@ -245,7 +261,7 @@ export default {
             icon: '#icon-xuexiao2',
             permission: [],
             isShow: true,
-            sort: 14,
+            sort: 15,
           },
         ],
       },
@@ -256,7 +272,7 @@ export default {
         role: ['admin', 'assist', 'leader', 'sales'],
         isShow: true,
         permission: '',
-        sort: 15,
+        sort: 16,
         child: [
           {
             name: '学校管理',
@@ -264,7 +280,7 @@ export default {
             icon: '#icon-xuexiao3',
             permission: [],
             isShow: true,
-            sort: 16,
+            sort: 17,
           },
           {
             name: '微能力点管理',
@@ -272,7 +288,7 @@ export default {
             icon: '#icon-tiaozheng1',
             permission: [],
             isShow: true,
-            sort: 17,
+            sort: 18,
           },
         ],
       },
@@ -591,6 +607,10 @@ body > .el-container {
 #asidebox .el-menu-item {
   padding: 0px 20px !important;
 }
+#asidebox .el-menu-item,
+#asidebox .el-sub-menu__title {
+  display: block;
+}
 #asidebox .indexse {
   letter-spacing: 14px;
 }

+ 307 - 82
TEAMModelBI/ClientApp/src/view/created/created.vue

@@ -17,9 +17,9 @@
             <el-form-item label="学区名称" class="special" prop="areaname.value">
               <div class="areanames">
                 <!-- <el-input v-model="formArea.areaname.value" disabled
-                            :placeholder="$t(`areaManages.createdArea.namehint`)"
+                            :placeholder="$t(`areaManages.createdArea.namehint`)"  
                             v-show="formArea.areaname.state == false" size="medium" /> -->
-                <el-input v-model="formArea.areaname.value" size="medium" placeholder="创建学区名称" />
+                <el-input v-model="formArea.areaname.value" placeholder="创建学区名称" />
               </div>
               <!-- <div class="areanames-btn">
                         <el-button type="primary" icon="el-icon-edit"
@@ -40,9 +40,9 @@
             <el-form-item :label="$t(`areaManages.createdArea.project`)" class="capacity-box">
               <el-select v-model="formArea.capacityvalue" :placeholder="$t(`areaManages.createdArea.projecthint`)">
                 <el-option v-for="item in formArea.options" :key="item.id" :label="item.name + '——' + item.standardName" :value="item.id">
-                  <el-tag class="reminder" effect="dark" style="float: left" size="small" v-if="item.id ==='02944f32-f534-3397-ea56-e6f1fc6c3714' || item.id==='69e3d413-50a1-4f5e-844a-e0f7c9622ea3'">标准</el-tag>
-                  <el-tag class="reminder" type="info" effect="dark" style="float: left" size="small" v-else-if="(item.id !=='02944f32-f534-3397-ea56-e6f1fc6c3714' || item.id !=='69e3d413-50a1-4f5e-844a-e0f7c9622ea3') && item.id !=='bde5c011-2ae4-461a-b46c-5483ba72ae45'">普通</el-tag>
-                  <el-tag class="reminder" type="success" effect="dark" style="float: left" size="small" v-else-if="item.id ==='bde5c011-2ae4-461a-b46c-5483ba72ae45'">完整</el-tag>
+                  <el-tag class="reminder" effect="dark" style="float: left" v-if="item.id ==='02944f32-f534-3397-ea56-e6f1fc6c3714' || item.id==='69e3d413-50a1-4f5e-844a-e0f7c9622ea3'">标准</el-tag>
+                  <el-tag class="reminder" type="info" effect="dark" style="float: left" v-else-if="(item.id !=='02944f32-f534-3397-ea56-e6f1fc6c3714' || item.id !=='69e3d413-50a1-4f5e-844a-e0f7c9622ea3') && item.id !=='bde5c011-2ae4-461a-b46c-5483ba72ae45'">普通</el-tag>
+                  <el-tag class="reminder" type="success" effect="dark" style="float: left" v-else-if="item.id ==='bde5c011-2ae4-461a-b46c-5483ba72ae45'">完整</el-tag>
                   <span>{{ item.name}}</span>——<span>{{item.standardName}}</span>
                 </el-option>
               </el-select>
@@ -133,13 +133,13 @@
   <div class="schoolbox" v-else-if="model == 'schollC'">
     <div class="batchCreation">
       <!-- <el-upload class="upload-demo" :before-upload="handleBeforeUpload" :on-exceed="handleExceed"> -->
-      <el-button size="small" type="primary" icon="el-icon-document-add" @click="batchDialogState = true">
+      <el-button type="primary" @click="batchDialogState = true">
         {{ $t(`schoolManages.createSchools.batch`) }}</el-button>
       <!-- </el-upload> -->
       <!-- <button class="created-btninfo">批量创校</button> -->
     </div>
     <div class="backs">
-      <el-button size="small" @click="closeandreturn('close', 'school')">返回</el-button>
+      <el-button @click="closeandreturn('close', 'school')">返回</el-button>
     </div>
     <div class="schoolListbox" v-loading="loadingSchool" :element-loading-text="loadingTexts">
       <div class="school-libox" v-for="(item, index) in schoolForm">
@@ -172,14 +172,14 @@
             <el-radio v-model="item.lang" label="2" size="large">繁体</el-radio>
             <el-radio v-model="item.lang" label="3" size="large">英语</el-radio>
           </el-form-item>
-          <el-form-item label="学段类型" prop="radio1">
-            <el-checkbox-group v-model="item.radio1">
-              <el-checkbox label="小学"></el-checkbox>
-              <el-checkbox label="初中"></el-checkbox>
+          <el-form-item label="学段类型" prop="radio1" class="radios-check">
+            <el-radio-group v-model="item.radio1">
+              <el-radio :label="item.name" v-for="item in phaselist" :key="item.value"></el-radio>
+              <!-- <el-checkbox label="初中"></el-checkbox>
               <el-checkbox label="高中"></el-checkbox>
               <el-checkbox label="职高"></el-checkbox>
-              <el-checkbox label="大学"></el-checkbox>
-            </el-checkbox-group>
+              <el-checkbox label="大学"></el-checkbox> -->
+            </el-radio-group>
           </el-form-item>
           <el-form-item label="预设管理员" class="scholl-admin" prop="presupposeAdmin">
             <el-input v-model="item.presupposeAdmin" placeholder="输入醍摩豆账号或手机号,预设学校管理员" />
@@ -247,7 +247,7 @@
       </div>
       <!--查询BB数据-->
       <div class="searchbox">
-        <el-input v-model="searchSchoolvalue" placeholder="搜索学校名称/简码 检验是否重复" size="small" @focus="searchboxState=true">
+        <el-input v-model="searchSchoolvalue" placeholder="搜索学校名称/简码 检验是否重复" @focus="searchboxState=true">
           <template #prefix>
             <el-icon class="el-input__icon">
               <search />
@@ -384,7 +384,7 @@
             <el-table-column prop="index" :label="$t(`schoolManages.createSchools.schoolinfo.serialnum`)" type=index align="center" />
             <el-table-column prop="name" :label="$t(`schoolManages.createSchools.schoolinfo.name`)" align="center" />
             <el-table-column prop="type" label="学校类型" align="center" />
-            <el-table-column prop="period" label="学段类型" align="center" />
+            <el-table-column prop="periodTxt" label="学段类型" align="center" />
             <el-table-column prop="admin" label="预设管理员" align="center" />
             <el-table-column prop="areaId" label="所属学区ID" align="center" />
             <el-table-column prop="id" label="简码" align="center" v-if="codeShow" />
@@ -509,10 +509,12 @@ const optionsData = siteValue === 'cn' ? option_cn : option_gl
 const schoolAssets = {
   num: 1,
   name: '',
-  radio1: [],
+  radio1: '',
   presupposeAdmin: '',
   code: '',
   schoolLocation: {
+    region: '',
+    regionvalue: '',
     province: '',
     provincevalue: '',
     city: '',
@@ -569,9 +571,9 @@ export default {
       type: [
         { required: true, message: '请选择学校的类型', trigger: 'change', },
       ],
-      radio1: [
-        { required: true, message: '选择学校的学段内容', trigger: 'change' },
-      ],
+      // radio1: [
+      //   { required: true, message: '选择学校的学段内容', trigger: 'change' },
+      // ],
       lang: [
         { required: true, message: '选择创建学校语系', trigger: 'change' },
       ],
@@ -579,6 +581,75 @@ export default {
         { required: true, message: '预设管理员不能为空', trigger: 'blur' },
       ]
     })
+    const phaselist_gl = [
+      { name: "學前", value: "pre" },
+      { name: "小學", value: "primary" },
+      { name: "初中", value: "junior" },
+      { name: "高中", value: "senior" },
+      { name: "中職(中專,技校,職高)", value: "secondary" },
+      { name: "高職(專科)", value: "college" },
+      { name: "大學本科", value: "university" },
+      { name: "特殊教育", value: "special" },
+      { name: "教育局", value: "edu-bureau" },
+      { name: "電教部門", value: "elecedu-dept" },
+      { name: "成人中專", value: "adult-secondary" },
+      { name: "成人高教", value: "adult-higher" },
+      { name: "碩士研究生", value: "master" },
+      { name: "博士研究生", value: "doctor" },
+      { name: "企業", value: "enterprise" },
+    ]
+    const phaselist_cn = [
+      { name: "学前", value: "pre" },
+      { name: "小学", value: "primary" },
+      { name: "初中", value: "junior" },
+      { name: "高中", value: "senior" },
+      { name: "中职(中专,技校,职高)", value: "secondary" },
+      { name: "高职(专科)", value: "college" },
+      { name: "大学本科", value: "university" },
+      { name: "特殊教育", value: "special" },
+      { name: "教育局", value: "edu-bureau" },
+      { name: "电教部门", value: "elecedu-dept" },
+      { name: "成人中专", value: "adult-secondary" },
+      { name: "成人高教", value: "adult-higher" },
+      { name: "硕士研究生", value: "master" },
+      { name: "博士研究生", value: "doctor" },
+      { name: "企业", value: "enterprise" },
+    ]
+    const phaselist = (siteValue === 'cn') ? phaselist_cn : phaselist_gl
+    const phaseIdlist_gl = [
+      { label: '學前', value: '11' },
+      { label: '小學', value: '21' },
+      { label: '初中', value: '31' },
+      { label: '高中', value: '34' },
+      { label: '中職(中專,技校,職高)', value: '36' },
+      { label: '大學本科', value: '41' },
+      { label: '高職(專科)', value: '44' },
+      { label: '特殊教育', value: '51' },
+      { label: '教育局', value: '91' },
+      { label: '電教部門', value: '51' },
+      { label: '成人中專', value: '33' },
+      { label: '成人高教', value: '42' },
+      { label: '碩士研究生', value: '41' },
+      { label: '博士研究生', value: '41' },
+      { label: '企業', value: '99' },
+    ]
+    const phaseIdlist_cn = [
+      { label: '学前', value: '11' },
+      { label: '小学', value: '21' },
+      { label: '初中', value: '31' },
+      { label: '高中', value: '34' },
+      { label: '中职(中专,技校,职高)', value: '36' },
+      { label: '大学本科', value: '41' },
+      { label: '高职(专科)', value: '44' },
+      { label: '特殊教育', value: '51' },
+      { label: '教育局', value: '91' },
+      { label: '电教部门', value: '51' },
+      { label: '成人中专', value: '33' },
+      { label: '成人高教', value: '42' },
+      { label: '硕士研究生', value: '41' },
+      { label: '博士研究生', value: '41' },
+      { label: '企业', value: '99' },
+    ]
     //创校归区
     let createdAreds = ref([])
     //结果成功or失败
@@ -654,11 +725,21 @@ export default {
       state: false,
       pass: false,
     })
+    let timer = ref('')
+    let regionInfoList = []
     onMounted(() => {
       formArea.value = JSON.parse(JSON.stringify(areaData))
       console.log(formArea, '初步的数据')
       let schoolData = schoolForm.value.push(schoolAssets)
       model.value = route.query.model
+      //製作region列表
+      if (siteValue === 'cn') {
+        regionInfoList.push({ code: 'CN', name: '中国' })
+      } else {
+        optionsData.forEach((item) => {
+          regionInfoList.push({ code: item.code, name: item.name })
+        });
+      }
     })
     //地区选择器
     function onChange (e, val) {
@@ -727,9 +808,18 @@ export default {
     function cascaderSchool (value) {
       console.log(value)
       let datas = value
+      if (siteValue === 'cn') {
+        schoolForm.value[0].schoolLocation.region = '中国'
+      }
       for (let i in optionsData) {
         if (optionsData[i].code === datas[0]) {
-          schoolForm.value[0].schoolLocation.province = optionsData[i].name
+          if (siteValue === 'cn') {
+            schoolForm.value[0].schoolLocation.province = optionsData[i].name
+          } else {
+            schoolForm.value[0].schoolLocation.region = optionsData[i].name.replace('地區', '')
+          }
+          schoolForm.value[0].schoolLocation.city = ''
+          schoolForm.value[0].schoolLocation.area = ''
           if (optionsData[i].children) {
             for (let a in optionsData[i].children) {
               if (optionsData[i].children[a].code === datas[1]) {
@@ -773,12 +863,15 @@ export default {
       //查找选中的名字
       console.log(formArea.value.capacityvalue, '选择名字')
       let names = ''
+      let standradValue = ''
       let users = JSON.parse(localStorage.getItem('userData'))
+      console.log(formArea.value.options, '8888')
       if (formArea.value.capacityvalue) {
         let selectName = formArea.value.options.filter((item) => {
           return item.id === formArea.value.capacityvalue
         })
-        formArea.value.options.forEach((item) => { item.standard === selectName[0].standard ? names = item.name : '' })
+        console.log(selectName, '787878787')
+        formArea.value.options.forEach((item) => { item.standard === selectName[0].standard ? (names = item.name, standradValue = item.standard) : '' })
       }
       let createdParame = {
         name: formArea.value.areaname.value,
@@ -792,7 +885,7 @@ export default {
         standardName: formArea.value.areaname.value,
         institution: formArea.value.institution,
         oldId: formArea.value.capacityvalue ? formArea.value.capacityvalue : '',
-        oldStandard: formArea.value.capacityvalue ? selectName[0].standard : '',
+        oldStandard: formArea.value.capacityvalue ? standradValue : '',
         oldName: formArea.value.capacityvalue ? names : '',
         areaAdmin: formArea.value.areaAdmin,
         tmdId: users.tmdId,
@@ -824,10 +917,12 @@ export default {
       let data = {
         num: idnum,
         name: '',
-        radio1: [],
+        radio1: '',
         presupposeAdmin: '',
         code: '',
         schoolLocation: {
+          region: '',
+          regionvalue: '',
           province: '',
           provincevalue: '',
           city: '',
@@ -856,7 +951,7 @@ export default {
         ElMessage.error('请完善创建创建学校类型')
         return
       }
-      if (schoolForm.value[0].radio1.length === 0) {
+      if (schoolForm.value[0].radio1 === '') {
         ElMessage.error('请完善创建创建学段类型')
         return
       }
@@ -889,17 +984,27 @@ export default {
         } else if (schoolForm.value[i].presupposeAdmin.includes(',')) {
           adminArr = schoolForm.value[i].presupposeAdmin.split(',')
         }
+        if (schoolForm.value[i].radio1 === '') {
+          ElMessage.error('请完善学段信息')
+          return
+        }
+        let newPeriod = []
+        // schoolForm.value[i].radio1.forEach((item) => {
+        for (let items of phaselist) {
+          items.name === schoolForm.value[i].radio1 ? newPeriod.push(items) : ''
+        }
         datas.push({
           name: schoolForm.value[i].name,
           admin: adminArr ? [adminArr] : [schoolForm.value[i].presupposeAdmin],
-          period: schoolForm.value[i].radio1,
+          period: newPeriod,
           size: parseInt(schoolForm.value[i].pitchSpace),
-          region: '中国',
+          region: schoolForm.value[i].schoolLocation.region,
           province: schoolForm.value[i].schoolLocation.province,
           city: schoolForm.value[i].schoolLocation.city,
           dist: schoolForm.value[i].schoolLocation.area,
           address: schoolForm.value[i].address,
           type: schoolForm.value[i].type,
+          lang: schoolForm.value[0].lang === '1' ? 'zh-CN' : schoolForm.value[0].lang === '2' ? 'zh-TW' : schoolForm.value[0].lang === '3' ? 'en-US' : 'zh-CN',
           areaId: schoolForm.value[i].areaIdcreated,
           code: schoolForm.value[i].code,
         })
@@ -933,7 +1038,7 @@ export default {
       schoolForm.value[0].name = ''
       schoolForm.value[0].presupposeAdmin = ''
       schoolForm.value[0].type = "1"
-      // schoolForm.value[0].radio1 = []
+      schoolForm.value[0].radio1 = ''
       schoolForm.value[0].pitchSpace = 0
       schoolForm.value[0].address = ''
       schoolForm.value[0].lang = "1"
@@ -1020,6 +1125,7 @@ export default {
         console.log(header, results)
         if (result) {
           results.forEach((item) => {
+            item.periodTxt = item.period
             var stringResult = item.period.split('、')
             item.period = stringResult
             item.admin = item.hasOwnProperty('admin') ? (item.admin.toString()).trim() : ''
@@ -1062,6 +1168,20 @@ export default {
           item.admin = scAdmin
         }
         scAdmin = []
+        let newPeriod = []
+        item.periodTxt = ''
+        if (item.hasOwnProperty("period")) {
+          item.period.forEach((periodItem) => {
+            (item.periodTxt != '') ? item.periodTxt += '、' : ''
+            item.periodTxt += periodItem
+            for (let items of phaselist) {
+              items.name === periodItem ? newPeriod.push(items) : ''
+            }
+          })
+        }
+        item.period = newPeriod
+        item.province = (item.hasOwnProperty("province")) ? item.province : ''
+        item.type = (item.hasOwnProperty("type")) ? item.type : 1
         presentData.push(item)
       })
       console.log(scAdmin, batchDatas, '处理结果')
@@ -1304,7 +1424,8 @@ export default {
     function getCodes () {
       console.log(schoolForm.value)
       let schooldata = schoolForm.value
-      let param = [{ id: '', name: schooldata[0].name, province: schooldata[0].schoolLocation.province, aname: schooldata[0].name, city: schooldata[0].schoolLocation.area, createCount: 0 }]
+      let provinceName = (siteValue === 'cn') ? schooldata[0].schoolLocation.province : schooldata[0].schoolLocation.region ////國際站以region為省名獲取學校簡碼
+      let param = [{ id: '', name: schooldata[0].name, province: provinceName, aname: schooldata[0].name, city: schooldata[0].schoolLocation.area, createCount: 0 }]
       let data = { schools: param }
       console.log(data, '提交数据')
       proxy.$api.getSchoolcode(data).then((res) => {
@@ -1338,7 +1459,12 @@ export default {
     //搜索学校(bb数据)
     function verifyInbb () {
       searchLoading.value = true
-      let data = { regionId: "CN" }
+      let verifycn = new RegExp("[\u4E00-\u9FA5]");
+      let verifycode = new RegExp("[A-Za-z]");
+      let state = verifycn.test(searchSchoolvalue.value) ? 'name' : verifycode.test(searchSchoolvalue.value) ? 'code' : ''
+      // let data = { regionId: "CN" }
+      let data = state === 'name' ? { regionId: "CN", name: searchSchoolvalue.value, nameFuzzy: true } : state === 'code' ? { regionId: "CN", shortCode: searchSchoolvalue.value, shortCodeFuzzy: false } : { regionId: "CN" }
+      console.log(data, '查询提交数据')
       proxy.$api.verifyDatainbb(data).then((res) => {
         console.log(res, '成功返回')
         res.length !== 0 ? resultschool.value = res : ''
@@ -1386,13 +1512,28 @@ export default {
       } else {
         adminList.push(schoolData[0].presupposeAdmin)
       }
+      //处理学段类型 数据组装
+      if (schoolData[0].radio1 === '') {
+        ElMessage.error('请完善学段信息')
+        return
+      }
+      let newPeriod = []
+      for (let items of phaselist) {
+        items.name === schoolForm.value[0].radio1 ? newPeriod.push(items) : ''
+      }
+      // for (let items of phaselist) {
+      //     items.name === schoolForm.value[i].radio1 ? newPeriod.push(items) : ''
+      // }
+      console.log(newPeriod, '新的学段')
+      let regionTmp = (siteValue === 'cn') ? '中国' : schoolData[0].schoolLocation.region
+      let provinceTmp = (siteValue === 'cn') ? schoolData[0].schoolLocation.province : schoolData[0].schoolLocation.region //計算簡碼時需要省分資料,國際站以region值代入
       let schoolonly = {
         name: schoolData[0].name,
         admin: adminList,
-        period: schoolData[0].radio1,
+        period: newPeriod,
         size: schoolData[0].pitchSpace,
-        region: '中国',
-        province: schoolData[0].schoolLocation.province,
+        region: regionTmp,
+        province: provinceTmp,
         city: schoolData[0].schoolLocation.city,
         dist: schoolData[0].schoolLocation.area,
         address: schoolData[0].address,
@@ -1424,6 +1565,8 @@ export default {
       // let site=siteValue === 'cn' ? "CN":siteValue ==='international' ? 
       let verifyData = []
       let users = JSON.parse(localStorage.getItem('userData'))
+      let regionCodeNow = ''
+      let regionNameNow = ''
       console.log(schoolForm.value)
       for (let i in schoolForm.value) {
         console.log(schoolForm.value[i].presupposeAdmin)
@@ -1433,13 +1576,26 @@ export default {
         } else if (schoolForm.value[i].presupposeAdmin.includes(',')) {
           adminArr = schoolForm.value[i].presupposeAdmin.split(',')
         }
+        //region欄位 國際站、大陸站 分站修正
+        if (siteValue === 'cn') {
+          regionNameNow = '中国'
+          regionCodeNow = 'CN'
+        } else {
+          regionInfoList.forEach(function (item) {
+            if (schoolForm.value[i].schoolLocation.region != '' && item['name'].includes(schoolForm.value[i].schoolLocation.region)) {
+              regionNameNow = item.name.replace('地區', '')
+              regionCodeNow = item.code
+            }
+          });
+        }
+        let provinceName = (siteValue === 'cn') ? schoolForm.value[i].schoolLocation.province : ''
         verifyData.push({
           name: schoolForm.value[i].name,
           admin: adminArr ? adminArr : schoolForm.value[i].presupposeAdmin,
           period: schoolForm.value[i].radio1,
           size: parseInt(schoolForm.value[i].pitchSpace),
-          region: '中国',
-          province: schoolForm.value[i].schoolLocation.province,
+          region: regionNameNow,
+          province: provinceName,
           city: schoolForm.value[i].schoolLocation.city,
           dist: schoolForm.value[i].schoolLocation.area,
           address: schoolForm.value[i].address,
@@ -1448,7 +1604,8 @@ export default {
           code: schoolForm.value[i].code,
         })
       }
-      let datas = { regionId: "CN", name: verifyData[0].name, nameFuzzy: false, shortCode: verifyData[0].code, shortCodeFuzzy: false }
+
+      let datas = { regionId: regionCodeNow, name: verifyData[0].name, nameFuzzy: false, shortCode: verifyData[0].code, shortCodeFuzzy: false }
       proxy.$api.verifyDatainbb(datas).then((res) => {
         console.log(res.length, '核验数据')
         res.length == 0 ? (verifyForstate.value.state = true, verifyForstate.value.pass = true, ElMessage.success('数据已通过核验,可执行创校')) : (verifyForstate.value.state = false, verifyForstate.value.pass = false, ElMessage.error('数据未通过核验,请检查表单内容'))
@@ -1461,9 +1618,25 @@ export default {
     //批量创建学校 数据验证BB
     function batchVerify (value, lodingverify) {
       let scArr = value
-      let snameList = []; let scodeList = []; let shortArr = [];
-      scArr.forEach((item) => { snameList.push(item.name); scodeList.push(item.id); shortArr.push(item.id) })
-      let data = { regionId: "CN", nameList: snameList, codeList: scodeList, shortCodeList: shortArr }
+      let snameList = []; let scodeList = []; let shortArr = []; let regionList = []; let regionInfoRowNow = [];
+      let regionCodeTmp = ''
+      scArr.forEach((item) => {
+        snameList.push(item.name);
+        scodeList.push(item.id);
+        shortArr.push(item.id);
+        regionInfoRowNow = regionInfoList.filter(function (rgitem) { return rgitem.name.includes(item.region) })
+        regionCodeTmp = (regionInfoRowNow.length > 0 && regionInfoRowNow[0].hasOwnProperty('code')) ? regionInfoRowNow[0]['code'] : ''
+        if (regionCodeTmp != '' && !regionList.includes(regionCodeTmp)) {
+          regionList.push(regionCodeTmp)
+        }
+      })
+      let data = { nameList: snameList, codeList: scodeList, shortCodeList: shortArr }
+      if (siteValue === 'cn') {
+        data['regionId'] = 'CN'
+      } else {
+        data['regionId'] = (regionList.length == 1) ? regionList[0] : ''
+        data['regionIdList'] = (regionList.length > 1) ? regionList : []
+      }
       proxy.$api.verifyDatainbb(data).then((res) => {
         res.length == 0 ? (ElMessage.success('数据已通过核验,可执行创校'), batchTablesArr.value = true) : (ElMessage.error('数据未通过核验,请检查表单内容'), batchTablesArr.value = true, verifyState.value = false)
       }).catch((error) => {
@@ -1475,52 +1648,67 @@ export default {
     function backTobb (value, loadingDom) {
       console.log(value, '即将回报的学校')
       let regionsJosn = siteValue === 'cn' ? option_cn : option_gl
-      let periodData = [
-        { label: '小学', value: '21' },
-        { label: '初中', value: '31' },
-        { label: '高中', value: '34' },
-        { label: '职高', value: '36' },
-        { label: '大学', value: '41' },
-      ]
+      let periodData = (siteValue === 'cn') ? phaseIdlist_cn : phaseIdlist_gl
       let periodValue = []
       for (let i in value[0].period) {
-        let name = value[0].period[i]
+        let name = value[0].period[i].name
         for (let n in periodData) {
           periodData[n].label === name ? periodValue.push(periodData[n].value) : ''
         }
       }
+      // periodValue = Array.from(new Set(periodValue))
+      periodValue = [...new Set(periodValue)]
+      //region 关键字剔除
+      let regionNums = value[0].region.indexOf('地區') !== -1 ? value[0].region.indexOf('地區') : value[0].region.length
+      let regionText = value[0].region.substr(0, regionNums)
+      let regionCodes = ''
       //省 关键字剔除
       let textNums = value[0].province.indexOf('省') !== -1 ? value[0].province.indexOf('省') : value[0].province.indexOf('自治区') !== -1 ? value[0].province.indexOf('自治区') : value[0].province.indexOf('市') !== -1 ? value[0].province.indexOf('市') : value[0].province.indexOf('特别行政区') !== -1 ? value[0].province.indexOf('特别行政区') : ''
       let provinceText = value[0].province.substr(0, textNums)
       let provinceCodes = ''
       //市 关键字剔除
-      let cityNums = value[0].city.indexOf('市') !== -1 && value[0].city !== '直辖市' ? value[0].city.indexOf('市') : value[0].city.indexOf('县') !== -1 ? value[0].city.indexOf('县') : value[0].city.indexOf('自治州') !== -1 ? value[0].city.indexOf('自治州') : value[0].city.indexOf('直辖市') !== -1 ? value[0].city.length : ''
-      let cityText = value[0].city.substr(0, cityNums)
+      let cityText = value[0].city
       let cityCodes = ''
+      if (siteValue === 'cn') {
+        let cityNums = value[0].city.indexOf('市') !== -1 && value[0].city !== '直辖市' ? value[0].city.indexOf('市') : value[0].city.indexOf('县') !== -1 ? value[0].city.indexOf('县') : value[0].city.indexOf('自治州') !== -1 ? value[0].city.indexOf('自治州') : value[0].city.indexOf('直辖市') !== -1 ? value[0].city.length : value[0].city.indexOf('区') !== -1 ? value[0].city.indexOf('区') : ''
+        cityText = value[0].city.substr(0, cityNums)
+      }
       //区 关键字剔除
       let distNums = value[0].dist.indexOf('区') !== -1 && value[0].dist.length > 2 ? value[0].dist.indexOf('区') : value[0].dist.indexOf('县') !== -1 ? value[0].dist.indexOf('县') : value[0].dist.indexOf('市') !== -1 ? value[0].dist.indexOf('市') : value[0].dist.indexOf('直辖市') !== -1 || value[0].dist.indexOf('天府新区') !== -1 ? value[0].dist.length : ''
       let distText = value[0].dist.substr(0, distNums)
+
       let childrenData = []
-      for (let i in regionsJosn) {
-        regionsJosn[i].name === value[0].province ? (provinceCodes = regionsJosn[i].code, childrenData = regionsJosn[i].children) : ''
-        for (let c in childrenData) {
-          childrenData[c].name === value[0].city ? cityCodes = childrenData[c].code : ''
+      if (siteValue === 'cn') {
+        regionCodes = 'CN'
+        for (let i in regionsJosn) {
+          regionsJosn[i].name === value[0].province ? (provinceCodes = regionsJosn[i].code, childrenData = regionsJosn[i].children) : ''
+          for (let c in childrenData) {
+            childrenData[c].name === value[0].city ? cityCodes = childrenData[c].code : ''
+          }
+        }
+      } else {
+        provinceCodes = ''
+        for (let i in regionsJosn) {
+          regionsJosn[i].name.replace('地區', '') === value[0].region ? (regionCodes = regionsJosn[i].code, childrenData = regionsJosn[i].children) : ''
+          for (let c in childrenData) {
+            childrenData[c].name === value[0].city ? cityCodes = childrenData[c].code : ''
+          }
         }
       }
-      console.log(provinceText, cityText, distText, provinceCodes, cityCodes)
+      console.log(regionText, provinceText, cityText, distText, regionCodes, provinceCodes, cityCodes)
       let backData = []
       backData.push(
         {
           code: value[0].code,
           name: value[0].name,
-          regionId: "CN",
-          regionName: "中国",
+          regionId: regionCodes,
+          regionName: regionText,
           provinceId: provinceCodes,
           provinceName: provinceText,
           cityId: cityCodes,
           cityName: cityText,
           address: value[0].address,
-          lang: "zh-cn",
+          lang: value[0].lang.toLowerCase(),
           shortCode: value[0].code,
           period: periodValue,
           source: "BI"
@@ -1537,57 +1725,72 @@ export default {
     //批量创校成功后,数据回报BB
     function batchSuccessback (data) {
       console.log(data, '准备回报数据')
+      let regionCodeNow = ''
+      let regionNameNow = ''
       let schoolObj = data
       let regionsJosn = siteValue === 'cn' ? option_cn : option_gl
-      let periodData = [
-        { label: '小学', value: '21' },
-        { label: '初中', value: '31' },
-        { label: '高中', value: '34' },
-        { label: '职高', value: '36' },
-        { label: '大学', value: '41' },
-      ]
+      let periodData = (siteValue === 'cn') ? phaseIdlist_cn : phaseIdlist_gl
       for (let i in schoolObj) {
         console.log(schoolObj[i])
         //取出学段
         schoolObj[i].backPeriod = '';
+        schoolObj[i].regionCode = ''
         schoolObj[i].provinceCode = ''
         schoolObj[i].cityCode = ''
         let periodValue = []
-        let phaseName = schoolObj[i].period
+        let phaseList = schoolObj[i].period
         //按照BB向 处理学段里面的值
-        for (let x in phaseName) {
-          let names = phaseName[x]
-          for (let d in periodData) {
-            periodData[d].label === names ? periodValue.push(periodData[d].value) : ''
-          }
+        for (let x in phaseList) {
+          let periodIdRow = periodData.filter((pitem) => {
+            return pitem.label === phaseList[x].name
+          })
+          periodIdRow.length > 0 ? periodValue.push(periodIdRow[0].value) : ''
         }
         //赋值给新学段内容
         schoolObj[i].backPeriod = periodValue
         //处理省 市 编码
-        for (let p in regionsJosn) {
-          if (regionsJosn[p].name === schoolObj[i].province) {
-            schoolObj[i].provinceCode = regionsJosn[p].code
-            let childrenData = regionsJosn[p].children
-            for (let c in childrenData) {
-              childrenData[c].name === schoolObj[i].city ? schoolObj[i].cityCode = childrenData[c].code : ''
+        if (siteValue === 'cn') {
+          schoolObj[i].regionCode = 'CN'
+          schoolObj[i].regionName = '中国'
+          schoolObj[i].langText = 'zh-cn'
+          for (let p in regionsJosn) {
+            if (regionsJosn[p].name === schoolObj[i].province) {
+              schoolObj[i].provinceCode = regionsJosn[p].code
+              let childrenData = regionsJosn[p].children
+              for (let c in childrenData) {
+                childrenData[c].name === schoolObj[i].city ? schoolObj[i].cityCode = childrenData[c].code : ''
+              }
+            }
+          }
+        } else {
+          for (let p in regionsJosn) {
+            if (regionsJosn[p].name.replace('地區', '') === schoolObj[i].region) {
+              schoolObj[i].regionCode = regionsJosn[p].code
+              schoolObj[i].regionName = regionsJosn[p].name.replace('地區', '')
+              schoolObj[i].langText = (schoolObj[i].regionCode === 'TW') ? 'zh-tw' : 'en-us'
+              let childrenData = regionsJosn[p].children
+              for (let c in childrenData) {
+                childrenData[c].name === schoolObj[i].city ? schoolObj[i].cityCode = childrenData[c].code : ''
+              }
             }
           }
         }
       }
       console.log(schoolObj, '处理数据后的内容')
       let submitData = []
+      let langText = ''
       schoolObj.forEach((item) => {
         submitData.push({
           code: item.id,
           name: item.name,
-          regionId: "CN",
-          regionName: "中国",
+          regionId: item.regionCode,
+          regionName: item.regionName,
           provinceId: item.provinceCode,
           provinceName: item.province,
           cityId: item.cityCode,
           cityName: item.city,
           address: item.address,
-          lang: "zh-cn",
+          lang: item.langText,
           shortCode: item.id,
           period: item.backPeriod,
           source: "BI"
@@ -1608,6 +1811,12 @@ export default {
         ElMessage.error('API异常,数据回报失败')
       })
     }
+    function debounce (fn, wait) {
+      if (timer.value !== null) {
+        clearTimeout(timer.value)
+      }
+      timer.value = setTimeout(fn, wait)
+    }
     getAllschool()
     getCapacitys()
     let a = isRepeat()
@@ -1618,7 +1827,10 @@ export default {
     watch(searchSchoolvalue, (newvalues) => {
       console.log(newvalues, '监听')
       // newvalues && resultschool.value.length ===0 ? resultschool.value.push({name: '成都市银都紫藤小学',time: '2019-08-15',ord:'王区管' }):''
-      newvalues && resultschool.value.length === 0 ? verifyInbb() : ''
+      //  newvalues && resultschool.value.length === 0 ? verifyInbb() : ''
+      // if (newvalues.trim().length !== 0) {
+      debounce(verifyInbb, 500)
+      // }
     })
     return {
       model,
@@ -1689,7 +1901,9 @@ export default {
       verifyBase,
       batchSuccessback,
       codeShow,
-      backstatus
+      backstatus,
+      phaselist,
+      timer
     }
   },
 }
@@ -2046,14 +2260,15 @@ export default {
   width: 100%;
   height: 100%;
   background-color: #ececec;
-  border: 1px solid #ececec;
+  border: 2px solid #ececec;
   border-radius: 0px 0px 3px 3px;
-  overflow: auto;
+  /* overflow: auto; */
 }
 .noisdata {
   width: 100%;
   height: 100%;
   position: relative;
+  z-index: 999;
 }
 .notdatas {
   width: 100%;
@@ -2114,6 +2329,9 @@ export default {
   margin-top: 5px;
   margin-right: 5px;
 }
+.institutionbox {
+  width: 100%;
+}
 </style>
 <style>
 .areabox .el-form {
@@ -2199,6 +2417,13 @@ export default {
 .bringbox button {
   padding: 5px 8px;
 }
+.result-data .el-table--fit {
+  z-index: 999;
+}
+
+.radios-check .el-radio {
+  margin-right: 20px;
+}
 @media screen and (max-width: 2600px) {
   .sizecontrol {
     width: 39.8% !important;

+ 31 - 24
TEAMModelBI/ClientApp/src/view/index/index.vue

@@ -22,23 +22,23 @@
                   </svg>
                 </div>
                 <div class="right-top-text">
-                  <p class="right-top-num">
-                    {{ item.num }}
-                  <div class="right-top-num-increase" v-show="item.classname === 'online'">
-                    <div class="right-top-num-increase-teach"><span class="right-top-num-increase-teach">教师:</span><span>{{ item.teach }}</span>
+                  <div class="right-top-num">
+                    <span class="right-valuenum">{{ item.num }}</span>
+                    <div class="right-top-num-increase" v-show="item.classname === 'online'">
+                      <div class="right-top-num-increase-teach"><span class="right-top-num-increase-teach">教师:</span><span>{{ item.teach }}</span>
+                      </div>
+                      <div class="right-top-num-increase-student"><span class="right-top-num-increase-teach">学生:</span><span>{{ item.student}}</span>
+                      </div>
                     </div>
-                    <div class="right-top-num-increase-student"><span class="right-top-num-increase-teach">学生:</span><span>{{ item.student}}</span>
+                    <div class="right-top-num-increase" v-if="(item.classname === 'datas' || item.classname === 'teach' || item.classname === 'student') && item.state === '1'">
+                      <span class="right-top-num-flag">+</span>
+                      <span class="right-top-num-nums">{{ item.increase }}</span>
+                    </div>
+                    <div class="right-top-num-reduce" v-else-if="(item.classname === 'datas' || item.classname === 'teach' || item.classname === 'student') && item.state === '2'">
+                      <span class="right-top-num-flag">-</span>
+                      <span class="right-top-num-nums">4</span>
                     </div>
                   </div>
-                  <div class="right-top-num-increase" v-if="(item.classname === 'datas' || item.classname === 'teach' || item.classname === 'student') && item.state === '1'">
-                    <span class="right-top-num-flag">+</span>
-                    <span class="right-top-num-nums">{{ item.increase }}</span>
-                  </div>
-                  <div class="right-top-num-reduce" v-else-if="(item.classname === 'datas' || item.classname === 'teach' || item.classname === 'student') && item.state === '2'">
-                    <span class="right-top-num-flag">-</span>
-                    <span class="right-top-num-nums">4</span>
-                  </div>
-                  </p>
                   <p class="right-top-title">
                   <div class="title-left">{{ item.title }}</div>
                   <!-- <div class="title-right">
@@ -2327,23 +2327,23 @@ export default {
           let basicsData = []; let standardData = []; let majorData = [];
           //基础版
           schoolList.forEach((x) => {
-            x.scale === 0 && x.size <= 100 ? basicsData.push(x) : ''
+            x.scale === 0 && x.size < 300 ? basicsData.push(x) : ''
             // x.scale === 500 && x.hard === 0 && x.serial === 0 && x.service === 0 ? standardData.push(x) : ''
             // x.scale === 500 && (x.hard !== 0 || x.serial !== 0 || x.service !== 0) ? majorData.push(x) : ''
             // ((x.scale ===300 && x.size === 500) || (x.size >100)) && (!x.service.includes('YMPCVCIM') && !x.service.includes('VLY6J6N6') && !x.service.includes('VABAJ6NV') ) ? standardData.push(x):''
             // ((x.scale === 300 && x.size === 500) || (x.size >100)) ? standardData.push(x):''
-            x.scale === 300 && x.size === 500 ? standardData.push(x) : x.size > 100 && (!x.service.includes('YMPCVCIM') && !x.service.includes('VLY6J6N6') && !x.service.includes('VABAJ6NV')) ? standardData.push(x) : ''
+            x.scale >= 500 && x.size >= 300 ? standardData.push(x) : x.size > 100 && (!x.service.includes('YMPCVCIM') && !x.service.includes('VLY6J6N6') && !x.service.includes('VABAJ6NV')) ? standardData.push(x) : ''
             x.service.includes('YMPCVCIM') || x.service.includes('VLY6J6N6') || x.service.includes('VABAJ6NV') ? majorData.push(x) : ''
           })
           console.log(basicsData, standardData, majorData, 7777777)
           if (siteValue.value === 'china') {
             versionsData.value.basics.num = basicsData.length
-            versionsData.value.basics.proportion = Math.round(((basicsData.length / schoolList.length) * 100))
+            versionsData.value.basics.proportion = ((basicsData.length / schoolList.length) * 100).toFixed(1)
             versionsData.value.standard.num = standardData.length
-            versionsData.value.standard.proportion = Math.round(((standardData.length / schoolList.length) * 100))
-            console.log(versionsData.value.standard.proportion, standardData.length, schoolList.length, '占比')
+            versionsData.value.standard.proportion = ((standardData.length / schoolList.length) * 100).toFixed(1)
             versionsData.value.major.num = majorData.length
-            versionsData.value.major.proportion = Math.round(((majorData.length / schoolList.length) * 100))
+            versionsData.value.major.proportion = ((majorData.length / schoolList.length) * 100).toFixed(1)
+            console.log(versionsData.value.standard.proportion, standardData.length, schoolList.length, '占比')
             let dataBasics = {
               title: {
                 text: '{a|' + versionsData.value.basics.proportion + '}{c|%}' + '\n' + '基础版占比',
@@ -3273,7 +3273,7 @@ export default {
 }
 
 .top-aspects {
-  width: 15%;
+  width: 16%;
   height: 110px;
   position: relative;
   /* border-radius: 10px; */
@@ -3298,12 +3298,12 @@ export default {
   display: table;
   text-align: center;
   /* background: rgba(223, 230, 233, 0.3); */
-  width: 25%;
+  width: 20%;
   position: relative;
 }
 
 .right-top-text {
-  width: 75%;
+  width: 80%;
   /* background: rgba(255, 255, 255, .9); */
   float: left;
   height: 100%;
@@ -3331,6 +3331,12 @@ export default {
   left: 50%;
   transform: translate(-50%, -50%);
   color: #dff9fb;
+  display: flex;
+  flex-wrap: nowrap;
+  justify-content: center;
+}
+.right-valuenum {
+  width: 65%;
 }
 
 /* .right-top-num span {
@@ -3877,6 +3883,7 @@ export default {
   font-size: 18px;
   display: inline-block;
   text-align: right;
+  width: 35%;
 }
 
 .right-top-num-reduce {
@@ -4055,7 +4062,7 @@ export default {
   padding-right: 0px;
   height: 30px;
   line-height: 30px;
-  background-color: #dfe6e9;
+  /* background-color: #dfe6e9; */
   border: 0px;
 }
 /*处理header 切换*/

+ 2 - 2
TEAMModelBI/ClientApp/src/view/index/operateLog.vue

@@ -28,7 +28,7 @@
         </div>
       </div>
       <div class="exportFile">
-        <el-button type="primary" size="small" @click="exportExcel">{{$t(`log.export`)}}</el-button>
+        <el-button type="primary" @click="exportExcel">{{$t(`log.export`)}}</el-button>
       </div>
       <div class="block" v-if="models==='time'">
         <div class="block-title"><span class="demonstration">日期:</span></div>
@@ -87,7 +87,7 @@
         <el-table-column property="convertTime" :label="$t(`log.tables.time`)" sortable :sort-by="['time']" align="center" />
         <el-table-column label="" align="center">
           <template #default="scope">
-            <el-button type="primary" size="small" @click.prevent="details(scope.$index, scope.row)" plain>{{$t(`log.tables.details`)}}</el-button>
+            <el-button type="primary" @click.prevent="details(scope.$index, scope.row)" plain>{{$t(`log.tables.details`)}}</el-button>
           </template>
         </el-table-column>
       </el-table>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 42850 - 0
TEAMModelBI/ClientApp/src/view/index/test.json


+ 167 - 0
TEAMModelBI/ClientApp/src/view/index/test.vue

@@ -0,0 +1,167 @@
+<template>
+  <div class="">
+    <div style="width: 100%; height: 600px">
+      <el-auto-resizer>
+        <template #default="{ height, width }">
+          <el-table-v2 :columns="columns" :data="tableData" :width="width" :height="height" :row-class="tableRowClassName" :sort-by="sortState" @column-sort="onSort" fixed />
+        </template>
+      </el-auto-resizer>
+    </div>
+    <!-- <div style="margin-top: 10px">
+      共
+      <el-link type="primary" style="font-size: 20px">{{
+        tableData.length
+      }}</el-link>
+      条数据
+    </div> -->
+  </div>
+</template>
+<script setup>
+import { ref, h } from "vue";
+import { ElMessageBox, ElMessage, ElButton, ElTag, ElCheckbox, TableV2SortOrder } from "element-plus";
+// import { request } from "../../api/request";
+import testJson from './test.json'
+import { Delete } from '@element-plus/icons-vue'
+//方式二
+// const ElButton = resolveComponent("ElButton");
+// const ElTag = resolveComponent("ElTag");
+const tableData = ref([]);
+//获取表格数据(mockjs生成)的方法
+// const getApiData = () => {
+//   setTimeout(tableData.value = testJson.schoolAssists, 5000)
+// };
+setTimeout(function () { tableData.value = testJson.schoolAssists }, 5000);
+// getApiData();
+//columns 是一个数组,里面的值为每一列的配置信息
+const columns = [
+  {
+    cellRenderer: (data) =>
+      h(
+        ElCheckbox,
+        // { onClick: () => handleDelete(data), type: "danger", icon: "Delete" },
+        { default: () => "" }
+      ),
+    width: 200,//当前列的宽度,必须设置
+    fixed: true,//是否固定列
+    align: 'center',
+  },
+  {
+    key: "id",
+    dataKey: "id",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: "id",//显示在单元格表头的文本
+    width: 200,//当前列的宽度,必须设置
+    fixed: false,//是否固定列
+    align: 'center',
+    sortable: true,
+  },
+  {
+    key: "name",
+    dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填name
+    title: "姓名",
+    width: 200,
+    fixed: false,
+  },
+  {
+    key: "id_number",
+    dataKey: "id_number",
+    title: "证件号码",
+    width: 280,
+  },
+  {
+    key: "department",
+    dataKey: "department",
+    title: "部门",
+    minWidth: 100,
+    width: 110,
+  },
+  {
+    key: "position",
+    dataKey: "position",
+    title: "职位",
+    width: 140,
+  },
+  {
+    key: "grade",
+    dataKey: "grade",
+    title: "等级",
+    width: 120,
+  },
+  {
+    key: "serial",
+    dataKey: "serial",
+    title: "发放状态",
+    width: 80,
+    cellRenderer: (data) => (
+      <>
+        <div title="学情分析"><svg class="listicon" aria-hidden="true" v-show={data.rowData.serial.length > 0 ? true : false}><use xlink:href="#icon-tongjifenxi">{{ data }}</use></svg></div>
+      </>
+    ),
+  },
+  {
+    key: "handle",
+    title: "操作",
+    width: 100,
+    align: "center",
+    cellRenderer: (data) =>
+      h(
+        ElButton,
+        { onClick: () => handleDelete(data), type: "danger", icon: Delete, size: "small" },
+        { default: () => "删除" }
+      ),
+  },
+];
+//自定义渲染带状态的表格(每隔一行显示不同的背景色)
+// const tableRowClassName = ({ row, rowIndex }) => {
+//   let step = 4;
+//   for (let i in tableData.value) {
+//     if (rowIndex === step * i - 3) {
+//       return "warning-row";
+//     }
+//     if (rowIndex === step * i - 1) {
+//       return "success-row";
+//     }
+//   }
+//   return "";
+// };
+// //删除操作
+// const handleDelete = (data) => {
+//   console.log(data, '数据')
+//   ElMessageBox.confirm(`确定删除 ${data.rowData.name}?`, "提 示", {
+//     confirmButtonText: "确定",
+//     cancelButtonText: "取消",
+//     type: "warning",
+//   })
+//     .then(() => {
+//       tableData.value.splice(data.rowIndex, 1);
+//       ElMessage({
+//         type: "success",
+//         message: "删除成功",
+//       });
+//     })
+//     .catch(() => {
+//       ElMessage({
+//         type: "info",
+//         message: "取消删除",
+//       });
+//     });
+// };
+// const sortState = ref({
+//   key: 'id',
+//   order: TableV2SortOrder.ASC,
+// })
+// const onSort = (sortBy) => {
+//   console.log(sortBy)
+//   tableData.value = tableData.value.reverse()
+//   sortState.value = sortBy
+// }
+</script>
+<style >
+.listicon {
+  width: 1.8em;
+  height: 1.8em;
+  vertical-align: -0.6em;
+  fill: currentColor;
+  overflow: hidden;
+  margin-left: 8px;
+}
+</style>

+ 3 - 0
TEAMModelBI/ClientApp/src/view/login.vue

@@ -139,6 +139,9 @@ export default {
           //     : (loading.close(), ElMessage.error(res.message))
           res.state === 200 ? ElMessage.success(proxy.$t(`login.loginSuccess`), loginSuccess(res)) : res.state === 0 ? ElMessage.error(res.msg) : res.state === 403 ? ElMessage.error('该用户无权或被禁用登录,请联系平台管理人员') : ElMessage.error('登录失败')
           loading.close()
+        }).catch((error) => {
+          ElMessage.error('API异常,登录失败')
+          loading.close()
         })
       }
       return {

+ 294 - 0
TEAMModelBI/ClientApp/src/view/participation/copy.vue

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

+ 198 - 11
TEAMModelBI/ClientApp/src/view/participation/examination.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="examinationbox">
+  <div class="examinationbox" v-if="uistate ==='default'" v-loading="paperloding" element-loading-text="数据加载中...">
     <div class="header-filter">
       <el-collapse v-model="activeNames" accordion>
         <el-collapse-item title="数据筛选" name="1">
@@ -42,7 +42,7 @@
             </el-select>
           </div>
           <div class="middlebox-left-serach">
-            <el-input v-model="findbox.searchValue" class="w-80 m-2" placeholder="输入试卷名进行搜索..." suffix-icon="el-icon-search" size="small" />
+            <el-input v-model="findValue" class="w-80 m-2" placeholder="输入试卷名进行搜索..." suffix-icon="el-icon-search" size="small" />
           </div>
         </div>
         <div class="middlebox-right">
@@ -50,7 +50,7 @@
         </div>
       </div>
     </div>
-    <div class="bottombox">
+    <div :class="[activeNames.length ===1 ? 'opensidebar':'','bottombox']">
       <div class="bottombox-list" v-if="paperData.data.length !==0">
         <div class="paperlist" v-for="item in paperData.data" :key="item.id">
           <div class="paperlist-name">
@@ -91,11 +91,11 @@
               </svg>
               <span class="paperlist-tools-download-title">下载</span>
             </span> -->
-            <span class="paperlist-tools-delete">
+            <span class="paperlist-tools-delete" @click="getExamblob(item)">
               <svg class="icon" aria-hidden="true">
                 <use xlink:href="#icon-shanchutianchong"></use>
               </svg>
-              <span class="paperlist-tools-download-title">删除</span>
+              <span class="paperlist-tools-download-title">查看</span>
             </span>
           </div>
         </div>
@@ -108,26 +108,39 @@
       </div>
     </div>
   </div>
+  <div v-else-if="uistate ==='details'" class="paperdetails">
+    <Paper @renew="backdefaults" :paperInfo="paperInfo"></Paper>
+  </div>
 </template>
 <script>
 import { ref, watch, getCurrentInstance } from 'vue'
 import { useStore } from 'vuex'
 import { ElMessage, ElLoading } from 'element-plus'
+import { useRouter } from 'vue-router'
+import BlobTool from '@/until/blobTool.js'
+import Paper from './paper.vue'
 export default {
   props: {
     detailsSchool: {
       default: {}
     },
   },
+  components: {
+    Paper
+  },
   setup (props) {
     let { proxy } = getCurrentInstance()
     const store = useStore()
+    let router = useRouter()
+    let uistate = ref('default')
     let activeNames = ref(['1'])
     const notdataImg = require('@/assets/img/notdata.png')
     let findbox = ref({
       tagValue: '',
       searchValue: ''
     })
+    let findValue = ref()
+    let timer = ref()
     const options = [
       {
         value: '测试',
@@ -164,13 +177,36 @@ export default {
     let paperData = ref({
       total: 0,
       data: [],
+      original: [],
       nowselectData: []
     })
+    //试卷相关信息
+    let paperInfo = ref({
+      total: 0,
+      title: '',
+      difficulty: 0,
+      list: [],
+      blob: {
+        url: '',
+        space: '',
+        sas: '',
+      },
+      id: '',
+      schoolcode: ''
+    })
+    let nowScode = ref('')
+    //blob相关
+    let blobData = ref({
+      osblob_uri: '',
+      osblob_sas: '',
+    })
+    let paperloding = ref(false)
     //处理筛选
     function filterInt (data) {
-      console.log(data, '试卷数据')
+      console.log(data, '开始进入方法')
       allperiod.value = data
       nowperiod.value = data.period
+      nowScode.value = data.id
       let schoolPeriod = data.period
       for (let i in schoolPeriod) {
         filters.value.pahse.option.push({ name: schoolPeriod[i].name, id: schoolPeriod[i].id })
@@ -182,7 +218,7 @@ export default {
       filters.value.grade.option = ([...allArr, ...schoolPeriod[0].grades])
       //filters.value.grade.option.unshift('全部')
       console.log(filters.value, '结果!')
-      getExamination(filters.value.pahse.option[0].id, filters.value.subject.option[0].id, true)
+      getExamination(filters.value.pahse.option[0].id, filters.value.subject.option[0].id)
     }
     //获取相应的试卷内容
     function getExamination (pahseId, subjectId, sort) {
@@ -217,6 +253,7 @@ export default {
             item.timeText = proxy.$common.timestampToTime(item.createTime, 'all')
           }
           paperData.value.data = papers
+          paperData.value.original = papers
           paperData.value.nowselectData = papers
           console.log(papers, '处理结果')
         }
@@ -234,12 +271,15 @@ export default {
         for (let p of nowperiod.value) {
           p.id === value ? (filters.value.subject.option = p.subjects, filters.value.grade.option = ([...['全部'], ...p.grades]), pahseids = value, subjects = p.subjects[0].id) : ''
         }
+        clickNum.value.subject = 0
+        clickNum.value.grade = 0
       } else if (state === 'subject') {
         clickNum.value.subject = index
         let data = nowperiod.value[clickNum.value.pahse]
         filters.value.grade.option = []
         filters.value.grade.option = ([...['全部'], ...data.grades])
         subjects = value; pahseids = nowperiod.value[clickNum.value.pahse].id
+        clickNum.value.grade = 0
       } else if (state === 'grade') {
         // clickNum.value.grade = value !== '全部' ? Number(index) + 1 : index
         clickNum.value.grade = index
@@ -272,6 +312,99 @@ export default {
       })
       paperData.value.data = selectData
     }
+    //处理HOST返回截取
+    function getBlobHost (url) {
+      let s = url || store.state.user.userProfile.blob_uri || store.state.user.studentProfile.blob_uri
+      let pattern = /[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/
+      return s.split('//')[0] + '//' + s.match(pattern)[0]
+    }
+    //获取试卷blob资源
+    async function getExamblob (value) {
+      console.log(value, '试卷内容')
+      let loading = ElLoading.service({
+        lock: false,
+        text: '正在加载试卷信息,请稍等...',
+        background: 'rgba(189, 195, 199,0.3)',
+      })
+      await getSas()
+      console.log(blobData.value, '现在去获取')
+      let paths = value.blob + '/index.json'
+      // let space = bolbs.osblob_uri.slice(bolbs.osblob_uri.indexOf('cn') + 3)
+      let urls = paths
+      // console.log(bolbs, host, space, '参数')
+      console.log(urls, '-------------', '拼接内容')
+      console.log(proxy.Blob, '原型挂载')
+      let urlheader = blobData.value.osblob_uri.substring(0, blobData.value.osblob_uri.indexOf('cn') + 2)
+      let space = blobData.value.osblob_uri.slice(blobData.value.osblob_uri.indexOf('cn') + 3)
+      console.log(urlheader, space, blobData.value.osblob_sas, '内容')
+      // let Blobs = new BlobTool(urlheader, space, '?' + blobData.value.osblob_sas, 'school')
+      // // urls = urls.slice(1)
+      // console.log(Blobs, urls, 'blob初始化')
+      proxy.$api.getExamintionpaper(blobData.value.osblob_uri + urls + '?' + blobData.value.osblob_sas).then(async (res) => {
+        console.log(res, '完整的试卷信息')
+        res.hasOwnProperty('slides') ? (await questions(res.slides, value.blob, res.name, res.score, value.id), loading.close()) : ''
+      })
+      uistate.value = 'details'
+      // router.push('/home/paperDetails')
+    }
+    //获取相应学校的sas
+    async function getSas () {
+      console.log(allperiod.value, '当前学校')
+      let schools = allperiod.value
+      let data = { cntr: schools.id }
+      await proxy.$api.getSchoolsas(data).then((res) => {
+        console.log(res, '返回的sas')
+        res.state === 200 ? (blobData.value.osblob_uri = res.osblob_uri, blobData.value.osblob_sas = res.osblob_sas) : ''
+        console.log(blobData.value, '值')
+      }).catch((error) => {
+        ElMessage.error('获取试卷信息失败,API异常')
+      })
+    }
+    //获取试题
+    async function questions (slider, blob, name, score, paperId) {
+      console.log(slider, blob, '调用到了')
+      let difficultyNum = 0
+      let listdata = []
+      for (let i of slider) {
+        console.log(blobData.value.osblob_uri + blob + '/' + i.url + '?' + blobData.value.osblob_sas, '访问的地址')
+        await proxy.$api.getExamintionpaper(blobData.value.osblob_uri + blob + '/' + i.url + '?' + blobData.value.osblob_sas).then((res) => {
+          console.log(res, res.exercise.level, '试题')
+          difficultyNum += res.exercise.level
+          listdata.push(res)
+        })
+      }
+      // paperInfo.value.difficulty = (difficultyNum / paperData.value.data.length).toFixed(0)
+      // console.log(difficultyNum, paperInfo.value.list.length)
+      paperInfo.value.list = listdata
+      paperInfo.value.title = name
+      paperInfo.value.total = score
+      paperInfo.value.difficulty = (difficultyNum / paperInfo.value.list.length).toFixed(0)
+      paperInfo.value.blob.url = blobData.value.osblob_uri
+      paperInfo.value.blob.space = blob
+      paperInfo.value.blob.sas = blobData.value.osblob_sas
+      paperInfo.value.schoolcode = nowScode.value
+      paperInfo.value.id = paperId
+      console.log(paperInfo.value, '试卷完整信息')
+    }
+    function debounce (fn, wait) {
+      if (timer.value !== null) {
+        clearTimeout(timer.value)
+      }
+      timer.value = setTimeout(fn, wait)
+    }
+    //试卷搜索
+    function personnelSearch () {
+      let arr = paperData.value.original
+      let newArr = arr.filter((item) => {
+        // return (item.name && item.name.includes(filterText.value)) || (item.mobile && item.mobile.includes(filterText.value)) || (item.mobile && item.mobile.tmdId.includes(filterText.value))
+        return item.name.includes(findValue.value)
+      })
+      paperData.value.total = newArr.length
+      paperData.value.data = newArr
+    }
+    function backdefaults (val) {
+      uistate.value = val
+    }
     watch(
       props,
       (newdata, olddata) => {
@@ -280,7 +413,46 @@ export default {
       },
       { immediate: true, deep: true }
     )
-    return { activeNames, findbox, options, filters, clickNum, filterInt, filterperiod, allperiod, getExamination, paperData, nowperiod, clickCut, notdataImg, selectContent }
+    watch(activeNames, (newdata, olddata) => {
+      console.log(newdata, olddata, '触发监听')
+    })
+    watch(findValue, (newvalue) => {
+      console.log(newvalue, '新值')
+      if (newvalue.trim().length !== 0) {
+        debounce(personnelSearch, 500)
+      } else {
+        paperData.value.total = paperData.value.original.length
+        paperData.value.data = paperData.value.original
+      }
+    })
+    return {
+      activeNames,
+      findbox,
+      options,
+      filters,
+      clickNum,
+      filterInt,
+      filterperiod,
+      allperiod,
+      getExamination,
+      paperData,
+      nowperiod,
+      clickCut,
+      notdataImg,
+      selectContent,
+      getExamblob,
+      getBlobHost,
+      getSas,
+      blobData,
+      questions,
+      uistate,
+      backdefaults,
+      paperInfo,
+      findValue,
+      timer,
+      paperloding,
+      nowScode
+    }
   },
 }
 </script>
@@ -329,7 +501,7 @@ export default {
 .bottombox {
   background-color: #e9eef3;
   margin: 10px 20px;
-  height: 75vh;
+  /* height: 75vh; */
   overflow: auto;
 }
 .paperlist {
@@ -422,8 +594,7 @@ export default {
 }
 .filtratebox {
   width: 100%;
-  padding: 10px 20px;
-  padding-bottom: 20px;
+  padding: 10px 20px 0px 20px;
   background: #fff;
   border-top: 1px solid #ccc;
 }
@@ -531,7 +702,17 @@ export default {
   font-size: 16px;
   color: #8395a7;
 }
+.paperdetails {
+  overflow: hidden;
+  height: 89vh;
+}
 @media screen and (max-width: 1920px) {
+  .bottombox {
+    height: 75vh !important;
+  }
+  .opensidebar {
+    height: 60vh !important;
+  }
 }
 @media screen and (max-width: 1400px) {
   .middlebox-left-tag {
@@ -543,6 +724,12 @@ export default {
   .examinationbox {
     height: 84vh !important;
   }
+  .bottombox {
+    height: 68vh !important;
+  }
+  .opensidebar {
+    height: 45vh !important;
+  }
 }
 </style>
 <style>

+ 440 - 162
TEAMModelBI/ClientApp/src/view/participation/index.vue

@@ -1,47 +1,41 @@
 <template>
   <!--学校列表-->
   <div class="schoolboxtad" v-show="models === 'default'">
-    <div class="select-List">
-      <!-- <div class="site-box">
-        <el-select v-model="siteList.siteValue" placeholder="站点">
-          <el-option v-for="item in siteList.list" :key="item.id" :label="item.label" :value="item.value">
-          </el-option>
-        </el-select>
-      </div> -->
-      <div class="province-box">
-        <el-select v-model="provinceOptions.provinceValue" :placeholder="$t(`areaManages.selector.provinceDefault`)" @change="areaSelctChange(provinceOptions.provinceValue, 'province')" size="small">
-          <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">
-        <el-select v-model="cityOptions.cityValue" :placeholder="$t(`areaManages.selector.cityDefault`)" @change="areaSelctChange(cityOptions.cityValue, 'city')" size="small">
-          <el-option v-for="item in cityOptions.cityInfo" :key="item.code" :label="item.name" :value="item.name">
-          </el-option>
-        </el-select>
+    <div class="select-top">
+      <div class="select-List">
+        <div class="province-box">
+          <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">
+          <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">
+          <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">
+          <svg class="closebtnIcon" aria-hidden="true" @click="closeSelectarea">
+            <use xlink:href="#icon-quxiao"></use>
+          </svg>
+        </div>
       </div>
-      <div class="dist-box">
-        <el-select v-model="distOptions.distValue" filterable allow-create default-first-option :placeholder="$t(`areaManages.selector.areaDefault`)" @change="areaSelctChange(distOptions.distValue, 'dist')" size="small">
-          <el-option v-for="item in distOptions.distInfo" :key="item.code" :label="item.name" :value="item.name">
-          </el-option>
-        </el-select>
+      <div class="boxselect">
+        <div class="schoolNums"><span>学校数量:</span><span>{{tablesccnt}}</span></div>
       </div>
-      <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 class="selectSchool-box">
+        <el-input v-model="schoolKey" placeholder="搜索 学校名称/学校简码" clearable />
       </div>
     </div>
-    <!-- <div class="boxselect" v-if="PowerShow">
-            <el-button size="small" @click="createdSchoolbtn">
-                <svg class="created-icon" aria-hidden="true">
-                    <use xlink:href="#icon-chuangjianx"></use>
-                </svg>
-                创建学校
-            </el-button>
-        </div> -->
-    <div class="school-list">
-      <el-table :data="tableData" id="tableExclusive" style="width: 100%" height="75vh" v-loading="loading" element-loading-text="加载中..." empty-text="暂无相关数据">
+    <div class="school-list" style="width: 96%; height: 75vh" v-loading="loading" element-loading-text="加载中...">
+      <!-- <el-table :data="tableData" id="tableExclusive" style="width: 100%" height="75vh" v-loading="loading" element-loading-text="加载中..." empty-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">
@@ -50,18 +44,8 @@
           </template>
         </el-table-column>
         <el-table-column prop="name" :label="$t(`schoolManages.tables.name`)" sortable align="center" />
-        <!-- <el-table-column label="学段" width="150" align="center">
-                    <template #default="scope">
-                        <span>{{scope.row.period[0].name}}</span>
-                    </template>
-                </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> -->
             <div class="scalebox">
               <p class="scalebox-content basic" v-if="scope.row.scale === 0 && scope.row.size <=100">
                 基础版
@@ -88,8 +72,6 @@
           </template>
         </el-table-column>
         <el-table-column prop="location" label="位置" align="center" />
-        <!-- <el-table-column prop="city" :label="$t(`schoolManages.tables.city`)" align="center" />
-                <el-table-column prop="dist" :label="$t(`schoolManages.tables.area`)" align="center" /> -->
         <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">
@@ -117,17 +99,20 @@
             </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">
           <template #default="scope">
-            <el-button type="primary" size="small" @click.prevent="deleteRow(scope.$index, scope.row)" v-if="userPower.roles.includes('sales')">
+            <el-button type="primary" @click.prevent="deleteRow(scope.$index, scope.row)" v-if="userPower.roles.includes('sales')">
               查看</el-button>
-            <!-- <el-button type="danger" size="small" @click="removeSchool(scope.row,scope.$index)">删除</el-button> -->
-            <el-button type="primary" size="small" @click.prevent="deleteRow(scope.$index, scope.row)" v-else>
+            <el-button type="primary" @click.prevent="deleteRow(scope.$index, scope.row)" v-else>
               {{ $t(`schoolManages.tables.operatecontent`) }}</el-button>
           </template>
         </el-table-column>
-      </el-table>
+      </el-table> -->
+      <el-auto-resizer>
+        <template #default="{ height, width }">
+          <el-table-v2 :columns="columns" :data="tableData" :width="width" :height="height" :estimated-row-height="40" :sort-by="sortState" @column-sort="onSort" fixed />
+        </template>
+      </el-auto-resizer>
     </div>
   </div>
   <!--学校列表end-->
@@ -140,7 +125,7 @@
         </svg>
         <span class="changebtn-title">{{ $t(`schoolManages.gradSet.save`) }}</span>
       </el-button>
-      <el-button type="primary" size="small" @click="schoolClose">
+      <el-button type="primary" @click="schoolClose">
         <svg class="back-icon" aria-hidden="true">
           <use xlink:href="#icon-fanhui"></use>
         </svg>
@@ -249,7 +234,7 @@
         </div>
       </el-tab-pane>
       <el-tab-pane :label="$t(`schoolManages.redactGrading`)">
-        <SetSchool :detailsSchool="detailsSchool" ref="setSchoolData"></SetSchool>
+        <SetSchool :detailsSchool="detailsSchool" ref="setSchoolData" @schoolDetailInfo="schoolDetailInfo"></SetSchool>
       </el-tab-pane>
       <el-tab-pane label="试卷资源">
         <Exammination :detailsSchool="detailsSchool"></Exammination>
@@ -259,11 +244,11 @@
   <!--编辑学校页面end-->
 </template>
 <script>
-import { reactive, ref, getCurrentInstance, toRef, onMounted, watch } from 'vue'
+import { reactive, ref, getCurrentInstance, onMounted, watch, h } from 'vue'
 import option_cn from '@/static/regions/region_cn.json'
 import option_gl from '@/static/regions/region_gl.json'
 import { useStore } from 'vuex'
-import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
+import { ElMessage, ElLoading, ElMessageBox, TableV2SortOrder, ElCheckbox } from 'element-plus'
 import { useRouter } from 'vue-router'
 import jwt_decode from 'jwt-decode'
 import SetSchool from './setPhase.vue'
@@ -320,6 +305,7 @@ export default {
       scale: 0,
     })
     let originalData = ref([])
+    let originalNum = ref(0)
     const options = optionsData
     const props = {
       value: 'name',
@@ -373,6 +359,7 @@ export default {
       { id: 5, name: '卷卡合一阅卷系统', icon: '#icon-pingtai_kaoshi', key: 'VABAJ6NV' },
       { id: 6, name: '教研中心模组', icon: '#icon-jiaoyan', key: 'VLY6J6N6' },
     ])
+    let tablesccnt = ref(0)
     provinceOptions.value.optionInfo = optionsData
     console.log(store.state.point)
     //下拉加载
@@ -387,14 +374,183 @@ export default {
       distCode: '',
     })
     let timer = ref()
+    const sortState = ref({
+      key: 'id',
+      order: TableV2SortOrder.ASC,
+    })
+    const onSort = (sortBy) => {
+      console.log(sortBy)
+      tableData.value = tableData.value.sort(function (a, b) {
+        if (sortBy.order === 'asc') {
+          return b.size - a.size
+        } else {
+          return a.size - b.size
+        }
+      })
+      sortState.value = sortBy
+    }
+    const columns = [
+      // {
+      //   cellRenderer: (data) =>
+      //     h(
+      //       ElCheckbox,
+      //       // { onClick: () => handleDelete(data), type: "danger", icon: "Delete" },
+      //       { onChange: () => selectChange(data.rowData) },
+      //       { default: () => "" }
+      //     ),
+      //   width: 100,//当前列的宽度,必须设置
+      //   align: 'center',
+      // },
+      {
+        // key: "name",
+        // dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填name
+        title: "校徽",
+        width: 200,
+        fixed: false,
+        align: 'center',
+        headerClass: 'testclass',
+        cellRenderer: (data) => (
+          <>
+            <el-image style="width: 55px; height: 55px;margin:5px" src={data.rowData.picture} fit="contain" v-show={data.rowData.picture ? true : false}></el-image>
+            <div style=" width: 55px;height: 55px;line-height: 55px;text-align: center;background-color: #bdc3c7;font-size: 10px;color: #ecf0f1;margin:5px;" v-show={!data.rowData.picture ? true : false}>暂无图片</div>
+          </>
+        )
+      },
+      {
+        key: "name",
+        dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填name
+        title: "名称",
+        width: 200,
+        fixed: false,
+        align: 'center',
+        headerClass: 'testclass',
+      },
+      {
+        // key: "name",
+        // dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填name
+        title: "规模版本",
+        width: 100,
+        fixed: false,
+        align: 'center',
+        headerClass: 'testclass',
+        // sortable: true,
+        cellRenderer: (data) => (
+          <>
+            <div style="color:#409EFF" v-show={data.rowData.scale === 0 && (data.rowData.size < 100 || data.rowData.size == 100) ? true : false}>基础版</div>
+            <div style="color:#67C23A" v-show={(data.rowData.scale === 300 && data.rowData.size === 500) || (data.rowData.size > 100 && (!data.rowData.service.includes('YMPCVCIM') && !data.rowData.service.includes('VLY6J6N6') && !data.rowData.service.includes('VABAJ6NV'))) ? true : false}>标准版</div>
+            <div style="color: #e6a23c;" v-show={data.rowData.service.includes('YMPCVCIM') || data.rowData.service.includes('VLY6J6N6') || data.rowData.service.includes('VABAJ6NV') ? true : false}>专业版</div>
+          </>
+        ),
+      },
+      {
+        key: "id",
+        dataKey: "id",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+        title: "学校简码",//显示在单元格表头的文本
+        width: 150,//当前列的宽度,必须设置
+        align: 'center',
+        headerClass: 'testclass',
+      },
+      {
+        key: "location",
+        dataKey: "location",
+        title: "位置",
+        align: 'center',
+        width: 200,
+        headerClass: 'testclass',
+      },
+      {
+        key: "size",
+        dataKey: "size",
+        title: "空间大小",
+        width: 170,
+        align: 'center',
+        sortable: true,
+        headerClass: 'testclass',
+      },
+      // {
+      //   key: "assisName",
+      //   dataKey: "assisName",
+      //   title: "关联管家",
+      //   align: 'center',
+      //   width: 150,
+      // },
+      {
+        key: "serial",
+        dataKey: "serial",
+        title: "模组情况",
+        align: 'center',
+        width: 200,
+        headerClass: 'testclass',
+        cellRenderer: (data) => (
+          <>
+            <div title="学情分析" v-show={data.rowData.service.includes('YMPCVCIM') ? true : false}>
+              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-tongjifenxi"></use></svg>
+            </div>
+            <div title="智慧学校管理服务" v-show={data.rowData.service.includes('IPDYZYLC') ? true : false}>
+              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-zhihuixiaoyuan"></use></svg>
+            </div>
+            <div title="A Class ONE 智慧学伴" v-show={data.rowData.service.includes('3CLYJ6NP') ? true : false}>
+              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-jxuexiao2"></use></svg>
+            </div>
+            <div title="数据存储服务空间" v-show={data.rowData.service.includes('IPALJ6NY') ? true : false}>
+              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-yuncunchu"></use></svg>
+            </div>
+            <div title="卷卡合一阅卷系统" v-show={data.rowData.service.includes('VABAJ6NV') ? true : false}>
+              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-pingtai_kaoshi"></use></svg>
+            </div>
+            <div title="教研中心模组" v-show={data.rowData.service.includes('VLY6J6N6') ? true : false}>
+              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-jiaoyan"></use></svg>
+            </div>
+          </>
+        ),
+      },
+      {
+        key: "areaName",
+        dataKey: "areaName",
+        title: "所属学区",
+        width: 150,
+        align: 'center',
+        headerClass: 'testclass',
+      },
+      {
+        title: '数据统计',
+        width: 150,
+        align: 'center',
+        headerClass: 'testclass',
+        cellRenderer: (data) => (
+          <>
+            <div title="查看学校相应分析" onClick={skipAnalyse.bind(this, data.rowData)}>
+              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-shujufenxi"></use></svg>
+            </div>
+          </>
+        )
+      },
+      {
+        key: "handle",
+        title: "操作",
+        width: 150,
+        align: "center",
+        headerClass: 'testclass',
+        // fixed: 'right',
+        cellRenderer: (data) =>
+        (
+          <>
+            <el-button type="primary" onClick={deleteRow.bind(this, data.rowData)} v-show={userVerify.roles.includes('sales') ? false : true}>编辑</el-button>
+            <el-button type="primary" onClick={deleteRow.bind(this, data.rowData)} v-show={userVerify.roles.includes('sales') ? true : false}>查看</el-button>
+          </>
+        ),
+      },
+    ];
+    let userVerify = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
+    let schoolKey = ref('')
     //学校详情 
     let detailsSchool = ref()
     onMounted(() => {
       //监听表格滚动事件
       // let table = mutipleTable.value._value.layout.table.refs.bodyWrapper;
-      let table = document.getElementById('tableExclusive')
-      console.log(table, '查看是否获取到')
-      table.addEventListener("scroll", (res) => { loadmore(res) }, true);
+      // let table = document.getElementById('tableExclusive')
+      // console.log(table, '查看是否获取到')
+      // table.addEventListener("scroll", (res) => { loadmore(res) }, true);
     })
     const loadmore = (res) => {
       if (res.target.scrollTop && ((res.target.scrollHeight - 20) <= (res.target.scrollTop + res.target.clientHeight))) {
@@ -416,34 +572,36 @@ export default {
         roleA = user.roles[0]
       }
       let data = roleA === 'admin' || roleA === 'leader' ? {} : { tmdId: JSON.parse(localStorage.getItem('userData')).tmdId, role: roleA }
-      proxy.$api.getSchooldata(data).then((res) => {
-        console.log(res, '获取学校列表assist')
+      proxy.$api.getSchool(data).then((res) => {
+        console.log(res, '获取学校列表assistV2')
         //处理关联管家  拼内容
         // res.schoolAssists.splice(3)
-        for (let i in res.schoolAssists) {
-          res.schoolAssists[i].serviceData = []
-          if (res.schoolAssists[i].assists) {
-            res.schoolAssists[i].assisName = ''
-            res.schoolAssists[i].location = res.schoolAssists[i].dist !== null ? res.schoolAssists[i].province + res.schoolAssists[i].city + res.schoolAssists[i].dist : res.schoolAssists[i].province + res.schoolAssists[i].city
-            let datas = res.schoolAssists[i].assists
+        //处理关联管家  拼内容
+        for (let i in res.scInfos) {
+          res.scInfos[i].serviceData = []
+          res.scInfos[i].location = res.scInfos[i].dist !== null ? res.scInfos[i].province + res.scInfos[i].city + res.scInfos[i].dist : res.scInfos[i].province + res.scInfos[i].city
+          if (res.scInfos[i].assists) {
+            res.scInfos[i].assisName = ''
+            let datas = res.scInfos[i].assists
             for (let y in datas) {
-              res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+              res.scInfos[i].assisName = res.scInfos[i].assisName + datas[y].name + ','
             }
           }
-          if (res.schoolAssists[i].service.length > 0) {
-            res.schoolAssists[i].service.forEach((x) => {
+          if (res.scInfos[i].service && res.scInfos[i].service.length > 0) {
+            res.scInfos[i].service.forEach((x) => {
               for (let m in patternIcon.value) {
-                patternIcon.value[m].key === x ? res.schoolAssists[i].serviceData.push(patternIcon.value[m]) : ''
+                patternIcon.value[m].key === x ? res.scInfos[i].serviceData.push(patternIcon.value[m]) : ''
               }
             })
           }
         }
         console.log(res)
-        res.state == 200 ? (tableData.value.push(...res.schoolAssists), (originalData.value = res.schoolAssists), (loading.value = false), tableNexttoken.value = res.continuationToken) : ''
+        res.state == 200 ? (tableData.value = [], originalData.value = [], tableData.value.push(...res.scInfos), (originalData.value = res.scInfos), tablesccnt.value = res.allCnt, originalNum.value = res.allCnt) : ''
+        loading.value = false
       })
     }
     //点击学校列表,详情
-    function deleteRow (index, data) {
+    function deleteRow (data, index) {
       console.log(index, data, 'DATA')
       let school = data
       //处理的基础设置
@@ -452,7 +610,7 @@ export default {
       nowPitchdata.value = Object.assign(nowPitchdata.value, data)
       nowPitchdata.value.address = data.address
       nowPitchdata.value.name = data.name
-      nowPitchdata.value.type = data.type.toString()
+      // nowPitchdata.value.type = data.type.toString()
       nowPitchdata.value.scale = data.scale
       nowPitchdata.value.standard = data.standard
       nowPitchdata.value.areaId = data.areaId
@@ -467,7 +625,7 @@ export default {
       console.log(store.state.point, '目前现有的所有区')
       store.state.point.length ? areaSelect.value.data.push(...store.state.point) : getoption()
       proxy.$api.getNowscholl({ schoolId: school.id }).then((res) => {
-        res.state === 200 ? (detailsSchool.value = res.schoolAssists, models.value = 'details') : ElMessage.error('详情API异常,访问失败')
+        res.state === 200 ? (detailsSchool.value = res.schoolAssists, nowPitchdata.value.type = res.schoolAssists.type.toString(), models.value = 'details') : ElMessage.error('详情API异常,访问失败')
       }).catch((error) => {
         ElMessage.error('详情API异常,访问失败')
         return
@@ -487,101 +645,116 @@ export default {
     }
     //地区选择
     async function areaSelctChange (value, model) {
-      console.log(value, model, '触发')
       loading.value = true
-      let user = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
-      console.log(user, '人员')
-      let roleA = ''
-      if (user.roles.length > 1) {
-        user.roles.includes('admin') ? roleA = 'admin' :
-          user.roles.includes('leader') ? roleA = 'leader' :
-            user.roles.includes('assist') ? roleA = 'assist' :
-              user.roles.includes('sales') ? roleA = 'sales' :
-                user.roles.includes('rdc') ? roleA = 'rdc' : ''
-      } else {
-        roleA = user.roles[0]
-      }
+      console.log(value, model)
       var schoolListDatas = []
       var nextPageToken = ''
+      // let textState = (values.includes('自治区') || values.includes('市')) && model === 'province' ? true : false
+      // let value = values.indexOf('省') === -1 && model === 'province' && textState === false ? values + '省' : values
+      // console.log(values, value, model, '调用的select')
       var regionsData = optionsData
       if (model === 'province') {
         //传输下一级的数据给select
         let cityData = regionsData.filter((item) => {
           return value.includes(item.name)
         })
-        cityOptions.value.cityInfo = cityData[0].children
-        let textNums = value.indexOf('省') !== -1 ? value.indexOf('省') : value.indexOf('自治区') !== -1 ? value.indexOf('自治区') : value.indexOf('市') !== -1 ? value.indexOf('市') : value.indexOf('特别行政区') !== -1 ? value.indexOf('特别行政区') : ''
-        let disposeText = value.substr(0, textNums)
-        console.log(textNums, disposeText, '位置')
-        let data = roleA === 'admin' || roleA === 'leader' ? { province: disposeText } : { province: disposeText, tmdId: user.tmdId }
-        await proxy.$api.getSchooldata(data).then((res) => {
-          console.log(res, '筛选结果')
-          // res.state === 200 ? tableData.value=res.schoolAssists:''
-          res.state === 200 ? (schoolListDatas = res.schoolAssists, selectValue.value.province = disposeText, nextPageToken = res.continuationToken) : ''
-        }).catch((error) => {
-          ElMessage.error('API异常,数据 省 筛选失败')
-        })
+        console.log(cityData, '筛选记过')
+        cityOptions.value.cityInfo = cityData[0].hasOwnProperty('children') ? cityData[0].children : []
+        let disposeText = ''
+        if (siteValue === 'cn') {
+          let textNums = value.indexOf('省') !== -1 ? value.indexOf('省') : value.indexOf('自治区') !== -1 ? value.indexOf('自治区') : value.indexOf('市') !== -1 ? value.indexOf('市') :
+            value.indexOf('特别行政区') !== -1 ? value.indexOf('特别行政区') : value.indexOf('地區') !== -1 ? value.indexOf('地區') : value
+          console.log(textNums, '数字')
+          disposeText = typeof textNums == 'number' ? value.substr(0, textNums) : value
+          console.log(textNums, disposeText, '位置')
+        } else {
+          disposeText = value
+        }
+        // let data = { province: disposeText }
+        console.log(disposeText, value, '省')
+        //遍历list
+        let schoolData = []
+        for (let item of originalData.value) {
+          item.province ? item.province.includes(disposeText) ? schoolData.push(item) : '' : ''
+        }
+        console.log(schoolData, '123456')
+        tableData.value = schoolData
+        // await proxy.$api.getSchooldata(data).then((res) => {
+        //   console.log(res, '筛选结果')
+        //   // res.state === 200 ? tableData.value=res.schoolAssists:''
+        //   res.state === 200 ? (schoolListDatas = res.schoolAssists, selectValue.value.province = disposeText, nextPageToken = res.continuationToken, tablesccnt.value = res.scCnt) : ''
+        // }).catch((error) => {
+        //   ElMessage.error('API异常,数据 省 筛选失败')
+        // })
         // tableData.value = schoolData
         // console.log(schoolData, tableData.value)
       } else if (model === 'city') {
         let distData = cityOptions.value.cityInfo.filter((item) => {
           return value.includes(item.name)
         })
-        distOptions.value.distInfo = distData[0].children
+        distOptions.value.distInfo = distData[0].hasOwnProperty('children') ? distData[0].children : []
         // let provinceData = provinceOptions.value.provinceValue
         // let schoolData = originalData.value.filter((items) => {
         //   return value.includes(items.city) && provinceData.includes(items.province)
         //   // return items.city === value && items.province === provinceData
         // })
         // tableData.value = schoolData
-        let cityNums = value.indexOf('市') !== -1 && value !== '直辖市' ? value.indexOf('市') : value.indexOf('县') !== -1 ? value.indexOf('县') : value.indexOf('自治州') !== -1 ? value.indexOf('自治州') : value.indexOf('直辖市') !== -1 ? value.length : ''
-        let disposeText = value.substr(0, cityNums)
-        console.log(cityNums, disposeText, '位置')
+        let disposeText = ''
+        if (siteValue === 'cn') {
+          let cityNums = value.indexOf('市') !== -1 && value !== '直辖市' ? value.indexOf('市') : value.indexOf('县') !== -1 ? value.indexOf('县') :
+            value.indexOf('自治州') !== -1 ? value.indexOf('自治州') : value.indexOf('縣') !== -1 ? value.indexOf('縣') : value.indexOf('直辖市') !== -1 ? value.length : ''
+          disposeText = value.substr(0, cityNums)
+          console.log(cityNums, disposeText, '位置')
+        } else {
+          disposeText = value
+        }
+        let CityschoolData = []
+        // originalData.value.filter((items) => {
+        //   return items.province.includes(selectValue.value.province) && items.city.includes(disposeText)
+        // })
+        for (let item of originalData.value) {
+          item.province && item.city ? item.province.includes(selectValue.value.province) && item.city.includes(disposeText) ? CityschoolData.push(item) : '' : ''
+        }
+        console.log(CityschoolData, '456789')
+        tableData.value = CityschoolData
         // let data = { province: selectValue.value.province ? selectValue.value.province : '', city: disposeText }
-        let data = roleA === 'admin' || roleA === 'leader' ? { province: selectValue.value.province ? selectValue.value.province : '', city: disposeText } : { province: selectValue.value.province ? selectValue.value.province : '', city: disposeText, tmdId: user.tmdId }
-        await proxy.$api.getSchooldata(data).then((res) => {
-          res.state === 200 ? (schoolListDatas = res.schoolAssists, selectValue.value.city = disposeText, nextPageToken = res.continuationToken) : ''
-        }).catch((error) => {
-          ElMessage.error('API异常,数据 市/县 筛选失败')
-        })
+        // await proxy.$api.getSchooldata(data).then((res) => {
+        //   res.state === 200 ? (schoolListDatas = res.schoolAssists, selectValue.value.city = disposeText, nextPageToken = res.continuationToken, tablesccnt.value = res.scCnt) : ''
+        // }).catch((error) => {
+        //   ElMessage.error('API异常,数据 市/县 筛选失败')
+        // })
       } else if (model === 'dist') {
         let provinceData = provinceOptions.value.provinceValue
         let cityData = cityOptions.value.cityValue
         console.log(cityData, provinceData, '进入到地区选择')
-        let distNums = value.indexOf('区') !== -1 && value.length > 2 ? value.indexOf('区') : value.indexOf('县') !== -1 ? value.indexOf('县') : value.indexOf('市') !== -1 ? value.indexOf('市') : value.indexOf('直辖市') !== -1 || value.indexOf('天府新区') !== -1 ? value.length : ''
-        let disposeText = value.substr(0, distNums)
-        console.log(distNums, disposeText, '位置')
-        // let data = { province: selectValue.value.province ? selectValue.value.province : '', city: selectValue.value.city ? selectValue.value.city : '', dist: disposeText }
-        let data = roleA === 'admin' || roleA === 'leader' ? { province: selectValue.value.province ? selectValue.value.province : '', city: selectValue.value.city ? selectValue.value.city : '', dist: disposeText } : { province: selectValue.value.province ? selectValue.value.province : '', city: selectValue.value.city ? selectValue.value.city : '', dist: disposeText, tmdId: user.tmdId }
-        await proxy.$api.getSchooldata(data).then((res) => {
-          res.state === 200 ? (schoolListDatas = res.schoolAssists, nextPageToken = res.continuationToken) : ''
-        }).catch((error) => {
-          ElMessage.error('API异常,数据 地区 筛选失败')
-        })
-      }
-      //统一处理
-      console.log(schoolListDatas, '处理前的')
-      for (let i in schoolListDatas) {
-        schoolListDatas[i].serviceData = []
-        if (schoolListDatas[i].assists) {
-          schoolListDatas[i].assisName = ''
-          schoolListDatas[i].location = schoolListDatas[i].dist !== null ? schoolListDatas[i].province + schoolListDatas[i].city + schoolListDatas[i].dist : schoolListDatas[i].province + schoolListDatas[i].city
-          let datas = schoolListDatas[i].assists
-          for (let y in datas) {
-            schoolListDatas[i].assisName = schoolListDatas[i].assisName + datas[y].tmdName + ','
-          }
+        // let schoolData = originalData.value.filter((items) => {
+        //   return cityData.includes(items.city) && provinceData.includes(items.province) && value.includes(items.dist)
+        //   // return items.city === cityData && items.province === provinceData && items.dist === value
+        // })
+        // tableData.value = schoolData
+        let disposeText = ''
+        if (siteValue === 'cn') {
+          let distNums = value.indexOf('区') !== -1 && value.length > 2 ? value.indexOf('区') : value.indexOf('县') !== -1 ? value.indexOf('县') : value.indexOf('市') !== -1 ? value.indexOf('市') : value.indexOf('直辖市') !== -1 || value.indexOf('天府新区') !== -1 ? value.length : ''
+          disposeText = value.substr(0, distNums)
+          console.log(distNums, disposeText, '位置')
+        } else {
+          disposeText = value
         }
-        if (schoolListDatas[i].service.length > 0) {
-          schoolListDatas[i].service.forEach((x) => {
-            for (let m in patternIcon.value) {
-              patternIcon.value[m].key === x ? schoolListDatas[i].serviceData.push(patternIcon.value[m]) : ''
-            }
-          })
+        let distschoolData = []
+        // originalData.value.filter((items) => {
+        //   return items.province.includes(selectValue.value.province) && items.city.includes(selectValue.value.city) && (items.dist !== null ? items.dist.indexOf(disposeText) !== -1 : '')
+        // })
+        for (let item of originalData.value) {
+          item.province && item.city && item.dist ? item.province.includes(selectValue.value.province) && item.city.includes(selectValue.value.city) && (item.dist !== null ? item.dist.indexOf(disposeText) !== -1 : '') ? distschoolData.push(item) : '' : ''
         }
+        tableData.value = distschoolData
+        // let data = { province: selectValue.value.province ? selectValue.value.province : '', city: selectValue.value.city ? selectValue.value.city : '', dist: disposeText }
+        // await proxy.$api.getSchooldata(data).then((res) => {
+        //   res.state === 200 ? (schoolListDatas = res.schoolAssists, nextPageToken = res.continuationToken, tablesccnt.value = res.scCnt) : ''
+        // }).catch((error) => {
+        //   ElMessage.error('API异常,数据 地区 筛选失败')
+        // })
       }
-      tableData.value = schoolListDatas
-      tableData.value.forEach((item) => { item.areaName = ''; areaSelect.value.data.forEach((itema) => { item.areaId === itema.id ? item.areaName = itema.name : '' }) })
-      tableNexttoken.value = nextPageToken
       loading.value = false
     }
     //学校详情 close
@@ -665,12 +838,14 @@ export default {
         areaId: nowPitchdata.value.areaId,
       }
       console.log(updateForm, '学校信息')
-      proxy.$api.updateSchoolinfo(updateForm).then((res) => {
-        console.log(res, '修改学校的返回')
-        res.state === 200
-          ? (ElMessage.success(proxy.$t(`commonMsg.schoolUpdateSuccess`), schoolClose()), updateSuccess())
-          : ElMessage.error(proxy.$t(`commonMsg.schoolUpdateError`))
-      })
+      console.log(nowPitchdata.value, '原本的学校信息')
+      console.log(assistData, '顾问信息')
+      // proxy.$api.updateSchoolinfo(updateForm).then((res) => {
+      //   console.log(res, '修改学校的返回')
+      //   res.state === 200
+      //     ? (ElMessage.success(proxy.$t(`commonMsg.schoolUpdateSuccess`), schoolClose()), updateSuccess())
+      //     : ElMessage.error(proxy.$t(`commonMsg.schoolUpdateError`))
+      // })
     }
     //学校加入区域或者修改
     async function schoolJoinarea () {
@@ -762,7 +937,7 @@ export default {
         })
     }
     function skipAnalyse (value) {
-      console.log(value, '学校信息')
+      console.log(value, '学校信息V2')
       routerInfo.push({ path: '/home/analyse', query: {} })
       store.commit('schoolDataInfo', value)
     }
@@ -830,9 +1005,31 @@ export default {
       })
       setTimeout(function () { loading.value = false }, 800);
     }
-    watch(scrollHeight, (newdata) => {
-      if (scrollHeight.value < 0) {
-        debounce(datascroll, 500)
+    function schoolDetailInfo (val) {
+      console.log(val, '88888888888888')
+    }
+    function personnelSearch () {
+      loading.value = true
+      let values = schoolKey.value
+      let arr = originalData.value
+      let newArr = arr.filter((item) => {
+        return item.name.includes(values) || item.id.includes(values)
+      })
+      tableData.value = newArr
+      tablesccnt.value = newArr.length
+      loading.value = false
+    }
+    watch(scrollHeight, (newdata, olddata) => {
+      if (newdata < olddata) {
+        scrollHeight.value < 0 ? debounce(datascroll, 500) : ''
+      }
+    })
+    watch(schoolKey, (newdata) => {
+      if (newdata.trim().length !== 0) {
+        debounce(personnelSearch, 500)
+      } else {
+        tableData.value = originalData.value
+        tablesccnt.value = originalNum.value
       }
     })
     getAllschool()
@@ -887,7 +1084,16 @@ export default {
       tableNexttoken,
       selectValue,
       userPower,
-      detailsSchool
+      detailsSchool,
+      tablesccnt,
+      columns,
+      userVerify,
+      schoolDetailInfo,
+      sortState,
+      onSort,
+      schoolKey,
+      personnelSearch,
+      originalNum
     }
   },
 }
@@ -896,21 +1102,35 @@ export default {
 .schoolboxtad {
   width: 100%;
   margin: 0 auto;
-  line-height: 80px;
+  line-height: 40px;
+  overflow: hidden;
 }
 
 .select-List {
-  line-height: 60px;
+  line-height: 40px;
   text-align: left;
-  padding: 1% 2%;
+  padding: 0.5% 2%;
   width: 75%;
-  float: left;
+  /* float: left; */
+}
+.select-top {
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+}
+.selectSchool-box {
+  line-height: 40px;
+  text-align: left;
+  padding: 0% 2%;
+  width: 75%;
+  margin-bottom: 1%;
+  /* float: left; */
 }
-
 .school-list {
   width: 96%;
-  max-height: 74vh;
+  max-height: 75vh;
   margin: 0 auto;
+  line-height: 20px;
   /* overflow-y: auto; */
 }
 
@@ -924,7 +1144,7 @@ export default {
 .backbtn {
   text-align: left;
   position: absolute;
-  top: 0.5%;
+  top: 0%;
   right: 10px;
   z-index: 999;
   line-height: 40px;
@@ -1012,7 +1232,7 @@ export default {
 /*btn*/
 .boxselect {
   width: 20%;
-  display: inline-block;
+  /* display: inline-block; */
   margin-top: 0.5%;
   text-align: right;
 }
@@ -1197,6 +1417,11 @@ export default {
   font-size: 12px;
   margin-left: 1%;
 }
+.schoolNums {
+  margin-right: 30px;
+  font-size: 14px;
+  color: #636e72;
+}
 @media screen and (max-width: 1920px) {
   .school-form-size {
     width: 65% !important;
@@ -1208,6 +1433,7 @@ export default {
   }
 }
 </style>
+
 <style>
 .schoolboxtad .el-cascader {
   width: 20%;
@@ -1329,14 +1555,66 @@ export default {
 .schoolDeatils .el-tabs__nav-wrap::after {
   width: 0%;
 }
+.school-list .el-table-v2__sort-icon {
+  display: block;
+}
 @media screen and (max-width: 1920px) {
   .school-formbox .school-form-badge {
     width: 17.5%;
   }
+  .selectSchool-box .el-input--suffix {
+    width: 47%;
+  }
+  .testclass {
+    width: 10% !important;
+  }
+  .el-table-v2__row .el-table-v2__row-cell {
+    width: 10% !important;
+  }
 }
 @media screen and (max-width: 1400px) {
   .school-formbox .school-form-badge {
     width: 15vw;
   }
+  .selectSchool-box .el-input--suffix {
+    width: 66%;
+  }
+  .testclass {
+    width: 8% !important;
+  }
+  .el-table-v2__row .el-table-v2__row-cell {
+    width: 8% !important;
+  }
+  /*针对1366*768表格处理 */
+  /* .testclass:nth-child(1) {
+    width: 3% !important;
+  }
+  .el-table-v2__row .el-table-v2__row-cell:nth-child(1) {
+    width: 3% !important;
+  } */
+  .testclass:nth-child(4) {
+    width: 5% !important;
+  }
+  .el-table-v2__row .el-table-v2__row-cell:nth-child(4) {
+    width: 5% !important;
+  }
+  .testclass:nth-child(7) {
+    width: 10% !important;
+  }
+  .el-table-v2__row .el-table-v2__row-cell:nth-child(7) {
+    width: 10% !important;
+  }
+  .testclass:nth-child(11) {
+    width: 8% !important;
+  }
+  .el-table-v2__row .el-table-v2__row-cell:nth-child(11) {
+    width: 8% !important;
+  }
+  .testclass:nth-child(9) {
+    width: 5% !important;
+  }
+  .el-table-v2__row .el-table-v2__row-cell:nth-child(9) {
+    width: 5% !important;
+  }
 }
 </style>

+ 829 - 0
TEAMModelBI/ClientApp/src/view/participation/paper.vue

@@ -0,0 +1,829 @@
+<template>
+  <div class="paperbox">
+    <!--试卷信息 难度总分-->
+    <div class="paperbox-header">
+      <div class="header-info">
+        <div class="header-info-items">
+          <div class="header-info-title">总分:<span class="header-info-num">{{paperdata.totalnum}}</span>分</div>
+          <div class="header-info-title">题目数:<span class="header-info-num">{{paperdata.paperList.length}}</span></div>
+          <div class="header-info-title difficulty">难度:
+            <el-rate v-model="paperdata.difficulty" disabled />
+          </div>
+        </div>
+        <div class="header-info-operate">
+          <div>
+            <el-button type="primary" @click="backDefault">
+              <el-icon>
+                <Back />
+              </el-icon>
+              返回列表
+            </el-button>
+          </div>
+          <div>
+            <el-button type="primary" @click="allUnfold">
+              <svg class="unfoldicons" aria-hidden="true">
+                <use :xlink:href="unfoldAll.icon"></use>
+              </svg>
+              {{unfoldAll.text}}
+            </el-button>
+          </div>
+          <div v-if="userShow.roles.includes('admin') || userShow.roles.includes('assist')">
+            <el-button type="primary" @click="copyPapers">
+              <el-icon>
+                <DocumentCopy />
+              </el-icon>
+              拷贝当前试卷
+            </el-button>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="paper-name">{{paperdata.title}}</div>
+    <div class="paper-view" v-for="(item,index) in paperdata.paperList" :key="item.id">
+      <!--单选和判断-->
+      <div v-if="(item.exercise.type ==='single' || item.exercise.type ==='judge' || item.exercise.type ==='multiple') && item.child.length === 0 && item.pid ===null">
+        <p class="paper-view-title"><span>{{toChinesNum(Number(index)+1)}}、</span>
+          <span v-if="item.exercise.type ==='single'">单选题</span>
+          <span v-else-if="item.exercise.type ==='judge'">判断题</span>
+          <span v-else-if="item.exercise.type ==='multiple'">多选题</span>
+          <span class="aggregate">(共 {{item.item.length}} 题,总计 {{item.exercise.score}} 分)</span>
+        </p>
+        <div class="problem">
+          <!--题目-->
+          <div class="problem-details" v-for="(itemQ,indexs) in item.item" :key="indexs">
+            <div class="problem-num">{{Number(index)+1}}:</div>
+            <div class="problem-content" v-html="itemQ.question"></div>
+          </div>
+          <!--题目end-->
+          <!--分数-->
+          <div class="numshow">
+            <div class="numshow-nums"><span> {{item.exercise.score}} 分</span></div>
+            <div class="numshow-icon">
+              <div class="numshow-icon-item">
+                <svg class="tagicons" aria-hidden="true" @click="unfold(index)">
+                  <use :xlink:href="item.show ? '#icon-shouhuishangxia':'#icon-moduanzhankai_o'"></use>
+                </svg>
+              </div>
+            </div>
+          </div>
+          <!--分数end-->
+          <!--选项-->
+          <div class="proble-single">
+            <div class="item-single" v-for="(options,index) in item.item[0].option" :key="index">
+              <div class=" item-single-tag">{{options.code}}:</div>
+              <div class="item-single-content" v-if="checkHtml(options.value)" v-html="options.value"></div>
+              <div class="item-single-content" v-else>{{options.value}}</div>
+            </div>
+            <!-- <div class="item-single">
+              <div class="item-single-tag">B:</div>
+              <div class="item-single-content">154323456</div>
+            </div>
+            <div class="item-single">
+              <div class="item-single-tag">C:</div>
+              <div class="item-single-content">123534534456</div>
+            </div>
+            <div class="item-single">
+              <div class="item-single-tag">D:</div>
+              <div class="item-single-content">123453543456</div>
+            </div> -->
+          </div>
+          <!--选项end-->
+          <!--展开内容-->
+          <div :class="[unfoldnum == index ? 'unfoldIndex':'','spreadbox']">
+            <p><span class="spreadbox-title">【题型】</span>
+              <span v-if="item.exercise.type ==='single'">单选题</span>
+              <span v-else-if="item.exercise.type ==='judge'">判断题</span>
+              <span v-else-if="item.exercise.type ==='multiple'">多选题</span>
+            </p>
+            <p>
+              <span class="spreadbox-title">【答案】</span>
+              <span v-if="checkHtml(item.exercise.answer)  " v-html="item.exercise.answer" class="spreadbox-title-contents"></span>
+              <span v-else v-for="answer in item.exercise.answer">{{answer ? answer:'暂无'}}</span>
+            </p>
+            <p>
+              <span class="spreadbox-title">【解析】</span>
+              <span v-if="checkHtml(item.exercise.explain)" v-html="item.exercise.explain" class="spreadbox-title-contents"></span>
+              <span v-else>{{item.exercise.explain ?item.exercise.explain:'暂无'}}</span>
+            </p>
+            <p>
+              <span class="spreadbox-title">【知识点】</span>
+              <span v-if="checkHtml(item.exercise.knowledge)" v-html="item.exercise.knowledge" :class="[item.exercise.knowledge ? 'knowledge':'']"></span>
+              <span v-else-if="!item.exercise.hasOwnProperty('knowledge')">暂无</span>
+              <span v-else :class="[item.exercise.knowledge ? 'knowledge':'']" v-for="itemK in item.exercise.knowledge">
+                {{itemK ? itemK:'暂无'}}
+              </span>
+              <!-- <span v-else-if="item.exercise.knowledge.length ===0">暂无</span> -->
+            </p>
+            <p>
+              <span class="spreadbox-title">【认知层次】</span>
+              <span>暂无</span>
+            </p>
+            <p>
+              <span class="spreadbox-title">【补救资源】</span>
+              <span>暂无</span>
+            </p>
+          </div>
+          <!--展开内容end-->
+        </div>
+      </div>
+      <!--单选和判断end-->
+      <!--填空题问答题-->
+      <div v-else-if="(item.exercise.type ==='complete' || item.exercise.type ==='subjective' || item.exercise.type ==='connector' || item.exercise.type ==='correct' || item.exercise.type ==='compose') && item.child.length === 0 && item.pid ===null">
+        <p class="paper-view-title"><span>{{toChinesNum(Number(index)+1)}}、</span>
+          <span v-if="item.exercise.type ==='complete'">填空题</span>
+          <span v-else-if="item.exercise.type ==='subjective'">问答题</span>
+          <span v-else-if="item.exercise.type ==='connector'">连线题</span>
+          <span v-else-if="item.exercise.type ==='correct'">改错题</span>
+          <span v-else-if="item.exercise.type ==='compose'">综合题</span>
+          <span class="aggregate">(共 {{item.item.length}} 题,总计 {{item.exercise.score}} 分)</span>
+        </p>
+        <div class="problem">
+          <!--题目-->
+          <div class="problem-details" v-for="(itemQ,indexs) in item.item" :key="indexs">
+            <div class="problem-num">{{Number(index)+1}}:</div>
+            <div class="problem-content" v-html="itemQ.question"></div>
+          </div>
+          <!--题目end-->
+          <!--分数-->
+          <div class="numshow">
+            <div class="numshow-nums"><span> {{item.exercise.score}} 分</span></div>
+            <div class="numshow-icon">
+              <div class="numshow-icon-item">
+                <svg class="tagicons" aria-hidden="true" @click="unfold(index)">
+                  <use :xlink:href="item.show ? '#icon-shouhuishangxia':'#icon-moduanzhankai_o'"></use>
+                </svg>
+              </div>
+            </div>
+          </div>
+          <!--分数end-->
+          <!--展开内容-->
+          <div :class="[unfoldnum == index ? 'unfoldIndex':'','spreadbox']">
+            <div>
+              <p>
+                <span class="spreadbox-title">【题型】</span>
+                <span v-if="item.exercise.type ==='complete'">填空题</span>
+                <span v-else-if="item.exercise.type ==='subjective'">问答题</span>
+                <span v-else-if="item.exercise.type ==='connector'">连线题</span>
+                <span v-else-if="item.exercise.type ==='correct'">改错题</span>
+                <span v-else-if="item.exercise.type ==='compose'">综合题</span>
+              </p>
+              <p>
+                <span class="spreadbox-title">【答案】</span>
+                <span v-if="checkHtml(item.exercise.answer)" v-html="item.exercise.answer" class="spreadbox-title-contents"></span>
+                <span v-else v-for="answer in item.exercise.answer">{{answer ? answer:'暂无'}}</span>
+              </p>
+              <p>
+                <span class="spreadbox-title">【解析】</span>
+                <span v-if="checkHtml(item.exercise.explain)" v-html="item.exercise.explain" class="spreadbox-title-contents"></span>
+                <span v-else>{{item.exercise.explain ?item.exercise.explain:'暂无'}}</span>
+              </p>
+              <p>
+                <span class="spreadbox-title">【知识点】</span>
+                <span v-if="checkHtml(item.exercise.knowledge) " v-html="item.exercise.knowledge" :class="[item.exercise.knowledge ? 'knowledge':'']"></span>
+                <span v-else-if="!item.exercise.hasOwnProperty('knowledge')">暂无</span>
+                <span v-else :class="[item.exercise.knowledge ? 'knowledge':'']" v-for="itemK in item.exercise.knowledge">
+                  {{itemK || itemK}}'暂无'
+                </span>
+                <!-- <span v-else-if="item.exercise.knowledge.length ===0">暂无</span> -->
+              </p>
+              <p>
+                <span class="spreadbox-title">【认知层次】</span>
+                <span>暂无</span>
+              </p>
+              <p>
+                <span class="spreadbox-title">【补救资源】</span>
+                <span>暂无</span>
+              </p>
+            </div>
+          </div>
+          <!--展开内容end-->
+        </div>
+      </div>
+      <!--填空题问答题end-->
+      <!--特殊情况,有小题-->
+      <div v-else-if="item.child.length !==0">
+        <p class="paper-view-title"><span>{{toChinesNum(Number(index)+1)}}、</span>
+          <span v-if="item.exercise.type ==='single'">单选题</span>
+          <span v-else-if="item.exercise.type ==='judge'">判断题</span>
+          <span v-else-if="item.exercise.type ==='multiple'">多选题</span>
+          <span v-else-if="item.exercise.type ==='complete'">填空题</span>
+          <span v-else-if="item.exercise.type ==='subjective'">问答题</span>
+          <span v-else-if="item.exercise.type ==='connector'">连线题</span>
+          <span v-else-if="item.exercise.type ==='correct'">改错题</span>
+          <span v-else-if="item.exercise.type ==='compose'">综合题</span>
+          <span class="aggregate">(共 {{item.item.length}} 题,总计 {{item.exercise.score}} 分)</span>
+        </p>
+        <div class="problem">
+          <!--题目-->
+          <div class="problem-details" v-for="(itemQ,indexs) in item.item" :key="indexs">
+            <div class="problem-num">{{Number(index)+1}}:</div>
+            <div class="problem-content" v-html="itemQ.question"></div>
+            <div class="problem-child">
+              <div class="problem-childbox special" v-for="(itemC,indexC) in item.child" :key="itemC.id">
+                <!--child题目-->
+                <div class="problem-child-question" v-for="(itemCq,indexCq) in itemC.item" :key="itemCq.uid">
+                  <div class="problem-child-num">({{Number(indexC)+1}})</div>
+                  <div class="problem-child-content" v-html="itemCq.question"></div>
+                </div>
+                <!--child题目end-->
+                <!--分数及展开-->
+                <div class="problem-child-numshow">
+                  <div class="numshow-nums"><span> {{itemC.exercise.score}} 分</span></div>
+                  <div class="numshow-icon">
+                    <div class="numshow-icon-item">
+                      <svg class="tagicons" aria-hidden="true" @click="unfold(index,indexC,'child')">
+                        <use :xlink:href="itemC.show ? '#icon-shouhuishangxia':'#icon-moduanzhankai_o'"></use>
+                      </svg>
+                    </div>
+                  </div>
+                </div>
+                <!--选项-->
+                <div class="proble-single" v-if="itemC.item[0].option.length !==0">
+                  <div class="item-single" v-for="(options,indexoptionC) in itemC.item[0].option" :key="indexoptionC">
+                    <div class="item-single-tag">{{options.code}}:</div>
+                    <div class="item-single-content" v-if="checkHtml(options.value)" v-html="options.value"></div>
+                    <div class="item-single-content" v-else>{{options.value}}</div>
+                  </div>
+                </div>
+                <!--选项end-->
+                <!--分数及展开end-->
+                <!--展开内容-->
+                <div :class="[unfoldnum == index && affiliateUnfold ==indexC ? 'child-unfoldIndex':'','child-spreadbox']">
+                  <div>
+                    <p>
+                      <span class="spreadbox-title">【答案】</span>
+                      <span v-if="checkHtml(itemC.exercise.answer)" v-html="itemC.exercise.answer" class="spreadbox-title-contents"></span>
+                      <span v-else v-for="answer in itemC.exercise.answer">{{answer ? answer:'暂无'}}</span>
+                    </p>
+                    <p>
+                      <span class="spreadbox-title">【解析】</span>
+                      <span v-if="checkHtml(itemC.exercise.explain)" v-html="itemC.exercise.explain" class="spreadbox-title-contents"></span>
+                      <span v-else>{{itemC.exercise.explain ?itemC.exercise.explain:'暂无'}}</span>
+                    </p>
+                    <p>
+                      <span class="spreadbox-title">【知识点】</span>
+                      <span v-if="checkHtml(itemC.exercise.knowledge)" v-html="itemC.exercise.knowledge" :class="[itemC.exercise.knowledge ? 'knowledge':'']"></span>
+                      <span v-else-if="!itemC.exercise.hasOwnProperty('knowledge') || itemC.exercise.knowledge.length ===0">暂无</span>
+                      <span v-else-if="itemC.exercise.knowledge.length >0" :class="[itemC.exercise.knowledge ? 'knowledge':'']" v-for="(itemK,indexK) in itemC.exercise.knowledge" :key="indexK">
+                        {{itemK}}
+                      </span>
+                      <span v-else-if="itemC.exercise.knowledge.length ===0">暂无</span>
+                    </p>
+                    <p>
+                      <span class="spreadbox-title">【认知层次】</span>
+                      <span>暂无</span>
+                    </p>
+                    <p>
+                      <span class="spreadbox-title">【补救资源】</span>
+                      <span>暂无</span>
+                    </p>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <!--题目end-->
+          <!--分数-->
+          <div class="numshow">
+            <div class="numshow-nums"><span> {{item.exercise.score}} 分</span></div>
+            <!-- <div class="numshow-icon">
+              <div class="numshow-icon-item">
+                <svg class="tagicons" aria-hidden="true" @click="unfold(index)">
+                  <use :xlink:href="item.show ? '#icon-shouhuishangxia':'#icon-moduanzhankai_o'"></use>
+                </svg>
+              </div>
+            </div> -->
+          </div>
+          <!--分数end-->
+        </div>
+      </div>
+      <!--特殊情况,有小题end-->
+    </div>
+    <div class="backtop" @click="backTops">
+      <img :src="backImg" />
+    </div>
+    <Copy ref="copypaper" :paperdata="paperdata"></Copy>
+  </div>
+</template>
+<script>
+import { ref, watch, getCurrentInstance, onMounted } from 'vue'
+import { useStore } from 'vuex'
+import { DocumentCopy, Back } from '@element-plus/icons-vue'
+import Copy from './copy.vue'
+import jwt_decode from 'jwt-decode'
+export default ({
+  props: {
+    paperInfo: {
+      type: Object,
+      default: () => { },
+    }
+  },
+  components: {
+    DocumentCopy, Back, Copy
+  },
+  setup (props, context) {
+    const { proxy } = getCurrentInstance()
+    const store = useStore()
+    let paper = ref("若CE=1,EB=3,求⊙O的半径;")
+    let backImg = require('@/assets/img/backtop.png')
+    let PowerShow = proxy.$access.identifyPosition(JSON.parse(localStorage.getItem('id_token')))
+    let userShow = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
+    console.log(PowerShow, userShow.roles, userShow.roles.includes('admin'), '身份')
+    let paperdata = ref({
+      totalnum: 0,
+      difficulty: 0,
+      title: '',
+      paperList: [],
+      id: '',
+      schoolcode: '',
+    })
+    let unfoldAll = ref({
+      text: '全部展开',
+      state: false,
+      icon: '#icon-zhankai-copy'
+    })
+    let value1 = ref(4)
+    let shows = ref(false)
+    let unfoldnum = ref(-1)
+    let affiliateUnfold = ref(-1)
+    let loading = ref(false)
+    let copypaper = ref(null)
+    let copyiconLoding = ref(false)
+    onMounted(() => {
+      //监听表格滚动事件
+      let rolllocation = document.getElementsByClassName('paperbox')
+      console.log(rolllocation, '获取元素')
+      rolllocation[0].addEventListener("scroll", (res) => { loadmore(res) }, true);
+    })
+    const loadmore = (res) => {
+      // if (res.target.scrollTop && ((res.target.scrollHeight - 20) <= (res.target.scrollTop + res.target.clientHeight))) {
+      //   scrollHeight.value = (res.target.scrollHeight - 20) - (res.target.scrollTop + res.target.clientHeight)
+      //   console.log(scrollHeight.value, '值')
+      // }
+      let showRoll = document.getElementsByClassName('backtop')
+      if (showRoll.length !== 0) {
+        res.target.scrollTop >= 100 ? showRoll[0].style.opacity = 1 : showRoll[0].style.opacity = 0
+      }
+    }
+    function unfold (index, indexs, state) {
+      console.log(index, indexs, unfoldnum.value, '进来的值和原本的值')
+      if (state !== 'child') {
+        if (index == unfoldnum.value) {
+          paperdata.value.paperList[index].show = false
+          unfoldnum.value = -1
+        } else {
+          paperdata.value.paperList[index].show = true
+          unfoldnum.value = index
+        }
+      } else {
+        console.log('进入child判断')
+        if (index == unfoldnum.value) {
+          paperdata.value.paperList[index].child[indexs].show = false
+          unfoldnum.value = -1
+          affiliateUnfold.value = -1
+        } else {
+          console.log(paperdata.value.paperList)
+          paperdata.value.paperList[index].child[indexs].show = true
+          unfoldnum.value = index
+          affiliateUnfold.value = indexs
+        }
+      }
+      console.log(paperdata.value, '整个数组变化')
+    }
+    function backDefault () {
+      context.emit('renew', 'default')
+    }
+    function paperInit (val) {
+      loading.value = true
+      let vals = JSON.parse(JSON.stringify(val))
+      paperdata.value.totalnum = vals.total
+      paperdata.value.title = vals.title
+      paperdata.value.difficulty = Number(vals.difficulty)
+      paperdata.value.id = val.id
+      paperdata.value.schoolcode = val.schoolcode
+      vals.list.forEach((item) => {
+        console.log(item, '内容111')
+        item.show = false
+        item.child = []
+        let urls = val.blob.url; let spaces = val.blob.space; let sass = val.blob.sas
+        if (item.item[0].question.indexOf('video') !== -1) {
+          let setVideo = /<video/g;  // 设置需要匹配的标签
+          let r = '<video[^<>]*? src="([^<>]*?)"'; // 设置匹配的正则
+          var videoSrc = item.item[0].question.match(r);
+          //拼接音频、视频地址
+          let replaceUrl = urls + spaces + '/' + videoSrc[1] + '?' + sass
+          item.item[0].question = item.item[0].question.replace(videoSrc[1], replaceUrl)
+        }
+        if (item.item[0].question.indexOf('audio') !== -1) {
+          console.log(item.item[0].question, '问题')
+          let audior = '<audio[^<>]*? src="([^<>]*?)"'; // 设置匹配的正则
+          var audioSrc = item.item[0].question.match(audior);
+          let replaceUrlAudio = '<audio src="' + urls + spaces + '/' + audioSrc[1] + '?' + sass + '"'
+          item.item[0].question = item.item[0].question.replace(audioSrc[0], replaceUrlAudio)
+        }
+      })
+      for (let i in vals.list) {
+        if (vals.list[i].pid) {
+          console.log(vals.list[i].id, vals.list[i].pid, '进入判断的')
+          let result = vals.list.find((nows) => { return vals.list[i].pid === nows.id })
+          result ? (result.child.push(vals.list[i])) : ''
+        }
+      }
+      //为的是清理数组,剔除掉有父元素pid的.
+      let disposeData = vals.list.filter((item) => { return item.pid === null })
+      paperdata.value.paperList = disposeData
+      //loading.value = false
+      setTimeout(function () {
+        loading.value = false
+      }, 800)
+      console.log(paperdata.value, '现在的数据')
+    }
+    //把数字转换成汉字
+    function toChinesNum (num) {
+      let changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
+      let unit = ['', '十', '百', '千', '万']
+      num = parseInt(num)
+      let getWan = (temp) => {
+        let strArr = temp.toString().split('').reverse()
+        let newNum = ''
+        let newArr = []
+        strArr.forEach((item, index) => {
+          newArr.unshift(item === '0' ? changeNum[item] : changeNum[item] + unit[index])
+        })
+        let numArr = []
+        newArr.forEach((m, n) => {
+          if (m !== '零') numArr.push(n)
+        })
+        if (newArr.length > 1) {
+          newArr.forEach((m, n) => {
+            if (newArr[newArr.length - 1] === '零') {
+              if (n <= numArr[numArr.length - 1]) {
+                newNum += m
+              }
+            } else {
+              newNum += m
+            }
+          })
+        } else {
+          newNum = newArr[0]
+        }
+        return newNum
+      }
+      let overWan = Math.floor(num / 10000)
+      let noWan = num % 10000
+      if (noWan.toString().length < 4) {
+        noWan = '0' + noWan
+      }
+      return overWan ? getWan(overWan) + '万' + getWan(noWan) : getWan(num)
+    }
+    //全部展开或折叠
+    function allUnfold () {
+      unfoldAll.value.state ? (unfoldAll.value.text = '全部展开', paperdata.value.paperList.forEach((item) => { item.show = false, item.child.length > 0 ? item.child.forEach((child) => { child.show = false }) : '' })) :
+        (unfoldAll.value.text = '全部折叠', paperdata.value.paperList.forEach((item) => { item.show = true, item.child.length > 0 ? item.child.forEach((child) => { child.show = true }) : '' }))
+      let domObj = document.getElementsByClassName('spreadbox')
+      let childDom = document.getElementsByClassName('child-spreadbox')
+      console.log(domObj, 'obj')
+      if (!unfoldAll.value.state) {
+        for (let i of domObj) {
+          i.classList.add('unfoldIndex')
+        }
+        for (let c of childDom) {
+          c.classList.add('child-unfoldIndex')
+        }
+        unfoldAll.value.icon = '#icon-zhankai'
+        unfoldAll.value.state = true
+      } else {
+        for (let i of domObj) {
+          i.classList.remove('unfoldIndex')
+        }
+        for (let c of childDom) {
+          c.classList.remove('child-unfoldIndex')
+        }
+        unfoldAll.value.icon = '#icon-zhankai-copy'
+        unfoldAll.value.state = false
+      }
+      console.log(paperdata.value)
+    }
+    function backTops () {
+      let showRoll = document.getElementsByClassName('paperbox')
+      let backbtn = document.getElementsByClassName('backtop')
+      console.log(showRoll, '获取的元素123')
+      ScrollTop(0, 300);
+    }
+    function ScrollTop (number = 0, time) {
+      if (!time) {
+        document.getElementsByClassName('paperbox')[0].scrollTop = document.getElementsByClassName('paperbox')[0].scrollTop = number;
+        return number;
+      }
+      const spacingTime = 20; // 设置循环的间隔时间  值越小消耗性能越高
+      let spacingInex = time / spacingTime; // 计算循环的次数
+      let nowTop = document.getElementsByClassName('paperbox')[0].scrollTop; // 获取当前滚动条位置
+      let everTop = (number - nowTop) / spacingInex; // 计算每次滑动的距离
+      let scrollTimer = setInterval(() => {
+        if (spacingInex > 0) {
+          spacingInex--;
+          ScrollTop(nowTop += everTop);
+        } else {
+          clearInterval(scrollTimer); // 清除计时器
+        }
+      }, spacingTime);
+    }
+    function checkHtml (htmlStr) {
+      var reg = /<[^>]+>/g;
+      return reg.test(htmlStr);
+    }
+    function copyPapers () {
+      copypaper.value.drawer = true
+    }
+    watch(props, (newpaper) => {
+      console.log(newpaper, '监听试卷的相关内容')
+      newpaper.paperInfo ? paperInit(newpaper.paperInfo) : ''
+    }, { deep: true, })
+    return {
+      paper,
+      value1,
+      shows,
+      unfold,
+      unfoldnum,
+      backDefault,
+      paperdata,
+      toChinesNum,
+      unfoldAll,
+      allUnfold,
+      loading,
+      backImg,
+      backTops,
+      ScrollTop,
+      checkHtml,
+      affiliateUnfold,
+      copypaper,
+      copyPapers,
+      copyiconLoding,
+      userShow,
+      PowerShow
+    }
+  },
+})
+</script>
+<style scoped>
+.paperbox {
+  width: 98%;
+  height: 85vh;
+  background: #fff;
+  margin: 1%;
+  padding: 0.5%;
+  line-height: 20px;
+  flex-wrap: wrap;
+  position: relative;
+  overflow: auto;
+}
+.paperbox-header {
+  width: 100%;
+}
+.header-info {
+  display: flex;
+  border-bottom: 1px dashed #ccc;
+  height: 80px;
+  line-height: 80px;
+}
+.header-info-items {
+  display: flex;
+  width: 45%;
+}
+.header-info-title {
+  width: 18%;
+  display: flex;
+  padding-left: 15px;
+}
+.difficulty {
+  width: 35%;
+}
+.header-info-operate {
+  width: 50%;
+  display: flex;
+  flex-direction: row-reverse;
+}
+.header-info-operate div {
+  margin-right: 10px;
+}
+.paper-name {
+  font-size: 30px;
+  font-weight: bold;
+  line-height: 60px;
+  margin-top: 1%;
+}
+.paper-view-title {
+  text-align: left;
+  font-size: 18px;
+  font-weight: bold;
+  padding-left: 1%;
+}
+.aggregate {
+  font-size: 16px;
+  padding-left: 5px;
+}
+.problem {
+  position: relative;
+  cursor: pointer;
+  text-align: left;
+  margin: 1%;
+  padding: 1%;
+  border: 1px solid transparent;
+}
+.problem-details {
+  width: 90%;
+  display: inline-block;
+  vertical-align: top;
+}
+.numshow {
+  width: 10%;
+  display: inline-block;
+  vertical-align: top;
+  text-align: right;
+}
+.problem-num {
+  display: inline-block;
+  vertical-align: top;
+  width: 30px;
+  font-weight: bold;
+}
+.problem-content {
+  display: inline-block;
+  vertical-align: top;
+  width: calc(90% - 30px);
+}
+.proble-single {
+  width: 85%;
+  margin-top: 1%;
+  padding-left: 1%;
+}
+.item-single {
+  margin: 8px 0px;
+  font-size: 16px;
+}
+.item-single div {
+  display: inline-block;
+  vertical-align: top;
+}
+.item-single-tag {
+  width: 35px;
+  font-weight: bold;
+}
+.tagicons {
+  width: 18px;
+  height: 18px;
+  fill: currentColor;
+  overflow: hidden;
+}
+.numshow-nums,
+.numshow-icon {
+  display: inline-block;
+  vertical-align: top;
+}
+.numshow-icon {
+  margin-left: 2%;
+}
+.numshow-icon-item {
+  width: 24px;
+  height: 24px;
+  background-color: #fff;
+  border: 1px solid #ccc;
+  border-radius: 50%;
+  text-align: center;
+}
+.problem:hover {
+  border: 1px solid #48dbfb;
+}
+.spreadbox {
+  margin-top: 1%;
+  padding-top: 1%;
+  /* border-top: 1px dashed #ccc; */
+  transition: max-height 0.8s;
+  max-height: 0;
+  overflow: hidden;
+}
+.child-spreadbox {
+  transition: max-height 0.8s;
+  max-height: 0;
+  overflow: hidden;
+}
+.spreadbox-title {
+  color: #48dbfb;
+}
+.unfoldIndex {
+  max-height: 50vh;
+  border-top: 1px dashed #ccc;
+}
+.child-unfoldIndex {
+  margin-top: 1%;
+  padding-top: 1%;
+  max-height: 50vh;
+  border-top: 1px dashed #ccc;
+}
+.unfoldicons {
+  height: 1.1em;
+  width: 1.1em;
+  line-height: 1.1em;
+  text-align: center;
+  margin-right: 3px;
+  fill: currentColor;
+}
+.knowledge {
+  padding: 0 10px;
+  border: 1px solid #d6d6d6;
+  margin-left: 10px;
+  border-radius: 4px;
+}
+.backtop {
+  /* height: 100px; */
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  opacity: 0;
+}
+.backtop img {
+  position: fixed;
+  bottom: 20px;
+  right: 20px;
+  width: 40px;
+  height: 40px;
+  cursor: pointer;
+  background: #fff;
+  border-radius: 50%;
+  z-index: 99;
+}
+.problem-child {
+  position: relative;
+  margin: 20px 10px 0 10px;
+  padding: 10px;
+}
+.problem-child-question {
+  width: 90%;
+  padding-left: 5px;
+}
+.problem-child-num,
+.problem-child-content {
+  display: inline-block;
+  /* vertical-align: top; */
+}
+.problem-child-content {
+  padding-left: 5px;
+}
+.problem-childbox {
+  border: 1px solid transparent;
+  padding: 0.5% 0.5%;
+}
+.problem-childbox:hover {
+  border: 1px solid #48dbfb;
+}
+.problem-child-numshow,
+.problem-child-question {
+  display: inline-block;
+}
+.problem-child-numshow {
+  width: 10%;
+  text-align: center;
+}
+.spreadbox-title-contents {
+  display: inline-block;
+}
+.special {
+  margin-top: 1%;
+}
+</style>
+<style>
+.header-info .el-rate {
+  line-height: 4.7;
+}
+.spreadbox-title-contents p {
+  margin-bottom: 0px !important;
+}
+.problem-child-content p {
+  margin-bottom: 5px !important;
+}
+.richText-audio {
+  position: relative;
+  display: inline-flex;
+  flex-direction: column;
+  cursor: pointer;
+  vertical-align: middle;
+}
+.richText-audio .audio-info {
+  padding: 8px;
+  background-color: #f1f3f4;
+  color: #000;
+  display: flex;
+  align-items: center;
+  min-width: 240px;
+}
+.problem-content p span:first-child {
+  display: block;
+}
+#audio {
+  width: auto;
+  display: inline-block;
+  background: #f1f3f4;
+}
+</style>

+ 189 - 27
TEAMModelBI/ClientApp/src/view/participation/setAbility.vue

@@ -3,12 +3,12 @@
     <!-- <div class="ability-names" v-show="treeModel === 'default'">微能力点管理</div> -->
     <!--外部呈现-->
     <div class="allbox" v-if="treeModel === 'default'">
-      <div class="site-box" v-show="siteCut.show">
+      <!-- <div class="site-box" v-show="siteCut.show">
         <span :class="[siteCut.positionIndex ===1 ? 'site-pitch':'']" @click="cutSite(1,'china')">中国</span>
         <span :class="[siteCut.positionIndex ===2 ? 'site-pitch':'']" @click="cutSite(2,'international')">国际</span>
-      </div>
+      </div> -->
       <div class="cardlist-card" v-if="showPattern.state">
-        <div class="readybox">
+        <div class="readybox" v-loading="loading" element-loading-text="数据加载中...">
           <div class="cardlist-card-title">
             <div class="cardlist-card-title-icon">
               <svg class="cardtitleIcon" aria-hidden="true">
@@ -17,13 +17,45 @@
             </div>
             <div class="cardlist-card-title-text"><span>我参与的</span></div>
           </div>
-          <div class="preinstallbox">
+          <!-- <div class="preinstallbox">
             <div class="cardbox" v-for="(item, index) in abilityProject" :key="item.id">
               <div class="mask1" @click="pitch(item)">
                 <el-image :src="redactImg" :fit="fit" />
                 <p class="hovertitles">编辑当前微能力点</p>
               </div>
               <el-card class="box-card">
+                <template #header>
+                  <div class="card-header">
+                    <span class="card-names" :title="item.standardName">{{ item.standardName }}</span>
+                  </div>
+                </template>
+                <div class="information-box">
+                  <p class="source">{{ $t(`abilityManages.source`) }}:<span class="source-title">{{ item.name}}</span></p>
+                  <p class="source">{{ $t(`abilityManages.area`) }}:<span class="source-title">{{item.provName}}{{ item.cityName }}</span></p>
+                  <p class="source">{{ $t(`abilityManages.affiliation`) }}:<span class="source-title">{{item.institution}}</span></p>
+                </div>
+              </el-card>
+            </div>
+          </div> -->
+          <div class="preinstallbox" v-if="abilityProject.length !==0">
+            <div class="cardbox" v-for="(item, index) in abilityProject" :key="item.id">
+              <div class="mask1">
+                <div v-if="item.id !=='bde5c011-2ae4-461a-b46c-5483ba72ae45'" @click="pitch(item)">
+                  <el-image :src="redactImg" :fit="fit" />
+                  <div class="hovertitles" v-if="item.id !=='bde5c011-2ae4-461a-b46c-5483ba72ae45'">编辑当前微能力点</div>
+                </div>
+                <div class="intactbox" v-else>
+                  <div class="intact-left" @click="pitch(item)">
+                    <el-image :src="intactImg.view" :fit="fit" class="intactimg" />
+                    <div class="hovertitles-intact">查看微能力点</div>
+                  </div>
+                  <!-- <div class="intact-right" @click="synchronize">
+                    <el-image :src="intactImg.synchronization" :fit="fit" class="intactimg" />
+                    <div class="hovertitles-intact">同步微能力点</div>
+                  </div> -->
+                </div>
+              </div>
+              <el-card :class="[item.id==='bde5c011-2ae4-461a-b46c-5483ba72ae45' ? 'intact':'','box-card']">
                 <!-- <div class="card-number">{{ index + 1 }}</div> -->
                 <template #header>
                   <div class="card-header">
@@ -36,10 +68,22 @@
                   <p class="source">{{ $t(`abilityManages.source`) }}:<span class="source-title">{{ item.name}}</span></p>
                   <p class="source">{{ $t(`abilityManages.area`) }}:<span class="source-title">{{item.provName}}{{ item.cityName }}</span></p>
                   <p class="source">{{ $t(`abilityManages.affiliation`) }}:<span class="source-title">{{item.institution}}</span></p>
+                  <!-- <p class="source">引用标准:
+                    <span class="source-title" v-if="item.quotename" :title="item.quotename">{{item.quotename}}</span>
+                    <span class="source-title available" v-else>暂无</span>
+                  </p> -->
                 </div>
               </el-card>
+              <!-- <div class="signboard" v-show="item.id==='bde5c011-2ae4-461a-b46c-5483ba72ae45'" title="即时同步" @click="synchronize">
+                <svg class="synchronization" aria-hidden="true">
+                  <use xlink:href="#icon-shangpintongbu"></use>
+                </svg>
+              </div> -->
             </div>
           </div>
+          <div class="preinstallbox" v-else>
+            <div class="notdatas">暂无数据</div>
+          </div>
         </div>
       </div>
       <div class="cutlist-table" v-else-if="showPattern.state === false">
@@ -77,10 +121,10 @@
             <span class="tabname">{{ $t(`abilityManages.abilityname`) }}({{ abilitylenth }})</span>
             <span class="tabinfos">
               <i class="el-icon-search" @click="operateModel = search"></i>
-              <i class="el-icon-s-tools" @click="setAbility"></i>
-              <i class="el-icon-edit" @click="editAbility('redact')"></i>
-              <i class="el-icon-delete-solid  deleAbility" @click="operationAbility('del')"></i>
-              <i class="el-icon-plus" @click="editAbility('add')"></i>
+              <i class="el-icon-s-tools" @click="setAbility" v-if="intactShow"></i>
+              <i class="el-icon-edit" @click="editAbility('redact')" v-if="intactShow"></i>
+              <i class="el-icon-delete-solid  deleAbility" @click="operationAbility('del')" v-if="intactShow"></i>
+              <i class="el-icon-plus" @click="editAbility('add')" v-if="intactShow"></i>
             </span>
           </p>
           <p class="abilitys-one" v-if="operateModel === search">
@@ -97,10 +141,8 @@
             <p>
               <span class="ability-num">{{ items.no }}</span>
               <span class="ability-name">{{ items.name }}</span>
-              <span class="ability-tag" v-if="items.currency === 3">{{ $t(`treeStructure.choose`)
-                            }}</span>
-              <span class="ability-must" v-if="items.currency === 1">{{ $t(`treeStructure.required`)
-                            }}</span>
+              <span class="ability-tag" v-if="items.currency === 3">{{ $t(`treeStructure.choose`)}}</span>
+              <span class="ability-must" v-if="items.currency === 1">{{ $t(`treeStructure.required`)}}</span>
               <span v-if="items.currency === 0"></span>
             </p>
             <p>
@@ -141,8 +183,8 @@
           </el-table-column>
         </el-table>
         <div>
-          <el-button type="success" style="margin: 20px 0;float: right;margin-left: 20px;" @click="onSaveCompulsory" :loading="idBtnLoading">保存</el-button>
-          <el-button style="margin: 20px 0;float: right;" @click="compulsoryModal = false">取消</el-button>
+          <el-button type="success" style="margin: 10px 0;float: right;margin-left: 10px;" @click="onSaveCompulsory" :loading="idBtnLoading">保存</el-button>
+          <el-button style="margin: 10px 0;float: right;" @click="compulsoryModal = false">取消</el-button>
         </div>
       </el-dialog>
     </div>
@@ -315,12 +357,14 @@ import { useStore } from 'vuex'
 import AbilityTree from '@/components/AbilityTree.vue'
 import dimension from '@/static/dimension.js'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import jwt_decode from 'jwt-decode'
 export default {
   components: {
     AbilityTree,
   },
   setup () {
     let { proxy } = getCurrentInstance()
+    let intactShow = ref(true)
     let treeData = reactive([
       {
         id: 1,
@@ -397,7 +441,7 @@ export default {
         address: 'No. 189, Grove St, Los Angeles',
       },
     ])
-    let abilityProject = reactive([])
+    let abilityProject = ref([])
     let treeModel = ref('default')
     let direction = dimension.DIMENSIONS()
     let abilityData = ref([])
@@ -526,12 +570,20 @@ export default {
     ])
     //为配合tree新增而声明的变量,完整数据
     let treeDataInfo = ref([])
+    const intactImg = {
+      view: require('@/assets/img/view.png'),
+      synchronization: require('@/assets/img/synchronization.png')
+    }
     const redactImg = require('@/assets/img/redacts.png')
+    //新的关联的学区 呈现的能力点
+    let newAreavalue = ref([])
+    let loading = ref(false)
     //获取到方案下的能力点,并默认选中第一个
     function pitch (data) {
       console.log(data, '查询册别传入的data')
       areaIds.value = data.id
       nowPitch = Object.assign({}, data)
+      data.id === 'bde5c011-2ae4-461a-b46c-5483ba72ae45' ? intactShow.value = false : intactShow.value = true
       console.log(nowPitch, data, '查询册别')
       let dataSA = data
       let num = ''
@@ -802,13 +854,39 @@ export default {
       console.log(data, newData, '处理过后的')
     }
     function init () {
-      store.state.point.length
-        ? abilityProject.push(...store.state.point)
-        : proxy.$api.getCapacity({}).then((res) => {
-          res.areas.splice(2)
-          abilityProject.push(...res.areas)
-          // store.commit('getPoint', res.areas)
+      loading.value = true
+      let userPower = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
+      console.log(userPower, '用户信息11')
+      let data = userPower.roles.includes('admin') || userPower.roles.includes('leader') ? {} : { tmdId: userPower.sub }
+      proxy.$api.getCapacity(data).then((res) => {
+        res.areas.map((item, index) => {
+          item.id === 'bde5c011-2ae4-461a-b46c-5483ba72ae45' ? res.areas.unshift(res.areas.splice(index, 1)[0]) : ''
         })
+        abilityProject.value = res.areas
+        loading.value = false
+      }).catch((error) => {
+        ElMessage.error('获取用户关联学区失败,API异常')
+        loading.value = false
+      })
+
+      // initFollow()
+    }
+    //处理当前关联的学区 以及 完整能力点
+    function initFollow () {
+      let userPower = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
+      console.log(userPower, '用户信息11')
+      let data = userPower
+      proxy.$api.getCapacity({ tmdId: userPower.sub }).then((res) => {
+        console.log(res, '返回的')
+        if (res.state === 200) {
+          // res.areas.forEach((item)=>{
+          //   let aredIds=item.
+          // })
+          newAreavalue.value = res.areas
+        }
+      }).catch((error) => {
+        ElMessage.error('获取用户关联学区失败,API异常')
+      })
     }
     //站点切换
     function cutSite (index, value) {
@@ -884,7 +962,11 @@ export default {
       redactImg,
       init,
       siteCut,
-      cutSite
+      cutSite,
+      intactImg,
+      initFollow,
+      loading,
+      intactShow
     }
   },
 }
@@ -945,15 +1027,16 @@ export default {
   margin-bottom: 18px;
 }
 
-.information-box .source {
+/* .information-box .source {
   font-size: 14px;
   color: #909399;
   text-align: left;
-  line-height: 45px;
+  line-height: 40px;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
-}
+  margin-bottom: 17px;
+} */
 
 .information-box .source:hover {
   overflow: visible;
@@ -1487,6 +1570,7 @@ export default {
   display: flex;
   flex-wrap: wrap;
   /* overflow: auto; */
+  /* position: relative; */
 }
 .site-box {
   display: inline-flex;
@@ -1514,6 +1598,72 @@ export default {
   font-weight: 600;
   color: #fff;
 }
+.information-box .source {
+  font-size: 14px;
+  color: #909399;
+  text-align: left;
+  line-height: 40px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  margin-bottom: 17px;
+}
+
+.information-box .source:hover {
+  overflow: visible;
+}
+.information-box .source .source-title {
+  font-size: 14px;
+  color: #303133;
+}
+.hovertitles {
+  font-size: 16px;
+  font-weight: bold;
+  color: rgba(255, 255, 255, 0.9);
+}
+.intact-left,
+.intact-right {
+  width: 40%;
+  padding: 1.5%;
+  margin: 7% 7% 7% 30%;
+  border: 1px solid #ecf0f1;
+  border-radius: 10px;
+  box-shadow: 0 1px 1px rgba(99, 110, 114, 1),
+    0 2px 2px rgba(99, 110, 114, 1) 0 4px 4px rgba(99, 110, 114, 1),
+    0 8px 8px rgba(99, 110, 114, 1);
+}
+.intactimg {
+  width: 45% !important;
+  margin-top: 40% !important;
+}
+.hovertitles-intact {
+  font-size: 14px;
+  font-weight: bold;
+  color: rgba(255, 255, 255, 0.9);
+}
+.intact-left:hover,
+.intact-right:hover {
+  background-color: rgba(99, 110, 114, 1) !important;
+}
+.available {
+  color: #909399 !important;
+}
+.intactbox {
+  width: 100%;
+  height: 100%;
+  display: flex;
+}
+.intact {
+  background: rgba(30, 144, 255, 0.5) !important;
+}
+.notdatas {
+  position: absolute;
+  top: 45%;
+  left: 45%;
+  font-size: 22px;
+  color: #95a5a6;
+  font-weight: bold;
+}
 @keyframes mymove {
   0% {
     top: -35px;
@@ -1594,7 +1744,7 @@ export default {
 }
 
 .compulsorydialog .el-table__body-wrapper {
-  max-height: 50vh;
+  height: 50vh;
   overflow-y: scroll;
 }
 
@@ -1658,7 +1808,7 @@ export default {
 }
 
 .compulsorydialog .el-table--fit {
-  height: 53vh;
+  height: 55vh;
 }
 
 .cardbox .el-card__header {
@@ -1678,11 +1828,23 @@ export default {
   .compulsorydialog .el-dialog {
     height: 75vh;
   }
+  .compulsorydialog .el-table__body-wrapper {
+    height: 44vh !important;
+  }
 }
 
 @media screen and (max-width: 1400px) {
   .compulsorydialog .el-dialog {
     height: 80vh;
   }
+  .cardbox {
+    width: 24% !important;
+  }
+  .information-box .source {
+    line-height: 40px !important;
+  }
+  .compulsorydialog .el-table__body-wrapper {
+    height: 45vh !important;
+  }
 }
 </style>

+ 72 - 5
TEAMModelBI/ClientApp/src/view/participation/setPhase.vue

@@ -411,6 +411,18 @@
     <!--编辑弹窗-->
     <div class="conductbox">
       <el-dialog v-model="editDialog" :title="editDialogName" width="30%">
+        <!--学段编辑-->
+        <el-form :model="stageData" v-if="dialogModels === 'stage'">
+          <el-form-item label="学段名称" prop="name" class="form-semester-name">
+            <el-input v-model="stageData.name" autocomplete="off"></el-input>
+          </el-form-item>
+          <el-form-item label="所属阶段" class="stage-checkbox">
+            <div class="checkbox-stage">
+              <el-checkbox v-for="(item,index) in stageData.checkeds" :key="index" v-model="item.state" :label="item.name" size="small" />
+            </div>
+          </el-form-item>
+        </el-form>
+        <!--学段编辑end-->
         <!--学期弹窗-->
         <el-form :model="form" :rules="rules" ref="ruleFormbox" v-if="dialogModels === 'semester'">
           <el-form-item :label="$t(`schoolManages.gradSet.popup.tables.name`) + ':'" prop="name" class="form-semester-name">
@@ -503,7 +515,7 @@ export default {
       default: {}
     },
   },
-  setup (props) {
+  setup (props, context) {
     let { proxy } = getCurrentInstance()
     // let PowerShow = proxy.$access.inspectPower('batchschool-upd')
     const store = useStore()
@@ -708,6 +720,43 @@ export default {
     let timeZoneList = ref([])
     let ruleFormbox = ref()
     let dialogModels = ref()
+    const stageTage = ref([
+      { name: '学前', value: 'pre', color: '#fd79a8' },
+      { name: '小学', value: 'primary', color: '#74b9ff' },
+      { name: '初中', value: 'junior', color: '#0984e3' },
+      { name: '高中', value: 'senior', color: '#00cec9' },
+      { name: '中职(中专,技校,职高)', value: 'secondary', color: '#2ed573' },
+      { name: '高职(专科)', value: 'college', color: '#eccc68' },
+      { name: '大学本科', value: 'university', color: '#e17055' },
+      { name: '特殊教育', value: 'special', color: '#a29bfe' },
+      { name: '教育局', value: 'edu-bureau', color: '#e84393' },
+      { name: '电教部门', value: 'elecedu-dept', color: '#5758BB' },
+      { name: '成人中专', value: 'adult-secondary', color: '#fab1a0' },
+      { name: '成人高教', value: 'adult-higher', color: '#e17055' },
+      { name: '硕士研究生', value: 'master', color: '#12CBC4' },
+      { name: '博士研究生', value: 'doctor', color: '#1289A7' },
+      { name: '企业', value: 'enterprise', color: '#778beb' },
+    ])
+    let stageData = ref({
+      name: '',
+      checkeds: [
+        { name: '学前', value: 'pre', state: false, },
+        { name: '小学', value: 'primary', state: false, },
+        { name: '初中', value: 'junior', state: false, },
+        { name: '高中', value: 'senior', state: false, },
+        { name: '中职(中专,技校,职高)', value: 'secondary', state: false, },
+        { name: '高职(专科)', value: 'college', state: false, },
+        { name: '大学本科', value: 'university', state: false, },
+        { name: '特殊教育', value: 'special', state: false, },
+        { name: '教育局', value: 'edu-bureau', state: false, },
+        { name: '电教部门', value: 'elecedu-dept', state: false, },
+        { name: '成人中专', value: 'adult-secondary', state: false, },
+        { name: '成人高教', value: 'adult-higher', state: false, },
+        { name: '硕士研究生', value: 'master', state: false, },
+        { name: '博士研究生', value: 'doctor', state: false, },
+        { name: '企业', value: 'enterprise', state: false, },
+      ],
+    })
     //获取当前学校的信息(API)
     function getnowSchool (data) {
       console.log(data, '进入调用API方法')
@@ -717,8 +766,8 @@ export default {
       // proxy.$api
       //   .getNowscholl({ schoolId: data })
       //   .then((res) => {
-      //     console.log(res, '返回的res内容')
-      //     res.state === 200 ? ((schoolData = res.schoolAssists), conductData(res.schoolAssists)) : ''
+      //     console.log(res, '返回的res内容CCCCC')
+      //     res.state === 200 ? ((schoolData = res.schoolAssists), conductData(res.schoolAssists), context.emit('schoolDetailInfo', res.schoolAssists)) : ''
       //   })
       //   .catch((res) => {
       //     ElMessage.error('获取学校数据异常')
@@ -785,8 +834,9 @@ export default {
     //修改学段名称
     function amendPhasename () {
       let num = pathNowphase.value
-      nowschoolData.value.period[num].changed = true
+      // nowschoolData.value.period[num].changed = true
       console.log(nowschoolData.value)
+      semesterCompile(nowschoolData.value.period[num], 'stage')
     }
     //学段名称修改完成 调整状态值
     function nameChanges (index) {
@@ -941,6 +991,18 @@ export default {
           (editDialogName.value = proxy.$t(`schoolManages.gradSet.popup.addTime`)),
           (dialogModels.value = 'timebucket'))
         : ''
+      state === 'stage'
+        ? (
+          (editDialogName.value = '编辑学段属性'),
+          (stageData.value.checkeds.forEach((a) => { a.state = false })),
+          (stageData.value.name = value.name),
+          (value.type.forEach((item) => {
+            stageData.value.checkeds.forEach((items) => {
+              item == items.value ? items.state = true : ''
+            })
+          })),
+          dialogModels.value = 'stage')
+        : ''
       console.log(form.value)
       editDialog.value = true
     }
@@ -1327,7 +1389,9 @@ export default {
       timeZoneList,
       semesterSort,
       gradeClassdata,
-      userPower
+      userPower,
+      stageTage,
+      stageData
     }
   },
 }
@@ -2199,6 +2263,9 @@ export default {
 .settimg-notdata {
   padding-top: 5%;
 }
+.checkbox-stage {
+  text-align: left;
+}
 </style>
 <style>
 .pitch .el-card__body {

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1135 - 0
TEAMModelBI/ClientApp/src/view/product/details.vue


+ 574 - 0
TEAMModelBI/ClientApp/src/view/product/index.vue

@@ -0,0 +1,574 @@
+<template>
+  <!--外层所有数据-->
+  <div class="productbox" v-if="showState==='default'">
+    <div class="header-select">
+      <el-collapse v-model="activeNames" accordion>
+        <el-collapse-item title="数据筛选" name="1">
+          <div class="filtratebox">
+            <!--产品类型-->
+            <div class="filtratebox-phase">
+              <span class="filtratebox-phase-title">{{productData.typeName}}:</span>
+              <div class="filtratebox-phase-content">
+                <div class="phase-item" v-for="(items,index) in productData.type" :key="items.value" :class="[index ===clickNum.pahse ? 'filter-click':'' ]">{{items.name}}</div>
+                <!-- <div class="phase-item">123</div>
+                <div class="phase-item">123</div>
+                <div class="phase-item">123</div>
+                <div class="phase-item">123</div> -->
+              </div>
+            </div>
+            <!--结果类型-->
+            <div class="filtratebox-phase">
+              <span class="filtratebox-phase-title">{{productData.dataType}}:</span>
+              <div class="filtratebox-phase-content">
+                <div class="phase-item" v-for="(items,index) in productData.datainfo" :key="items.value" :class="[index ===clickNum.resultType ? 'filter-click':'' ]" @click="clickNum.resultType=index">{{items.name}}</div>
+              </div>
+            </div>
+            <!--结果类型end-->
+            <!--产品类型end-->
+            <div class="filtratebox-phase">
+              <span class="filtratebox-phase-title">筛选类型:</span>
+              <div class="filtratebox-phase-content">
+                <div class="phase-item" v-for="(items,index) in productData.filtrate" :key="items.value" :class="[index ===clickNum.filter ? 'filter-click':'' ]" @click="clickNum.filter=index">{{items.name}}</div>
+              </div>
+            </div>
+            <div class="select-result">
+              <!--来源类型-->
+              <div v-show="clickNum.filter === 0">
+                <div class="filtratebox-phase">
+                  <span class="filtratebox-phase-title subclass">{{productData.sourceName}}:</span>
+                  <div class="filtratebox-phase-content">
+                    <div class="phase-item" v-for="(items,index) in productData.source" :key="items.value" :class="[index ===clickNum.subject ? 'filter-click':'' ]">{{items.name}}</div>
+                    <!-- <div class="phase-item filter-click">456456</div>
+                <div class="phase-item">456456</div>
+                <div class="phase-item">456456</div> -->
+                  </div>
+                </div>
+                <div class="filtratebox-phase">
+                  <span class="filtratebox-phase-title subclass">时间范围:</span>
+                  <div class="filtratebox-phase-content">
+                    <div class="phase-item" v-for="(items,index) in productData.time" :key="items.value" :class="[index ===clickNum.time ? 'filter-click':'' ]" @click="(timeScope=items.timeV,clickNum.time=index)">{{items.name}}</div>
+                  </div>
+                </div>
+                <div class="filtratebox-phase">
+                  <span class="filtratebox-phase-title subclass">精准选择:</span>
+                  <div class="filtratebox-phase-content precise">
+                    <div>
+                      <el-cascader :options="options" :props="props2" clearable />
+                    </div>
+                    <div>
+                      <el-date-picker v-model="productData.timevalue" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="截止时间" value-format="x" v-if="timeScope ==='daterange'" />
+                      <el-date-picker v-model="productData.timevalue" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="截止时间" value-format="x" v-else-if="timeScope ==='dates'" />
+                      <el-date-picker v-model="productData.timevalue" type="week" format="YYYY[年]MM[月]DD[日] [第]ww[周]" placeholder="请选择 某一周 来进行数据统计" value-format="x" v-else-if="timeScope ==='week'" />
+                      <el-date-picker v-model="productData.timevalue" type="monthrange" range-separator="至" start-placeholder="开始月份" end-placeholder="结束月份" value-format="x" v-else-if="timeScope ==='month'" />
+                      <el-date-picker v-model="productData.timevalue" type="year" placeholder="请选择 某一年 来进行数据统计" value-format="x" v-else-if="timeScope ==='year'" />
+                    </div>
+                  </div>
+                </div>
+              </div>
+              <!--来源类型end-->
+              <!--地区选择-->
+              <div v-show="clickNum.filter === 1">
+                <div class="filtratebox-phase">
+                  <span class="filtratebox-phase-title subclass">{{productData.districtName}}:</span>
+                  <div class="filtratebox-phase-content">
+                    <div class="phase-item" v-for="(items,index) in productData.district" :key="items.value" :class="[index ===clickNum.district ? 'filter-click':'' ]" @click="clickCut(items,index,'grade')">{{items.name}}</div>
+                  </div>
+                </div>
+                <div class="filtratebox-phase">
+                  <span class="filtratebox-phase-title subclass">时间类型:</span>
+                  <div class="filtratebox-phase-content">
+                    <div class="phase-item" v-for="(items,index) in productData.time" :key="items.value" :class="[index ===clickNum.time ? 'filter-click':'' ]">{{items.name}}</div>
+                  </div>
+                </div>
+                <div class="filtratebox-phase">
+                  <span class="filtratebox-phase-title subclass">精准选择:</span>
+                  <div class="filtratebox-phase-content precise">
+                    <div>
+                      <el-cascader :options="options" :props="props2" clearable />
+                    </div>
+                    <div>
+                      <el-date-picker v-model="productData.timevalue" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="截止时间" />
+                    </div>
+                  </div>
+                </div>
+              </div>
+              <!--地区选择end-->
+              <!--时间选择-->
+              <div v-show="clickNum.filter === 2">
+                <div class="filtratebox-phase">
+                  <span class="filtratebox-phase-title subclass">{{productData.timeName}}:</span>
+                  <div class="filtratebox-phase-content">
+                    <div class="phase-item" v-for="(items,index) in productData.time" :key="items.value" :class="[index ===clickNum.time ? 'filter-click':'' ]" @click="(timeScope=items.timeV,clickNum.time=index)">{{items.name}}</div>
+                  </div>
+                </div>
+                <div class="filtratebox-phase">
+                  <span class="filtratebox-phase-title subclass">精准选择:</span>
+                  <div class="filtratebox-phase-content precise">
+                    <div>
+                      <!-- <el-date-picker v-model="productData.timevalue" type="dates" placeholder="选择日期" size="default" /> -->
+                      <el-date-picker v-model="productData.timevalue" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="截止时间" value-format="x" v-if="timeScope ==='daterange'" />
+                      <el-date-picker v-model="productData.timevalue" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="截止时间" value-format="x" v-else-if="timeScope ==='dates'" />
+                      <el-date-picker v-model="productData.timevalue" type="week" format="YYYY[年]MM[月]DD[日] [第]ww[周]" placeholder="请选择 某一周 来进行数据统计" value-format="x" v-else-if="timeScope ==='week'" />
+                      <el-date-picker v-model="productData.timevalue" type="monthrange" range-separator="至" start-placeholder="开始月份" end-placeholder="结束月份" value-format="x" v-else-if="timeScope ==='month'" />
+                      <el-date-picker v-model="productData.timevalue" type="year" placeholder="请选择 某一年 来进行数据统计" value-format="x" v-else-if="timeScope ==='year'" />
+                    </div>
+                  </div>
+                </div>
+              </div>
+              <!--时间选择end-->
+            </div>
+          </div>
+        </el-collapse-item>
+      </el-collapse>
+    </div>
+    <div class="middlebox">
+      <div class="middlebox-content">
+        <div class="middlebox-left">
+          <div class="middlebox-left-serach">
+            <el-input v-model="findValue" class="w-80 m-2" placeholder="输入信息ID进行搜索..." suffix-icon="el-icon-search" size="small" />
+          </div>
+        </div>
+        <div class="middlebox-right">
+          <div class="middlebox-right-title">共有<span class="middlebox-right-num">45</span>条数据</div>
+          <div class="exportbtn">
+            <el-button type="success" plain @click="exportstate=true">导出数据到Execl</el-button>
+            <!-- <el-button type="success" plain disabled>导出数据到Execl</el-button> -->
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="data-tables">
+      <el-auto-resizer>
+        <template #default="{ height, width }">
+          <el-table-v2 :columns="columns" :data="data" :width="width" :height="height" fixed />
+        </template>
+      </el-auto-resizer>
+    </div>
+  </div>
+  <div v-else-if="showState==='details'">
+    <Details @myback="changStateshow"></Details>
+  </div>
+  <div class="dialog-filter" v-if="exportstate">
+    <el-dialog v-model="exportstate" title="筛选导出" width="35%">
+      <div class="exports-title">导出筛选</div>
+      <!-- <el-checkbox-group v-model="checkList">
+        <div class="selectbox-ck">
+          <div class="check-selectbox-item" v-for="(item,index) in  exportStandard" :key="index">
+            <el-checkbox :label="item.key">
+              <span>{{item.title}}:</span>
+              <el-select v-model="item.value" placeholder="请选择范围" filterable @blur="selectBlur($event)" clearable v-if="checkList.includes(item.key)">
+                <el-option v-for="(items,index) in item.option" :key="index" :label="items.name" :value="items.value">
+                </el-option>
+              </el-select>
+              <el-select v-model="item.value" placeholder="请选择范围" filterable disabled v-else-if="!checkList.includes(item.key)">
+                <el-option v-for="(items,index) in item.option" :key="index" :label="items.name" :value="items.value">
+                </el-option>
+              </el-select>
+            </el-checkbox>
+          </div>
+        </div>
+      </el-checkbox-group> -->
+      <div class="selectbox-ck">
+        <el-checkbox-group v-model="fieldList">
+          <el-checkbox label="名称" />
+          <el-checkbox label="教室数" />
+          <el-checkbox label="教师数" />
+          <el-checkbox label="学生数" />
+          <el-checkbox label="课堂总数" />
+          <el-checkbox label="T指数" />
+          <el-checkbox label="课堂时间数" />
+          <el-checkbox label="授权类型" />
+          <el-checkbox label="时间" />
+        </el-checkbox-group>
+      </div>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="exportstate = false">取消</el-button>
+          <el-button type="primary" @click="exportstate = false">
+            确认
+          </el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import option_cn from '@/static/regions/region_cn.json'
+import { ref, getCurrentInstance, watch } from 'vue'
+import Details from './details.vue'
+let drawer = ref(false)
+let direction = ref('ttb')
+let activeNames = ref(['1'])
+let showState = ref('default')
+let findValue = ref()
+let columns = ref([
+  {
+    key: "id",
+    dataKey: "id",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: "编号",//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    fixed: false,//是否固定列
+    headerClass: 'header-class',
+  },
+  {
+    key: "name",
+    dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: "名称",//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+  },
+  {
+    key: "classnum",
+    dataKey: "classnum",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: "教室数",//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+  },
+  {
+    key: "teachnum",
+    dataKey: "teachnum",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: "教师数",//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+  },
+  {
+    key: "studennum",
+    dataKey: "studennum",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: "学生人数",//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+  },
+  {
+    key: "classtotal",
+    dataKey: "classtotal",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: "课堂总数",//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+  },
+  {
+    key: "studentime",
+    dataKey: "studentime",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: "课堂总时数",//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+  },
+  {
+    key: "tnum",
+    dataKey: "tnum",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: "T指数",//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+  },
+  {
+    key: "time",
+    dataKey: "time",
+    title: "时间",
+    width: 100,
+    headerClass: 'general',
+  },
+  {
+    key: "handle",
+    title: "操作",
+    width: 150,
+    align: "center",
+    headerClass: 'btn-class',
+    cellRenderer: (data) =>
+    (
+      <>
+        <el-button type="primary" onClick={changeState.bind(this, data)}>查看</el-button>
+      </>
+    )
+  },
+])
+let data = ref([
+  { id: 1, name: '1111', classnum: '33091', teachnum: 123, studennum: 80, classtotal: 7, studentime: '120Min', tnum: 75, type: '1', time: '2023-03-01' },
+  { id: 2, name: '2222', classnum: '33092', teachnum: 123, studennum: 55, classtotal: 8, studentime: '110Min', tnum: 45, type: '2', time: '2023-03-02' },
+  { id: 3, name: '3333', classnum: '33093', teachnum: 123, studennum: 130, classtotal: 9, studentime: '60Min', tnum: 55, type: '0', time: '2023-03-03' },
+  { id: 4, name: '4444', classnum: '33094', teachnum: 123, studennum: 70, classtotal: 7, studentime: '50Min', tnum: 85, type: '1', time: '2023-03-04' },
+  { id: 5, name: '5555', classnum: '33095', teachnum: 123, studennum: 66, classtotal: 8, studentime: '130Min', tnum: 80, type: '2', time: '2023-03-05' },
+  { id: 6, name: '666', classnum: '33096', teachnum: 123, studennum: 50, classtotal: 9, studentime: '140Min', tnum: 95, type: '2', time: '2023-03-07' },
+  { id: 7, name: '77777', classnum: '33097', teachnum: 123, studennum: 32, classtotal: 6, studentime: '120Min', tnum: 65, type: '0', time: '2023-03-08' },
+])
+let productData = ref({
+  dataType: '结果类型',
+  datainfo: [
+    { name: '累计统计', value: 'aggregate' },
+    { name: '独立统计', value: 'onlyone' }
+  ],
+  typeName: '产品类型',
+  type: [
+    { name: 'HiTeach', value: 'HiTeach' },
+    { name: 'HiTA', value: 'HiTA' },
+    { name: 'webIrs', value: 'webIrs' },
+  ],
+  filtrateName: '筛选类型',
+  filtrate: [
+    { name: '来源类型', key: 'source' },
+    { name: '地区城市', key: 'areaCity' },
+    { name: '时间选择', key: 'areaCity' },
+  ],
+  sourceName: '目标范围',
+  source: [
+    // { name: '全部', value: 'sourceAll' },
+    { name: '学校', value: 'school' },
+    { name: '学区', value: 'area' },
+    { name: '城市', value: 'city' }
+  ],
+  districtName: '地区选择',
+  district: [
+    // { name: '所有', value: 'districtAll' },
+    { name: '省', value: 'province' },
+    { name: '城市', value: 'city' },
+    { name: '学区', value: 'area' },
+  ],
+  timeName: '时间选择',
+  timevalue: '',
+  time: [
+    // { name: '全部', value: 'timeAll', timeV: 'daterange' },
+    { name: '天', value: 'day', timeV: 'dates' },
+    { name: '周', value: 'week', timeV: 'week' },
+    { name: '月', value: 'month', timeV: 'month' },
+    { name: '年', value: 'year', timeV: 'year' }
+  ]
+})
+let clickNum = ref({
+  pahse: 0,
+  subject: 0,
+  filter: 0,
+  district: 0,
+  time: 0,
+  resultType: 0
+})
+let timeScope = ref('daterange')
+let cellWidth = ref((100 / columns.value.length).toFixed(2))
+let options = ref([
+  { value: 'Aarea', label: 'A学区', children: [{ value: 'A-1', label: 'A-1学校' }, { value: 'A-2', label: 'A-2学校' }, { value: 'A-3', label: 'A-3学校' }, { value: 'A-4', label: 'A-4学校' }] },
+  { value: 'Barea', label: 'B学区', children: [{ value: 'B-1', label: 'B-1学校' }, { value: 'B-2', label: 'B-2学校' }, { value: 'B-3', label: 'B-3学校' }, { value: 'B-4', label: 'B-4学校' }] }
+])
+const props2 = {
+  multiple: true,
+  checkStrictly: true,
+}
+/*地区相关配套json*/
+//省
+let optionCopy = option_cn
+let province = function () {
+  let optionProvince = option_cn
+  optionProvince.map((item) => { return delete item.children })
+  return optionProvince
+}()
+console.log(province, '省')
+/*地区相关配套json end*/
+let changeHight = ref(56)
+let exportstate = ref(false)
+let dataForm = ref({
+  newData: '',
+  selectOption: [
+    {
+      value: 'Option1',
+      label: 'Option1',
+    },
+    {
+      value: 'Option2',
+      label: 'Option2',
+    },
+    {
+      value: 'Option3',
+      label: 'Option3',
+    },
+    {
+      value: 'Option4',
+      label: 'Option4',
+    },
+    {
+      value: 'Option5',
+      label: 'Option5',
+    },
+  ]
+})
+let checkList = ref([])
+let fieldList = ref(['名称', '教室数', '教师数', '学生数', 'T指数'])
+let exportStandard = ref([
+  { title: '参与人次', value: 0, key: 'personnum', option: [{ name: '小于50', value: '50' }, { name: '大于50,小于100', value: '50-100' }, { name: '大于100', value: '101' }, { name: '大于300', value: '301' }] },
+  { title: '授课时间', value: 0, key: 'classtime', option: [{ name: '小于等于45分钟', value: '45' }, { name: '大于45分钟,小于90分钟', value: '45-90' }, { name: '小于90分钟', value: '91' }] },
+  { title: 'T指标数', value: 0, key: 'Tnum', option: [{ name: '无绿灯', value: '0' }, { name: '单绿灯', value: '1' }, { name: '双绿灯', value: '2' }] },
+  { title: '授权类型', value: 0, key: 'powertype', option: [{ name: '全部', value: 'all' }, { name: '试用', value: 'test' }, { name: '已授权', value: 'power' }] },
+])
+function changeState (value) {
+  console.log(value)
+  showState.value = 'details'
+}
+function changStateshow (value) {
+  console.log(value, '状态改变')
+  showState.value = value
+}
+function selectBlur (e) {
+  dataForm.value.newData = e.target.value;
+}
+watch(activeNames, (newdata) => {
+  if (newdata.length === 0) {
+    changeHight.value = 80
+  } else {
+    changeHight.value = 56
+  }
+})
+watch(checkList, (newvalue) => {
+  console.log(newvalue)
+})
+</script>
+<style scoped>
+.productbox {
+  line-height: 40px;
+}
+.header-select,
+.middlebox {
+  /* width: 100%; */
+  /* background-color: #fff; */
+  margin: 10px 20px;
+}
+.filtratebox {
+  width: 100%;
+  padding: 10px 20px 0px 20px;
+  background: #fff;
+  border-top: 1px solid #ccc;
+}
+.filtratebox-phase {
+  width: 100%;
+  margin-top: 10px;
+  display: flex;
+}
+.filtratebox-phase-title {
+  width: 8%;
+  font-size: 16px;
+  font-weight: bold;
+  margin-right: 10px;
+  min-width: 45px;
+}
+.filtratebox-phase-content {
+  width: 92%;
+  display: flex;
+  flex-wrap: wrap;
+}
+.phase-item {
+  padding: 0 10px;
+  margin-left: 15px;
+  height: 28px;
+  line-height: 28px;
+  box-shadow: none !important;
+  border: none !important;
+  font-size: 14px;
+  cursor: pointer;
+}
+.phase-item:hover {
+  color: #409eff;
+}
+.filter-click {
+  background: #10abe7;
+  box-shadow: none;
+  color: #fff !important;
+  border-radius: 5px;
+}
+.middlebox {
+  background-color: #fff;
+}
+.middlebox-content {
+  display: flex;
+}
+.middlebox-left {
+  width: 50%;
+  text-align: left;
+  padding-left: 1%;
+  font-size: 14px;
+  display: flex;
+}
+.middlebox-left-tag {
+  width: 35%;
+}
+.middlebox-left-serach {
+  width: 65%;
+}
+.middlebox-right {
+  width: 50%;
+  text-align: right;
+  font-size: 16px;
+  line-height: 48px;
+  padding-right: 1%;
+  display: flex;
+  flex-direction: row-reverse;
+}
+.middlebox-right-num {
+  font-size: 18px;
+  color: #eb4d4b;
+}
+.data-tables {
+  width: 100%;
+  padding: 10px 20px;
+  height: v-bind(changeHight + "vh");
+}
+.select-result {
+  /* padding: 0.5%; */
+}
+.subclass {
+  color: #7f8c8d;
+}
+.precise div {
+  width: 25%;
+  padding-left: 1%;
+  text-align: left;
+}
+.exportbtn {
+  margin-right: 2%;
+}
+.selectbox-ck {
+  width: 100%;
+  padding: 2%;
+  display: flex;
+  flex-wrap: wrap;
+  overflow: hidden;
+  text-align: left;
+  margin-top: 1%;
+}
+.check-selectbox-item {
+  padding: 0.5% 1%;
+  margin-top: 2%;
+  box-shadow: 0 2px 5px #e9e9e9;
+  width: 50%;
+  border: 1px solid #e9e9e9;
+}
+.exports-title {
+  font-size: 16px;
+  line-height: 18px;
+  color: #7f8c8d;
+  text-align: left;
+}
+</style>
+<style>
+.data-tables .header-class,
+.data-tables .el-table-v2__row-cell {
+  width: v-bind(cellWidth + "%") !important;
+  justify-content: center;
+  text-align: center;
+}
+.data-tables .general {
+  width: v-bind(cellWidth + "%") !important;
+  justify-content: center;
+  text-align: center;
+}
+.data-tables .btn-class {
+  width: v-bind(cellWidth + "%") !important;
+  justify-content: center;
+  text-align: center;
+}
+.precise div .el-cascader,
+.precise div .el-input {
+  width: 100%;
+}
+.header-select .el-collapse-item__header {
+  font-size: 16px;
+  padding-left: 0.5%;
+}
+.dialog-filter .el-dialog__header,
+.dialog-filter .el-dialog__footer {
+  line-height: 60px;
+}
+</style>

+ 80 - 0
TEAMModelBI/ClientApp/src/view/resultpage.vue

@@ -0,0 +1,80 @@
+<template>
+  <div class="backbox">
+    <div class="positionbox">
+      <div class="icons">
+        <svg class="icons-img" aria-hidden="true">
+          <use :xlink:href="lockicon"></use>
+        </svg>
+      </div>
+      <div class="title">{{text}}</div>
+    </div>
+  </div>
+</template>
+<script setup>
+import { ref } from 'vue'
+let a = ref()
+let lockicon = ref('#icon-chenggong1')
+let text = ref('操作成功')
+let headers = window.document.location.href.indexOf('code=')
+let tail = window.document.location.href.indexOf('&msg')
+let headerHost = window.document.location.href.slice(headers + 5, tail)
+console.log(headerHost, '33333')
+function init () {
+  let codeNum = headerHost
+  console.log(codeNum, '当前的值')
+  switch (codeNum) {
+    case '1':
+      lockicon.value = '#icon-chenggong1'; text.value = '操作成功';
+      break;
+    case '2':
+      lockicon.value = '#icon-71shibai'; text.value = '操作失败';
+      break;
+    case '0':
+      lockicon.value = '#icon-71shibai'; text.value = '凭据失效';
+      break;
+    case '400':
+      lockicon.value = '#icon-71shibai'; text.value = '参数异常';
+      break;
+    case '500':
+      lockicon.value = '#icon-71shibai'; text.value = '服务器异常';
+    default:
+      break;
+  }
+}
+init()
+</script>
+<style  scoped>
+.backbox {
+  width: 100%;
+  /* height: 100vh; */
+  /* display: flex;
+  align-items: center;
+  justify-content: center; */
+  /* background-color: #ecf0f1; */
+}
+.positionbox {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  text-align: center;
+  width: 100%;
+  height: 100%;
+  background-color: #ecf0f1;
+}
+.icons,
+.title {
+  width: 100%;
+  text-align: center;
+  margin-top: 50%;
+}
+.title {
+  font-size: 1.8em;
+  font-weight: bold;
+  margin-top: 2%;
+}
+.icons-img {
+  width: 8em;
+  height: 8em;
+}
+</style>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 802 - 271
TEAMModelBI/ClientApp/src/view/schoolServe/school.vue


+ 71 - 29
TEAMModelBI/ClientApp/src/view/schoolServe/setSchooladmin.vue

@@ -16,7 +16,7 @@
           <!-- <p class="list-item-left-content"><span class="list-item-left-title">手机号:</span><span>{{item.mobile}}</span></p> -->
         </div>
         <div class="list-item-right">
-          <div class="deletebtn" @click="removeadmin(item)">
+          <div class="deletebtn" @click="nowUser=item,removeData.state=true">
             <svg class="undock" aria-hidden="true">
               <use xlink:href="#icon-yichuhaoyou"></use>
             </svg>
@@ -32,7 +32,7 @@
             <div class="hint"><span>请输入用户</span><span class="emphasize">手机号、醍摩豆账号</span><span>等相关信息进行搜索</span></div>
             <div class="search-box">
               <!-- <input class="search-txt" type="text" id="serachname" :value="filterText" placeholder="搜索相关人名" @oninput="personnelSearch()" @compositionend="personnelSearch()"> -->
-              <el-input v-model="adminfilter" placeholder="Please input" class="search-txt" />
+              <el-input v-model="adminfilter" placeholder="输入手机号、醍摩豆账号搜索" class="search-txt" />
               <svg class="serachbox-empty" aria-hidden="true" v-if="adminfilter !==''" @click="adminfilter=''">
                 <use xlink:href="#icon-qingkong"></use>
               </svg>
@@ -44,7 +44,7 @@
               <p>未搜索到相关用户信息,请检验后重新输入搜索</p>
             </div>
             <div class="submitbtn">
-              <el-button type="primary" size="small" @click=serachPersonnel(adminfilter) class="anewbox-btn blue">搜索人员</el-button>
+              <el-button type="primary" @click=serachPersonnel(adminfilter) class="anewbox-btn blue">搜索人员</el-button>
             </div>
           </div>
           <div class="admin-text-box" v-else-if="searchState ===true">
@@ -57,8 +57,8 @@
                 <p class="result-text-phone">{{searchData.mobile}}</p>
               </div>
               <div class="anewbox">
-                <el-button type="primary" size="small" @click="addAdmin()" class="anewbox-btn">加入到学校管理员</el-button>
-                <el-button type="primary" size="small" class="anewbox-btn" @click="searchState=false,searchData='',adminfilter=''">重新检索人员</el-button>
+                <el-button type="primary" @click="addAdmin()" class="anewbox-btn">加入到学校管理员</el-button>
+                <el-button type="primary" class="anewbox-btn" @click="searchState=false,searchData='',adminfilter=''">重新检索人员</el-button>
               </div>
             </div>
           </div>
@@ -81,6 +81,22 @@
       </div>
     </div>
   </div>
+  <div class="inquirybox">
+    <el-dialog v-model="removeData.state" title="移除学校管理员" width="30%" center>
+      <span>
+        请问您确定从当前学校管理员列表中移除{{nowUser.name}}吗?
+      </span>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="removeData.state = false">取消</el-button>
+          <el-button type="primary" @click="removeadmin(1)">只移除管理者身份</el-button>
+          <el-button type="primary" @click="removeadmin(2)">
+            从学校移除该教师
+          </el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
 </template>
 <script>
 import { ref, getCurrentInstance, watch } from 'vue'
@@ -106,6 +122,11 @@ export default {
     let searchState = ref(false)
     let searchNodata = ref(false)
     let schoolValue = ref()
+    let removeData = ref({
+      show: false,
+      type: 0,
+    })
+    let nowUser = ref({})
     function getAdmin () {
       let data = { scId: schoolValue.value.id }
       proxy.$api
@@ -136,32 +157,32 @@ export default {
     }
 
     function removeadmin (value) {
-      console.log(value)
+      console.log(value, nowUser)
       if (adminData.value.length <= 1) {
         return ElMessage.info('管理员至少存在一位,无法移除当前人员')
       }
-      ElMessageBox.confirm(`请问您确定从当前学校管理员列表中移除  ${value.name}  吗?`, '移除学校管理员', {
-        confirmButtonText: proxy.$t(`commonMsg.confirm`),
-        cancelButtonText: proxy.$t(`commonMsg.closes`),
-        type: 'error',
-        center: true,
-      }).then(() => {
-        let data = { tmdId: value.id, scIds: [schoolValue.value.id] }
-        proxy.$api
-          .deleteSchooladmin(data)
-          .then((res) => {
-            res.state === 200 ?
-              (ElMessage.success('操作成功'), getAdmin()) :
-              res.state === 403 ?
-                ElMessage.error('管理员至少存在一位,无法移除当前人员') :
-                res.state === 1 ?
-                  ElMessage.error('无法删除自己,操作失败') :
-                  ''
-          })
-          .catch((error) => {
-            ElMessage.error('删除失败')
-          })
-      })
+      // ElMessageBox.confirm(`请问您确定从当前学校管理员列表中移除  ${value.name}  吗?`, '移除学校管理员', {
+      //   confirmButtonText: proxy.$t(`commonMsg.confirm`),
+      //   cancelButtonText: proxy.$t(`commonMsg.closes`),
+      //   type: 'error',
+      //   center: true,
+      // }).then(() => {
+      // })
+      let data = { tmdId: nowUser.value.id, scIds: [schoolValue.value.id], rmvFromSc: value === 1 ? false : value === 2 ? true : false }
+      proxy.$api
+        .deleteSchooladmin(data)
+        .then((res) => {
+          res.state === 200 ?
+            (ElMessage.success('操作成功'), removeData.value.state = false, getAdmin()) :
+            res.state === 403 ?
+              ElMessage.error('管理员至少存在一位,无法移除当前人员') :
+              res.state === 1 ?
+                ElMessage.error('无法删除自己,操作失败') :
+                ''
+        })
+        .catch((error) => {
+          ElMessage.error('删除失败')
+        })
     }
 
     function addAdmin () {
@@ -203,7 +224,9 @@ export default {
       removeadmin,
       addAdmin,
       searchNodata,
-      userRoles
+      userRoles,
+      removeData,
+      nowUser
     }
   },
 }
@@ -526,4 +549,23 @@ export default {
 .headerPhoto .el-image {
   display: block;
 }
+.search-box .el-input__wrapper {
+  width: 100%;
+  padding: 0px;
+  /* background: #bdc3c7; */
+  background: transparent;
+  box-shadow: 0px 0px 0px 0px transparent;
+}
+.search-box .el-input__wrapper .is-focues {
+  border: 0px;
+  box-shadow: 0px 0px 0px 0px transparent;
+}
+.search-box .el-input__wrapper:hover {
+  border: 0px;
+  box-shadow: 0px 0px 0px 0px transparent;
+}
+.inquirybox .el-dialog {
+  line-height: 40px;
+  border-radius: 5px;
+}
 </style>

+ 41 - 16
TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue

@@ -412,7 +412,9 @@
           </el-form-item>
           <el-form-item label="所属阶段" class="stage-checkbox">
             <div class="checkbox-stage">
-              <el-checkbox v-for="(item,index) in stageData.checkeds" :key="index" v-model="item.state" :label="item.name" size="small" />
+              <el-radio-group v-model="stageData.ptichValue">
+                <el-radio v-for="(item,index) in stageData.checkeds" :key="index" :label="item.name" size="small" />
+              </el-radio-group>
             </div>
           </el-form-item>
         </el-form>
@@ -509,7 +511,7 @@ export default {
       default: '',
     },
   },
-  setup (props) {
+  setup (props, context) {
     let { proxy } = getCurrentInstance()
     let PowerShow = proxy.$access.identifyPosition(JSON.parse(localStorage.getItem('id_token')))
     const store = useStore()
@@ -669,12 +671,17 @@ export default {
       { name: '小学', value: 'primary', color: '#74b9ff' },
       { name: '初中', value: 'junior', color: '#0984e3' },
       { name: '高中', value: 'senior', color: '#00cec9' },
-      { name: '中职', value: 'secondary', color: '#2ed573' },
-      { name: '高职', value: 'college', color: '#eccc68' },
+      { name: '中职(中专,技校,职高)', value: 'secondary', color: '#2ed573' },
+      { name: '高职(专科)', value: 'college', color: '#eccc68' },
       { name: '大学本科', value: 'university', color: '#e17055' },
       { name: '特殊教育', value: 'special', color: '#a29bfe' },
       { name: '教育局', value: 'edu-bureau', color: '#e84393' },
       { name: '电教部门', value: 'elecedu-dept', color: '#5758BB' },
+      { name: '成人中专', value: 'adult-secondary', color: '#fab1a0' },
+      { name: '成人高教', value: 'adult-higher', color: '#e17055' },
+      { name: '硕士研究生', value: 'master', color: '#12CBC4' },
+      { name: '博士研究生', value: 'doctor', color: '#1289A7' },
+      { name: '企业', value: 'enterprise', color: '#778beb' },
     ])
     //学段编辑弹窗需要数据
     let stageData = ref({
@@ -690,7 +697,13 @@ export default {
         { name: '特殊教育', value: 'special', state: false, },
         { name: '教育局', value: 'edu-bureau', state: false, },
         { name: '电教部门', value: 'elecedu-dept', state: false, },
+        { name: '成人中专', value: 'adult-secondary', state: false, },
+        { name: '成人高教', value: 'adult-higher', state: false, },
+        { name: '硕士研究生', value: 'master', state: false, },
+        { name: '博士研究生', value: 'doctor', state: false, },
+        { name: '企业', value: 'enterprise', state: false, },
       ],
+      ptichValue: ''
     })
     //学期弹窗需要数据
     let form = ref({
@@ -751,8 +764,8 @@ export default {
       proxy.$api
         .getNowscholl({ schoolId: data })
         .then((res) => {
-          console.log(res, '返回的res内容')
-          res.state === 200 ? ((schoolData = res.schoolAssists), conductData(res.schoolAssists)) : ''
+          console.log(res, '返回的res内容CCCCC')
+          res.state === 200 ? ((schoolData = res.schoolAssists), conductData(res.schoolAssists), context.emit('schoolDetails', res.schoolAssists)) : ''
         })
         .catch((res) => {
           ElMessage.error('获取学校数据异常')
@@ -808,11 +821,14 @@ export default {
     //显示学段的tag标签
     function stageTags () {
       let data = nowschoolData.value
-      console.log(data, '当前数据')
-      for (let i in data.period) {
-        data.period[i].typedata = []
-        data.period[i].type.forEach((a) => { stageTage.value.forEach((b) => { a === b.value ? data.period[i].typedata.push(b) : '' }) })
-      }
+      console.log(data, '当前数据tag')
+      //暂停服务,后面处理
+      // for (let i in data.period) {
+      //   if (data.period[i].type !== null) {
+      //     data.period[i].typedata = []
+      //     data.period[i].type.forEach((a) => { stageTage.value.forEach((b) => { a === b.value ? data.period[i].typedata.push(b) : '' }) })
+      //   }
+      // }
       console.log(data, '处理阶段的数据')
     }
     //切换学段(右边渲染数据切换)
@@ -955,7 +971,15 @@ export default {
           (dialogModels.value = 'subjects'))
         :
         state === 'stage'
-          ? (editDialogName.value = '编辑学段属性', stageData.value.checkeds.forEach((a) => { a.state = false }), (stageData.value.name = value.name), value.type.forEach((item) => { console.log(item), stageData.value.checkeds.forEach((items) => { console.log(item, items.value), item == items.value ? items.state = true : '' }) }), dialogModels.value = 'stage')
+          ? (
+            (editDialogName.value = '编辑学段属性'),
+            console.log(stageData, value, '属性属性'),
+            (stageData.value.checkeds.forEach((a) => { a.state = false })),
+            (stageData.value.name = value.name),
+            stageData.value.checkeds.forEach((items) => {
+              items.value == value.periodType ? stageData.value.ptichValue = items.name : ''
+            }),
+            dialogModels.value = 'stage')
           : ''
       if (state === 'updateTimebucket') {
         let timetables = nowschoolData.value.period[pathNowphase.value].timetable
@@ -1042,10 +1066,11 @@ export default {
         : ''
       //编辑学段名称和阶段
       if (dialogModels.value === 'stage') {
+        console.log(nowschoolData.value.period, '当前学段')
         nowschoolData.value.period[pathNowphase.value].name = stageData.value.name
-        let stageTrue = []
-        stageData.value.checkeds.forEach((item) => { item.state === true ? stageTrue.push(item.value) : '' })
-        nowschoolData.value.period[pathNowphase.value].type = stageTrue
+        let stageTrue = ''
+        stageData.value.checkeds.forEach((item) => { item.name === stageData.value.ptichValue ? stageTrue = item.value : '' })
+        nowschoolData.value.period[pathNowphase.value].periodType = stageTrue
         stageTags()
       }
       console.log(nowschoolData.value, pathNowphase.value, '修改后的数据')
@@ -1269,7 +1294,7 @@ export default {
         for (let i = 0; i < nowschoolData.value.period[pathNowphase.value].semesters.length; i++) {
           if (i == nowschoolData.value.period[pathNowphase.value].semesters.length - 1) {
             index = i
-            break
+            continue
           } else {
             let sDate = year + '-' + nowschoolData.value.period[pathNowphase.value].semesters[i].month + '-' + nowschoolData.value.period[pathNowphase.value].semesters[i].day
             let eDate = year + '-' + nowschoolData.value.period[pathNowphase.value].semesters[i + 1].month + '-' + nowschoolData.value.period[pathNowphase.value].semesters[i + 1].day

+ 15 - 15
TEAMModelBI/ClientApp/src/view/schoolmanage/index.vue

@@ -1,6 +1,6 @@
 <template>
-    <div class="school-analyse">
-        <!-- <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+  <div class="school-analyse">
+    <!-- <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
             <el-tab-pane label="数据分析" name="first">
                 <Schoolanalyse></Schoolanalyse>
             </el-tab-pane>
@@ -8,29 +8,29 @@
                 <SchoolManage></SchoolManage>
             </el-tab-pane>
         </el-tabs> -->
-        <Schoolanalyse></Schoolanalyse>
-    </div>
+    <Schoolanalyse></Schoolanalyse>
+  </div>
 </template>
 <script>
 import { ref } from 'vue'
 import Schoolanalyse from './schoolAnalyse.vue'
 import SchoolManage from './schoolManege.vue'
 export default {
-    components: {
-        Schoolanalyse,
-        SchoolManage,
-    },
-    setup() {
-        const activeName = ref('first')
-        return { activeName }
-    },
+  components: {
+    Schoolanalyse,
+    SchoolManage,
+  },
+  setup () {
+    const activeName = ref('first')
+    return { activeName }
+  },
 }
 </script>
 <style scoped>
 .school-analyse {
-    width: 100%;
-    line-height: 20px;
-    padding: 1%;
+  width: 100%;
+  line-height: 20px;
+  padding: 0% 1%;
 }
 </style>
 <style>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 594 - 176
TEAMModelBI/ClientApp/src/view/schoolmanage/schoolAnalyse.vue


+ 10 - 8
TEAMModelBI/ClientApp/src/view/schoolmanage/schoolManege.vue

@@ -506,12 +506,14 @@ export default {
         areaId: nowPitchdata.value.areaId,
       }
       console.log(updateForm, '学校信息')
-      proxy.$api.updateSchoolinfo(updateForm).then((res) => {
-        console.log(res, '修改学校的返回')
-        res.state === 200
-          ? (ElMessage.success(proxy.$t(`commonMsg.schoolUpdateSuccess`), schoolJoinarea(), schoolClose()), updateSuccess())
-          : ElMessage.error(proxy.$t(`commonMsg.schoolUpdateError`))
-      })
+      console.log(nowPitchdata.value, '原本的学校信息')
+      console.log(assistData, '顾问信息')
+      // proxy.$api.updateSchoolinfo(updateForm).then((res) => {
+      //   console.log(res, '修改学校的返回')
+      //   res.state === 200
+      //     ? (ElMessage.success(proxy.$t(`commonMsg.schoolUpdateSuccess`), schoolJoinarea(), schoolClose()), updateSuccess())
+      //     : ElMessage.error(proxy.$t(`commonMsg.schoolUpdateError`))
+      // })
     }
     //学校加入区域或者修改
     async function schoolJoinarea () {
@@ -825,9 +827,9 @@ export default {
 }
 </style>
 <style>
-.schoolbox .el-cascader {
+/* .schoolbox .el-cascader {
   width: 20%;
-}
+} */
 .school-form-badge .el-form-item__label {
   line-height: 107px;
 }

+ 294 - 134
TEAMModelBI/ClientApp/src/view/systemConfig/correlation.vue

@@ -13,8 +13,8 @@
     <div class="school-list-header">
       <div class="correlationbox-titles">目前用户所关联学校:<span>关联数量:<span class="correlationbox-num">{{nowUsers.handleSchools.length}}</span></span></div>
       <div class="correlationbox-btn">
-        <el-button type="primary" size="small" v-if="removeBatchschool.length >0 && PowerShow" @click="multipeRemove"> 移除选中学校</el-button>
-        <el-button type="primary" size="small" v-else-if="removeBatchschool.length ===0 && PowerShow" disabled>移除选中学校</el-button>
+        <el-button type="primary" size="small" v-if="removeBatchschool.length >0 && PowerShow && adminOrleader===false" @click="multipeRemove"> 移除选中学校</el-button>
+        <el-button type="primary" size="small" v-else-if="removeBatchschool.length ===0 && PowerShow && adminOrleader===true" disabled>移除选中学校</el-button>
       </div>
     </div>
     <!-- <p class="correlationbox-title">目前用户所关联学校:</p>
@@ -22,9 +22,9 @@
       <el-button type="primary" size="small" v-if="multipleSchool.length >0 && PowerShow" @click="multipleCorrelation">关联选中学校</el-button>
       <el-button type="primary" size="small" v-else-if="multipleSchool.length ===0 && PowerShow" disabled>关联选中学校</el-button>
     </div> -->
-    <div class="possessbox" v-if="nowUsers.handleSchools.length >0">
-      <el-table :data="nowUsers.handleSchools" style="width: 100%" height="20vh" size="small" @selection-change="removeBatch" v-loading="loadingData.possess" element-loading-text="数据加载中...">
-        <el-table-column type="selection" v-if="PowerShow" />
+    <div class="possessbox">
+      <el-table :data="nowUsers.handleSchools" style="width: 100%" height="20vh" size="small" @selection-change="removeBatch" v-loading="loadingData.possess" element-loading-text="数据加载中..." empty-text='暂无相关数据'>
+        <el-table-column type="selection" v-if="PowerShow && adminOrleader ===false" />
         <el-table-column label="校徽" align="center">
           <template #default="scope">
             <el-image style="width: 40px; height: 40px;" :src="scope.row.picture" fit="fill" v-if="scope.row.picture"></el-image>
@@ -42,34 +42,42 @@
             </el-select>
           </template>
           <template #default="scope">
-            <span class="areaitem-name">{{scope.row.areaName}}</span><span class="areaitem-insti">({{scope.row.institution}})</span>
+            <!-- <span class="areaitem-name">{{scope.row.areaName}}</span><span class="areaitem-insti">({{scope.row.institution}})</span> -->
+            <span class="areaitem-name">{{scope.row.areaName}}</span>
+            <span class="areaitem-insti" v-if="scope.row.institution">({{scope.row.institution}})</span>
+            <span class="areaitem-insti" v-else>{{scope.row.institution}}</span>
           </template>
         </el-table-column>
-        <el-table-column fixed="right" label="操作" width='80' align="center" v-if="PowerShow">
+        <el-table-column fixed="right" label="操作" width='80' align="center" v-if="PowerShow && adminOrleader===false">
           <template #default="scope">
-            <el-button type="text" size="small" @click="removeSchool(scope.row,scope.$index)">取消关联</el-button>
+            <el-button type="danger" size="small" @click="removeSchool(scope.row,scope.$index)">取消关联</el-button>
           </template>
         </el-table-column>
       </el-table>
     </div>
-    <div class="nodata" v-else-if="nowUsers.handleSchools.length ===0">
+    <!-- <div class="nodata" v-else-if="nowUsers.handleSchools.length ===0">
       <div>暂无关联学校</div>
-    </div>
+    </div> -->
     <div class="school-list">
       <div class="school-list-header">
         <div class="correlationbox-titles">学校列表:</div>
         <div class="correlationbox-search">
-          <el-input v-model="schoolSearch" placeholder="输入学校名称/简码 搜索" :prefix-icon="Search" size="small" clearable />
+          <el-input v-model="schoolSearch" placeholder="输入学校名称/简码 搜索" :prefix-icon="Search" clearable />
+        </div>
+        <div class="areaSelect">
+          <el-select v-model="areaList.value" placeholder="进行学区筛选" @change="getAreaschool">
+            <el-option v-for="item in areaList.data" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
         </div>
         <div class="correlationbox-btn">
-          <el-button type="primary" size="small" v-if="multipleSchool.length >0 && PowerShow" @click="multipleCorrelation">关联选中学校</el-button>
-          <el-button type="primary" size="small" v-else-if="multipleSchool.length ===0 && PowerShow" disabled>关联选中学校</el-button>
+          <el-button type="primary" size="small" v-if="multipleSchool.length >0 && PowerShow && adminOrleader===false" @click="multipleCorrelation">关联选中学校</el-button>
+          <el-button type="primary" size="small" v-else-if="multipleSchool.length ===0 && PowerShow && adminOrleader===true" disabled>关联选中学校</el-button>
         </div>
       </div>
-      <div class="listbox">
-        <el-table :data="tableData" id="schoolList" style="width: 100%" height="45vh" size="small" @selection-change="checkSchool" empty-text='暂无相关搜索数据' v-loading="loadingData.list" element-loading-text="数据加载中...">
-          <el-table-column type="selection" v-if="PowerShow" />
-          <el-table-column label="校徽" align="center">
+      <div class="listbox" style="width: 100%; height: 42vh" v-loading="loadingData.list" element-loading-text="数据加载中...">
+        <!-- <el-table :data="tableData" id="schoolList" style="width: 100%" height="45vh" size="small" @selection-change="checkSchool" empty-text='暂无相关搜索数据' v-loading="loadingData.list" element-loading-text="数据加载中...">
+          <el-table-column type="selection" v-if="PowerShow && adminOrleader ===false" />
+          <el-table-column label=" 校徽" align="center">
             <template #default="scope">
               <el-image style="width: 40px; height: 40px;" :src="scope.row.picture" fit="fill" v-if="scope.row.picture"></el-image>
               <div class="notimage" v-else>暂无<br />图片</div>
@@ -77,7 +85,6 @@
           </el-table-column>
           <el-table-column prop="name" label="名称" align="center" />
           <el-table-column prop="id" label="学校简码" align="center" />
-          <!-- <el-table-column prop="name" label="版本" /> -->
           <el-table-column prop="assisName" label="目前顾问" align="center" />
           <el-table-column align="center">
             <template #header>
@@ -91,21 +98,27 @@
               <span class="areaitem-insti" v-else>{{scope.row.institution}}</span>
             </template>
           </el-table-column>
-          <el-table-column fixed="right" label="操作" width='80' align="center" v-if="PowerShow">
+          <el-table-column fixed="right" label="操作" width='80' align="center" v-if="PowerShow && adminOrleader===false">
             <template #default="scope">
               <el-button type="text" size="small" @click="correlation(scope.row,tableData)">关联学校</el-button>
             </template>
           </el-table-column>
-        </el-table>
+        </el-table> -->
+        <el-auto-resizer>
+          <template #default="{ height, width }">
+            <el-table-v2 :columns="columns" :data="tableData" :width="width" :height="height" fixed />
+          </template>
+        </el-auto-resizer>
       </div>
     </div>
   </div>
 </template>
 <script>
-import { ref, getCurrentInstance, watch, onMounted } from 'vue'
-import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
-import { Search } from '@element-plus/icons'
+import { ref, getCurrentInstance, watch, onMounted, h } from 'vue'
+import { ElMessage, ElLoading, ElMessageBox, ElCheckbox, HeaderCellSlotProps, } from 'element-plus'
+import { Search, Filter } from '@element-plus/icons'
 import { useStore } from 'vuex'
+import jwt_decode from 'jwt-decode'
 export default {
   props: {
     userdata: {
@@ -120,10 +133,11 @@ export default {
   components: {
     Search
   },
-  setup (props) {
+  setup (props, context) {
     let { proxy } = getCurrentInstance()
     const store = useStore()
     let PowerShow = proxy.$access.identifyPosition(JSON.parse(localStorage.getItem('id_token')))
+    let userVerify = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
     const tableDatas = ref([])
     let tableData = ref([])
     let nowUsers = ref()
@@ -147,68 +161,180 @@ export default {
     })
     //关联筛选原始data
     let correlaData = ref([])
-    onMounted(() => {
-      //监听表格滚动事件
-      // let table = mutipleTable.value._value.layout.table.refs.bodyWrapper;
-      let table = document.getElementById('schoolList')
-      console.log(table, '查看是否获取到')
-      table.addEventListener("scroll", (res) => { loadmore(res) }, true);
-    })
-    const loadmore = (res) => {
-      // console.log(res, res.target.scrollHeight, res.target.scrollTop + res.target.clientHeight, '实际高度')
-      if (res.target.scrollTop && ((res.target.scrollHeight - 10) <= (res.target.scrollTop + res.target.clientHeight))) {
-        scrollHeight.value = (res.target.scrollHeight - 10) - (res.target.scrollTop + res.target.clientHeight)
-        console.log(scrollHeight.value, '值')
-      }
-    }
+    let adminOrleader = ref(false)
+    const columns = [
+      {
+        cellRenderer: (data) =>
+          h(
+            ElCheckbox,
+            // { onClick: () => handleDelete(data), type: "danger", icon: "Delete" },
+            { onChange: () => checkSchool(data.rowData) },
+            { default: () => "" }
+          ),
+        width: 30,//当前列的宽度,必须设置
+        // fixed: true,//是否固定列
+        align: 'center',
+        // cellRenderer: ({ rowData }) => {
+        //   const onChange = (value: CheckboxValueType) => (rowData.checked = value)
+        //   return <SelectionCell value={rowData.checked} onChange={onChange} />
+        // },
+      },
+      {
+        // key: "name",
+        // dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填name
+        title: "校徽",
+        width: 100,
+        fixed: false,
+        align: 'center',
+        cellRenderer: (data) => (
+          <>
+            <el-image style="width: 40px; height: 40px;margin:5px" src={data.rowData.picture} fit="contain" v-show={data.rowData.picture ? true : false}></el-image>
+            <div style=" width: 40px; height: 40px;line-height: 40px;text-align: center;background-color: #bdc3c7;font-size: 10px;color: #ecf0f1;margin:5px;" v-show={!data.rowData.picture ? true : false}>暂无图片</div>
+          </>
+        )
+      },
+      {
+        key: "name",
+        dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填name
+        title: "名称",
+        width: 100,
+        fixed: false,
+        align: 'center',
+      },
+      {
+        key: "id",
+        dataKey: "id",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+        title: "学校简码",//显示在单元格表头的文本
+        width: 100,//当前列的宽度,必须设置
+        align: 'center',
+      },
+      {
+        key: "assisName",
+        dataKey: "assisName",
+        title: "关联管家",
+        align: 'center',
+        width: 100,
+      },
+      {
+        key: "areaName",
+        dataKey: "areaName",
+        title: "所属学区",
+        width: 130,
+        align: 'center',
+      },
+      {
+        key: "handle",
+        title: "操作",
+        width: 100,
+        align: "center",
+        // fixed: 'right',
+        cellRenderer: (data) =>
+        (
+          <>
+            <el-button type="primary" onClick={correlation.bind(this, data.rowData)} v-show={userVerify.roles.includes('admin') ? true : false} size="small">关联学校</el-button>
+          </>
+        ),
+      },
+    ];
+    // const shouldFilter = ref(false)
+    // const popoverRef = ref()
+    // columns[5].headerCellRenderer = (props = HeaderCellSlotProps) => {
+    //   return (
+    //     <div class="flex items-center justify-center">
+    //       <span class="mr-2 text-xs">{props.column.title}</span>
+    //       <ElPopover ref={popoverRef} trigger="click" {...{ width: 200 }}>
+    //         {{
+    //           default: () => h(
+    //             <template>
+    //               <div class="filter-wrapper">
+    //                 <div class="filter-group">
+    //                   <select>
+    //                     <option v-for={item in options}>123123</option>
+    //                   </select>
+    //                 </div>
+    //                 <div class="el-table-v2__demo-filter">
+    //                   <ElButton text>
+    //                     Confirm
+    //                   </ElButton>
+    //                   <ElButton text>
+    //                     Reset
+    //                   </ElButton>
+    //                 </div>
+    //               </div>
+    //             </template>
+    //           ),
+    //           reference: () => (
+    //             <ElIcon>
+    //               <Filter />
+    //             </ElIcon>
+    //           ),
+    //         }
+    //         }
+    //       </ElPopover>
+    //     </div >
+    //   )
+    // }
     function getSchoolList (value, state) {
       console.log(value, nextpageToken.value, '触发下一页')
-      if ((nextpageToken.value === null) && state !== 'restart') {
-        ElMessage.success('已经到最底了')
-        return
-      }
       loadingData.value.list = true
-      let data = value ? { contToken: value } : {}
       proxy.$api
-        .getSchooldata(data)
+        .getSchool({})
         .then((res) => {
-          console.log(res, '学校的返回列表')
+          console.log(res, '学校的返回列表V222')
           // res.state === 200 ? (tableData.value = res.schoolAssists) : ''
           if (res.state === 200) {
-            for (let i in res.schoolAssists) {
-              if (res.schoolAssists[i].assists) {
-                res.schoolAssists[i].assisName = ''
-                let datas = res.schoolAssists[i].assists
+            // for (let i in res.schoolAssists) {
+            //   if (res.schoolAssists[i].assists) {
+            //     res.schoolAssists[i].assisName = ''
+            //     let datas = res.schoolAssists[i].assists
+            //     for (let y in datas) {
+            //       res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+            //     }
+            //   }
+            // }
+            // nextpageToken.value = res.continuationToken
+            // //处理学区呈现
+            // console.log(areaList.value.data, '是否有数据')
+            // for (let y in res.schoolAssists) {
+            //   let areaValue = res.schoolAssists[y].areaId
+            //   console.log(areaValue, '学区的值')
+            //   res.schoolAssists[y].areaName = ''
+            //   res.schoolAssists[y].institution = ''
+            //   for (let i in areaList.value.data) {
+            //     areaValue === areaList.value.data[i].value ? (res.schoolAssists[y].areaName = areaList.value.data[i].label, res.schoolAssists[y].institution = areaList.value.data[i].situate) : ''
+            //   }
+            // }
+            // console.log(res.schoolAssists, '是否有数据')
+            // if (!value) {
+            //   tableData.value = res.schoolAssists;
+            //   original.value = JSON.parse(JSON.stringify(res.schoolAssists));
+            // } else {
+            //   tableData.value.push(...res.schoolAssists)
+            //   // original.value = tableData.value
+            //   scrollHeight.value = 'init'
+            // }
+            // processingSchool()
+            //处理关联管家  拼内容
+            for (let i in res.scInfos) {
+              res.scInfos[i].serviceData = []
+              res.scInfos[i].location = res.scInfos[i].dist !== null ? res.scInfos[i].province + res.scInfos[i].city + res.scInfos[i].dist : res.scInfos[i].province + res.scInfos[i].city
+              if (res.scInfos[i].assists) {
+                res.scInfos[i].assisName = ''
+                let datas = res.scInfos[i].assists
                 for (let y in datas) {
-                  res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+                  res.scInfos[i].assisName = res.scInfos[i].assisName + datas[y].name + ','
                 }
               }
             }
-            nextpageToken.value = res.continuationToken
-            //处理学区呈现
-            console.log(areaList.value.data, '是否有数据')
-            for (let y in res.schoolAssists) {
-              let areaValue = res.schoolAssists[y].areaId
-              console.log(areaValue, '学区的值')
-              res.schoolAssists[y].areaName = ''
-              res.schoolAssists[y].institution = ''
-              for (let i in areaList.value.data) {
-                areaValue === areaList.value.data[i].value ? (res.schoolAssists[y].areaName = areaList.value.data[i].label, res.schoolAssists[y].institution = areaList.value.data[i].situate) : ''
-              }
-            }
-            console.log(res.schoolAssists, '是否有数据')
-            if (!value) {
-              tableData.value = res.schoolAssists;
-              original.value = JSON.parse(JSON.stringify(res.schoolAssists));
-            } else {
-              tableData.value.push(...res.schoolAssists)
-              // original.value = tableData.value
-              scrollHeight.value = 'init'
-            }
+            tableData.value = []; original.value = []
+            tableData.value.push(...res.scInfos),
+              original.value = res.scInfos
             processingSchool()
+            // loadingData.value.list = false
           }
         })
         .catch((err) => {
+          loadingData.value.list = false
           ElMessage.error('获取学校列表失败')
         })
     }
@@ -221,15 +347,16 @@ export default {
         center: true,
       }).then(() => {
         let schoolArr = [value.id]
-        let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'add' }
+        let roles = nowUsers.value.handleRoles[0] === 'sales' ? 'sales' : nowUsers.value.handleRoles[0] === 'assist' ? 'assist' : nowUsers.value.handleRoles[0] === 'admin' || nowUsers.value.handleRoles[0] === 'leader' ? '' : ''
+        let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'add', role: roles }
         proxy.$api
           .setAistschool(data)
           .then((res) => {
             console.log(res, '成功的返回')
             res.state === 200
-              ? (nowUsers.value.handleSchools.push(value), getSchoolList('', 'restart'), processingSchool(), ElMessage.success('操作成功'))
+              ? (nowUsers.value.handleSchools.push(value), getSchoolList(), processingSchool(), multipleSchool.value = [], ElMessage.success('操作成功'), context.emit('changerestart', true))
               : res.state === 201
-                ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList('', 'restart'))
+                ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList())
                 : ''
           })
           .catch((error) => {
@@ -246,11 +373,12 @@ export default {
         center: true,
       }).then(() => {
         let schoolArr = [value.id]
-        let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'del' }
+        let roles = nowUsers.value.handleRoles[0] === 'sales' ? 'sales' : nowUsers.value.handleRoles[0] === 'assist' ? 'assist' : nowUsers.value.handleRoles[0] === 'admin' || nowUsers.value.handleRoles[0] === 'leader' ? '' : ''
+        let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'del', role: roles }
         proxy.$api
           .setAistschool(data)
           .then((res) => {
-            res.state === 200 ? (nowUsers.value.handleSchools.splice(index, 1), getSchoolList('', 'restart'), processingSchool(), ElMessage.success('操作成功')) : ''
+            res.state === 200 ? (nowUsers.value.handleSchools.splice(index, 1), getSchoolList(), processingSchool(), context.emit('changerestart', true), ElMessage.success('操作成功')) : ''
           })
           .catch((error) => {
             ElMessage.error('取消关联失败,API异常')
@@ -258,7 +386,13 @@ export default {
       })
     }
     function checkSchool (value, row) {
-      multipleSchool.value = value
+      if (multipleSchool.value.length === 0) {
+        multipleSchool.value.push(value)
+      } else {
+        let nums = multipleSchool.value.findIndex((item) => { return item.id === value.id })
+        nums !== -1 ? multipleSchool.value.splice(nums, 1) : multipleSchool.value.push(value)
+        console.log(nums, 'nums')
+      }
       console.log(multipleSchool.value, '111')
     }
     function removeBatch (value) {
@@ -287,15 +421,17 @@ export default {
         for (let i in schoolData) {
           schoolArr.push(schoolData[i].id)
         }
-        let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'add' }
+        console.log(nowUsers.value, '用户信息')
+        let roles = nowUsers.value.handleRoles[0] === 'sales' ? 'sales' : nowUsers.value.handleRoles[0] === 'assist' ? 'assist' : nowUsers.value.handleRoles[0] === 'admin' || nowUsers.value.handleRoles[0] === 'leader' ? '' : ''
+        let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'add', role: roles }
         proxy.$api
           .setAistschool(data)
           .then((res) => {
             console.log(res, '成功的返回')
             res.state === 200
-              ? ((nowUsers.value.handleSchools = nowUsers.value.handleSchools.concat(schoolData)), getSchoolList('', 'restart'), processingSchool())
+              ? ((nowUsers.value.handleSchools = nowUsers.value.handleSchools.concat(schoolData)), getSchoolList(), processingSchool(), multipleSchool.value = [], context.emit('changerestart', true), ElMessage.success('操作成功'))
               : res.state === 201
-                ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList())
+                ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList('', 'restart'))
                 : ''
           })
           .catch((error) => {
@@ -327,7 +463,8 @@ export default {
         for (let s of schoolData) {
           s.id ? schoolArr.push(s.id) : ''
         }
-        let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'del' }
+        let roles = nowUsers.value.handleRoles[0] === 'sales' ? 'sales' : nowUsers.value.handleRoles[0] === 'assist' ? 'assist' : nowUsers.value.handleRoles[0] === 'admin' || nowUsers.value.handleRoles[0] === 'leader' ? '' : ''
+        let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, schoolIds: schoolArr, busy: 'del', role: roles }
         proxy.$api
           .setAistschool(data)
           .then((res) => {
@@ -343,6 +480,7 @@ export default {
               })
               getSchoolList('', 'restart')
               processingSchool()
+              context.emit('changerestart', true)
               ElMessage.success('操作成功')
             }
           })
@@ -372,26 +510,34 @@ export default {
       timer.value = setTimeout(fn, wait)
     }
     function personnelSearch () {
+      loadingData.value.list = true
       let names = schoolSearch.value
-      let reg = new RegExp("[\\u4E00-\\u9FFF]+", "g")
-      let data = reg.test(names) ? { name: names } : { scId: names }
-      proxy.$api.getSchooldata(data).then((res) => {
-        if (res.state === 200) {
-          for (let i in res.schoolAssists) {
-            if (res.schoolAssists[i].assists) {
-              res.schoolAssists[i].assisName = ''
-              let datas = res.schoolAssists[i].assists
-              for (let y in datas) {
-                res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
-              }
-            }
-          }
-          tableData.value = res.schoolAssists
-          processingSchool()
-        }
-      }).catch((error) => {
-        ElMessage.error('搜索学校失败,API异常')
+      // let reg = new RegExp("[\\u4E00-\\u9FFF]+", "g")
+      // let data = reg.test(names) ? { name: names } : { scId: names }
+      // proxy.$api.getSchooldata(data).then((res) => {
+      //   if (res.state === 200) {
+      //     for (let i in res.schoolAssists) {
+      //       if (res.schoolAssists[i].assists) {
+      //         res.schoolAssists[i].assisName = ''
+      //         let datas = res.schoolAssists[i].assists
+      //         for (let y in datas) {
+      //           res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+      //         }
+      //       }
+      //     }
+      //     tableData.value = res.schoolAssists
+      //     processingSchool()
+      //   }
+      // }).catch((error) => {
+      //   ElMessage.error('搜索学校失败,API异常')
+      // })
+      let arr = original.value
+      let newArr = arr.filter((item) => {
+        return item.name.includes(names) || item.id.includes(names)
       })
+      tableData.value = newArr
+      loadingData.value.list = false
+      processingSchool()
     }
     //加载所有学区信息
     async function areaData () {
@@ -406,33 +552,40 @@ export default {
     function getAreaschool (value) {
       console.log(value, 'V')
       tableData.value = []
-      let data = value !== 'all' ? { areaId: value } : getSchoolList('', 'restart')
+      let filterData = []
+      // let data = value !== 'all' ? { areaId: value } : getSchoolList('', 'restart')
       if (value !== 'all') {
-        loadingData.value.list = true
-        proxy.$api.getForareaSchool(data).then((res) => {
-          console.log(res, '现在区域拥有的学校')
-          if (res.state === 200) {
-            for (let y in res.joinAreaSchools) {
-              let areaValue = res.joinAreaSchools[y].areaId
-              res.joinAreaSchools[y].areaName = ''
-              res.joinAreaSchools[y].institution = ''
-              res.joinAreaSchools[y].assisName = ''
-              for (let i in areaList.value.data) {
-                areaValue === areaList.value.data[i].value ? (res.joinAreaSchools[y].areaName = areaList.value.data[i].label, res.joinAreaSchools[y].institution = areaList.value.data[i].situate) : ''
-              }
-              for (let e in res.joinAreaSchools[y].assists) {
-                res.joinAreaSchools[y].assisName !== '' ? res.joinAreaSchools[y].assisName = res.joinAreaSchools[y].assisName + ',' + res.joinAreaSchools[y].assists[e].tmdName : res.joinAreaSchools[y].assisName = res.joinAreaSchools[y].assists[e].tmdName
-              }
-            }
-            tableData.value = res.joinAreaSchools
-            processingSchool()
-            nextpageToken.value = null
-          }
-          loadingData.value.list = false
-        }).catch((error) => {
-          ElMessage.error('获取筛选学校列表失败')
-          loadingData.value.list = false
+        //   loadingData.value.list = true
+        //   proxy.$api.getForareaSchool(data).then((res) => {
+        //     console.log(res, '现在区域拥有的学校')
+        //     if (res.state === 200) {
+        //       for (let y in res.joinAreaSchools) {
+        //         let areaValue = res.joinAreaSchools[y].areaId
+        //         res.joinAreaSchools[y].areaName = ''
+        //         res.joinAreaSchools[y].institution = ''
+        //         res.joinAreaSchools[y].assisName = ''
+        //         for (let i in areaList.value.data) {
+        //           areaValue === areaList.value.data[i].value ? (res.joinAreaSchools[y].areaName = areaList.value.data[i].label, res.joinAreaSchools[y].institution = areaList.value.data[i].situate) : ''
+        //         }
+        //         for (let e in res.joinAreaSchools[y].assists) {
+        //           res.joinAreaSchools[y].assisName !== '' ? res.joinAreaSchools[y].assisName = res.joinAreaSchools[y].assisName + ',' + res.joinAreaSchools[y].assists[e].tmdName : res.joinAreaSchools[y].assisName = res.joinAreaSchools[y].assists[e].tmdName
+        //         }
+        //       }
+        //       tableData.value = res.joinAreaSchools
+        //       processingSchool()
+        //       nextpageToken.value = null
+        //     }
+        //     loadingData.value.list = false
+        //   }).catch((error) => {
+        //     ElMessage.error('获取筛选学校列表失败')
+        //     loadingData.value.list = false
+        //   })
+        original.value.forEach((item) => {
+          item.areaId === value ? filterData.push(item) : ''
         })
+        tableData.value = filterData
+      } else {
+        tableData.value = original.value
       }
     }
     //关联的筛选
@@ -450,6 +603,7 @@ export default {
     }
     //处理显示目前关联的
     function nowRelevance (value) {
+      console.log(value, '这个人的身份')
       nowUsers.value = JSON.parse(JSON.stringify(value))
       let nowUserdata = nowUsers.value
       nowUserdata.handleSchools.forEach((item) => {
@@ -461,14 +615,15 @@ export default {
       })
       nowUsers.value.handleSchools = nowUserdata.handleSchools
       correlaData.value = nowUserdata.handleSchools
+      value.handleRoles.includes('admin') || value.handleRoles.includes('leader') ? adminOrleader.value = true : adminOrleader.value = false
       loadingData.value.possess = false
     }
-    watch(scrollHeight, (newdata, olddata) => {
-      console.log(newdata, olddata, '监听的数据')
-      if (newdata < olddata) {
-        newdata <= 0 ? getSchoolList(nextpageToken.value) : ''
-      }
-    })
+    // watch(scrollHeight, (newdata, olddata) => {
+    //   console.log(newdata, olddata, '监听的数据')
+    //   if (newdata < olddata) {
+    //     newdata <= 0 ? getSchoolList(nextpageToken.value) : ''
+    //   }
+    // })
     watch(
       props,
       (newuser) => {
@@ -482,6 +637,7 @@ export default {
         debounce(personnelSearch, 500)
       } else {
         tableData.value = original.value
+        processingSchool()
       }
     })
     getSchoolList()
@@ -511,7 +667,10 @@ export default {
       removeBatch,
       nowRelevance,
       correlaData,
-      correlaSchool
+      correlaSchool,
+      adminOrleader,
+      columns,
+      userVerify
     }
   },
 }
@@ -533,7 +692,7 @@ export default {
 }
 .school-list {
   width: 100%;
-  margin-top: 7%;
+  margin-top: 5%;
 }
 .nodata {
   width: 100%;
@@ -583,8 +742,9 @@ export default {
   color: #b2bec3;
   text-align: left;
 }
-.correlationbox-search {
-  width: 45%;
+.correlationbox-search,
+.areaSelect {
+  width: 35%;
 }
 .correlationbox-btn {
   width: 30%;

+ 225 - 86
TEAMModelBI/ClientApp/src/view/systemConfig/manageschool.vue

@@ -45,7 +45,7 @@
         </el-table-column>
         <el-table-column fixed="right" label="操作" align="center" v-if="PowerShow">
           <template #default="scope">
-            <el-button type="text" size="small" @click="removeSchool(scope.row,scope.$index)">移除管理</el-button>
+            <el-button type="danger" size="small" @click="removeSchool(scope.row,scope.$index)">移除管理</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -57,15 +57,20 @@
       <div class="school-list-header">
         <div class="correlationbox-titles">学校列表:</div>
         <div class="correlationbox-search">
-          <el-input v-model="schoolSearch" placeholder="输入学校名称/简码 搜索" :prefix-icon="Search" size="small" clearable />
+          <el-input v-model="schoolSearch" placeholder="输入学校名称/简码 搜索" :prefix-icon="Search" clearable />
+        </div>
+        <div class="areaSelect">
+          <el-select v-model="areaList.value" placeholder="进行学区筛选" @change="getAreaschool">
+            <el-option v-for="item in areaList.data" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
         </div>
         <div class="correlationbox-btn">
           <el-button type="primary" size="small" v-if="multipleSchool.length >0 && PowerShow" @click="multipleCorrelation">添加管理员选中学校</el-button>
           <el-button type="primary" size="small" v-else-if="multipleSchool.length ===0 && PowerShow" disabled>添加管理员选中学校</el-button>
         </div>
       </div>
-      <div class="listbox">
-        <el-table :data="tableData" id="schoolManagelist" style="width: 100%" height="45vh" size="small" @selection-change="checkSchool" empty-text='暂无相关搜索数据' v-loading="loadingData.list" element-loading-text="数据加载中...">
+      <div class="listbox" style="width: 100%; height: 42vh" v-loading="loadingData.list" element-loading-text="数据加载中...">
+        <!-- <el-table :data="tableData" id="schoolManagelist" style="width: 100%" height="45vh" size="small" @selection-change="checkSchool" empty-text='暂无相关搜索数据' v-loading="loadingData.list" element-loading-text="数据加载中...">
           <el-table-column type="selection" v-if="PowerShow" align="center" />
           <el-table-column label="校徽" align="center">
             <template #default="scope">
@@ -75,7 +80,6 @@
           </el-table-column>
           <el-table-column prop="name" label="名称" />
           <el-table-column prop="id" label="学校简码" />
-          <!-- <el-table-column prop="name" label="版本" /> -->
           <el-table-column prop="assisName" label="目前管理员">
             <template #default="scope">
               <div class="adminnamedata">{{scope.row.admin}}</div>
@@ -98,16 +102,22 @@
               <el-button type="text" size="small" @click="correlation(scope.row,tableData)">添加管理学校</el-button>
             </template>
           </el-table-column>
-        </el-table>
+        </el-table> -->
+        <el-auto-resizer>
+          <template #default="{ height, width }">
+            <el-table-v2 :columns="columns" :data="tableData" :width="width" :height="height" fixed />
+          </template>
+        </el-auto-resizer>
       </div>
     </div>
   </div>
 </template>
   <script>
-import { ref, getCurrentInstance, watch, onMounted } from 'vue'
-import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
+import { ref, getCurrentInstance, watch, onMounted, h } from 'vue'
+import { ElMessage, ElLoading, ElMessageBox, ElCheckbox } from 'element-plus'
 import { Search } from '@element-plus/icons'
 import { useStore } from 'vuex'
+import jwt_decode from 'jwt-decode'
 export default {
   props: {
     userdata: {
@@ -126,6 +136,7 @@ export default {
     let { proxy } = getCurrentInstance()
     const store = useStore()
     let PowerShow = proxy.$access.identifyPosition(JSON.parse(localStorage.getItem('id_token')))
+    let userVerify = jwt_decode(JSON.parse(localStorage.getItem('id_token')))
     const tableDatas = ref([])
     let tableData = ref([])
     let nowUsers = ref()
@@ -152,65 +163,134 @@ export default {
       exist: [],
       notExist: [],
     })
+    const columns = [
+      {
+        cellRenderer: (data) =>
+          h(
+            ElCheckbox,
+            // { onClick: () => handleDelete(data), type: "danger", icon: "Delete" },
+            { onChange: () => checkSchool(data.rowData) },
+            { default: () => "" }
+          ),
+        width: 50,//当前列的宽度,必须设置
+        // fixed: true,//是否固定列
+        align: 'center',
+        // cellRenderer: ({ rowData }) => {
+        //   const onChange = (value: CheckboxValueType) => (rowData.checked = value)
+        //   return <SelectionCell value={rowData.checked} onChange={onChange} />
+        // },
+      },
+      {
+        // key: "name",
+        // dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填name
+        title: "校徽",
+        width: 100,
+        fixed: false,
+        align: 'center',
+        cellRenderer: (data) => (
+          <>
+            <el-image style="width: 40px; height: 40px;margin:5px" src={data.rowData.picture} fit="contain" v-show={data.rowData.picture ? true : false}></el-image>
+            <div style=" width: 40px; height: 40px;line-height: 40px;text-align: center;background-color: #bdc3c7;font-size: 10px;color: #ecf0f1;margin:5px;" v-show={!data.rowData.picture ? true : false}>暂无图片</div>
+          </>
+        )
+      },
+      {
+        key: "name",
+        dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填name
+        title: "名称",
+        width: 180,
+        fixed: false,
+        align: 'center',
+      },
+      {
+        key: "id",
+        dataKey: "id",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+        title: "学校简码",//显示在单元格表头的文本
+        width: 100,//当前列的宽度,必须设置
+        align: 'center',
+      },
+      {
+        key: "areaName",
+        dataKey: "areaName",
+        title: "所属学区",
+        width: 120,
+        align: 'center',
+      },
+      {
+        key: "handle",
+        title: "操作",
+        width: 120,
+        align: "center",
+        // fixed: 'right',
+        cellRenderer: (data) =>
+        (
+          <>
+            <el-button type="primary" onClick={correlation.bind(this, data.rowData)} v-show={userVerify.roles.includes('admin') ? true : false} size="small">添加管理学校</el-button>
+          </>
+        ),
+      },
+    ];
     onMounted(() => {
       //监听表格滚动事件
       // let table = mutipleTable.value._value.layout.table.refs.bodyWrapper;
-      let table = document.getElementById('schoolManagelist')
-      console.log(table, '查看是否获取到')
-      table.addEventListener("scroll", (res) => { loadmore(res) }, true);
-      console.log(store.state.point, '查看这个时候是否有数据')
+      // let table = document.getElementById('schoolManagelist')
+      // console.log(table, '查看是否获取到')
+      // table.addEventListener("scroll", (res) => { loadmore(res) }, true);
+      // console.log(store.state.point, '查看这个时候是否有数据')
     })
-    const loadmore = (res) => {
-      // console.log(res, res.target.scrollHeight, res.target.scrollTop + res.target.clientHeight, '实际高度')
-      if (res.target.scrollTop && ((res.target.scrollHeight - 10) <= (res.target.scrollTop + res.target.clientHeight))) {
-        scrollHeight.value = (res.target.scrollHeight - 10) - (res.target.scrollTop + res.target.clientHeight)
-        console.log(scrollHeight.value, '值')
-      }
-    }
     function getSchoolList (value) {
-      console.log(value, '触发下一页')
-      if (nextpageToken.value == null) {
-        ElMessage.success('已经到最底了')
-        return
-      }
       loadingData.value.list = true
-      let data = value ? { contToken: value } : {}
       proxy.$api
-        .getSchooldata(data)
+        .getSchool({})
         .then((res) => {
-          console.log(res, '学校的返回列表')
+          console.log(res, '学校的返回列表V2222V')
           // res.state === 200 ? (tableData.value = res.schoolAssists) : ''
           if (res.state === 200) {
-            for (let i in res.schoolAssists) {
-              if (res.schoolAssists[i].scAdmin) {
-                res.schoolAssists[i].admin = ''
-                let datas = res.schoolAssists[i].scAdmin
+            // for (let i in res.schoolAssists) {
+            //   if (res.schoolAssists[i].scAdmin) {
+            //     res.schoolAssists[i].admin = ''
+            //     let datas = res.schoolAssists[i].scAdmin
+            //     for (let y in datas) {
+            //       datas.length === 1 ? res.schoolAssists[i].admin = datas[y].tmdName : res.schoolAssists[i].admin = res.schoolAssists[i].admin + datas[y].tmdName + ','
+            //       // res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+            //     }
+            //   }
+            // }
+            // nextpageToken.value = res.continuationToken
+            // if (!value) {
+            //   tableData.value = res.schoolAssists;
+            //   original.value = res.schoolAssists;
+            // } else {
+            //   tableData.value.push(...res.schoolAssists)
+            //   original.value = tableData.value
+            //   scrollHeight.value = 'init'
+            // }
+            // //处理学区呈现
+            // console.log(areaList.value.data, '是否有数据')
+            // for (let y in res.schoolAssists) {
+            //   let areaValue = res.schoolAssists[y].areaId
+            //   console.log(areaValue, '学区的值')
+            //   res.schoolAssists[y].areaName = ''
+            //   res.schoolAssists[y].institution = ''
+            //   for (let i in areaList.value.data) {
+            //     areaValue === areaList.value.data[i].value ? (res.schoolAssists[y].areaName = areaList.value.data[i].label, res.schoolAssists[y].institution = areaList.value.data[i].situate) : ''
+            //   }
+            // }
+
+            for (let i in res.scInfos) {
+              res.scInfos[i].serviceData = []
+              res.scInfos[i].location = res.scInfos[i].dist !== null ? res.scInfos[i].province + res.scInfos[i].city + res.scInfos[i].dist : res.scInfos[i].province + res.scInfos[i].city
+              if (res.scInfos[i].assists) {
+                res.scInfos[i].assisName = ''
+                let datas = res.scInfos[i].assists
                 for (let y in datas) {
-                  datas.length === 1 ? res.schoolAssists[i].admin = datas[y].tmdName : res.schoolAssists[i].admin = res.schoolAssists[i].admin + datas[y].tmdName + ','
-                  // res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+                  res.scInfos[i].assisName = res.scInfos[i].assisName + datas[y].name + ','
                 }
               }
             }
-            nextpageToken.value = res.continuationToken
-            if (!value) {
-              tableData.value = res.schoolAssists;
-              original.value = res.schoolAssists;
-            } else {
-              tableData.value.push(...res.schoolAssists)
-              original.value = tableData.value
-              scrollHeight.value = 'init'
-            }
-            //处理学区呈现
-            console.log(areaList.value.data, '是否有数据')
-            for (let y in res.schoolAssists) {
-              let areaValue = res.schoolAssists[y].areaId
-              console.log(areaValue, '学区的值')
-              res.schoolAssists[y].areaName = ''
-              res.schoolAssists[y].institution = ''
-              for (let i in areaList.value.data) {
-                areaValue === areaList.value.data[i].value ? (res.schoolAssists[y].areaName = areaList.value.data[i].label, res.schoolAssists[y].institution = areaList.value.data[i].situate) : ''
-              }
-            }
+            tableData.value = []; original.value = []
+            tableData.value.push(...res.scInfos),
+              original.value = res.scInfos
             processingSchool()
           }
         })
@@ -219,8 +299,12 @@ export default {
         })
     }
     function correlation (value, data) {
+      console.log(value, data)
       value ? multipleSchool.value.push(value) : ''
       multipleCorrelation()
+
+
+
       // console.log(value, data)
       // ElMessageBox.confirm(`请问您确定将 ${nowUsers.value.name} 设为 ${value.name} 管理员吗 ?`, '添加管理学校', {
       //   confirmButtonText: proxy.$t(`commonMsg.confirm`),
@@ -256,8 +340,14 @@ export default {
       })
     }
     function checkSchool (value, row) {
-      multipleSchool.value = value
-      console.log(multipleSchool.value, '111')
+      if (multipleSchool.value.length === 0) {
+        multipleSchool.value.push(value)
+      } else {
+        let nums = multipleSchool.value.findIndex((item) => { return item.id === value.id })
+        nums !== -1 ? multipleSchool.value.splice(nums, 1) : multipleSchool.value.push(value)
+        console.log(nums, 'nums')
+      }
+      console.log(multipleSchool.value, '222')
     }
     function multipleCorrelation () {
       let schoolData = multipleSchool.value
@@ -289,7 +379,7 @@ export default {
           .then((res) => {
             console.log(res, '成功的返回')
             res.state === 200
-              ? ((adminlist.value = adminlist.value.concat(schoolData)), getSchoolList(), processingSchool(), ElMessage.success('操作成功'))
+              ? ((adminlist.value = adminlist.value.concat(schoolData)), getSchoolList(), processingSchool(), multipleSchool.value = [], ElMessage.success('操作成功'))
               : res.state === 201
                 ? (ElMessage.success('已关联,请勿重复操作'), getSchoolList())
                 : ''
@@ -367,26 +457,35 @@ export default {
       timer.value = setTimeout(fn, wait)
     }
     function personnelSearch () {
+      loadingData.value.list = true
       let names = schoolSearch.value
-      let reg = new RegExp("[\\u4E00-\\u9FFF]+", "g")
-      let data = reg.test(names) ? { name: names } : { scId: names }
-      proxy.$api.getSchooldata(data).then((res) => {
-        if (res.state === 200) {
-          for (let i in res.schoolAssists) {
-            if (res.schoolAssists[i].assists) {
-              res.schoolAssists[i].assisName = ''
-              let datas = res.schoolAssists[i].assists
-              for (let y in datas) {
-                res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
-              }
-            }
-          }
-          tableData.value = res.schoolAssists
-          processingSchool()
-        }
-      }).catch((error) => {
-        ElMessage.error('搜索学校失败,API异常')
+      // let names = schoolSearch.value
+      // let reg = new RegExp("[\\u4E00-\\u9FFF]+", "g")
+      // let data = reg.test(names) ? { name: names } : { scId: names }
+      // proxy.$api.getSchooldata(data).then((res) => {
+      //   if (res.state === 200) {
+      //     for (let i in res.schoolAssists) {
+      //       if (res.schoolAssists[i].assists) {
+      //         res.schoolAssists[i].assisName = ''
+      //         let datas = res.schoolAssists[i].assists
+      //         for (let y in datas) {
+      //           res.schoolAssists[i].assisName = res.schoolAssists[i].assisName + datas[y].tmdName + ','
+      //         }
+      //       }
+      //     }
+      //     tableData.value = res.schoolAssists
+      //     processingSchool()
+      //   }
+      // }).catch((error) => {
+      //   ElMessage.error('搜索学校失败,API异常')
+      // })
+      let arr = original.value
+      let newArr = arr.filter((item) => {
+        return item.name.includes(names) || item.id.includes(names)
       })
+      tableData.value = newArr
+      loadingData.value.list = false
+      processingSchool()
     }
     //当前管理员 管理的学校
     function adminManegeSc (id) {
@@ -462,12 +561,45 @@ export default {
         processingSchool()
       }
     }
-    watch(scrollHeight, (newdata, olddata) => {
-      console.log(newdata, olddata, '监听的数据')
-      if (newdata < olddata) {
-        newdata <= 0 ? getSchoolList(nextpageToken.value) : ''
+    function getAreaschool (value) {
+      console.log(value, 'V')
+      tableData.value = []
+      let filterData = []
+      // let data = value !== 'all' ? { areaId: value } : getSchoolList('', 'restart')
+      if (value !== 'all') {
+        //   loadingData.value.list = true
+        //   proxy.$api.getForareaSchool(data).then((res) => {
+        //     console.log(res, '现在区域拥有的学校')
+        //     if (res.state === 200) {
+        //       for (let y in res.joinAreaSchools) {
+        //         let areaValue = res.joinAreaSchools[y].areaId
+        //         res.joinAreaSchools[y].areaName = ''
+        //         res.joinAreaSchools[y].institution = ''
+        //         res.joinAreaSchools[y].assisName = ''
+        //         for (let i in areaList.value.data) {
+        //           areaValue === areaList.value.data[i].value ? (res.joinAreaSchools[y].areaName = areaList.value.data[i].label, res.joinAreaSchools[y].institution = areaList.value.data[i].situate) : ''
+        //         }
+        //         for (let e in res.joinAreaSchools[y].assists) {
+        //           res.joinAreaSchools[y].assisName !== '' ? res.joinAreaSchools[y].assisName = res.joinAreaSchools[y].assisName + ',' + res.joinAreaSchools[y].assists[e].tmdName : res.joinAreaSchools[y].assisName = res.joinAreaSchools[y].assists[e].tmdName
+        //         }
+        //       }
+        //       tableData.value = res.joinAreaSchools
+        //       processingSchool()
+        //       nextpageToken.value = null
+        //     }
+        //     loadingData.value.list = false
+        //   }).catch((error) => {
+        //     ElMessage.error('获取筛选学校列表失败')
+        //     loadingData.value.list = false
+        //   })
+        original.value.forEach((item) => {
+          item.areaId === value ? filterData.push(item) : ''
+        })
+        tableData.value = filterData
+      } else {
+        tableData.value = original.value
       }
-    })
+    }
     watch(
       props,
       (newuser) => {
@@ -481,6 +613,7 @@ export default {
         debounce(personnelSearch, 500)
       } else {
         tableData.value = original.value
+        processingSchool()
       }
     })
     // watch(() => [...store.state.point], (newdata, olddata) => {
@@ -513,7 +646,10 @@ export default {
       removeMultiple,
       removeCheck,
       primitiveData,
-      filterTable
+      filterTable,
+      columns,
+      userVerify,
+      getAreaschool
     }
   },
 }
@@ -535,7 +671,7 @@ export default {
 }
 .school-list {
   width: 100%;
-  margin-top: 7%;
+  margin-top: 5%;
 }
 .nodata {
   width: 100%;
@@ -585,9 +721,9 @@ export default {
   color: #b2bec3;
   text-align: left;
 }
-.correlationbox-search {
+/* .correlationbox-search {
   width: 45%;
-}
+} */
 .correlationbox-btn {
   width: 30%;
   text-align: right;
@@ -617,11 +753,14 @@ export default {
 .correlationbox-num {
   color: #409eff;
 }
+.correlationbox-search,
+.areaSelect {
+  width: 35%;
+}
 </style>
-  <style>
+<style>
 .school-list-header .el-button--small {
   min-height: 25px;
   padding: 7px 10px;
 }
-</style>
-  
+</style>

+ 36 - 37
TEAMModelBI/ClientApp/src/view/systemConfig/operate.vue

@@ -13,10 +13,10 @@
     <div class="identitybox">
       <p class="identitybox-title">当前身份:</p>
       <div class="identitybox-select">
-        <el-select v-model="identityValue" size="small" placeholder="当前身份" multiple @change="changeIdentity" v-if="PowerShow">
+        <el-select v-model="identityValue" size="small" placeholder="当前身份" @change="changeIdentity" v-if="PowerShow">
           <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
         </el-select>
-        <el-select v-model="identityValue" size="small" placeholder="当前身份" multiple disabled v-else>
+        <el-select v-model="identityValue" size="small" placeholder="当前身份" disabled v-else>
           <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
         </el-select>
       </div>
@@ -35,21 +35,21 @@
               </svg>
             </div>
             <el-switch v-model="items.state" v-else-if="!PowerShow" disabled />
-            <el-switch v-model="items.state" v-else @change="changeAuthority"/>
+            <el-switch v-model="items.state" v-else @change="changeAuthority" />
           </div>
         </div>
       </div>
       <div class="authority-block">
         <p class="authority-block-title">账户登录状态</p>
         <div class="authority-block-item">
-        <div class="login-block-item">禁用登录</div>
-        <div class="login-block-item-state">
-          <div class="login-text">
+          <div class="login-block-item">禁用登录</div>
+          <div class="login-block-item-state">
+            <div class="login-text">
               <span v-show="userisDisable" class="impower">已授权登录</span>
               <span v-show="!userisDisable" class="forbid">已禁止用户登录</span>
-        </div>
-        <el-switch v-model="userisDisable"  @change="changeAuthority" :style="'--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949'"/>
-        </div>
+            </div>
+            <el-switch v-model="userisDisable" @change="changeAuthority" :style="'--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949'" />
+          </div>
         </div>
       </div>
       <!-- <div class="authority-block">
@@ -84,12 +84,8 @@ export default {
     console.log(props)
     let { proxy } = getCurrentInstance()
     let PowerShow = proxy.$access.identifyPosition(JSON.parse(localStorage.getItem('id_token')))
-    const identityValue = ref([])
+    const identityValue = ref('')
     const options = [
-      {
-        value: 'rdc',
-        label: '研发部',
-      },
       {
         value: 'sales',
         label: '销售',
@@ -150,7 +146,7 @@ export default {
       //   ]
       // }
     ])
-    let userisDisable=ref(false)
+    let userisDisable = ref(false)
     let siteList = ref([
       { id: 1, label: '中国站点', key: 'china-read', state: false },
       { id: 2, label: '国际站点', key: 'global-read', state: false }
@@ -160,8 +156,8 @@ export default {
     let nowIdentity = ref([])
     function init () {
       let userInfo = nowUsers.value.handlePermissions
-      let userLoginstate=nowUsers.value.isDisable
-      userisDisable.value=false
+      let userLoginstate = nowUsers.value.isDisable
+      userisDisable.value = false
       console.log(userInfo)
       for (let i in userInfo) {
         let authorityName = userInfo[i]
@@ -172,10 +168,10 @@ export default {
           }
         }
       }
-    userisDisable.value=userLoginstate === 1 ? true:userLoginstate===0 ? false:''
+      userisDisable.value = userLoginstate === 1 ? true : userLoginstate === 0 ? false : ''
     }
     function initialize () {
-      identityValue.value = []
+      identityValue.value = ''
       for (let y in authorityList.value) {
         let listData = authorityList.value[y].children
         listData.map((x) => (x.state = false))
@@ -183,10 +179,11 @@ export default {
       for (let i in nowUsers.value.handleRoles) {
         let role = nowUsers.value.handleRoles[i]
         for (let u in options) {
-          options[u].value === role ? identityValue.value.push(options[u].value) : ''
+          // options[u].value === role ? identityValue.value.push(options[u].value) : ''
+          options[u].value === role ? identityValue.value = options[u].value : ''
         }
       }
-      identityValue.value = [...new Set(identityValue.value)]
+      identityValue.value = identityValue.value
       nowAuthority.value = []
       nowIdentity.value = []
     }
@@ -206,20 +203,22 @@ export default {
       }
       context.emit('changeShow', true)
       nowAuthority.value = [...new Set(nowAuthority.value)]
-      console.log(nowAuthority.value,'权限')
+      console.log(nowAuthority.value, '权限')
     }
     function notarizeChange () {
       changeAuthority()
-      console.log('触发子组件的修改方法')
-      let rolesinfo = identityValue.value
+      console.log(identityValue.value, '触发子组件的修改方法')
+      let rolesinfo = [identityValue.value]
       let permissionsinfo = nowAuthority.value
-      let loginState=userisDisable.value ? 1:0
-      let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, permissions: permissionsinfo, roles: rolesinfo,isDisable:loginState}
+      let loginState = userisDisable.value ? 1 : 0
+      let data = { partitionKey: nowUsers.value.partitionKey, userId: nowUsers.value.userId, tmdId: nowUsers.value.tmdId, permissions: permissionsinfo, roles: rolesinfo, isDisable: loginState }
       proxy.$api
         .setRolesandPower(data)
         .then((res) => {
           console.log(res, '变更返回')
-          res.state === 200 ? (ElMessage.success('保存成功'), context.emit('changeShow', false)) : ElMessage.error('变更保存失败')
+          let backData = { state: '', data: [] }
+          res.state === 200 ? (ElMessage.success('保存成功'), nowUsers.value = res.ddUserInfo[0], backData.state = false, backData.data = res.ddUserInfo[0], context.emit('changeShow', backData)) : ElMessage.error('变更保存失败')
+          console.log(nowUsers.value, '更改过后的值')
           return true
         })
         .catch((err) => {
@@ -236,7 +235,7 @@ export default {
       },
       { immediate: true, deep: true }
     )
-    return { identityValue, options, authorityList, nowUsers, init, changeIdentity, changeAuthority, notarizeChange, siteList, PowerShow,userisDisable}
+    return { identityValue, options, authorityList, nowUsers, init, changeIdentity, changeAuthority, notarizeChange, siteList, PowerShow, userisDisable }
   },
 }
 </script>
@@ -278,7 +277,7 @@ export default {
   padding-left: 10px;
   color: #636e72;
 }
-.login-block-item{
+.login-block-item {
   width: 40%;
   display: inline-block;
   vertical-align: top;
@@ -293,7 +292,7 @@ export default {
   text-align: right;
   padding-right: 5%;
 }
-.login-block-item-state{
+.login-block-item-state {
   width: 52%;
   display: inline-block;
   vertical-align: top;
@@ -348,16 +347,16 @@ export default {
   padding-left: 10px;
   color: #636e72;
 }
-.login-text{
-  font-size:14px;
+.login-text {
+  font-size: 14px;
   display: inline-block;
-  margin-right:1%;
+  margin-right: 1%;
 }
-.impower{
-  color: #95d475
+.impower {
+  color: #95d475;
 }
-.forbid{
-  color:#909399
+.forbid {
+  color: #909399;
 }
 </style>
 <style>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1478 - 0
TEAMModelBI/ClientApp/src/view/systemConfig/pushmsg/createdpush.vue


+ 441 - 0
TEAMModelBI/ClientApp/src/view/systemConfig/pushmsg/index.vue

@@ -0,0 +1,441 @@
+<template>
+  <div class="msgbox">
+    <div class="header">
+      <div class="block">
+        <el-date-picker v-model="value1" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" :locale="locale" />
+      </div>
+      <div>
+        <el-button type="primary" @click="skipcreated">
+          <el-icon>
+            <ChatDotSquare />
+          </el-icon>
+          发布消息推送
+        </el-button>
+      </div>
+    </div>
+    <div class="center-table" v-if="showState =='default'">
+      <el-table :data="tableData" style="width: 100%" height="82vh" v-loading="loading" element-loading-text="数据加载中..." empty-text="暂无消息数据">
+        <el-table-column label="类型" align="center">
+          <template #header>
+            <el-select v-model="tableSelect.value" class="m-2" placeholder="类型选择" size="small" @change="changeTag">
+              <el-option v-for="item in tableSelect.options" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+          </template>
+          <template #default="scope">
+            <el-tag color="rgba(99, 205, 218,.5)" effect="dark" v-if="scope.row.type ===1">系统</el-tag>
+            <el-tag type="info" effect="dark" v-if="scope.row.type ===2">普通</el-tag>
+            <el-tag type="" effect="dark" v-if="scope.row.type ===3">提示</el-tag>
+            <el-tag type="success" effect="dark" v-if="scope.row.type ===4">特殊</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="theme" label="消息主题" align="center" />
+        <el-table-column prop="content" label="消息内容" align="center" />
+        <el-table-column prop="address" label="接收产品" align="center">
+          <template #default="scope">
+            <!-- <el-tag class="ml-2 product-tag" v-for="(item,index) in scope.row.crowd.types" :key="index" :type="item ==='hita5' || item ==='HiTA'? 'success':item ==='HiTeach' ? '':'info'" size="small" effect="light ">{{item}}</el-tag> -->
+            {{scope.row.crowd.types}}
+          </template>
+        </el-table-column>
+        <el-table-column prop="time" label="时间" align="center" />
+        <el-table-column label="操作" fixed="right" align="center">
+          <template #default="scope">
+            <div class="look-btn">
+              <el-button type="primary" size="small" @click="detailsMsg(scope.row)">查看</el-button>
+            </div>
+            <!-- <div class="del-btn">
+              <el-button type="danger" size="small">删除</el-button>
+            </div> -->
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="center-table" v-else-if="showState ==='details'">
+      <div class="detailsbox">
+        <div class="datumbox">
+          <div class="crowd">
+            <p class="result-title">接收人群</p>
+            <div class="crowdbox">
+              <el-tag class="crowd-tag" v-for="item in nowPitch.receive" :type="item.dataType ==='area' ? 'warning':item.dataType ==='school' ? 'success':'' ">
+                {{item.name}}
+              </el-tag>
+            </div>
+          </div>
+          <div class="type">
+            <p class="result-title">接收产品类型</p>
+            <div class="typebox">
+              <!-- <el-tag class="crowd-tag" v-for="item in nowPitch.crowd.types" :type="item ==='HiTeach' ? '':item ==='HiTA' ? 'success':item ==='IES5' ? 'info':''" effect="dark" round>
+                {{item}}
+              </el-tag> -->
+              <el-tag class="crowd-tag" :type="item ==='HiTeach' ? '':item ==='HiTA' ? 'success':item ==='IES5' ? 'info':''" effect="dark" round>{{nowPitch.crowd.types}}</el-tag>
+            </div>
+          </div>
+          <div class="push-content">
+            <p class="result-title">消息内容</p>
+            <div class="pushbox-content">
+              <div class="pushcontent">
+                <el-form :model="nowPitch" class="created-one-form" label-position="left">
+                  <el-form-item label="消息主题" prop="theme">
+                    <el-input v-model="nowPitch.theme" placeholder="请填写推送消息的主题" disabled />
+                  </el-form-item>
+                  <el-form-item label="消息内容" prop="content">
+                    <el-input v-model="nowPitch.content" :autosize="{ minRows: 2, maxRows: 4 }" type="textarea" placeholder="推送消息的内容" disabled />
+                  </el-form-item>
+                  <el-form-item label="消息类型" prop="content" class="form-type">
+                    <el-radio-group v-model="nowPitch.type" class="radio-type">
+                      <el-radio label="1" disabled>
+                        <el-tag color="rgba(99, 205, 218,.5)">系统型</el-tag>
+                      </el-radio>
+                      <el-radio label="2" disabled>
+                        <el-tag type="info">普通型</el-tag>
+                      </el-radio>
+                      <el-radio label="3" disabled>
+                        <el-tag>提示型</el-tag>
+                      </el-radio>
+                      <el-radio label="4" disabled>
+                        <el-tag type="success">特殊型</el-tag>
+                      </el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                  <el-form-item label="是否跳转" prop="content" class="skip-switch">
+                    <div class="skip-switch">
+                      <!-- <div class="skip-title">是否跳转地址</div> -->
+                      <div class="skip-content">
+                        <div>
+                          <el-switch v-model="nowPitch.skipstate" class="ml-2" style="--el-switch-on-color: #13ce66; --el-switch-off-color: #b2bec3" disabled />
+                        </div>
+                      </div>
+                      <div class="skip-url" v-show="nowPitch.jumpUrl ? true:false">
+                        <el-input v-model="nowPitch.jumpUrl" placeholder="填写跳转地址" disabled />
+                      </div>
+                    </div>
+                  </el-form-item>
+                  <el-form-item label="回调执行" prop="content" class="skip-switch">
+                    <div class="skip-switch">
+                      <!-- <div class="skip-title">是否跳转地址</div> -->
+                      <div class="skip-content">
+                        <div>
+                          <el-switch v-model="nowPitch.callbackstate" class="ml-2" style="--el-switch-on-color: #13ce66; --el-switch-off-color: #b2bec3" disabled />
+                        </div>
+                      </div>
+                      <div class="skip-functions" v-show="nowPitch.callbackstate">
+                        <!-- <el-input v-model="nowPitch.callbackUrl" placeholder="填写回调执行名称" disabled /> -->
+                        <el-radio-group v-model="nowPitch.callbackFn" class="ml-4" disabled>
+                          <el-radio label="1" size="large">同意/拒绝</el-radio>
+                          <el-radio label="2" size="large">查看</el-radio>
+                        </el-radio-group>
+                      </div>
+                    </div>
+                  </el-form-item>
+                  <el-form-item label="消息来源">
+                    <div class="sourcetitle">{{nowPitch.source}}</div>
+                  </el-form-item>
+                  <el-form-item label="发送时间">
+                    <div class="sourcetitle">{{nowPitch.time}}</div>
+                  </el-form-item>
+                </el-form>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="copybox">
+          <el-button @click="copyReuse">复用此条消息</el-button>
+        </div>
+        <div class="back">
+          <el-button @click="backs">返回列表</el-button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup>
+import { ref, getCurrentInstance, watch, onMounted, } from 'vue'
+import { ChatDotSquare } from '@element-plus/icons-vue'
+import { ElMessageBox, ElMessage, ElLoading } from 'element-plus'
+import zhCn from "element-plus/lib/locale/lang/zh-cn";
+import { useRouter } from 'vue-router'
+import { useStore } from 'vuex'
+let value1 = ref('')
+let { proxy } = getCurrentInstance()
+let locale = zhCn
+const router = useRouter()
+const store = useStore()
+let tableData = ref([
+  // {
+  //   theme: '测试主题1',
+  //   content: '测试内容123456789',
+  //   receive: ['HiTeach', 'HiTA'],
+  //   time: '2016-05-04',
+  //   type: 1
+  // },
+  // {
+  //   theme: '测试主题2',
+  //   content: '测试内容123456789',
+  //   receive: ['HiTA'],
+  //   time: '2016-05-04',
+  //   type: 2
+  // },
+  // {
+  //   theme: '测试主题3',
+  //   content: '测试内容123456789',
+  //   receive: ['HiTA'],
+  //   time: '2016-05-04',
+  //   type: 3
+  // },
+  // {
+  //   theme: '测试主题4',
+  //   content: '测试内容123456789',
+  //   receive: ['HiTA', 'HiTeach'],
+  //   time: '2016-05-04',
+  //   type: 1
+  // }
+])
+let originalData = ref([])
+let nowPitch = ref()
+const disabledDate = () => {
+  let time = new Date()
+  return time.getTime() > Date.now()
+}
+let tableSelect = ref({
+  value: 'all',
+  options: [
+    { value: 'all', label: '全部' },
+    { value: 'common', label: '普通' },
+    { value: 'hint', label: '提示' },
+    { value: 'special', label: '特殊' },
+  ]
+})
+let showState = ref('default')
+let loading = ref(false)
+function skipcreated () {
+  router.push('/home/createdpush')
+}
+function init () {
+  loading.value = true
+  proxy.$api.getMsglist({}).then((res) => {
+    console.log(res, '78787878787')
+    if (res.state === 200) {
+      res.bINotices.forEach((item) => {
+        item.time = proxy.$common.timestampToTime(item.sendTime, 'all');
+        item.type = Number(item.type) + 1
+        item.receive = []
+        item.crowd.areaIds.forEach((areas) => { item.receive.push({ id: areas.id, name: areas.name, dataType: 'area' }) })
+        item.crowd.schoolIds.forEach((school) => { item.receive.push({ id: school.id, name: school.name, dataType: 'school' }) })
+        item.crowd.tmdIds.forEach((tmdinfo) => { item.receive.push({ id: tmdinfo.id, name: tmdinfo.name, dataType: 'tmdinfo' }) })
+      })
+      console.log(res.bINotices, 'update')
+      tableData.value = res.bINotices
+      originalData.value = res.bINotices
+      loading.value = false
+    }
+  }).catch((err) => {
+    loading.value = false
+    ElMessage.error('获取消息列表异常,API异常')
+  })
+}
+function changeTag (val) {
+  console.log(val)
+  let values = val
+  if (values === 'all') {
+    tableData.value = originalData.value
+  } else if (values === 'common') {
+    tableData.value = originalData.value.filter((item) => { return item.type === 2 })
+  } else if (values === 'hint') {
+    tableData.value = originalData.value.filter((item) => { return item.type === 3 })
+  } else if (values === 'special') {
+    tableData.value = originalData.value.filter((item) => { return item.type === 4 })
+  }
+}
+function detailsMsg (val) {
+  val.skipstate = val.jumpUrl ? true : false
+  val.callbackstate = val.callbackName ? true : false
+  val.type = val.type.toString()
+  nowPitch.value = val
+  nowPitch.value.callbackFn = val.callbackName === '同意' && val.callbackstate ? '1' : '2'
+  showState.value = 'details'
+  console.log(nowPitch.value, '详情')
+}
+function backs () {
+  showState.value = 'default'
+  init()
+}
+function copyReuse () {
+  store.commit('copyMsgs', nowPitch.value)
+  router.push('/home/createdpush')
+  console.log(store.state.msgData, '数据')
+}
+init()
+</script>
+<style scoped>
+.msgbox {
+  width: 100%;
+  padding: 1%;
+  display: flex;
+  flex-direction: column;
+  flex: 0 0 auto;
+  line-height: 20px;
+}
+.header {
+  width: 100%;
+  display: flex;
+  justify-content: space-between;
+}
+.center-table {
+  padding: 1% 0%;
+}
+.look-btn,
+.del-btn {
+  display: inline-block;
+}
+.del-btn {
+  margin-left: 5px;
+}
+.product-tag {
+  display: inline-block;
+}
+/* .push-icon {
+  width: 15px;
+  height: 15px;
+  vertical-align: -5px;
+  fill: currentColor;
+  overflow: hidden;
+  margin-left: 0px;
+} */
+.detailsbox {
+  width: 100%;
+  height: 82vh;
+  padding: 1%;
+  background-color: #fff;
+  display: flex;
+}
+.datumbox {
+  width: 85%;
+  height: 100%;
+  /* margin: 0 auto; */
+  border: 1px solid #ccc;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  line-height: 20px;
+  /* box-shadow: 0px 5px 10px 0px rgba(204, 204, 204, 0.7); */
+}
+.type {
+  width: 35%;
+  height: 40%;
+}
+.crowd {
+  width: 65%;
+  height: 40%;
+  overflow: hidden;
+}
+.crowd {
+  border-right: 1px solid #ccc;
+}
+.push-content {
+  width: 100%;
+  height: 60%;
+  border-top: 1px solid #ccc;
+}
+.result-title {
+  font-size: 14px;
+  color: #b2bec3;
+  line-height: 28px;
+  position: sticky;
+  margin-bottom: 10px;
+  border-bottom: 1px dashed #ccc;
+  box-shadow: 0 2px 5px #e9e9e9;
+}
+.crowdbox {
+  margin: 1%;
+  /* border: 1px solid #ccc; */
+  line-height: 20px;
+  overflow-y: auto;
+  height: 15vh;
+}
+.crowd-tag {
+  margin: 0.5% 0.2%;
+}
+.pushcontent {
+  width: 85%;
+  margin: 0 auto;
+}
+.pushtime {
+  width: 85%;
+  margin: 0 auto;
+  font-weight: bold;
+  color: #409eff;
+  display: flex;
+  justify-content: space-between;
+}
+.back {
+  width: 5%;
+  text-align: center;
+}
+.copybox {
+  width: 10%;
+  margin-top: 3%;
+}
+.sourcetitle {
+  font-size: 14px;
+  font-weight: bold;
+  color: #95afc0;
+}
+.skip-switch {
+  width: 70%;
+  text-align: left;
+}
+.skip-content {
+  display: inline-block;
+  width: 15%;
+  text-align: center;
+}
+.skip-url,
+.skip-functions {
+  display: inline-block;
+  width: 70%;
+}
+</style>
+<style>
+.header .el-date-editor .el-range-separator {
+  width: 10%;
+}
+.copybox .el-button {
+  color: rgba(255, 255, 255, 0.9);
+  border-radius: 20px;
+  /* width: 300px;
+  height: 100px; */
+  /* font-size: 30px; */
+  text-align: center;
+  /* line-height: 100px; */
+  background: linear-gradient(-45deg, #ffa63d, #ff3d77, #338aff, #3cf0c5);
+  background-size: 600%;
+  -webkit-animation: anime 6s linear infinite;
+  animation: anime 6s linear infinite;
+}
+@keyframes anime {
+  0% {
+    background-position: 0% 50%;
+  }
+
+  50% {
+    background-position: 100% 50%;
+  }
+
+  100% {
+    background-position: 0% 50%;
+  }
+}
+
+@-webkit-keyframes anime {
+  0% {
+    background-position: 0% 50%;
+  }
+
+  50% {
+    background-position: 100% 50%;
+  }
+
+  100% {
+    background-position: 0% 50%;
+  }
+}
+</style>

+ 16 - 4
TEAMModelBI/ClientApp/src/view/systemConfig/setAdmin.vue

@@ -32,7 +32,7 @@
             <div class="hint"><span>请输入用户</span><span class="emphasize">手机号、醍摩豆账号</span><span>等相关信息进行搜索</span></div>
             <div class="search-box">
               <!-- <input class="search-txt" type="text" id="serachname" :value="filterText" placeholder="搜索相关人名" @oninput="personnelSearch()" @compositionend="personnelSearch()"> -->
-              <el-input v-model="adminfilter" placeholder="Please input" class="search-txt" />
+              <el-input v-model="adminfilter" placeholder="输入手机号、醍摩豆账号搜索" class="search-txt" />
               <svg class="serachbox-empty" aria-hidden="true" v-if="adminfilter !==''" @click="adminfilter=''">
                 <use xlink:href="#icon-qingkong"></use>
               </svg>
@@ -375,12 +375,12 @@ export default {
   opacity: 1;
   width: 100%;
   /* padding: 0px; */
-  height: 30px !important;
-  line-height: 30px;
+  height: 25px !important;
+  line-height: 25px;
   border: 0px;
   background-color: #bdc3c7;
   vertical-align: top;
-  border-radius: 8px;
+  /* border-radius: 8px; */
   padding-bottom: 10px;
   color: #333 !important;
 }
@@ -391,6 +391,18 @@ export default {
 .headerPhoto .el-image {
   display: block;
 }
+.search-box .el-input__wrapper {
+  background: #bdc3c7;
+  padding: 0px;
+}
+.search-box .el-input__wrapper:hover {
+  border: 0px;
+  box-shadow: 0px 0px 0px 0px transform;
+}
+.search-box .el-input__wrapper .is-focues {
+  border: 0px;
+  box-shadow: 0px 0px 0px 0px transform;
+}
 </style>
 
 

+ 77 - 11
TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue

@@ -15,7 +15,7 @@
         </div> -->
     <div class="search-box">
       <!-- <input class="search-txt" type="text" id="serachname" :value="filterText" placeholder="搜索相关人名" @oninput="personnelSearch()" @compositionend="personnelSearch()"> -->
-      <el-input v-model="filterText" placeholder="Please input" class="search-txt" />
+      <el-input v-model="filterText" placeholder="搜索相关人名" class="search-txt" />
       <svg class="serachbox-empty" aria-hidden="true" @click="filterText='',valueinfo='all'">
         <use xlink:href="#icon-qingkong"></use>
       </svg>
@@ -37,7 +37,16 @@
   </div>
   <div class="manage-table">
     <el-table :data="tableData" style="width: 100%" height="85vh" v-loading="loading" element-loading-text="数据加载中..." class="customer-table" :empty-text='$t(`personnelManagement.personnelTable.nodatas`)'>
-      <el-table-column prop="id" :label="$t(`personnelManagement.personnelTable.serialnum`)" sortable align="center" />
+      <el-table-column prop="id" :label="$t(`personnelManagement.personnelTable.serialnum`)" sortable align="center" class="tables-numstate" />
+      <el-table-column width="60">
+        <template #default="scope">
+          <div class="tables-state" title="更新同步该人员信息" v-show="scope.row.tmdMobile !== scope.row.mobile && (scope.row.tmdMobile && scope.row.mobile)" @click="synchronizationAlone(scope.row)">
+            <svg class="areaaddschool" aria-hidden="true">
+              <use xlink:href="#icon-NMStubiao-1"></use>
+            </svg>
+          </div>
+        </template>
+      </el-table-column>
       <el-table-column :label="$t(`personnelManagement.personnelTable.headportrait`)" align="center">
         <template #default="scope">
           <el-image style="width: 50px; height: 50px;border-radius:50%" :src="scope.row.avatar" fit="fill" v-if="scope.row.avatar !=='' "></el-image>
@@ -77,7 +86,7 @@
       <el-table-column prop="title" label="公司职位" align="center" />
       <el-table-column :label="$t(`personnelManagement.personnelTable.operate`)" align="center">
         <template #default="scope">
-          <el-button type="primary" size="small" @click="handleClick(scope.$index,tableData)">
+          <el-button type="primary" @click="handleClick(scope.$index,tableData)">
             <svg class="qxmages" aria-hidden="true">
               <use xlink:href="#icon-quanxianguanli-"></use>
             </svg>
@@ -94,8 +103,8 @@
         <el-tab-pane label="权限/身份" name="first">
           <Operates ref="roaming" :userdata="nowUser" @changeShow="changeState"></Operates>
         </el-tab-pane>
-        <el-tab-pane label="关联学校" name="second" v-if="(nowUser.handleRoles.includes('assist') || nowUser.handleRoles.includes('admin') || nowUser.handleRoles.includes('sales')) && nowUser.tmdId !==''">
-          <Correlation :userdata="nowUser" :areadata="areaDatas"></Correlation>
+        <el-tab-pane label="关联学校" name="second" v-if="(nowUser.handleRoles.includes('assist') || nowUser.handleRoles.includes('sales')) && nowUser.tmdId !==''">
+          <Correlation :userdata="nowUser" :areadata="areaDatas" @changerestart="changerestart"></Correlation>
         </el-tab-pane>
         <el-tab-pane label="管理学校" name="manegeschool" v-if="nowUser.tmdId !==''">
           <Manageschool :userdata="nowUser" :areadata="areaDatas"></Manageschool>
@@ -206,6 +215,7 @@ export default {
     let managebox = ref(false)
     let manageList = ref([])
     let operateUser = ref({}) //当前操作的人员信息
+    let restartState = ref(false) //是否需要关闭侧边栏重新加载人员数据
     const isAdmin = jwt_decode(JSON.parse(localStorage.getItem('id_token'))).roles.includes('admin')
     let userisAdmin = ref({
       name: proxy.$t(`personnelManagement.authority.isAdmin`),
@@ -444,7 +454,7 @@ export default {
     }
     //人员搜索
     function personnelSearch () {
-      let arr = tableData.value
+      let arr = original.value
       let newArr = arr.filter((item) => {
         // return (item.name && item.name.includes(filterText.value)) || (item.mobile && item.mobile.includes(filterText.value)) || (item.mobile && item.mobile.tmdId.includes(filterText.value))
         return item.name.includes(filterText.value)
@@ -459,9 +469,16 @@ export default {
     }
     function closeDrawer () {
       activeName.value = 'first'
+      // restartState.value === true ? (getEvery(), restartState.value = false) : ''
     }
     function changeState (value) {
-      drawerChange.value = value
+      console.log(value, '触发到了')
+      !value.hasOwnProperty('data') ? drawerChange.value = value : (drawerChange.value = value.state, nowUser.value = value.data, restartState.value = true)
+      // drawerChange.value = value
+    }
+    function changerestart (value) {
+      console.log(value, '关联的也触发到了')
+      restartState.value = value
     }
     function changeSubmit () {
       console.log(roaming.value)
@@ -482,13 +499,38 @@ export default {
         ElMessage.error('API异常,获取学区失败')
       })
     }
+    //同步某个人员人员信息
+    function synchronizationAlone (val) {
+      console.log(val, '8888')
+      loading.value = true
+      let data = { "partitionKey": val.partitionKey, "rowKey": val.rowKey, role: val.handleRoles[0] || '' }
+      proxy.$api.updateAlone(data).then((res) => {
+        console.log(res, '同步返回')
+        if (res.state === 200) {
+          for (let i in tableData.value) {
+            tableData.value[i].partitionKey === res.upUserInfo[0].partitionKey && tableData.value[i].rowKey === res.upUserInfo[0].rowKey ?
+              (res.upUserInfo[0].id = Number(i) + 1, tableData.value.splice(i, 1, res.upUserInfo[0])) : ''
+          }
+          ElMessage.success('个人信息同步成功')
+        }
+        loading.value = false
+      }).catch((error) => {
+        ElMessage.error('API异常,同步人员失败')
+        loading.value = false
+      })
+    }
     watch(filterText, (newdata) => {
+      console.log(newdata, '搜索监听')
       if (newdata.trim().length !== 0) {
         debounce(personnelSearch, 500)
       } else {
         tableData.value = original.value
       }
     })
+    watch(drawer, (news) => {
+      console.log(news, '监听开关')
+      news === false && restartState.value === true ? (getEvery(), valueinfo.value = 'all', restartState.value = false) : ''
+    })
     areaData()
     return {
       proxy,
@@ -527,7 +569,10 @@ export default {
       schoolSort,
       identityArr,
       areaData,
-      areaDatas
+      areaDatas,
+      restartState,
+      changerestart,
+      synchronizationAlone
     }
   },
 }
@@ -779,6 +824,16 @@ export default {
   margin-left: 5px;
   font-weight: 600;
 }
+.areaaddschool {
+  width: 20px !important;
+  height: 20px !important;
+  vertical-align: -5px !important;
+  fill: currentColor !important;
+  overflow: hidden !important;
+}
+.tables-state {
+  cursor: pointer;
+}
 </style>
 <style>
 .manatips .el-dialog__header,
@@ -807,7 +862,7 @@ export default {
   border: 0px;
   background-color: #bdc3c7;
   vertical-align: top;
-  border-radius: 8px;
+  /* border-radius: 8px; */
   color: #333;
 }
 .search-box:hover .el-input__inner {
@@ -830,8 +885,8 @@ export default {
   right: 4px;
 }
 .personnel-drawer .el-drawer.rtl {
-  top: 5.5%;
-  height: 94.5vh;
+  top: 6%;
+  height: 94vh;
 }
 .personnel-drawer .el-drawer__header {
   line-height: 20px;
@@ -847,4 +902,15 @@ export default {
   min-height: 20px;
   padding: 5px 8px;
 }
+.cell .tables-num,
+.cell .tables-state {
+  display: inline-block;
+}
+.search-box .el-input__wrapper {
+  background: #bdc3c7;
+  padding: 0px;
+}
+.search-txt .el-input__wrapper .is-focues {
+  border: 0px;
+}
 </style>

+ 2 - 2
TEAMModelBI/ClientApp/src/view/teachermanage/school.vue

@@ -46,7 +46,7 @@
       </a>
     </div>
     <div class="school-list">
-      <el-table :data="tableData" style="width: 100%" height="75vh" v-loading="loading" element-loading-text="加载中...">
+      <el-table :data="tableData" style="width: 100%" height="75vh" v-loading="loading" element-loading-text="加载中..." :default-sort="{ prop: 'scale', order: 'descending' }">
         <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">
@@ -59,7 +59,7 @@
                         <span>{{scope.row.period[0].name}}</span>
                     </template>
                 </el-table-column> -->
-        <el-table-column :label="$t(`schoolManages.tables.scale`)" class="school-table-edition" align="center">
+        <el-table-column prop="scale" :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">

+ 44 - 15
TEAMModelBI/ClientApp/src/view/teachermanage/traitmanage.vue

@@ -131,7 +131,8 @@
     <div v-else-if="treeModel === 'tree'" class="treeinfo">
       <div class="synchronizationuIcon" v-show="nowPitch.hasOwnProperty('cutArea') && nowPitch.cutArea"><span>已同步省平台</span></div>
       <div class="backbtn">
-        <el-button type="primary" icon="el-icon-back" size="small" @click="treeModel = 'default'">返回</el-button>
+        <el-button type="primary" @click="treeModel = 'default'">返回</el-button>
+        <!-- <el-icon><Back /></el-icon> -->
       </div>
       <div class="ability-box">
         <div class="abilitys">
@@ -139,11 +140,26 @@
             <i class="dian"></i>
             <span class="tabname">{{ $t(`abilityManages.abilityname`) }}({{ abilitylenth }})</span>
             <span class="tabinfos">
-              <i class="el-icon-search" @click="operateModel = search"></i>
-              <i class="el-icon-s-tools" @click="setAbility" v-if="PowerShow"></i>
-              <i class="el-icon-edit" @click="editAbility('redact')" v-if="PowerShow"></i>
-              <i class="el-icon-delete-solid  deleAbility" @click="operationAbility('del')" v-if="PowerShow"></i>
-              <i class="el-icon-plus" @click="editAbility('add')" v-if="PowerShow"></i>
+              <!-- <i class="el-icon-search" ></i> -->
+              <el-icon @click="operateModel = search">
+                <Search />
+              </el-icon>
+              <!-- <i class="el-icon-s-tools" @click="setAbility" v-if="PowerShow && intactShow"></i> -->
+              <el-icon @click="setAbility" v-if="PowerShow && intactShow">
+                <Setting />
+              </el-icon>
+              <!-- <i class="el-icon-edit" @click="editAbility('redact')" v-if="PowerShow && intactShow"></i> -->
+              <el-icon @click="editAbility('redact')" v-if="PowerShow && intactShow">
+                <Edit />
+              </el-icon>
+              <!-- <i class="el-icon-delete-solid  deleAbility" @click="operationAbility('del')" v-if="PowerShow && intactShow"></i> -->
+              <el-icon class="deleAbility" @click="operationAbility('del')" v-if="PowerShow && intactShow">
+                <Delete />
+              </el-icon>
+              <!-- <i class="el-icon-plus" @click="editAbility('add')" v-if="PowerShow && intactShow"></i> -->
+              <el-icon @click="editAbility('add')" v-if="PowerShow && intactShow">
+                <Plus />
+              </el-icon>
             </span>
           </p>
           <p class="abilitys-one" v-if="operateModel === search">
@@ -160,10 +176,8 @@
             <p>
               <span class="ability-num">{{ items.no }}</span>
               <span class="ability-name">{{ items.name }}</span>
-              <span class="ability-tag" v-if="items.currency === 3">{{ $t(`treeStructure.choose`)
-                            }}</span>
-              <span class="ability-must" v-if="items.currency === 1">{{ $t(`treeStructure.required`)
-                            }}</span>
+              <span class="ability-tag" v-if="items.currency === 3">{{ $t(`treeStructure.choose`)}}</span>
+              <span class="ability-must" v-if="items.currency === 1">{{ $t(`treeStructure.required`)}}</span>
               <span v-if="items.currency === 0"></span>
             </p>
             <p>
@@ -204,8 +218,8 @@
           </el-table-column>
         </el-table>
         <div>
-          <el-button type="success" style="margin: 20px 0;float: right;margin-left: 20px;" @click="onSaveCompulsory" :loading="idBtnLoading">保存</el-button>
-          <el-button style="margin: 20px 0;float: right;" @click="compulsoryModal = false">取消</el-button>
+          <el-button type="success" style="margin: 10px 0;float: right;margin-left: 10px;" @click="onSaveCompulsory" :loading="idBtnLoading">保存</el-button>
+          <el-button style="margin: 10px 0;float: right;" @click="compulsoryModal = false">取消</el-button>
         </div>
       </el-dialog>
     </div>
@@ -376,9 +390,15 @@ import { useStore } from 'vuex'
 import AbilityTree from '@/components/AbilityTree.vue'
 import dimension from '@/static/dimension.js'
 import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
+import { Search, Setting, Edit, Delete, Plus } from '@element-plus/icons-vue'
 export default {
   components: {
     AbilityTree,
+    Search,
+    Setting,
+    Edit,
+    Delete,
+    Plus,
   },
   setup () {
     let { proxy } = getCurrentInstance()
@@ -434,6 +454,7 @@ export default {
     ])
     const store = useStore()
     let PowerShow = proxy.$access.identifyPosition(JSON.parse(localStorage.getItem('id_token')))
+    let intactShow = ref(true)
     let activeName = 'first'
     let tableData = reactive([
       {
@@ -600,6 +621,7 @@ export default {
     //获取到方案下的能力点,并默认选中第一个
     function pitch (data) {
       console.log(data, '查询册别传入的data')
+      data.id === 'bde5c011-2ae4-461a-b46c-5483ba72ae45' ? intactShow.value = false : intactShow.value = true
       areaIds.value = data.id
       nowPitch = Object.assign({}, data)
       console.log(nowPitch, data, '查询册别')
@@ -997,7 +1019,8 @@ export default {
       nowPitch,
       synchronize,
       intactImg,
-      loadingData
+      loadingData,
+      intactShow
     }
   },
 }
@@ -1806,7 +1829,7 @@ export default {
 }
 
 .compulsorydialog .el-table__body-wrapper {
-  max-height: 50vh;
+  height: 44vh;
   overflow-y: scroll;
 }
 
@@ -1870,7 +1893,7 @@ export default {
 }
 
 .compulsorydialog .el-table--fit {
-  height: 53vh;
+  height: 55vh;
 }
 
 .cardbox .el-card__header {
@@ -1881,6 +1904,9 @@ export default {
   .compulsorydialog .el-dialog {
     height: 75vh;
   }
+  .compulsorydialog .el-table__body-wrapper {
+    height: 46vh !important;
+  }
 }
 
 @media screen and (max-width: 1400px) {
@@ -1893,5 +1919,8 @@ export default {
   .information-box .source {
     line-height: 40px !important;
   }
+  .compulsorydialog .el-table__body-wrapper {
+    height: 44vh !important;
+  }
 }
 </style>

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

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

+ 275 - 0
TEAMModelBI/Controllers/BICommon/BINoticeController.cs

@@ -0,0 +1,275 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using System.Net.Http;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK;
+using TEAMModelOS.Models;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Context.Constant;
+using System.Collections.Generic;
+using System.Text;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelBI.Models;
+using System.Linq;
+using TEAMModelBI.Filter;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using Azure.Cosmos;
+using System;
+using TEAMModelOS.SDK.Models.Service.BI;
+using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
+using TEAMModelBI.Tool.Extension;
+using TEAMModelOS.SDK.Models;
+using DocumentFormat.OpenXml.Spreadsheet;
+using System.Net.Http.Json;
+
+namespace TEAMModelBI.Controllers.BICommon
+{
+    [Route("notice")]
+    [ApiController]
+    public class BINoticeController : ControllerBase
+    {
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly IConfiguration _configuration;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly IHttpClientFactory _http;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly IWebHostEnvironment _environment; //读取文件
+        private readonly HttpClient _httpClient;
+
+        public BINoticeController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment, HttpClient httpClient)
+        {
+            _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _azureStorage = azureStorage;
+            _option = option?.Value;
+            _configuration = configuration;
+            _serviceBus = serviceBus;
+            _http = http;
+            _coreAPIHttpService = coreAPIHttpService;
+            _environment = hostingEnvironment;
+            _httpClient = httpClient;
+        }
+
+        /// <summary>
+        /// 查询账户信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [AuthToken(Roles = "admin,rdc,assist,sales")]
+        [HttpPost("get-info")]
+        public async Task<IActionResult> GetInfo(JsonElement jsonElement)
+        {
+            jsonElement.TryGetProperty("ids", out JsonElement _ids);
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            List<string> ids = new();
+            ids = _ids.ToObject<List<string>>();
+            List<TmdUserinfo> userinfos = new();
+            List<string> noFound = new();
+            if (ids.Count > 0)
+            {
+                var content = new StringContent(ids.ToArray().ToJsonString(), Encoding.UTF8, "application/json");
+                string idJson = await _coreAPIHttpService.GetUserInfos(content);
+                userinfos = idJson.ToObject<List<TmdUserinfo>>();
+
+                foreach (var item in ids)
+                {
+                    var tempId = userinfos.Where(s => s.id.Equals(item)).ToList();
+                    var tempMail = userinfos.Where(s => !string.IsNullOrEmpty($"{s.mail}") && s.mail.Equals(item)).ToList();
+                    var tempmobile = userinfos.Where(s => !string.IsNullOrEmpty($"{s.mobile}") && s.mobile.Equals(item)).ToList();
+                    if (tempId.Count == 0 && tempMail.Count == 0 && tempmobile.Count == 0)
+                        noFound.Add(item);
+                }
+            }
+
+            return Ok(new { state = RespondCode.Ok, userinfos, noFound });
+        }
+
+        /// <summary>
+        /// 依据学校id查询学校教师信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        //[AuthToken(Roles = "admin,rdc,assist,sales")]
+        [HttpPost("get-tchinfos")]
+        public async Task<IActionResult> GetSchoolTeacher(JsonElement jsonElement)
+        {
+            if (!jsonElement.TryGetProperty("scId", out JsonElement scId)) return BadRequest();
+
+            List<IdInfo> idInfos = new();
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<IdInfo>(queryText: "select c.id,c.name,c.picture from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{scId}") }))
+            {
+                idInfos.Add(item);
+            }
+
+            return Ok(new { state = RespondCode.Ok, idInfos });
+        }
+
+        /// <summary>
+        /// BI发布端外消息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [AuthToken(Roles = "admin,rdc,assist,sales")]
+        [HttpPost("push-info")]
+        public async Task<IActionResult> PushNotion(JsonElement jsonElement)
+        {
+            try
+            {
+                var (_tmdId, _tmdName, _, _, _, _) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
+
+                jsonElement.TryGetProperty("type", out JsonElement type);
+                jsonElement.TryGetProperty("jumpUrl", out JsonElement jumpUrl);
+                jsonElement.TryGetProperty("callbackName", out JsonElement callbackName);
+                jsonElement.TryGetProperty("refuseName", out JsonElement refuseName);
+                if (!jsonElement.TryGetProperty("theme", out JsonElement theme)) return BadRequest();
+                if (!jsonElement.TryGetProperty("content", out JsonElement content)) return BadRequest();
+                jsonElement.TryGetProperty("tmdIds", out JsonElement _tmdIds);
+                jsonElement.TryGetProperty("schoolIds", out JsonElement _schoolIds);
+                jsonElement.TryGetProperty("areaIds", out JsonElement _areaIds);
+                if (!jsonElement.TryGetProperty("crowdType", out JsonElement _crowdType)) return BadRequest();
+                if (!jsonElement.TryGetProperty("sendTime", out JsonElement sendTime)) return BadRequest();
+                jsonElement.TryGetProperty("source", out JsonElement source);
+
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                //DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+
+                List<IdNameCode> idNameCodes = new();
+                BINotice bINotice = new();
+                List<CrowdInfo> tmdIds = new();
+                List<CrowdInfo> schoolIds = new();
+                List<CrowdInfo> areaIds = new();
+
+                List<string> tempScIds = new();
+
+                //if (!string.IsNullOrEmpty($"{sendTime}"))
+                //    dateTime = DateTimeOffset.Parse($"{sendTime}");
+                if (string.IsNullOrEmpty($"{_tmdIds}") && string.IsNullOrEmpty($"{_schoolIds}") && string.IsNullOrEmpty($"{_areaIds}"))
+                    return Ok(new { state = RespondCode.ParamsError, msg = "发送人群不能为空" });
+                if (!string.IsNullOrEmpty($"{_tmdIds}"))
+                    tmdIds = _tmdIds.ToObject<List<CrowdInfo>>();
+                if (!string.IsNullOrEmpty($"{_schoolIds}"))
+                    schoolIds = _schoolIds.ToObject<List<CrowdInfo>>();
+                if (!string.IsNullOrEmpty($"{_areaIds}"))
+                    areaIds = _areaIds.ToObject<List<CrowdInfo>>();
+
+                Crowd crowd = new()
+                {
+                    tmdIds = tmdIds.Count > 0 ? tmdIds : new List<CrowdInfo>(),
+                    schoolIds = schoolIds.Count > 0 ? schoolIds : new List<CrowdInfo>(),
+                    areaIds = areaIds.Count > 0 ? areaIds : new List<CrowdInfo>(),
+                    types = $"{_crowdType}"
+                };
+
+                if (tmdIds.Count > 0)
+                {
+                    StringBuilder tchSql = new($"select c.id, c.name,c.code,c.picture,c.nickname from c ");
+                    if (tmdIds.Count > 0)
+                    {
+                        tchSql.Append(BICommonWay.ManyScSql(" where c.id ", tmdIds.Select(s => s.id).ToList()));
+                        await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<IdNameCode>(queryText: tchSql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                        {
+                            var tempId = idNameCodes.FindAll(fa => fa.id.Equals(item.id)).ToList();
+                            if (tempId.Count == 0)
+                                idNameCodes.Add(item);
+                        }
+                    }
+                }
+
+                if (areaIds.Count > 0)
+                {
+                    StringBuilder scAreaSql = new($"select value(c.id) from c");
+                    if (schoolIds.Count > 0)
+                    {
+                        scAreaSql.Append(BICommonWay.ManyScSql(" where c.areaId", areaIds.Select(s => s.id).ToList()));
+                        await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<string>(queryText: scAreaSql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                        {
+                            var tempScId = schoolIds.FindAll(fa => fa.Equals(item)).ToList();
+                            if (tempScId.Count == 0)
+                                tempScIds.Add(item);
+                        }
+                    }
+                }
+
+                if (schoolIds.Count > 0)
+                {
+                    StringBuilder scTchSql = new($"select c.id, c.name, c.picture,c.nickname from c where c.pk='Teacher'");
+                    if (schoolIds.Count > 0)
+                    {
+                        scTchSql.Append(BICommonWay.ManyScSql(" and c.code", schoolIds.Select(s => s.id).ToList(), $"Teacher-"));
+                        await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<IdNameCode>(queryText: scTchSql.ToString(), requestOptions: new QueryRequestOptions() { }))
+                        {
+                            var tempId = idNameCodes.FindAll(fa => fa.id.Equals(item.id)).ToList();
+                            if (tempId.Count == 0)
+                                idNameCodes.Add(item);
+                        }
+                    }
+                }
+
+                string tagServiceName = ($"{_crowdType}".ToLower().Contains("hita")) ? "HiTA" : $"{_crowdType}";
+                bINotice = new()
+                {
+                    id = Guid.NewGuid().ToString(),
+                    code = "BINotice",
+                    type = !string.IsNullOrEmpty($"{type}") ? type.GetInt32() : 0,
+                    jumpUrl = !string.IsNullOrEmpty($"{jumpUrl}") ? $"{jumpUrl}" : "",
+                    callbackName = !string.IsNullOrEmpty($"{callbackName}") ? $"{callbackName}" : "",
+                    refuseName = !string.IsNullOrEmpty($"{refuseName}") ? $"{refuseName}" : "",
+                    theme = $"{theme}",
+                    content = $"{content}",
+                    crowd = crowd,
+                    crowdIds = idNameCodes.Select(s => $"{s.id}_{tagServiceName}").ToList(),
+                    createId = _tmdId,
+                    sendTime = sendTime.GetInt64(),//发布时间待解决
+                    createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                    source = !string.IsNullOrEmpty($"{source}") ? $"{source}" : "BI"
+                };
+
+                bINotice = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync<BINotice>(bINotice, new PartitionKey("BINotice"));
+                //BI发送端外通知
+                _coreAPIHttpService.BIPushNotify(bINotice, new Dictionary<string, object> { { "tmdid", _tmdIds }, { "sendId", bINotice.crowdIds} }, _option.Location, _configuration, _dingDing);
+
+                return Ok(new { state = RespondCode.Ok, bINotice });
+            }
+            catch (Exception ex)
+            {
+                _ = _dingDing.SendBotMsg($"BI,{_option.Location},notion/PushNotion() \n{ex.Message}\n{ex.StackTrace}\n", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
+        /// <summary>
+        /// 查询发布的消息信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [HttpPost("get-infos")]
+        [AuthToken(Roles = "admin,rdc,assist,sales")]
+        public async Task<IActionResult> GetInfos(JsonElement jsonElement)
+        {
+            jsonElement.TryGetProperty("id", out JsonElement id);
+
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            List<BINotice> bINotices = new();
+            StringBuilder sql = new("select value(c) from c");
+            if (!string.IsNullOrEmpty($"{id}"))
+                sql.Append($" where c.id='{id}'");
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<BINotice>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BINotice") }))
+            {
+                bINotices.Add(item);
+            }
+
+            return Ok(new { state = RespondCode.Ok, bINotices });
+        }
+
+
+    }
+}

+ 106 - 0
TEAMModelBI/Controllers/BICommon/BIProductUseRecordController.cs

@@ -0,0 +1,106 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using System.Net.Http;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK;
+using TEAMModelOS.Models;
+using Microsoft.Extensions.Options;
+using System.Text.Json;
+using TEAMModelOS.SDK.Context.Constant;
+using System.Threading.Tasks;
+using System;
+using TEAMModelOS.SDK.Models.Cosmos.BI.BICommon;
+using Azure.Cosmos;
+using TEAMModelOS.SDK.Extension;
+using System.Collections.Generic;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
+using System.Linq;
+
+namespace TEAMModelBI.Controllers.BICommon
+{
+    [Route("poduct")]
+    [ApiController]
+    public class BIProductUseRecordController : ControllerBase
+    {
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly IConfiguration _configuration;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly IHttpClientFactory _http;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly IWebHostEnvironment _environment; //读取文件
+        private readonly HttpClient _httpClient;
+
+        public BIProductUseRecordController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment, HttpClient httpClient)
+        {
+            _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _azureStorage = azureStorage;
+            _option = option?.Value;
+            _configuration = configuration;
+            _serviceBus = serviceBus;
+            _http = http;
+            _coreAPIHttpService = coreAPIHttpService;
+            _environment = hostingEnvironment;
+            _httpClient = httpClient;
+        }
+
+        /// <summary>
+        /// 查询使用情况
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-userecord")]
+        public async Task<IActionResult> GetUseRecord(JsonElement jsonElement) 
+        {
+            jsonElement.TryGetProperty("year", out JsonElement _year);
+            int year = DateTimeOffset.UtcNow.Year;
+            if (!string.IsNullOrEmpty($"{_year}")) 
+            {
+                year = _year.GetInt32();
+            }
+
+            var cosmosClient = _azureCosmos.GetCosmosClient(); 
+            ProductUseRecord productUseRecord = null;
+            UseRecord useRecord = new();
+            var resUseRecord = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync($"{year}", new PartitionKey("ProductUseRecord"));
+            if (resUseRecord.Status == 200)
+            {
+                using var fileJson = await JsonDocument.ParseAsync(resUseRecord.ContentStream);
+                productUseRecord = fileJson.ToObject<ProductUseRecord>();
+            }
+
+            if (productUseRecord != null) 
+            {
+                useRecord.hiTaHour = productUseRecord.hiTaHour;
+                useRecord.hiTeachHour = productUseRecord.hiTeachHour;
+                useRecord.hiTeachccHour = productUseRecord.hiTeachccHour;
+                useRecord.hiTaDay = BICommonWay.ManyDoubleMerge(new List<List<double>>() { productUseRecord.hiTaDay });
+                useRecord.hiTeachDay = BICommonWay.ManyDoubleMerge(new List<List<double>>() { productUseRecord.hiTeachccHour });
+                useRecord.hiTeachccDay = BICommonWay.ManyDoubleMerge(new List<List<double>>() { productUseRecord.hiTeachccDay });
+            }
+
+            return Ok(new { state = RespondCode.Ok, useRecord });
+        }
+
+        /// <summary>
+        /// 使用信息
+        /// </summary>
+        public record UseRecord 
+        {
+            public List<double> hiTaHour { get; set; }
+            public List<double> hiTeachHour { get; set; }
+            public List<double> hiTeachccHour { get; set; }
+            public List<double> hiTaDay { get; set; }
+            public List<double> hiTeachDay { get; set; }
+            public List<double> hiTeachccDay { get; set; }
+        }
+
+    }
+}

+ 100 - 0
TEAMModelBI/Controllers/BICommon/StatsNoticeController.cs

@@ -0,0 +1,100 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using System.Net.Http;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK;
+using TEAMModelOS.Models;
+using Microsoft.Extensions.Options;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Context.Constant;
+using System;
+using Azure.Cosmos;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.BI.BICommon;
+using System.Collections.Generic;
+using System.Text;
+using DocumentFormat.OpenXml.Office2010.Excel;
+
+namespace TEAMModelBI.Controllers.BICommon
+{
+    [Route("statsnotice")]
+    [ApiController]
+    public class StatsNoticeController : ControllerBase
+    {
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly IConfiguration _configuration;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly IHttpClientFactory _http;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly IWebHostEnvironment _environment; //读取文件
+        private readonly HttpClient _httpClient;
+
+        public StatsNoticeController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment, HttpClient httpClient)
+        {
+            _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _azureStorage = azureStorage;
+            _option = option?.Value;
+            _configuration = configuration;
+            _serviceBus = serviceBus;
+            _http = http;
+            _coreAPIHttpService = coreAPIHttpService;
+            _environment = hostingEnvironment;
+            _httpClient = httpClient;
+        }
+
+        /// <summary>
+        /// 获取统计通知
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-infos")]
+        public async Task<IActionResult> GetInfos(JsonElement jsonElement)
+        {
+            try
+            {
+                jsonElement.TryGetProperty("dateTime", out JsonElement dateTime);
+                jsonElement.TryGetProperty("id", out JsonElement id);
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+
+                string dt = "";
+                if (string.IsNullOrEmpty($"{dateTime}"))
+                {
+                    dt = DateTimeOffset.UtcNow.ToString("yyyyMMdd");
+                }
+                else
+                {
+                    dt = $"{dateTime}";
+                }
+
+                StringBuilder sqlTxt = new($"select value(c) from c where c.day='{dt}'");
+                if (!string.IsNullOrEmpty($"{id}"))
+                {
+                    sqlTxt.Append($" and c.rangeId = '{id}'");
+                }
+                List<StatsNotice> statsNotices = new();
+
+                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<StatsNotice>(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("StatsNotice") }))
+                {
+                    statsNotices.Add(item);
+                }
+
+                return Ok(new { state = RespondCode.Ok, statsNotices });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location},/statsnotice/get-infos  \n{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
+
+    }
+}

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

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

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

@@ -19,6 +19,7 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
 using TEAMModelOS.SDK.Models.Table;
 
 namespace TEAMModelBI.Controllers.BIHome
@@ -356,6 +357,11 @@ namespace TEAMModelBI.Controllers.BIHome
                         int tempDay = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? tempDay = 29 : tempDay = 28;
                         timeDay = new DateTime(year, i, tempDay, 0, 0, 0);
                     }
+                    else
+                    {
+                        timeDay = new DateTime(year, i, 1, 0, 0, 0);
+                    }
+
                     var (monthS, monthE) = TimeHelper.GetStartOrEnd(timeDay, "month");   //本月开始/结束时间
 
                     var openLesn = allLess.Where(item => item.startTime >= monthS && item.startTime <= monthE && item.upload == 0).ToList();

+ 10 - 20
TEAMModelBI/Controllers/BINormal/AreaRelevantController.cs

@@ -21,8 +21,7 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
-using Top.Api;
-using static TEAMModelBI.Controllers.BITest.TestController;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.BINormal
 {
@@ -38,8 +37,9 @@ namespace TEAMModelBI.Controllers.BINormal
         private readonly Option _option;
         private readonly IConfiguration _configuration;
         private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly HttpTrigger _httpTrigger;
 
-        public AreaRelevantController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService)
+        public AreaRelevantController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, HttpTrigger httpTrigger)
         {
             _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
@@ -47,6 +47,7 @@ namespace TEAMModelBI.Controllers.BINormal
             _option = option?.Value;
             _configuration = configuration;
             _coreAPIHttpService = coreAPIHttpService;
+            _httpTrigger = httpTrigger;
         }
 
         /// <summary>
@@ -207,6 +208,10 @@ namespace TEAMModelBI.Controllers.BINormal
                 }
                 School school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(tempSchool, tempSchool.id, new PartitionKey("Base"));
 
+                //创建/修改学校信息中间件
+                //_ = _httpTrigger.RequestHttpTrigger(new { school = $"{school}" }, _option.Location, "set-sc-birelation");
+                await BIStats.SetSchoolBIRelation(cosmosClient, blobClient, tableClient, _dingDing, school);
+
                 //保存操作记录
                 await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "school-update", $"{_tmdName}【{_tmdId}】已操作学校(ID:{schoolId})移除已区域(ID:{areaId})", _dingDing, httpContext: HttpContext);
                 return Ok(new { state = 200, school });
@@ -253,7 +258,7 @@ namespace TEAMModelBI.Controllers.BINormal
             List<SimpleInfo> errorSc = new();
             StringBuilder strMsg = new($"{_tmdName}【{_tmdId}】账户将{tmdName}【{tmdId}】");
 
-            Teacher teacher = null;
+            Teacher teacher = new();
             var response = await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync($"{tmdId}", new PartitionKey($"Base"));
             if (response.Status == 200)
             {
@@ -317,7 +322,7 @@ namespace TEAMModelBI.Controllers.BINormal
                                     {
                                         id = $"{tmdId}",
                                         code = $"Teacher-{item.id}",
-                                        roles = new List<string> { "admin", "teacher" },
+                                        roles = new List<string> { "admin" },
                                         job = "管理员",
                                         name = $"{tmdName}",
                                         picture = string.IsNullOrEmpty($"{item.picture}") ? "" : $"{item.picture}",
@@ -561,20 +566,6 @@ namespace TEAMModelBI.Controllers.BINormal
 
         }
 
-        public record AreaAssist
-        {
-            public string userId { get; set; }
-            public string unionId { get; set; }
-            public string name { get; set; }
-            public string mobile { get; set; }
-            public string avatar { get; set; }
-            public string tmdId { get; set; }
-            public string tmdName { get; set; }
-            public string tmdMobile { get; set; }
-            public string picture { get; set; }
-            public string roles { get; set; }
-            public string schoolIds { get; set; }
-        }
 
         /// <summary>
         /// 通过区域ID查询学校前端暂时
@@ -612,6 +603,5 @@ namespace TEAMModelBI.Controllers.BINormal
             public List<SchoolTeacherRoles> assists { get; set; } = new List<SchoolTeacherRoles>();
             public List<SchoolTeacherRoles> scAdmin { get; set; } = new List<SchoolTeacherRoles>();
         }
-
     }
 }

+ 25 - 60
TEAMModelBI/Controllers/BINormal/BatchAreaController.cs

@@ -27,13 +27,13 @@ using System.Net.Http.Json;
 using System.Net;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Context.BI;
-using TEAMModelOS.SDK.DI.CoreAPI;
 using System.Text;
 using DocumentFormat.OpenXml.Bibliography;
 using Microsoft.Extensions.Hosting;
 using Microsoft.AspNetCore.Hosting;
-using static TEAMModelBI.Controllers.RepairApi.InitialAreaController;
 using TEAMModelOS.SDK.Context.Constant;
+using TEAMModelOS.SDK.Models.Service.BI;
+using TEAMModelBI.Models;
 
 namespace TEAMModelBI.Controllers.BINormal
 {
@@ -46,20 +46,18 @@ namespace TEAMModelBI.Controllers.BINormal
         private readonly Option _option;
         private readonly AzureStorageFactory _azureStorage;
         private readonly IConfiguration _configuration;
-        private readonly NotificationService _notificationService;
         private readonly AzureServiceBusFactory _serviceBus;
         private readonly IHttpClientFactory _http;
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IWebHostEnvironment _environment; //读取文件
 
-        public BatchAreaController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService, AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment) 
+        public BatchAreaController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration,   AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment) 
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
             _azureStorage = azureStorage;
             _option = option?.Value;
             _configuration = configuration;
-            _notificationService = notificationService;
             _serviceBus = serviceBus;
             _http = http;
             _coreAPIHttpService = coreAPIHttpService;
@@ -78,6 +76,7 @@ namespace TEAMModelBI.Controllers.BINormal
             {
                 jsonElement.TryGetProperty("id", out JsonElement id);
                 jsonElement.TryGetProperty("name", out JsonElement name);
+                jsonElement.TryGetProperty("tmdId", out JsonElement tmdId);
                 //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
 
                 int? pageSize = 100;      //默认不指定返回大小        
@@ -116,6 +115,22 @@ namespace TEAMModelBI.Controllers.BINormal
 
                 if (string.IsNullOrEmpty($"{id}") && !string.IsNullOrEmpty($"{name}"))
                     areaSql.Append($" where Contains(c.name,'{name}')");
+               
+                if (!string.IsNullOrEmpty($"{tmdId}"))
+                {
+                    List<string> schoolIds = new();
+                    schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", roles: "assist", isMany: true);
+                    if (schoolIds.Count > 0)
+                    {
+                        string scsSql = BICommonWay.ManyScSql("c.id", schoolIds);
+                        StringBuilder scAreaIdSql = new($"select distinct value(c.areaId) from c where c.pk='School'");
+                        scAreaIdSql.Append($" and {scsSql} and (c.areaId!='' or c.areaId!='' or IS_DEFINED(c.areaId) = false)");
+
+                        List<string> areaIds = await CommonFind.GetValueSingle(cosmosClient, "School", scAreaIdSql.ToString(), "Base");
+                        if (areaIds.Count > 0)
+                            areaSql.Append(BICommonWay.ManyScSql(" where c.id", areaIds));
+                    }
+                }
 
                 await foreach (var itemArea in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryStreamIterator(queryText: areaSql.ToString(), continuationToken: pageToken, requestOptions: new QueryRequestOptions() { MaxItemCount = pageSize, PartitionKey = new PartitionKey("Base-Area") })) 
                 {
@@ -591,25 +606,10 @@ namespace TEAMModelBI.Controllers.BINormal
                 {
                     return Ok(new { state = 201, msg = "能力点复制成功,复制能力点的文件失败," });
                 }
+ 
 
-                //发送消息实体
-                Notification notification = new Notification
-                {
-                    hubName = "hita",
-                    type = "msg",
-                    from = $"BI:{_option.Location}:private",
-                    to = new List<string> { $"{ _tmdId}" },
-                    label = $"{partitionCode}_start",
-                    body = new { location = _option.Location, biz = partitionCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
-                    expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
-                };
-
-                var notiUrl = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
-                var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
-                var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
-                var location = _option.Location;
-                await _notificationService.SendNotification(clientID, clientSecret, location, notiUrl, notification); //站内发送消息
-
+            
+              
                 //保存操作记录
                 //await _azureStorage.SaveBILog("area-add", $"{_tmdName}【{_tmdId}】已操作创区功能模块:{name},当前标准【{standard}】,复制的微能力点:{tempStandard}", _dingDing, httpContext: HttpContext);
                 await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "area-add", $"{_tmdName}【{_tmdId}】已操作创区功能模块:{name},当前标准【{standard}】,复制的微能力点:{tempStandard}", _dingDing, httpContext: HttpContext);
@@ -862,24 +862,7 @@ namespace TEAMModelBI.Controllers.BINormal
                     return Ok(new { state = 201 ,msg = "能力点复制成功,复制能力点的文件失败," });
                 }
 
-                //发送消息实体
-                Notification notification = new()
-                {
-                    hubName = "hita",
-                    type = "msg",
-                    from = $"BI:{_option.Location}:private",
-                    to = new List<string> { $"{ _tmdId}" },
-                    label = $"{partitionCode}_start",
-                    body = new { location = _option.Location, biz = partitionCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
-                    expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
-                };
-
-                var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
-                var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
-                var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
-                var location = _option.Location;
-                await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //发送站内发送消息
-
+              
                 //保存操作记录
                 await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "area-cut", $"{_tmdName}【{_tmdId}】已操作【{_oldStandard}】切换至{_newStandard}微能力点,复制标准:{_newStandard}", _dingDing, httpContext: HttpContext);
                 return Ok(new { state = 200 });
@@ -938,7 +921,7 @@ namespace TEAMModelBI.Controllers.BINormal
                         await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(item, item.id, new PartitionKey("Base"));
                     }
 
-                    List<string> scIds = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.areaId='{area.id}' and c.standard ='{area.standard}'", "Base");
+                    List<string> scIds = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.areaId='{area.id}' and c.standard ='{area.standard}'", "Base");
 
                     foreach (var item in scIds)
                     {
@@ -1212,24 +1195,6 @@ namespace TEAMModelBI.Controllers.BINormal
                         {
                             return Ok(new { state = 201, msg = "能力点复制成功,复制能力点的文件失败," });
                         }
-
-                        //发送消息实体
-                        Notification notification = new()
-                        {
-                            hubName = "hita",
-                            type = "msg",
-                            from = $"BI:{_option.Location}:private",
-                            to = new List<string> { $"{_tmdId}" },
-                            label = $"{partitionCode}_start",
-                            body = new { location = _option.Location, biz = partitionCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
-                            expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
-                        };
-
-                        var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
-                        var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
-                        var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
-                        var location = _option.Location;
-                        await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //发送站内发送消息
                     }
 
                     StandardFile saveFile = new();

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

@@ -65,7 +65,7 @@ namespace TEAMModelBI.Controllers.BINormal
                 bizConfig.code = "BizConfig";
                 bizConfig.pk = "BizConfig";
                 bizConfig.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-                var auth_token = JwtAuthExtension.CreateBusinessApiToken(_option.Location, bizConfig.id, _option.JwtSecretKey);
+                var auth_token = JwtAuthExtension.CreateBusinessApiToken(_option.Location, bizConfig.id, _option.JwtSecretKey, bizConfig.isCustomize);
                 bizConfig.jti = auth_token.jti;
                 bizConfig.token = auth_token.jwt;
 
@@ -188,7 +188,7 @@ namespace TEAMModelBI.Controllers.BINormal
             {
                 using var json = await JsonDocument.ParseAsync(response.ContentStream);
                 bizConfig = json.ToObject<BizConfig>();
-                var auth_token = JwtAuthExtension.CreateBusinessApiToken(_option.Location, bizConfig.id, _option.JwtSecretKey);
+                var auth_token = JwtAuthExtension.CreateBusinessApiToken(_option.Location, bizConfig.id, _option.JwtSecretKey, bizConfig.isCustomize);
                 bizConfig.jti = auth_token.jti;
                 bizConfig.token = auth_token.jwt;
 

+ 101 - 32
TEAMModelBI/Controllers/BINormal/BusinessUsersController.cs

@@ -1,16 +1,19 @@
 using Azure.Cosmos;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Options;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Reflection;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelBI.Filter;
 using TEAMModelBI.Tool.Extension;
 using TEAMModelOS.Models;
+using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Context.BI;
 using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.DI;
@@ -27,12 +30,17 @@ namespace TEAMModelBI.Controllers.BINormal
         public readonly AzureStorageFactory _azureStorage;
         public readonly DingDing _dingDing;
         public readonly Option _option;
-        public BusinessUsersController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option)
+        //读取配置信息
+        private readonly IConfiguration _configuration;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        public BusinessUsersController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService)
         {
             _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
             _dingDing = dingDing;
             _option = option?.Value;
+            _configuration = configuration;
+            _coreAPIHttpService = coreAPIHttpService;
         }
 
         /// <summary>
@@ -55,8 +63,8 @@ namespace TEAMModelBI.Controllers.BINormal
                 sqlTxt.Append($" where c.id='{id}'");
             }
 
-            List<BusinessUsers> bizUsers = new();
-            await foreach (var items in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BusinessUsers>(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
+            List<BizUsers> bizUsers = new();
+            await foreach (var items in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BizUsers>(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
             {
                 bizUsers.Add(items);
             }
@@ -90,7 +98,6 @@ namespace TEAMModelBI.Controllers.BINormal
             string type = "";
             if (string.IsNullOrEmpty(bizUsers.id))
             {
-
                 bizUsers.id = Guid.NewGuid().ToString();
                 bizUsers.code = "BizUsers";
                 bizUsers.name = string.IsNullOrEmpty(bizUsers.name)? bizUsers.mobile.ToString(): bizUsers.name;
@@ -129,6 +136,35 @@ namespace TEAMModelBI.Controllers.BINormal
             return Ok(new { state = RespondCode.Ok, bizUsers });
         }
 
+        /// <summary>
+        /// 通过手机号查询信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [AuthToken(Roles = "admin,rdc,assist")]
+        [HttpPost("get-mobileuser")]
+        public async Task<IActionResult> GetMobileUser(JsonElement jsonElement)
+        {
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            if (!jsonElement.TryGetProperty("mobile", out JsonElement mobile)) return BadRequest();
+
+            string sql = $"select value(c) from c where c.mobile ={mobile}";
+
+            List<BizUsers> bizUsers = new();
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS,"Normal").GetItemQueryIterator<BizUsers>(queryText:sql,requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
+            {
+                bizUsers.Add(item);
+            }
+            CoreUser coreUser = null;
+            if (bizUsers.Count <= 0)
+            {
+                coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{mobile}" } }, _option.Location, _configuration);
+            }
+
+            return Ok(new { state = RespondCode.Ok, bizUsers, coreUser });
+        }
+
         /// <summary>
         /// 重置密码
         /// </summary>
@@ -183,14 +219,14 @@ namespace TEAMModelBI.Controllers.BINormal
         [HttpPost("rel-biz")]
         public async Task<ActionResult> RelationBusiness(JsonElement jsonElement) 
         {
-            if(!jsonElement.TryGetProperty("id", out JsonElement id)) return BadRequest();
+            if(!jsonElement.TryGetProperty("id", out JsonElement _id)) return BadRequest();
             if (!jsonElement.TryGetProperty("bizs", out JsonElement _bizs)) return BadRequest();
             if (!jsonElement.TryGetProperty("type", out JsonElement type)) return BadRequest();
+            jsonElement.TryGetProperty("userType", out JsonElement _userType);
             //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
             var (tmdId, tmdName, pic, _, _, _) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
 
             List<BizRel> bizRels = _bizs.ToObject<List<BizRel>>();
-
             var cosmosClient = _azureCosmos.GetCosmosClient();
             var tableClient = _azureStorage.GetCloudTableClient();
             var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
@@ -201,8 +237,37 @@ namespace TEAMModelBI.Controllers.BINormal
             //    tableClient = _azureStorage.GetCloudTableClient(BIConst.Global);
             //    blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public", BIConst.Global);
             //}
-
+            string id = $"{_id}";
+            string userType = "default";
+            if (!string.IsNullOrWhiteSpace($"{_userType}")) 
+            {
+                userType = $"{_userType}";
+            }
+            
             StringBuilder strMsg = new($"{tmdName}[{tmdId}]给");
+            BizUsers bizUsers = new();
+            List<BizRel> noBizRel = new();
+
+            if ($"{userType}".Equals("tmdId"))
+            {
+                var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{id}" } }, _option.Location, _configuration);
+                string salt = Utils.CreatSaltString(8);
+                bizUsers = new()
+                {
+                    id = Guid.NewGuid().ToString(),
+                    mobile = long.Parse($"{coreUser.mobile}"),
+                    name = coreUser.name,
+                    tmdId = coreUser.id,
+                    picture = coreUser.picture,
+                    mail = coreUser.mail,
+                    code = "BizUsers",
+                    salt = salt,
+                    pwd = string.IsNullOrEmpty(bizUsers.pwd) ? Utils.HashedPassword(bizUsers.mobile.ToString(), salt) : Utils.HashedPassword(bizUsers.pwd, salt),
+                };
+
+                id = bizUsers.id;
+            }
+
             if ($"{type}".Equals("add"))
             {
                 strMsg.Append($"用户【{id}】关联企业信息:添加企业:");
@@ -213,42 +278,46 @@ namespace TEAMModelBI.Controllers.BINormal
             }
             else { return Ok(new { state = RespondCode.ParamsError, msg = "类型错误" }); }
 
-            List<BizRel> noBizRel = new();
-            BizUsers bizUsers = new();
-
             var response = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"{id}", new PartitionKey("BizUsers"));
             if (response.Status == RespondCode.Ok)
             {
                 using var json = await JsonDocument.ParseAsync(response.ContentStream);
                 bizUsers = json.ToObject<BizUsers>();
-                foreach (var item in bizRels)
+            }
+
+            foreach (var item in bizRels)
+            {
+                var temp = bizUsers.relation.Find(f => f.bizId == item.bizId);
+                if ($"{type}".Equals("add"))
                 {
-                    var temp = bizUsers.relation.Find(f => f.bizId == item.bizId);
-                    if ($"{type}".Equals("add"))
+                    if (temp != null)
+                        noBizRel.Add(item);
+                    else
                     {
-                        if (temp != null)
-                            noBizRel.Add(item);
-                        else
-                        {
-                            bizUsers.relation.Add(item);
-                            strMsg.Append($"{item.name}[{item.bizId}]|");
-                        }
+                        bizUsers.relation.Add(item);
+                        strMsg.Append($"{item.name}[{item.bizId}]|");
                     }
-                    else if ($"{type}".Equals("del"))
+                }
+                else if ($"{type}".Equals("del"))
+                {
+                    if (temp != null)
                     {
-                        if (temp != null)
-                        {
-                            bizUsers.relation.Add(item);
-                            strMsg.Append($"{item.name}[{item.bizId}]|");
-                        }
-                        else
-                            noBizRel.Add(item);
+                        bizUsers.relation.Remove(temp);
+                        strMsg.Append($"{item.name}[{item.bizId}]|");
                     }
+                    else
+                        noBizRel.Add(item);
                 }
+            }
 
+            if (response.Status == RespondCode.Ok) 
+            {
                 bizUsers = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<BizUsers>(bizUsers, bizUsers.id, new PartitionKey("BizUsers"));
             }
-            else return Ok(new { state = RespondCode.NotFound, msg = "未找到该用户" });
+            else
+            {
+                bizUsers = await cosmosClient.GetContainer("TEAMModelOS", "Normal").CreateItemAsync<BizUsers>(bizUsers, new PartitionKey("BizUsers"));
+            }
 
             //保存操作记录
             await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "bizconfig-addSchool", strMsg.ToString(), _dingDing, httpContext: HttpContext);
@@ -274,9 +343,9 @@ namespace TEAMModelBI.Controllers.BINormal
             //if ($"{site}".Equals(BIConst.Global))
             //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
 
-            List<BusinessUsers> businessUsers = new();
-            string sql = $"select value(c) from c join s in c.relation  where c.code='BizUsers' and s.bizId = '80e1bb6c-acba-46ab-9939-4851c4ef2158'";
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BusinessUsers>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
+            List<BizUsers> businessUsers = new();
+            string sql = $"select value(c) from c join s in c.relation  where c.code='BizUsers' and s.bizId = '{id}'";
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BizUsers>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
             {
                 businessUsers.Add(item);
             }

+ 323 - 164
TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs

@@ -37,6 +37,8 @@ using DocumentFormat.OpenXml.Wordprocessing;
 using DocumentFormat.OpenXml.Bibliography;
 using HTEXLib;
 using TEAMModelOS.SDK.Models.Service.BI;
+using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
+using DocumentFormat.OpenXml.Vml.Office;
 
 namespace TEAMModelBI.Controllers.BISchool
 {
@@ -53,8 +55,9 @@ namespace TEAMModelBI.Controllers.BISchool
         //读取配置信息
         private readonly IConfiguration _configuration;
         private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly HttpTrigger _httpTrigger;
 
-        public BatchSchoolController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IWebHostEnvironment hostingEnvironment, IConfiguration configuration, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService)
+        public BatchSchoolController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IWebHostEnvironment hostingEnvironment, IConfiguration configuration, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, HttpTrigger httpTrigger)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
@@ -64,6 +67,7 @@ namespace TEAMModelBI.Controllers.BISchool
             _configuration = configuration;
             _http = http;
             _coreAPIHttpService = coreAPIHttpService;
+            _httpTrigger = httpTrigger;
         }
 
         /// <summary>
@@ -185,7 +189,7 @@ namespace TEAMModelBI.Controllers.BISchool
                             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();
@@ -211,6 +215,8 @@ namespace TEAMModelBI.Controllers.BISchool
                                 schoolCode = createSchoolInfo.id,
                                 period = PresetSchoolPeriod(bischool.period, foundSchools.lang, campusId),
                                 scale = bischool.size >= 300 ? 500 : 0,
+                                isinit = true,
+                                openLessonRecord = (_option.Location.Contains("Global")) ? false : true,
                                 createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
                             };
                             scInfos.Add(createSchoolInfo);
@@ -218,9 +224,16 @@ namespace TEAMModelBI.Controllers.BISchool
                             stringBuilder.Append($"创建学校:{upSchool.name}【{upSchool.id}】");
                             noticeDD.Append($"{upSchool.name}【{upSchool.id}】 \r 学校管理员信息:");
                             upSc.Add(upSchool.id);
+
                             //创建学校
                             await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<School>(upSchool, new PartitionKey(upSchool.code));
-                            
+                            //创建学校信息中间件
+                            //_ = _httpTrigger.RequestHttpTrigger(new { school = $"{upSchool}" }, _option.Location, "set-sc-birelation");
+                            await BIStats.SetSchoolBIRelation(cosmosClient, blobClient, tableClient, _dingDing, upSchool);
+
+                            //创建BI和统计信息
+                            await BIStats.SetScStatsInfo(cosmosClient, _dingDing,upSchool);
+
                             var content = new StringContent(bischool.admin.ToArray().ToJsonString(), Encoding.UTF8, "application/json");
                             string json = await _coreAPIHttpService.GetUserInfos(content);
                             List<TmdUserinfo> tmdInfos = json.ToObject<List<TmdUserinfo>>();
@@ -235,7 +248,7 @@ namespace TEAMModelBI.Controllers.BISchool
                                     teacher = tchJson.ToObject<Teacher>();
                                     Teacher.TeacherSchool tchSc = null;
                                     //var tempTch = teacher.schools.Select(x => x.schoolId.Equals(upSchool.id)).ToString();
-                                    tchSc = teacher.schools.Find(x => x.schoolId.Equals(upSchool.id));                                
+                                    tchSc = teacher.schools.Find(x => x.schoolId.Equals(upSchool.id));
                                     if (tchSc == null)
                                     {
                                         //教师存在,在该教师信息中添加要管理的学校信息
@@ -247,7 +260,7 @@ namespace TEAMModelBI.Controllers.BISchool
                                     {
                                         id = tmdIndo.id,
                                         code = $"Teacher-{createSchoolInfo.id}",
-                                        roles = new List<string> { "admin" },
+                                        roles = new List<string> { "admin", "teacher" },
                                         job = "管理员",
                                         name = teacher.name,
                                         picture = teacher.picture,
@@ -285,7 +298,7 @@ namespace TEAMModelBI.Controllers.BISchool
                                     {
                                         id = tmdIndo.id,
                                         code = $"Teacher-{createSchoolInfo.id}",
-                                        roles = new List<string> { "admin" },
+                                        roles = new List<string> { "admin", "teacher" },
                                         job = "管理员",
                                         name = $"{tmdIndo.name}",
                                         picture = "",
@@ -295,7 +308,7 @@ namespace TEAMModelBI.Controllers.BISchool
                                         ttl = -1
                                     };
 
-                                    stringBuilder.Append($"权限:{string.Join(",", schoolTeacher.roles)}】"); 
+                                    stringBuilder.Append($"权限:{string.Join(",", schoolTeacher.roles)}】");
                                     noticeDD.Append($"{schoolTeacher.name}【{schoolTeacher.id}】");
                                     await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<SchoolTeacher>(schoolTeacher, new PartitionKey(schoolTeacher.code));
                                 }
@@ -476,9 +489,10 @@ namespace TEAMModelBI.Controllers.BISchool
 
                 if (upSc.Count > 1)
                     await _dingDing.SendBotMsg($"BI,{_option.Location} \n 批量建校信息:{noticeDD}", GroupNames.成都开发測試群組);
-                else if(upSc.Count == 1)
+                else if (upSc.Count == 1)
                     await _dingDing.SendBotMsg($"BI,{_option.Location} \n 单个建校信息:{noticeDD}", GroupNames.成都开发測試群組);
 
+
                 ////v2通知
                 //Teacher targetTeacher = await cosmosClient.GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>($"{_tmdId}", new PartitionKey($"Base"));
                 //_coreAPIHttpService.PushNotify(new List<IdNameCode> { new IdNameCode { id = targetTeacher.id, name = targetTeacher.name, code = targetTeacher.lang } }, "create-school", Constant.NotifyType_IES5_Management, new Dictionary<string, object> { { "tmdname", $"{_tmdName}" }, { "schooName", $"{vsSql}" } }, _option.Location, _configuration, _dingDing, _environment.ContentRootPath);
@@ -514,6 +528,7 @@ namespace TEAMModelBI.Controllers.BISchool
             try
             {
                 jsonElement.TryGetProperty("tmdId", out JsonElement tmdId);
+                jsonElement.TryGetProperty("role", out JsonElement role);
                 jsonElement.TryGetProperty("scId", out JsonElement scId);
                 jsonElement.TryGetProperty("name", out JsonElement name);
                 jsonElement.TryGetProperty("order", out JsonElement order);
@@ -548,15 +563,41 @@ namespace TEAMModelBI.Controllers.BISchool
                 if (jsonElement.TryGetProperty("contToken", out JsonElement ContToken))
                     pageToken = ContToken.GetString();
 
+                if (!string.IsNullOrEmpty($"{scId}") && string.IsNullOrEmpty($"{name}"))
+                {
+                    stringBuilder.Append($" where c.id='{scId}'");
+                    scCntSql.Append($" where c.id='{scId}'");
+                }
+                if (string.IsNullOrEmpty($"{scId}") && !string.IsNullOrEmpty($"{name}"))
+                {
+                    stringBuilder.Append($" where Contains(c.name,'{name}')");
+                    scCntSql.Append($" where Contains(c.name,'{name}')");
+                }
+                if (!string.IsNullOrEmpty($"{province}") && string.IsNullOrEmpty($"{city}") && string.IsNullOrEmpty($"{dist}"))
+                {
+                    stringBuilder.Append($" where Contains(c.province,'{province}')");
+                    scCntSql.Append($" where  Contains(c.province,'{province}')");
+                }
+                if (!string.IsNullOrEmpty($"{city}") && !string.IsNullOrEmpty($"{city}") && string.IsNullOrEmpty($"{dist}"))
+                {
+                    stringBuilder.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}')");
+                    scCntSql.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}')");
+                }
+                if (!string.IsNullOrEmpty($"{dist}") && !string.IsNullOrEmpty($"{city}") && !string.IsNullOrEmpty($"{dist}"))
+                {
+                    stringBuilder.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}') and Contains(c.dist,'{dist}')");
+                    scCntSql.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}') and Contains(c.dist,'{dist}')");
+                }
+
+                if ($"{order}".Equals("desc"))
+                    stringBuilder.Append(" order by c.createTime desc");
+
                 if (!string.IsNullOrEmpty($"{tmdId}"))
                 {
-                    schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
+                    schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", roles: !string.IsNullOrEmpty($"{role}") ? $"{role}" : "assist", isMany: true);
                     string scsSql = BICommonWay.ManyScSql("c.id", schoolIds);
                     scCntSql.Append($" where {scsSql}");
-                }
 
-                if (schoolIds.Count > 0)
-                {
                     scCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", scCntSql.ToString(), "Base");
                     foreach (var id in schoolIds)
                     {
@@ -564,6 +605,8 @@ namespace TEAMModelBI.Controllers.BISchool
 
                         if ($"{order}".Equals("desc"))
                             sqlTxt.Append(" order by c.createTime desc");
+                        else
+                            sqlTxt.Append(" order by c.createTime asc");
 
                         await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<AssistSchool>(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
                         {
@@ -573,35 +616,6 @@ namespace TEAMModelBI.Controllers.BISchool
                 }
                 else
                 {
-                    if (!string.IsNullOrEmpty($"{scId}") && string.IsNullOrEmpty($"{name}"))
-                    {
-                        stringBuilder.Append($" where c.id='{scId}'");
-                        scCntSql.Append($" where c.id='{scId}'");
-                    }
-                    if (string.IsNullOrEmpty($"{scId}") && !string.IsNullOrEmpty($"{name}"))
-                    {
-                        stringBuilder.Append($" where Contains(c.name,'{name}')");
-                        scCntSql.Append($" where Contains(c.name,'{name}')");
-                    }
-                    if (!string.IsNullOrEmpty($"{province}") && string.IsNullOrEmpty($"{city}") && string.IsNullOrEmpty($"{dist}"))
-                    {
-                        stringBuilder.Append($" where Contains(c.province,'{province}')");
-                        scCntSql.Append($" where  Contains(c.province,'{province}')");
-                    }
-                    if (!string.IsNullOrEmpty($"{city}") && !string.IsNullOrEmpty($"{city}") && string.IsNullOrEmpty($"{dist}")) 
-                    {
-                        stringBuilder.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}')");
-                        scCntSql.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}')");
-                    }
-                    if (!string.IsNullOrEmpty($"{dist}") && !string.IsNullOrEmpty($"{city}") && !string.IsNullOrEmpty($"{dist}"))
-                    {
-                        stringBuilder.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}') and Contains(c.dist,'{dist}')");
-                        scCntSql.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}') and Contains(c.dist,'{dist}')");
-                    }
-
-                    if ($"{order}".Equals("desc"))
-                        stringBuilder.Append(" order by c.createTime desc");
-
                     scCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", scCntSql.ToString(), "Base");
 
                     await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: stringBuilder.ToString(), continuationToken: pageToken, requestOptions: new QueryRequestOptions() { MaxItemCount = pageSize, PartitionKey = new PartitionKey("Base") }))
@@ -622,6 +636,73 @@ namespace TEAMModelBI.Controllers.BISchool
                     }
                 }
 
+                //if (schoolIds.Count > 0)
+                //{
+                //    scCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", scCntSql.ToString(), "Base");
+                //    foreach (var id in schoolIds)
+                //    {
+                //        StringBuilder sqlTxt = new($"select c.id,c.code,c.schoolCode,c.name,c.region,c.province,c.city,c.dist,c.size,c.address,c.picture,c.type,c.scale,c.areaId,c.standard from c where c.id='{id}'");
+
+                //        if ($"{order}".Equals("desc"))
+                //            sqlTxt.Append(" order by c.createTime desc");
+
+                //        await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<AssistSchool>(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                //        {
+                //            schoolAssists.Add(itemSchool);
+                //        }
+                //    }
+                //}
+                //else
+                //{
+                //    if (!string.IsNullOrEmpty($"{scId}") && string.IsNullOrEmpty($"{name}"))
+                //    {
+                //        stringBuilder.Append($" where c.id='{scId}'");
+                //        scCntSql.Append($" where c.id='{scId}'");
+                //    }
+                //    if (string.IsNullOrEmpty($"{scId}") && !string.IsNullOrEmpty($"{name}"))
+                //    {
+                //        stringBuilder.Append($" where Contains(c.name,'{name}')");
+                //        scCntSql.Append($" where Contains(c.name,'{name}')");
+                //    }
+                //    if (!string.IsNullOrEmpty($"{province}") && string.IsNullOrEmpty($"{city}") && string.IsNullOrEmpty($"{dist}"))
+                //    {
+                //        stringBuilder.Append($" where Contains(c.province,'{province}')");
+                //        scCntSql.Append($" where  Contains(c.province,'{province}')");
+                //    }
+                //    if (!string.IsNullOrEmpty($"{city}") && !string.IsNullOrEmpty($"{city}") && string.IsNullOrEmpty($"{dist}")) 
+                //    {
+                //        stringBuilder.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}')");
+                //        scCntSql.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}')");
+                //    }
+                //    if (!string.IsNullOrEmpty($"{dist}") && !string.IsNullOrEmpty($"{city}") && !string.IsNullOrEmpty($"{dist}"))
+                //    {
+                //        stringBuilder.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}') and Contains(c.dist,'{dist}')");
+                //        scCntSql.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}') and Contains(c.dist,'{dist}')");
+                //    }
+
+                //    if ($"{order}".Equals("desc"))
+                //        stringBuilder.Append(" order by c.createTime desc");
+
+                //    scCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", scCntSql.ToString(), "Base");
+
+                //    await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: stringBuilder.ToString(), continuationToken: pageToken, requestOptions: new QueryRequestOptions() { MaxItemCount = pageSize, PartitionKey = new PartitionKey("Base") }))
+                //    {
+                //        using var json = await JsonDocument.ParseAsync(itemSchool.ContentStream);
+                //        if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetInt16() > 0)
+                //        {
+                //            foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                //            {
+                //                schoolAssists.Add(obj.ToObject<AssistSchool>());
+                //            }
+                //            if (iscontinuation)
+                //            {
+                //                continuationToken = itemSchool.GetContinuationToken();
+                //                break;
+                //            }
+                //        }
+                //    }
+                //}
+
                 foreach (var item in schoolAssists)
                 {
                     var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(item.id, new PartitionKey("ProductSum"));
@@ -637,7 +718,7 @@ namespace TEAMModelBI.Controllers.BISchool
                     }
 
                     item.assists = await CommonFind.FindSchoolRoles(cosmosClient, item.id, "assist");
-                    item.scAdmin = await CommonFind.FindSchoolRoles(cosmosClient, item.id, "admin");                    
+                    item.scAdmin = await CommonFind.FindSchoolRoles(cosmosClient, item.id, "admin");
                     item.lessonCount = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"select value(count(c.id)) from c ", $"LessonRecord-{item.id}");
                 }
 
@@ -674,6 +755,133 @@ namespace TEAMModelBI.Controllers.BISchool
             }
         }
 
+        /// <summary>
+        /// 所有信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-allscinfo")]
+        public async Task<IActionResult> GetAllScsInfo(JsonElement jsonElement)
+        {
+            try
+            {
+                jsonElement.TryGetProperty("tmdId", out JsonElement tmdId);
+                jsonElement.TryGetProperty("role", out JsonElement role);
+                jsonElement.TryGetProperty("scId", out JsonElement scId);
+                jsonElement.TryGetProperty("name", out JsonElement name);
+                jsonElement.TryGetProperty("order", out JsonElement order);
+
+                jsonElement.TryGetProperty("province", out JsonElement province);
+                jsonElement.TryGetProperty("city", out JsonElement city);
+                jsonElement.TryGetProperty("dist", out JsonElement dist);
+
+                //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                ////分开部署,就不需要,一站多用时,取消注释
+                //if ($"{site}".Equals(BIConst.Global))
+                //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
+                int scCnt = 0;
+
+                List<AssistSchool> schoolAssists = new(); //返回学校列表集合
+                List<string> schoolIds = new();
+                StringBuilder stringBuilder = new("select c.id,c.code,c.schoolCode,c.name,c.region,c.province,c.city,c.dist,c.size,c.address,c.picture,c.type,c.scale,c.areaId,c.standard from c ");
+                StringBuilder scCntSql = new($"select value(count(c.id)) from c");
+
+                if (!string.IsNullOrEmpty($"{scId}") && string.IsNullOrEmpty($"{name}"))
+                {
+                    stringBuilder.Append($" where c.id='{scId}'");
+                    scCntSql.Append($" where c.id='{scId}'");
+                }
+                if (string.IsNullOrEmpty($"{scId}") && !string.IsNullOrEmpty($"{name}"))
+                {
+                    stringBuilder.Append($" where Contains(c.name,'{name}')");
+                    scCntSql.Append($" where Contains(c.name,'{name}')");
+                }
+                if (!string.IsNullOrEmpty($"{province}") && string.IsNullOrEmpty($"{city}") && string.IsNullOrEmpty($"{dist}"))
+                {
+                    stringBuilder.Append($" where Contains(c.province,'{province}')");
+                    scCntSql.Append($" where  Contains(c.province,'{province}')");
+                }
+                if (!string.IsNullOrEmpty($"{city}") && !string.IsNullOrEmpty($"{city}") && string.IsNullOrEmpty($"{dist}"))
+                {
+                    stringBuilder.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}')");
+                    scCntSql.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}')");
+                }
+                if (!string.IsNullOrEmpty($"{dist}") && !string.IsNullOrEmpty($"{city}") && !string.IsNullOrEmpty($"{dist}"))
+                {
+                    stringBuilder.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}') and Contains(c.dist,'{dist}')");
+                    scCntSql.Append($" where Contains(c.province,'{province}') and Contains(c.city,'{city}') and Contains(c.dist,'{dist}')");
+                }
+
+                if (!string.IsNullOrEmpty($"{tmdId}"))
+                {
+                    schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", roles: !string.IsNullOrEmpty($"{role}") ? $"{role}" : "assist", isMany: true);
+                    string scsSql = BICommonWay.ManyScSql("c.id", schoolIds);
+                    scCntSql.Append($" where {scsSql}");
+
+                    scCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", scCntSql.ToString(), "Base");
+                    foreach (var id in schoolIds)
+                    {
+                        StringBuilder sqlTxt = new($"select c.id,c.code,c.schoolCode,c.name,c.region,c.province,c.city,c.dist,c.size,c.address,c.picture,c.type,c.scale,c.areaId,c.standard from c where c.id='{id}'");
+
+                        if ($"{order}".Equals("desc"))
+                            sqlTxt.Append(" order by c.createTime desc");
+
+                        await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<AssistSchool>(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                        {
+                            schoolAssists.Add(itemSchool);
+                        }
+                    }
+                }
+                else
+                {
+                    if ($"{order}".Equals("desc"))
+                        stringBuilder.Append(" order by c.createTime desc");
+
+                    scCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", scCntSql.ToString(), "Base");
+
+                    await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: stringBuilder.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                    {
+                        using var json = await JsonDocument.ParseAsync(itemSchool.ContentStream);
+                        if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetInt16() > 0)
+                        {
+                            foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                            {
+                                schoolAssists.Add(obj.ToObject<AssistSchool>());
+                            }
+                        }
+                    }
+                }
+
+                foreach (var item in schoolAssists)
+                {
+                    var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(item.id, new PartitionKey("ProductSum"));
+                    if (response.Status == 200)
+                    {
+                        using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                        if (json.RootElement.TryGetProperty("serial", out JsonElement serial) && !serial.ValueKind.Equals(JsonValueKind.Null))
+                            item.serial = serial.ToObject<List<SchoolProductSumData>>().Select(x => x.prodCode).ToList();
+                        if (json.RootElement.TryGetProperty("service", out JsonElement service) && !service.ValueKind.Equals(JsonValueKind.Null))
+                            item.service = service.ToObject<List<SchoolProductSumData>>().Select(x => x.prodCode).ToList();
+                        if (json.RootElement.TryGetProperty("hard", out JsonElement hard) && !hard.ValueKind.Equals(JsonValueKind.Null))
+                            item.hard = hard.ToObject<List<SchoolProductSumDataHard>>().Select(x => x.prodCode).ToList();
+                    }
+
+                    item.assists = await CommonFind.FindSchoolRoles(cosmosClient, item.id, "assist");
+                    item.scAdmin = await CommonFind.FindSchoolRoles(cosmosClient, item.id, "admin");
+                    item.lessonCount = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"select value(count(c.id)) from c ", $"LessonRecord-{item.id}");
+                }
+
+                return Ok(new { state = 200, scCnt, schoolAssists });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location}  /batchschool/get-allscinfo()  \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
         /// <summary>
         /// 使用yieId 关键字 本地效率未测出
         /// </summary>
@@ -829,20 +1037,18 @@ namespace TEAMModelBI.Controllers.BISchool
                 if (!jsonElement.TryGetProperty("picture", out JsonElement picture)) return BadRequest();
                 if (!jsonElement.TryGetProperty("size", out JsonElement size)) return BadRequest();
                 if (!jsonElement.TryGetProperty("scale", out JsonElement scale)) return BadRequest();
-                if (!jsonElement.TryGetProperty("assistId", out JsonElement _assistId)) return BadRequest();
                 if (!jsonElement.TryGetProperty("type", out JsonElement _type)) return BadRequest();
                 jsonElement.TryGetProperty("province", out JsonElement province);
                 jsonElement.TryGetProperty("city", out JsonElement city);
                 jsonElement.TryGetProperty("dist", out JsonElement dist);
                 jsonElement.TryGetProperty("address", out JsonElement address);
 
+                jsonElement.TryGetProperty("assist", out JsonElement assist);
+                List<IdInfo> idInfos = assist.ToObject<List<IdInfo>>();
                 //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
 
                 var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
 
-                List<string> assistId = _assistId.ToObject<List<string>>();
-                //List<string> periodS = period.ToObject<List<string>>();
-                Dictionary<string, List<Dictionary<string, string>>> haveSchoolManger = new();
                 var cosmosClient = _azureCosmos.GetCosmosClient();
                 var tableClient = _azureStorage.GetCloudTableClient();
                 var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
@@ -880,6 +1086,10 @@ namespace TEAMModelBI.Controllers.BISchool
                     //修改学校
                     await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(tempShool, tempShool.id, new PartitionKey("Base"));
 
+                    //创建学校信息中间件
+                    //_ = _httpTrigger.RequestHttpTrigger(new { school = $"{tempShool}" }, _option.Location, "set-sc-birelation");
+                    //await BIStats.SetSchoolBIRelation(cosmosClient, blobClient, tableClient, _dingDing, tempShool);
+
                     //修改学校教师关联的信息
                     string sql = $"SELECT distinct value(c) FROM c join A1 in c.schools where A1.schoolId='{tempShool.id}'";
                     List<Teacher> teachers = new();
@@ -899,114 +1109,63 @@ namespace TEAMModelBI.Controllers.BISchool
                         await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(item, item.id, new PartitionKey($"Base"));
                     }
 
-                    if (assistId.Count > 0)
+                    //需要重大修改后保留
+                    BIRelation biRel = new();
+                    var respRel = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(tempShool.id, new PartitionKey("BIRel"));
+                    if (respRel.Status == 200)
                     {
-                        //修改学校顾问
-                        string sqlTxt = $"SELECT value(c) From c WHERE ARRAY_CONTAINS(c.roles,'assist',true)";
-                        List<SchoolTeacher> schoolTeachers = new();
-                        await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<SchoolTeacher>(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{tempShool.id}") }))
-                        {
-                            if (!assistId.Contains(item.id))
-                            {
-                                if (item.roles.Contains("assist"))
-                                {
-                                    item.roles.Remove("assist");
-                                    if (item.roles.Count > 0)
-                                    {
-                                        await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(item, item.id, new PartitionKey(item.code));
-                                    }
-                                    else
-                                    {
-                                        await cosmosClient.GetContainer("TEAMModelOS", "School").DeleteItemAsync<SchoolTeacher>(item.id, new PartitionKey(item.code));
-                                    }
-                                }
-                            }
-                        }
-
-                        foreach (var itemTeacher in assistId)
-                        {
-                            Teacher tempTeacher = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>($"{itemTeacher}", new PartitionKey("Base"));
-                            if (tempTeacher != null)
-                            {
-                                var haveTeacher = tempTeacher.schools.Find(x => x.schoolId.Equals($"{_schoolId}"));
-                                if (haveTeacher == null)
-                                {
-                                    Teacher.TeacherSchool teacherSchool = new()
-                                    {
-                                        schoolId = tempShool.id,
-                                        name = tempShool.name,
-                                        status = "join",
-                                        time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
-                                        picture = tempShool.picture,
-                                        areaId = tempShool.areaId
-                                    };
-                                    tempTeacher.schools.Add(teacherSchool);
-                                    //给醍摩豆顾问添加学校
-                                    await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(tempTeacher, tempTeacher.id, new PartitionKey($"Base"));
-
-                                    ////不存在则在原来的基础上添加顾问角色
-                                    //SchoolTeacher addSchoolTeacher = new()
-                                    //{
-                                    //    id = itemTeacher,
-                                    //    code = $"Teacher-{tempShool.id}",
-                                    //    pk = "Teacher",
-                                    //    status = "join",
-                                    //    roles = new List<string>() { "assist" },
-                                    //    name = tempTeacher.name,
-                                    //    job = $"{tempShool.name}-顾问",
-                                    //    size = 0,
-                                    //    createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
-                                    //};
-
-                                    //var resScTch = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{itemTeacher}", new PartitionKey($"Teacher-{tempShool.id}"));
-                                    //if(resScTch.)
-
-                                    ////添加学校学校顾问
-                                    //await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<SchoolTeacher>(addSchoolTeacher, new PartitionKey($"Teacher-{tempShool.id}"));
-                                }
+                        using var fileJson = await JsonDocument.ParseAsync(respRel.ContentStream);
+                        biRel = fileJson.ToObject<BIRelation>();
+                    }
+                    else
+                    {
+                        biRel.id = tempShool.id;
+                    }
 
-                                //查询该教师是否存在该校
-                                SchoolTeacher schoolTeacher = null;
-                                var resScTch = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{itemTeacher}", new PartitionKey($"Teacher-{tempShool.id}"));
-                                if (resScTch.Status == 200) 
-                                {
-                                    using var tchJson = await JsonDocument.ParseAsync(resScTch.ContentStream);
-                                    schoolTeacher = tchJson.ToObject<SchoolTeacher>();
-                                }
+                    string aName = null;
+                    if (!string.IsNullOrEmpty($"{tempShool.areaId}"))
+                    {
+                        aName = await CosmosQueryHelper.GetStr(cosmosClient, "Normal", $"select value(c.name) from c where c.id='{tempShool.areaId}'", "Base-Area");
+                    }
 
-                                if (schoolTeacher != null)
-                                {
-                                    if (!schoolTeacher.roles.Contains("assist"))
-                                    {
-                                        schoolTeacher.roles.Add("assist");
-                                        //添加顾问权限
-                                        await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, schoolTeacher.id, new PartitionKey($"Teacher-{tempShool.id}"));
-                                    }
-                                }
-                                else
-                                {
-                                    SchoolTeacher addSchoolTeacher = new()
-                                    {
-                                        id = itemTeacher,
-                                        code = $"Teacher-{tempShool.id}",
-                                        pk = "Teacher",
-                                        status = "join",
-                                        roles = new List<string>() { "assist" },
-                                        name = tempTeacher.name,
-                                        job = $"{tempShool.name}-顾问",
-                                        size = 0,
-                                        createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
-                                    };
-                                    //添加学校顾问
-                                    await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<SchoolTeacher>(addSchoolTeacher, new PartitionKey($"Teacher-{tempShool.id}"));
-                                }
-                            }
+                    biRel.name = tempShool.name;
+                    biRel.picture = tempShool.picture;
+                    biRel.region = tempShool.region;
+                    biRel.province = tempShool.province;
+                    biRel.city = tempShool.city;
+                    biRel.dist = tempShool.dist;
+                    biRel.address = tempShool.address;
+                    biRel.areaId = tempShool.areaId;
+                    biRel.size = tempShool.size;
+                    biRel.scale = tempShool.scale;
+                    biRel.upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                    biRel.areaName = aName;
+                    if (idInfos.Count > 0)
+                    {
+                        foreach (var item in idInfos)
+                        {
+                            var tempAss = biRel.assists.Find(f => f.id.Equals(item.id));
+                            if (tempAss == null)
+                                biRel.assists.Add(item);
                         }
                     }
+                    else
+                    {
+                        biRel.assists = idInfos;
+                    }
+
+                    if (respRel.Status == 200)
+                    {
+                        await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<BIRelation>(biRel, biRel.id, new PartitionKey("BIRel"));
+                    }
+                    else
+                    {
+                        await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<BIRelation>(biRel, new PartitionKey("BIRel"));
+                    }
                 }
 
                 //保存操作记录
-                await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "school-update", $"{_tmdName}【{_tmdId}】修改学校功能,修改的学校:{_schoolId},{_type},{picture},{size},{string.Join("|", assistId.ToArray())}", _dingDing, httpContext: HttpContext);
+                await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "school-update", $"{_tmdName}【{_tmdId}】修改学校功能,修改的学校:{_schoolId},{_type},{picture},{size},{idInfos.ToArray()}", _dingDing, httpContext: HttpContext);
 
                 return Ok(new { state = 200 });
             }
@@ -1109,13 +1268,13 @@ namespace TEAMModelBI.Controllers.BISchool
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-checlkexist")]
-        public async Task<IActionResult> GetCheckExist(JsonElement jsonElement) 
+        public async Task<IActionResult> GetCheckExist(JsonElement jsonElement)
         {
             if (!jsonElement.TryGetProperty("scNames", out JsonElement _scNames)) return BadRequest();
             if (!jsonElement.TryGetProperty("accounts", out JsonElement _accounts)) return BadRequest();
             if (!jsonElement.TryGetProperty("areaIds", out JsonElement _areaIds)) return BadRequest();
             jsonElement.TryGetProperty("schools", out JsonElement schools);
-            
+
             var cosmosClient = _azureCosmos.GetCosmosClient();
             List<CreateSchoolInfo> cSchools = new();
             if (!string.IsNullOrEmpty($"{schools}"))
@@ -1156,10 +1315,10 @@ namespace TEAMModelBI.Controllers.BISchool
                     tmdInfos.ForEach(tmd =>
                     {
                         if (!string.IsNullOrEmpty(tmd.id))
-                            if (tmd.id.Equals($"{ac}")) 
+                            if (tmd.id.Equals($"{ac}"))
                                 noTmdInfo = tmd;
                         if (!string.IsNullOrEmpty(tmd.mobile))
-                            if (tmd.mobile.Equals($"{ac}")) 
+                            if (tmd.mobile.Equals($"{ac}"))
                                 noTmdInfo = tmd;
                         if (!string.IsNullOrEmpty(tmd.mail))
                             if (tmd.mail.Equals($"{ac}"))
@@ -1171,7 +1330,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 });
             }
 
-            if (areaIds.Count > 0) 
+            if (areaIds.Count > 0)
             {
                 foreach (var item in areaIds)
                 {
@@ -1212,7 +1371,7 @@ namespace TEAMModelBI.Controllers.BISchool
             if (existScNames.Count > 0 || noAccounts.Count > 0 || noAreaIds.Count > 0 || synPro.Count > 0)
                 return Ok(new { state = RespondCode.Created, existScNames, noAccounts, noAreaIds, synPro, createScInfo });
             else
-                return Ok(new { state = RespondCode.Ok , createScInfo });
+                return Ok(new { state = RespondCode.Ok, createScInfo });
         }
 
         /// <summary>
@@ -1329,7 +1488,7 @@ namespace TEAMModelBI.Controllers.BISchool
 
             var cosmosClient = _azureCosmos.GetCosmosClient();
 
-            List<string> scIds= _scIds.ToObject<List<string>>();
+            List<string> scIds = _scIds.ToObject<List<string>>();
             List<string> manages = _manages.ToObject<List<string>>();
 
             List<ExistScManage> existScManages = new();
@@ -1373,7 +1532,7 @@ namespace TEAMModelBI.Controllers.BISchool
                                 };
 
                                 var haveTeacher = tempTeacher.schools.Find(x => x.schoolId.Equals($"{scId}"));
-                                if (haveTeacher == null) 
+                                if (haveTeacher == null)
                                 {
                                     School school = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>(scId, new PartitionKey("Base"));
                                     //教师存在,在该教师信息中添加要管理的学校信息
@@ -1398,7 +1557,7 @@ namespace TEAMModelBI.Controllers.BISchool
                                 School scInfo = tchJson.ToObject<School>();
                                 teacher.schools.Add(new() { schoolId = scInfo.id, name = scInfo.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = scInfo.picture, areaId = scInfo.areaId });
                             }
-                            
+
                             teacher = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey("Base"));
                             SchoolTeacher addSchoolTeacher = new()
                             {
@@ -1434,7 +1593,7 @@ namespace TEAMModelBI.Controllers.BISchool
         [ProducesDefaultResponseType]
         [AuthToken(Roles = "admin")]
         [HttpPost("batch-scmanage")]
-        public async Task<IActionResult> BatchScManage(JsonElement jsonElement) 
+        public async Task<IActionResult> BatchScManage(JsonElement jsonElement)
         {
             if (!jsonElement.TryGetProperty("scManages", out JsonElement _scManages)) return BadRequest();
             var cosmosClient = _azureCosmos.GetCosmosClient();
@@ -1594,7 +1753,7 @@ namespace TEAMModelBI.Controllers.BISchool
                     periods.Add(new Period
                     {
                         id = Guid.NewGuid().ToString(),
-                        name = x.pidName,
+                        name = x.name,
                         campusId = campusId,
                         semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
                         new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
@@ -1614,12 +1773,12 @@ namespace TEAMModelBI.Controllers.BISchool
                             eugenics = schoolConfig.PresetExam[0].eugenics,
                             touch = schoolConfig.PresetExam[0].touch
                         },
-                        type = x.pidType
-                        
+                        periodType = x.value
+
                     });
                 });
             }
-            else 
+            else
             {
                 periods.Add(new Period
                 {
@@ -1760,8 +1919,8 @@ namespace TEAMModelBI.Controllers.BISchool
         /// </summary>
         public record PeriodType
         {
-            public List<string> pidType { get; set; }
-            public string pidName { get; set; }
+            public string name { get; set; }
+            public string value { get; set; }
         }
 
         /// <summary>
@@ -1769,7 +1928,7 @@ namespace TEAMModelBI.Controllers.BISchool
         /// </summary>
         public record ExistScManage
         {
-            public string scId{ get; set; }
+            public string scId { get; set; }
             public string tmdId { get; set; }
         }
 
@@ -1777,7 +1936,7 @@ namespace TEAMModelBI.Controllers.BISchool
         /// <summary>
         /// 管理员
         /// </summary>
-        public record ScManages 
+        public record ScManages
         {
             public string id { get; set; }
             public string name { get; set; }

+ 141 - 214
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -29,7 +29,6 @@ using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Context.BI;
 using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.DI;
-using TEAMModelOS.SDK.DI.CoreAPI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
@@ -48,12 +47,11 @@ namespace TEAMModelBI.Controllers.BISchool
         private readonly AzureStorageFactory _azureStorage;
         private readonly AzureRedisFactory _azureRedis;
         private readonly IConfiguration _configuration;
-        private readonly NotificationService _notificationService;
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IWebHostEnvironment _environment; //读取文件
-        private readonly HttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClient;
 
-        public SchoolController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, AzureRedisFactory azureRedis, IConfiguration configuration, NotificationService notificationService, CoreAPIHttpService coreAPIHttpService, HttpClient httpClient, IWebHostEnvironment hostingEnvironment)
+        public SchoolController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, AzureRedisFactory azureRedis, IConfiguration configuration,   CoreAPIHttpService coreAPIHttpService, IHttpClientFactory httpClient, IWebHostEnvironment hostingEnvironment)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
@@ -61,7 +59,6 @@ namespace TEAMModelBI.Controllers.BISchool
             _option = option?.Value;
             _azureRedis = azureRedis;
             _configuration = configuration;
-            _notificationService = notificationService;
             _coreAPIHttpService = coreAPIHttpService;
             _httpClient = httpClient;
             _environment = hostingEnvironment;
@@ -125,12 +122,12 @@ 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(),
-                                areaId = obj.GetProperty("areaId").GetString(),
-                                standard = obj.GetProperty("standard").GetString()
                             };
                             try
                             {
+                                notAreaSchool.dist = obj.GetProperty("dist").GetString();
+                                notAreaSchool.areaId = obj.GetProperty("areaId").GetString();
+                                notAreaSchool.standard = obj.GetProperty("standard").GetString();
                                 notAreaSchool.areas = obj.GetProperty("manyAreas").ToObject<List<SchoolArea>>();
                             }
                             catch { }
@@ -171,6 +168,60 @@ namespace TEAMModelBI.Controllers.BISchool
             }
         }
 
+        /// <summary>
+        /// 查询未加入区域的学校 国际站接口 不分页
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-nojoinsc")]
+        public async Task<IActionResult> GetNoJoinAreaSc()
+        {
+            try
+            {
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                //StringBuilder sqltxt = new($"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period,c.areaId,c.standard,c.manyAreas FROM c WHERE c.pk='School' and (c.areaId = '' or c.areaId = null or IS_DEFINED(c.areaId) = false)");
+                string sqltxt = $"SELECT value(c) FROM c WHERE (c.areaId = '' or c.areaId = null or IS_DEFINED(c.areaId) = false)";
+                List<NotAreaSchool> notAreaSchools = new();
+                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: sqltxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            NotAreaSchool notAreaSchool = new()
+                            {
+                                id = obj.GetProperty("id").GetString(),
+                                name = obj.GetProperty("name").GetString(),
+                                schoolCode = obj.GetProperty("schoolCode").GetString(),
+                                picture = obj.GetProperty("picture").GetString(),
+                                period = obj.GetProperty("period").ToObject<List<Period>>().Select(x => x.name).ToList(),
+                                province = obj.GetProperty("province").GetString(),
+                                city = obj.GetProperty("city").GetString()
+                            };
+                            try
+                            {
+                                notAreaSchool.dist = obj.GetProperty("dist").GetString();
+                                notAreaSchool.areaId = obj.GetProperty("areaId").GetString();
+                                notAreaSchool.standard = obj.GetProperty("standard").GetString();
+                                notAreaSchool.areas = obj.GetProperty("manyAreas").ToObject<List<SchoolArea>>();
+                            }
+                            catch { }
+                            notAreaSchools.Add(notAreaSchool);
+                        }
+                    }
+                }
+
+                return Ok(new { state = 200, notAreaSchools });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location}  /schoolcheck/get-nojoinsc   \n    {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
         /// <summary>
         /// 学校加入区    //已对接
         /// </summary>
@@ -524,6 +575,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 if (!jsonElement.TryGetProperty("partitionKey", out JsonElement parKey)) return BadRequest();
                 jsonElement.TryGetProperty("userId", out JsonElement userId);
                 jsonElement.TryGetProperty("tmdId", out JsonElement tmdId);
+                jsonElement.TryGetProperty("role", out JsonElement role);
                 if (!jsonElement.TryGetProperty("schoolIds", out JsonElement jsSchoolIds)) return BadRequest();
                 if (!jsonElement.TryGetProperty("busy", out JsonElement busy)) return BadRequest();
                 //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
@@ -586,7 +638,7 @@ namespace TEAMModelBI.Controllers.BISchool
                                 //}
                                 //else return Ok(new { state = 404, msg = "依据钉钉手机号未找到醍摩豆账号!" });
                             }
-                            List<string> noSchool = await SchoolWay.SchoolAdviser(cosmosClient, ddInfo, schoolIds, $"{busy}");
+                            List<string> noSchool = await SchoolWay.SchoolAdviser(cosmosClient, ddInfo, schoolIds, $"{role}", $"{busy}");
                             if (noSchool.Count > 0)
                             {
                                 noSchools.Add(ddInfo.tmdId, noSchool);
@@ -736,6 +788,7 @@ namespace TEAMModelBI.Controllers.BISchool
                         schoolTeacher = json.ToObject<SchoolTeacher>();
                         if (!schoolTeacher.roles.Contains("admin"))
                         {
+                            if(!schoolTeacher.roles.Contains("teacher")) schoolTeacher.roles.Add("teacher");
                             schoolTeacher.roles.Add("admin");
                             schoolTeacher.status = "join";
                             schoolTeacher = await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, schoolTeacher.id, new PartitionKey($"Teacher-{schoolId}"));
@@ -789,6 +842,7 @@ namespace TEAMModelBI.Controllers.BISchool
             var (_tmdId, _tmdName, _, _, _, _) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
             if (!jsonElement.TryGetProperty("tmdId", out JsonElement tmdId)) return BadRequest();
             if (!jsonElement.TryGetProperty("scIds", out JsonElement _scIds)) return BadRequest();
+            bool rmvFromSc = (jsonElement.TryGetProperty("rmvFromSc", out JsonElement rmvFromScJobj)) ? rmvFromScJobj.GetBoolean() : false; //rmvFromSc Bool true:移除SchoolTeacher document false:只移除roles中"admin"身分
             //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
 
             List<string> scIds = _scIds.ToObject<List<string>>();
@@ -806,16 +860,23 @@ namespace TEAMModelBI.Controllers.BISchool
                 var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{tmdId}", new PartitionKey($"Teacher-{scId}"));
                 if (response.Status == 200)
                 {
-                    using var json = await JsonDocument.ParseAsync(response.ContentStream);
-                    scTeacher = json.ToObject<SchoolTeacher>();
-                    if (scTeacher.roles.Contains("admin"))
+                    if (rmvFromSc)
                     {
-                        scTeacher.roles.Remove("admin");
-                        strMsg.Append($"{scId},");
-                        scTeacher = await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(scTeacher, scTeacher.id, new PartitionKey($"Teacher-{scId}"));
+                        await cosmosClient.GetContainer("TEAMModelOS", "School").DeleteItemAsync<SchoolTeacher>($"{tmdId}", new PartitionKey($"Teacher-{scId}"));
                     }
                     else
-                        existScId.Add(scId);
+                    {
+                        using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                        scTeacher = json.ToObject<SchoolTeacher>();
+                        if (scTeacher.roles.Contains("admin"))
+                        {
+                            scTeacher.roles.Remove("admin");
+                            strMsg.Append($"{scId},");
+                            scTeacher = await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(scTeacher, scTeacher.id, new PartitionKey($"Teacher-{scId}"));
+                        }
+                        else
+                            existScId.Add(scId);
+                    }
                 }
                 else
                     existScId.Add(scId);
@@ -882,6 +943,8 @@ namespace TEAMModelBI.Controllers.BISchool
                         {
                             teacher.schools.Add(new Teacher.TeacherSchool { schoolId = $"{school.id}", name = $"{school.name}", status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = string.IsNullOrEmpty($"{school.picture}") ? "" : $"{school.picture}", areaId = string.IsNullOrEmpty($"{school.areaId}") ? "" : $"{school.areaId}" });
                         }
+                        else
+                            existSchool.name = school.name;
 
                         var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{tmdId}", new PartitionKey($"Teacher-{school.id}"));
                         if (response.Status == 200)
@@ -902,7 +965,7 @@ namespace TEAMModelBI.Controllers.BISchool
                             {
                                 id = $"{tmdId}",
                                 code = $"Teacher-{school.id}",
-                                roles = new List<string> { "admin", "teacher" },
+                                roles = new List<string> { "admin" },
                                 job = "管理员",
                                 name = $"{tmdName}",
                                 picture = string.IsNullOrEmpty($"{picture}") ? "" : $"{picture}",
@@ -988,6 +1051,13 @@ namespace TEAMModelBI.Controllers.BISchool
                     else
                         delSchoolRels.Add(new DelSchoolRel() { id = $"{tempId}", code = "Base", type = 1, status = response.Status });
 
+                    //删除学校信息中间
+                    var resBiRel = await cosmosClient.GetContainer("TEAMModelOS", "School").DeleteItemStreamAsync($"{tempId}", new PartitionKey($"BIRel"));
+                    if (resBiRel.Status == 204)
+                        msg.AppendLine($"{tmdName}【{tmdId}】删除学校信息中间件,删除状态:{resBiRel.Status},删除ID:{tempId}");
+                    else
+                        delSchoolRels.Add(new DelSchoolRel() { id = $"{tempId}", code = "Base", type = 1, status = response.Status });
+
                     foreach (var item in scTchIds)
                     {
                         //学校教师信息
@@ -1444,6 +1514,9 @@ namespace TEAMModelBI.Controllers.BISchool
                     case "admin":
                         schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", "admin");
                         break;
+                    case "sales":
+                        schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", "sales");
+                        break;
                     default:
                         schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
                         break;
@@ -1534,9 +1607,15 @@ namespace TEAMModelBI.Controllers.BISchool
                     {
                         case "admin":
                             schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", "admin");
+                            scSql = BICommonWay.ManyScSql("c.school", schoolIds);
+                            break;
+                        case "sales":
+                            schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", "sales");
+                            scSql = BICommonWay.ManyScSql("c.school", schoolIds);
                             break;
                         default:
                             schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
+                            scSql = BICommonWay.ManyScSql("c.school", schoolIds);
                             break;
                     }
                 }
@@ -1555,17 +1634,18 @@ namespace TEAMModelBI.Controllers.BISchool
 
             //if ((string.IsNullOrEmpty($"{tmdId}") && string.IsNullOrEmpty($"{schooId}")) || (!string.IsNullOrEmpty($"{tmdId}") && !string.IsNullOrEmpty($"{schooId}")))
                 
-            List<MonthStartEnd> mthStartEnds = await TimeHelper.GetYearSataMthCtMth(DateTimeOffset.UtcNow);
+            List<StartEndTime> mthStartEnds = await TimeHelper.GetYearSataMthCtMth(DateTimeOffset.UtcNow);
             if (mthStartEnds.Count > 0)
             {
                 foreach (var item in mthStartEnds)
                 {
-                    YearCnt yearCnt = new() { name = item.yearMonth };
+                    YearCnt yearCnt = new() { name = item.date };
                     string selessSql = $"{strSql} and {scSql.ToString()} and c.startTime >= {item.start} and c.startTime <= {item.end}";
                     yearCnt.lessCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", selessSql);
 
                     string interactSql = $"select value(sum(c.clientInteractionAverge)) from c where c.pk='LessonRecord' and {scSql} and c.startTime >= {item.start} and c.startTime <= {item.end}";
-                    yearCnt.interCnt = await CommonFind.GetSqlValueDoubleCounnt(cosmosClient, "School", interactSql);
+                    //double iCnt = await CommonFind.GetSqlValueDoubleCounnt(cosmosClient, "School", interactSql);
+                    yearCnt.interCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", interactSql);
 
                     string mthActSql = $"and {scSql} and c.createTime >= {item.start} and c.createTime <= {item.end}";
                     yearCnt.actCnt = await ActivityWay.GetCnt(cosmosClient, condSql: mthActSql);
@@ -1624,6 +1704,10 @@ namespace TEAMModelBI.Controllers.BISchool
                     case "admin":
                         schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", "admin");
                         break;
+                    case "sales":
+                        schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", "sales");
+                        //scSql = BICommonWay.ManyScSql("c.school", schoolIds);
+                        break;
                     default:
                         schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
                         break;
@@ -1746,6 +1830,31 @@ namespace TEAMModelBI.Controllers.BISchool
             return Ok(new { state = RespondCode.Ok, school, gradeCnt, subCnt });
         }
 
+        /// <summary>
+        /// 学校简要信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-schools")]
+        public async Task<IActionResult> GetSchools (JsonElement jsonElement)
+        {
+            jsonElement.TryGetProperty("areaId", out JsonElement areaId);
+            List<ScBriefInfo> scBriefs = new();
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+
+            StringBuilder sql = new("select c.id,c.name,c.picture,c.areaId,c.size,c.period from c ");
+            if (!string.IsNullOrEmpty($"{areaId}"))
+                sql.Append($" where c.areaId = '{areaId}'");
+
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS,"School").GetItemQueryIterator<ScBriefInfo>(queryText: sql.ToString(), requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")}))
+            {
+                scBriefs.Add(item);
+            }
+
+            return Ok(new { state = RespondCode.Ok, scBriefs });
+        }
+
         /// <summary>
         /// 通过tmdID 账户查询学校专业和模组   //已对接
         /// </summary>
@@ -1776,6 +1885,9 @@ namespace TEAMModelBI.Controllers.BISchool
                     case "admin":
                         schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", "admin");
                         break;
+                    case "sales":
+                        schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}", "sales");
+                        break;
                     default:
                         schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
                         break;
@@ -1916,7 +2028,7 @@ namespace TEAMModelBI.Controllers.BISchool
             if (!string.IsNullOrEmpty($"{areaId}"))
             {
                 List<string> schools = new();
-                schools = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.areaId='{areaId}'", "Base");
+                schools = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.areaId='{areaId}'", "Base");
 
                 allSize = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"select value(sum(c.size)) from c where c.areaId='{areaId}'", "Base"); //区域所有学校空间
 
@@ -2092,26 +2204,6 @@ namespace TEAMModelBI.Controllers.BISchool
 
                 //发送消息实体
                 string shiftCode = "shift-assist";
-                Notification notification = new Notification
-                {
-                    hubName = "hita",
-                    type = "msg",
-                    from = $"BI:{_option.Location}:{_school}",
-                    to = new List<string> { $"{_shiftTeacher}" },
-                    label = $"{shiftCode}_school",
-                    body = new { location = _option.Location, biz = shiftCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
-                    expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
-                };
-
-                if (notification != null)
-                {
-                    var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
-                    var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
-                    var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
-                    var location = _option.Location;
-                    await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);//站内发送消息
-                }
-
                 //保存操作记录
                 await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "schoolTeacher-add", $"{_tmdName}【{_tmdId}】移交顾问给{newSchoolTeacher.name}【{newSchoolTeacher.id}】", _dingDing, httpContext: HttpContext);
                 return Ok(new { state = 200 });
@@ -2192,173 +2284,7 @@ namespace TEAMModelBI.Controllers.BISchool
 
             return Ok(new { state = RespondCode.Ok, scSimple });
         }
-
-
-        /// <summary>
-        /// 添加新学段的学校
-        /// </summary>
-        /// <param name="jsonElement"></param>
-        /// <returns></returns>
-        [ProducesDefaultResponseType]
-        [HttpPost("set-allscperiod")]
-        public async Task<IActionResult> SetAllScPeriod(JsonElement jsonElement)
-        {
-            jsonElement.TryGetProperty("Language", out JsonElement Language);
-            jsonElement.TryGetProperty("scId", out JsonElement scId);
-            jsonElement.TryGetProperty("periodName", out JsonElement periodName);
-            var cosmosClient = _azureCosmos.GetCosmosClient();
-            var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
-            StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
-            StringBuilder stringBuilder = new();
-            string text;
-            string scName = "默认学段";
-            while ((text = streamReader.ReadLine()) != null)
-            {
-                stringBuilder.Append(text.ToString());
-            }
-            streamReader.Close();
-            string input = stringBuilder.ToString();
-            List<SchoolConfig> schoolConfigs = input.ToObject<List<SchoolConfig>>();
-            SchoolConfig schoolConfig = null;
-            if (!string.IsNullOrEmpty($"{Language}"))
-                schoolConfig = schoolConfigs.Find(x => x.Lang.Contains($"{Language}"));
-
-            if (schoolConfig == null)
-            {
-                if ($"{Language}".Contains("en"))
-                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("en-US"));
-                else
-                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("zh-CN"));
-            }
-            string campusId = Guid.NewGuid().ToString();
-
-            StringBuilder noPeriodScSql = new("SELECT value(c) FROM c ");
-            List<School> allSc = new();
-
-            if (!string.IsNullOrEmpty($"{scId}"))
-                noPeriodScSql.Append($" where c.id='{scId}'");
-            else
-                noPeriodScSql.Append($" where c.code='Base' and c.period=[]");
-
-            if (!string.IsNullOrEmpty($"{periodName}"))
-                scName = $"{periodName}";
-
-            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(noPeriodScSql.ToString(),requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")}))
-            {
-                allSc.Add(item);
-            }
-            foreach (var school in allSc)
-            {
-                if (school.campuses.Count > 0)
-                    campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
-                
-                school.period.Add(new Period
-                {
-                    id = Guid.NewGuid().ToString(),
-                    name = scName,
-                    campusId = campusId,
-                    semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
-                        new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
-                    subjects = new List<Subject>() {
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
-                        },
-                    grades = schoolConfig.grades,
-                    analysis = new Analysis()
-                    {
-                        type = new List<ExamSimple>() { new ExamSimple { id = Guid.NewGuid().ToString(), name = schoolConfig.PresetExam[0].type[0].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[1].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[2].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[3].name } },
-                        income = schoolConfig.PresetExam[0].income,
-                        eugenics = schoolConfig.PresetExam[0].eugenics,
-                        touch = schoolConfig.PresetExam[0].touch
-                    }
-                });
-                if (!school.campuses.Select(x => x.id).Contains(campusId))
-                    school.campuses.Add(new Campus { name = school.name, id = campusId });
-
-                School rSchool = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey("Base"));
-            }
-
-            return Ok(new { state = RespondCode.Ok });
-        }
-
-        /// <summary>
-        /// 设置学校学段
-        /// </summary>
-        /// <param name="jsonElement"></param>
-        /// <returns></returns>
-        [ProducesDefaultResponseType]
-        [HttpPost("set-scperiod")]
-        public async Task<IActionResult> SetScPeriod(JsonElement jsonElement)
-        {
-            if (!jsonElement.TryGetProperty("scId", out JsonElement scId)) return BadRequest();
-            jsonElement.TryGetProperty("Language", out JsonElement Language);
-
-            var cosmosClient = _azureCosmos.GetCosmosClient();
-            var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
-            StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
-            StringBuilder stringBuilder = new();
-            string text;
-            while ((text = streamReader.ReadLine()) != null)
-            {
-                stringBuilder.Append(text.ToString());
-            }
-            streamReader.Close();
-            string input = stringBuilder.ToString();
-            List<SchoolConfig> schoolConfigs = input.ToObject<List<SchoolConfig>>();
-            SchoolConfig schoolConfig = null;
-            if (!string.IsNullOrEmpty($"{Language}"))
-                schoolConfig = schoolConfigs.Find(x => x.Lang.Contains($"{Language}"));
-
-            if (schoolConfig == null)
-            {
-                if ($"{Language}".Contains("en"))
-                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("en-US"));
-                else
-                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("zh-CN"));
-            }
-            string campusId = Guid.NewGuid().ToString();
-            School school = null;
-
-            school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{scId}", new PartitionKey("Base"));
-            if (school != null)
-            {
-                school.period.Add(new Period
-                {
-                    id = Guid.NewGuid().ToString(),
-                    name = "默认学段",
-                    campusId = campusId,
-                    semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
-                        new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
-                    subjects = new List<Subject>() {
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
-                        },
-                    grades = schoolConfig.grades,
-                    analysis = new Analysis()
-                    {
-                        type = new List<ExamSimple>() { new ExamSimple { id = Guid.NewGuid().ToString(), name = schoolConfig.PresetExam[0].type[0].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[1].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[2].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[3].name } },
-                        income = schoolConfig.PresetExam[0].income,
-                        eugenics = schoolConfig.PresetExam[0].eugenics,
-                        touch = schoolConfig.PresetExam[0].touch
-                    }
-                });
-
-                school.campuses.Add(new Campus { name = school.name, id = campusId });
-            }
-
-            school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey("Base"));
-
-            return Ok(new { state = RespondCode.Ok, school });
-        }
-
+        
         #region 购买记录
 
         /// <summary>
@@ -2373,10 +2299,11 @@ namespace TEAMModelBI.Controllers.BISchool
             {
                 string url = _configuration.GetValue<string>("HaBookAuth:CoreBBAPI") + "/ies5/get-school-order";
                 string AccessToken = await getCoreAccessToken();
-                _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
+                var client = _httpClient.CreateClient();
+                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
                 string paramJson = JsonConvert.SerializeObject(new { school_code = schoolCode });
                 var content = new StringContent(paramJson, Encoding.UTF8, "application/json");
-                HttpResponseMessage responseMessage = await _httpClient.PostAsync(url, content);
+                HttpResponseMessage responseMessage = await client.PostAsync(url, content);
                 if (responseMessage.StatusCode == HttpStatusCode.OK)
                 {
                     string responseBody = responseMessage.Content.ReadAsStringAsync().Result;
@@ -2400,7 +2327,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 string ClientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
                 string Secret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
                 var content = new { grant_type = GrantType, client_id = ClientID, client_secret = Secret };
-                var response = await _httpClient.PostAsJsonAsync($"{Url}", content);
+                var response = await _httpClient.CreateClient().PostAsJsonAsync($"{Url}", content);
                 if (response.IsSuccessStatusCode)
                 {
                     string responseBody = response.Content.ReadAsStringAsync().Result;
@@ -2454,9 +2381,9 @@ namespace TEAMModelBI.Controllers.BISchool
             public List<string> period { get; set; }
             public string province { get; set; }
             public string city { get; set; }
-            public string dist { get; set; }
-            public string areaId { get; set; }
-            public string standard { get; set; }
+            public string dist { get; set; } = "";
+            public string areaId { get; set; } = "";
+            public string standard { get; set; } = "";
             public List<SchoolArea> areas { get; set; } = new List<SchoolArea>();
         }
 

+ 30 - 10
TEAMModelBI/Controllers/BIServer/BiServersController.cs

@@ -18,6 +18,8 @@ using System.Net.Http.Json;
 using TEAMModelOS.SDK;
 using TEAMModelBI.Filter;
 using Microsoft.AspNetCore.Authorization;
+using Azure.Storage.Sas;
+using TEAMModelOS.SDK.Context.Constant;
 
 namespace TEAMModelBI.Controllers.BIServer
 {
@@ -29,21 +31,24 @@ namespace TEAMModelBI.Controllers.BIServer
         private readonly DingDing _dingDing;
         //数据库连接
         public AzureCosmosFactory _azureCosmos;
+        //文件容器
+        private readonly AzureStorageFactory _azureStorage;
         private readonly Option _option;
         //读取配置信息
         private readonly IConfiguration _configuration;
 
-        private readonly IHttpClientFactory _http;
+        private readonly IHttpClientFactory httpClient;
         private readonly CoreAPIHttpService _coreAPIHttpService;
 
 
-        public BiServersController(AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService)
+        public BiServersController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService)
         {
             _azureCosmos = azureCosmos;
+            _azureStorage = azureStorage;
             _dingDing = dingDing;
             _option = option?.Value;
             _configuration = configuration;
-            _http = http;
+            httpClient = http;
             _coreAPIHttpService = coreAPIHttpService;
         }
 
@@ -76,7 +81,7 @@ namespace TEAMModelBI.Controllers.BIServer
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-userinfo")]
-        public async Task<IActionResult> SendMobileGetUserIfo(JsonElement jsonElment) 
+        public async Task<IActionResult> SendMobileGetUserIfo(JsonElement jsonElment)
         {
             try
             {
@@ -86,7 +91,7 @@ namespace TEAMModelBI.Controllers.BIServer
                     return Ok(new { state = 200, coreUser });
                 else return Ok(new { state = 404, msg = "未找到改账户" });
 
-                //HttpClient httpClient = _http.CreateClient();
+                //HttpClient IHttpClientFactory = _http.CreateClient();
                 //string url = _configuration.GetValue<string>("HaBookAuth:CoreId:userinfo");
                 //HttpResponseMessage responseMessage = await httpClient.PostAsJsonAsync(url, jsonElment);
                 //List<userInfo> userInfos = new List<userInfo>();
@@ -131,8 +136,8 @@ namespace TEAMModelBI.Controllers.BIServer
                 if (!jsonElement.TryGetProperty("HasUser", out JsonElement HasUser)) return BadRequest();
 
                 string smsurl = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
-                HttpClient httpClient = _http.CreateClient();
-                HttpResponseMessage responseMessage = await httpClient.PostAsJsonAsync($"{smsurl}/service/sandsms/pin", jsonElement);
+                 
+                HttpResponseMessage responseMessage = await httpClient.CreateClient().PostAsJsonAsync($"{smsurl}/service/sandsms/pin", jsonElement);
                 if (responseMessage.StatusCode == HttpStatusCode.OK)
                 {
                     string str_json = await responseMessage.Content.ReadAsStringAsync();
@@ -171,9 +176,9 @@ namespace TEAMModelBI.Controllers.BIServer
                 if (!jsonElement.TryGetProperty("Authorization_Pin", out JsonElement sms)) return BadRequest();
 
                 string smsurl = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
-                HttpClient httpClient = _http.CreateClient();
+      
                 var temp_job = new { Authorization_Pin = sms };
-                HttpResponseMessage responseMessage = await httpClient.PostAsJsonAsync($"{smsurl}/service/verifiy/pin", temp_job);
+                HttpResponseMessage responseMessage = await httpClient.CreateClient().PostAsJsonAsync($"{smsurl}/service/verifiy/pin", temp_job);
 
                 if (responseMessage.StatusCode == HttpStatusCode.OK)
                 {
@@ -209,7 +214,22 @@ namespace TEAMModelBI.Controllers.BIServer
             }
         }
 
-
+        /// <summary>
+        /// 获取blob容器key
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-cntrkey")]
+        public async Task<IActionResult> GetCntrKey(JsonElement jsonElement)
+        {
+            if (!jsonElement.TryGetProperty("cntr", out JsonElement cntr)) return BadRequest();
+            string osblob_uri = null, osblob_sas = null;
+            if (string.IsNullOrEmpty($"{cntr}"))
+                return Ok(new { state = RespondCode.ParamsError, msg = "容器不能为空!" });
+            (osblob_uri, osblob_sas) = _azureStorage.GetBlobContainerSAS($"{cntr}", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete);
+            return Ok(new { state = RespondCode.Ok, osblob_uri, osblob_sas });
+        }
 
         public record userInfo
         {

+ 131 - 2
TEAMModelBI/Controllers/BISystem/CoreController.cs

@@ -12,6 +12,17 @@ using TEAMModelOS.SDK.DI;
 using Microsoft.Extensions.Options;
 using System.Net.Http;
 using TEAMModelOS.Models;
+using static TEAMModelOS.SDK.CoreAPIHttpService;
+using System.Collections.Generic;
+using System.IdentityModel.Tokens.Jwt;
+using System.Text;
+using System.Web;
+using TEAMModelOS.SDK.Extension;
+using System.Net;
+using Microsoft.Extensions.Configuration;
+using System.Configuration;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Context.Constant;
 
 namespace TEAMModelBI.Controllers.BISystem
 {
@@ -25,14 +36,18 @@ namespace TEAMModelBI.Controllers.BISystem
         private readonly AzureStorageFactory _azureStorage;
         private readonly DingDing _dingDing;
         private readonly IPSearcher _searcher;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly IConfiguration _configuration;
         private readonly Option _option;
 
 
-        public CoreController(AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IPSearcher searcher, HttpClient httpClient)
+        public CoreController(AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis, CoreAPIHttpService coreAPIHttpService, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, IPSearcher searcher, IHttpClientFactory httpClient)
         {
             _azureCosmos = azureCosmos;
             _azureRedis = azureRedis;
-            _azureStorage= azureStorage;
+            _coreAPIHttpService = coreAPIHttpService;
+            _configuration = configuration;
+            _azureStorage = azureStorage;
             _dingDing = dingDing;
             _searcher = searcher;
             _option = option?.Value;
@@ -94,5 +109,119 @@ namespace TEAMModelBI.Controllers.BISystem
 
             return Ok(new { os, version, description, nowtime, region, ip });
         }
+
+
+        public class NotifyData
+        {
+            public string notifyCode { get; set; }
+            public string data { get; set; }
+            public int notifyEvent { get; set; }
+            public string ticket { get; set; }
+            public string token { get; set; }
+        }
+
+        /// <summary>
+        /// 处理信息
+        /// </summary>
+        /// <param name="notifyData"></param>
+        /// <returns></returns>
+        [HttpGet("process-notify")]
+        public async Task<IActionResult> ProcessNotify([FromQuery] NotifyData notifyData)
+        {
+            string msg = "";
+            /// code =-1 参数异常,0 凭据失效 1不是管理员,2操作成功,3服务端异常
+            int code = -1;
+            string scope = "";
+            //string lang = _option.Location.Contains("China") ? "zh-cn" : "en-us";
+            //string path = Path.Combine("", $"Lang/{lang}.json");
+            //var jsonAuth = System.IO.File.ReadAllText(path, Encoding.UTF8);
+            //var jsonData = jsonAuth.ToObject<JsonElement>();
+            //var status = jsonData.GetProperty("notify-status");
+            var status = "";
+            try
+            {
+                string opttmdid = "";
+                if (!string.IsNullOrWhiteSpace(notifyData.ticket))
+                {
+                    var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+                    (HttpStatusCode statusCode, CoreAPIToken token) = await _coreAPIHttpService.GetCoreAPIoAuth2Token(
+                         new Dictionary<string, object> { { "client_id", clientID }, { "grant_type", "authorization_code" }, { "code", notifyData.ticket } }, _option.Location, _configuration, _dingDing);
+                    if (statusCode.Equals(HttpStatusCode.OK))
+                    {
+                        var jwt = new JwtSecurityToken(token.id_token);
+                        opttmdid = jwt.Payload.Sub;
+                    }
+                    else
+                    {
+                        code = 0;
+                        msg = "凭据失效";
+                    }
+                    scope = "HiTA";
+                }
+                else if (!string.IsNullOrWhiteSpace(notifyData.token) && string.IsNullOrWhiteSpace(opttmdid))
+                {
+                    var jwt = new JwtSecurityToken(notifyData.token);
+                    opttmdid = jwt.Payload.Sub;
+                    scope = "BI";
+                }
+                if (string.IsNullOrWhiteSpace(opttmdid))
+                {
+                    code = 400;
+                    msg = "参数异常";
+                    //msg = status.TryGetProperty($"code{code}", out JsonElement text) ? $"{text}" : msg;
+                }
+                var rdata = HttpUtility.UrlDecode(notifyData.data, Encoding.UTF8);
+                var dataByte = Convert.FromBase64String(rdata);
+                string data = Encoding.Unicode.GetString(dataByte);
+                Dictionary<string, object> dict = data.ToObject<Dictionary<string, object>>();
+                dict.TryGetValue("notifyCode", out object notifyCode); //消息类型
+                dict.TryGetValue("noticeId", out object noticeId);   //存在BI中的消息id
+                dict.TryGetValue("tmdid", out object _tmdid);   //发送人ID
+                dict.TryGetValue("sendId", out object _sendId);  //接收人群
+
+                switch ($"{notifyCode}")
+                {
+                    case "notify_agree": //同意拒绝
+                        if (notifyData.notifyEvent == 1) 
+                        {
+                            code = 1;
+                            msg = "操作成功";
+                        }
+                        if (notifyData.notifyEvent == 2)
+                        {
+                            code = 2;
+                            msg = "操作成功";
+                        }
+                        break;
+                    case "notify_see":  //查看
+                        code = 1;
+                        msg = "查看成功";
+                        break;
+                    default:  //默认
+                        code = 3;
+                        msg = "普通通知";
+                        break;
+                }
+
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"{ex.Message}\n{ex.StackTrace}\n{notifyData.ToJsonString()}", GroupNames.成都开发測試群組);
+                code = 500;
+                msg = "服务端异常";
+            }
+
+            if (scope.Equals("HiTA"))
+            {
+                string HostName = HttpContext.GetHostName();
+                var rurl = $"https://{HostName}/#/resultPage?code={code}&msg={HttpUtility.UrlEncode(msg)}";
+                return Redirect(rurl);
+            }
+            else
+            {
+                return Ok(new { code, msg });
+            }
+        }
+
     }
 }

+ 374 - 28
TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs

@@ -29,6 +29,9 @@ using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Context.BI;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Context.Constant;
+using TEAMModelOS.SDK.Models.Dtos;
+using DocumentFormat.OpenXml.Bibliography;
+using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
 
 namespace TEAMModelBI.Controllers.BITable
 {
@@ -88,8 +91,6 @@ namespace TEAMModelBI.Controllers.BITable
 
                 var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
 
-                //HttpClient httpClient = _http.CreateClient();
-                //string url = _configuration.GetValue<string>("HaBookAuth:CoreId:userinfo");
 
                 //获取access_token
                 IDingTalkClient tokenClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
@@ -179,8 +180,6 @@ namespace TEAMModelBI.Controllers.BITable
                     }
                 }
 
-                //保存操作记录
-                await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "tabledd-update", $"{_tmdName}【{_tmdId}】从钉钉组织结构更新至Azure Table表【DDUserInfo】中。", _dingDing, httpContext: HttpContext);
                 var tempddUserInfos = ddUserInfos.GroupBy(c => c.userId).Select(c => c.First()).ToList();//去重
                 //List<DingDingUserInfo> TempdingDingUserInfos = await _azureStorage.SaveOrUpdateAll(dingDingUserInfos);  //只是保存至Table
                 //查询数据的数据 并和钉钉查询的数据对比,找出不同的数据,并删除  待后期测试
@@ -191,18 +190,21 @@ namespace TEAMModelBI.Controllers.BITable
                 {
                     //var temps = users.Union(tempddUserInfos).Except(users.Intersect(tempddUserInfos));
                     List<DingDingUserInfo> existsUserInfo = users.Where(u => !tempddUserInfos.Exists(e => u.userId.Equals(e.userId) && u.PartitionKey.Equals(e.PartitionKey))).ToList();
-                    if (users.Count > tempddUserInfos.Count)
-                    {
-                        existsUserInfo.AddRange(tempddUserInfos.Where(e => !users.Exists(u => e.userId.Equals(u.userId) && e.PartitionKey.Equals(u.PartitionKey))).ToList());
-                    }
+                    //if (users.Count > tempddUserInfos.Count)
+                    //{
+                    //    existsUserInfo.AddRange(tempddUserInfos.Where(e => !users.Exists(u => e.userId.Equals(u.userId) && e.PartitionKey.Equals(u.PartitionKey))).ToList());
+                    //}
                     ////List<DingDingUserInfo> existsUserInfo = users.Where((x, i) => users.FindIndex(z => z.userId.Equals(x.userId) && x.PartitionKey.Equals(divide)) == i).Select(x => x).ToList();
                     if (existsUserInfo.Count > 0)
                     {
                         noExisits = await table.DeleteAll(existsUserInfo);
                     }
                 }
+                //保存和修改至Table
+                List<DingDingUserInfo> UserInfo = await table.SaveOrUpdateAll(tempddUserInfos);  
 
-                List<DingDingUserInfo> UserInfo = await table.SaveOrUpdateAll(tempddUserInfos);  //保存和修改至Table
+                //保存操作记录
+                await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "tabledd-update", $"{_tmdName}【{_tmdId}】从钉钉组织结构更新至Azure Table表【DDUserInfo】中。", _dingDing, httpContext: HttpContext);
                 return Ok(new { state = 200, UserInfo, noExisits });
             }
             catch (Exception ex)
@@ -353,16 +355,10 @@ namespace TEAMModelBI.Controllers.BITable
                 if (!jsonElement.TryGetProperty("permissions", out JsonElement _permissions)) return BadRequest();
                 if (!jsonElement.TryGetProperty("roles", out JsonElement _roles)) return BadRequest();
                 if (!jsonElement.TryGetProperty("isDisable", out JsonElement _isDisable)) return BadRequest();
-                //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
 
+                var cosmosCliet = _azureCosmos.GetCosmosClient();
                 var tableClient = _azureStorage.GetCloudTableClient();
                 var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
-                ////分开部署,就不需要,一站多用时,取消注释
-                //if ($"{site}".Equals(BIConst.Global))
-                //{
-                //    tableClient = _azureStorage.GetCloudTableClient(BIConst.Global);
-                //    blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public", BIConst.Global);
-                //}
 
                 long isDisable = 0;
                 try
@@ -378,7 +374,7 @@ namespace TEAMModelBI.Controllers.BITable
                 var table = tableClient.GetTableReference("BIDDUserInfo");
                 var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
 
-                List<DingDingUserInfo> ddUserInfo = new();
+                List<DingDingUserInfo> ddUserInfos = new();
                 List<string> listper = _permissions.ToObject<List<string>>();
                 List<string> listroles = _roles.ToObject<List<string>>();
                 List<string> roles = new();//角色列表
@@ -386,13 +382,10 @@ namespace TEAMModelBI.Controllers.BITable
                 StringBuilder stringBuilder = new($"{_tmdName}【{_tmdId}】醍摩豆账号");
                 Dictionary<string, object> dic = new() { { "PartitionKey", $"{partitionKey}" } };
                 if (!string.IsNullOrEmpty($"{userId}"))
-                {
                     dic.Add("userId", $"{userId}");
-                }
+
                 if (!string.IsNullOrEmpty($"{tmdId}"))
-                {
                     dic.Add("tmdId", $"{tmdId}");
-                }
 
                 if (string.IsNullOrEmpty($"{userId}") && string.IsNullOrEmpty($"{tmdId}")) 
                 {
@@ -400,21 +393,150 @@ namespace TEAMModelBI.Controllers.BITable
                 }
 
                 var tempUser = await table.FindListByDict<DingDingUserInfo>(dic);
+                List<string> oldRoles = new();
+                List<Task<ItemResponse<BIRelation>>> upBIRel = new();
+
+                //List<Task<ItemResponse<SchoolTeacher>>> upScTch = new();
 
                 foreach (var item in tempUser)
                 {
+                    oldRoles = !string.IsNullOrEmpty($"{item.roles}") ? new List<string>(item.roles.Split(",")) : new List<string>();
+
                     stringBuilder.Append($"操作醍摩豆账户{item.tmdName}【{item.tmdId}】修改权限:{string.Join("|", listper.ToArray())}");
                    
                     item.roles = listroles.Count > 0 ? string.Join(",", listroles) : "assist";
                     item.permissions = string.Join(",", listper);
                     item.isDisable = isDisable;
-                    ddUserInfo.Add(item);
+                    ddUserInfos.Add(item);
 
                     roles = !string.IsNullOrEmpty($"{item.roles}") ? new List<string>(item.roles.Split(",")) : new List<string>();
                     permissions = !string.IsNullOrEmpty($"{item.permissions}") ? new List<string>(item.permissions.Split(",")) : new List<string>();
+
+                    foreach (var itemR in listroles)
+                    {
+                        if(itemR.Equals("assist"))
+                        {
+                            string tempSql = $"select value(c) from c join a in c.sales where a.id='{itemR}'";
+
+                            await foreach (var itemRel in cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<BIRelation>(queryText: tempSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BIRel") }))
+                            {
+                                var tempRel = itemRel.sales.Find(f => f.id.Equals(itemR));
+                                itemRel.sales.Remove(tempRel);
+                                itemRel.assists.Add(tempRel);
+                                itemRel.upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                                upBIRel.Add(cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<BIRelation>(itemRel, itemRel.id, new PartitionKey("BIRel")));
+                            }
+
+                            //string sql = $"select value(c) from c where c.pk='Teacher' and c.id='{item.tmdId}'";
+                            //await foreach (var scTch in cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<SchoolTeacher>(queryText: sql, requestOptions: new QueryRequestOptions() { })) 
+                            //{
+                            //    if (scTch.roles.Contains("sales"))
+                            //    {
+
+                            //        //int index = scTch.roles.FindIndex(fi => fi.Equals("sales"));
+                            //        //scTch.roles[index]= "assist";
+                            //        //scTch.job = "顾问";
+                            //        //upScTch.Add(cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(scTch, scTch.id, new PartitionKey($"{scTch.code}")));
+
+                            //        int index = scTch.roles.FindIndex(fi => fi.Equals("sales"));
+                            //        if (index >= 0)
+                            //        {
+                            //            scTch.roles[index] = "assist";
+                            //            scTch.job = "顾问";
+
+                            //            upScTch.Add(cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(scTch, scTch.id, new PartitionKey($"{scTch.code}")));
+                            //        }
+                            //    }                                
+                            //}                            
+                        }
+                        if (itemR.Equals("sales"))
+                        {
+
+
+                            string tempSql = $"select value(c) from c join a in c.assists where a.id='{itemR}'";
+
+                            await foreach (var itemRel in cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<BIRelation>(queryText: tempSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BIRel") }))
+                            {
+                                var tempRel = itemRel.sales.Find(f => f.id.Equals(itemR));
+                                itemRel.assists.Remove(tempRel);
+                                itemRel.sales.Add(tempRel);
+                                itemRel.upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                                upBIRel.Add(cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<BIRelation>(itemRel, itemRel.id, new PartitionKey("BIRel")));
+                            }
+
+                            //string sql = $"select value(c) from c where c.pk='Teacher' and c.id='{item.tmdId}'";
+                            //await foreach (var scTch in cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<SchoolTeacher>(queryText: sql, requestOptions: new QueryRequestOptions() { }))
+                            //{
+                            //    if (scTch.roles.Contains("assist"))
+                            //    {
+                            //        int index = scTch.roles.FindIndex(fi => fi.Equals("assist"));
+                            //        if (index >= 0) 
+                            //        {
+                            //            scTch.roles[index] = "sales";
+                            //            scTch.job = "销售";
+                            //            upScTch.Add(cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(scTch, scTch.id, new PartitionKey($"{scTch.code}")));
+                            //        }
+                            //    }
+                            //}
+                        }
+                    }
+                }
+
+                if (upBIRel.Count < 256)
+                {
+                    await Task.WhenAll(upBIRel);
+                }
+                else
+                {
+                    int pages = (upBIRel.Count + 255) / 256;
+                    for (int i = 0; i < pages; i++)
+                    {
+                        List<Task<ItemResponse<BIRelation>>> tempRel = upBIRel.Skip((i) * 256).Take(256).ToList();
+                        await Task.WhenAll(tempRel);
+                    }
                 }
 
-                ddUserInfo = await table.UpdateAll<DingDingUserInfo>(ddUserInfo);
+                ddUserInfos = await table.UpdateAll<DingDingUserInfo>(ddUserInfos);
+                List<DDUserInfo> ddUserInfo = new();
+                foreach (var item in ddUserInfos)
+                {
+                    DDUserInfo tempInfo = new()
+                    {
+                        partitionKey = item.PartitionKey,
+                        rowKey = item.RowKey,
+                        userId = item.userId,
+                        unionId = item.unionId,
+                        name = item.name,
+                        title = item.title,
+                        stateCode = item.stateCode,
+                        mobile = item.mobile,
+                        jobNumber = item.jobNumber,
+                        pid = item.pid,
+                        deptId = item.deptId,
+                        deptName = item.deptName,
+                        depts = item.depts,
+                        avatar = item.avatar,
+                        isAdmin = item.isAdmin,
+                        tmdId = item.tmdId,
+                        tmdName = item.tmdName,
+                        tmdMobile = item.tmdMobile,
+                        mail = item.mail,
+                        picture = item.picture,
+                        roles = item.roles,
+                        joinTime = item.joinTime,
+                        isDisable = item.isDisable,
+                        permissions = item.permissions,
+                        handleRoles = !string.IsNullOrEmpty($"{item.roles}") ? new List<string>(item.roles.Split(",")) : new List<string>(),
+                        handlePermissions = !string.IsNullOrEmpty($"{item.permissions}") ? new List<string>(item.permissions.Split(",")) : new List<string>(),
+                    };
+
+                    if (!string.IsNullOrEmpty(item.schoolIds))
+                    {
+                        List<string> tempSchoolIds = new(item.schoolIds.Split("|"));
+                        tempInfo.handleSchools = await SchoolWay.GetSchoolInfos(cosmosCliet, tempSchoolIds);
+                    }
+                    ddUserInfo.Add(tempInfo);
+                }
 
                 //保存操作记录
                 await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "tabledd-update", stringBuilder?.ToString(), _dingDing, httpContext: HttpContext);
@@ -422,7 +544,7 @@ namespace TEAMModelBI.Controllers.BITable
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"BI,{_option.Location}  /tabledd/set-rolesper   \n  {ex.Message}\n{ex.StackTrace} ", GroupNames.成都开发測試群組);
+                await _dingDing.SendBotMsg($"BI,{_option.Location}  /tabledd/tabledd-update   \n  {ex.Message}\n{ex.StackTrace} ", GroupNames.成都开发測試群組);
                 return BadRequest();
             }
         }
@@ -723,7 +845,7 @@ namespace TEAMModelBI.Controllers.BITable
                     {
                         if (string.IsNullOrEmpty(user.roles))
                         {
-                            user.roles = "admin,assist";
+                            user.roles = "admin";
                         }
                         List<string> tempRoles = new(user.roles.Split(","));
                         if (!tempRoles.Contains("admin"))
@@ -818,8 +940,6 @@ namespace TEAMModelBI.Controllers.BITable
 
                 var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
 
-                //HttpClient httpClient = _http.CreateClient();
-                //string url = _configuration.GetValue<string>("HaBookAuth:CoreId:userinfo");
 
                 //获取access_token
                 IDingTalkClient tokenClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
@@ -1067,7 +1187,7 @@ namespace TEAMModelBI.Controllers.BITable
             {
                 if (string.IsNullOrEmpty(user.roles))
                 {
-                    user.roles = "admin,assist";
+                    user.roles = "admin";
                 }
                 List<string> tempRoles = new(user.roles.Split(","));
                 if (!tempRoles.Contains("admin"))
@@ -1284,6 +1404,231 @@ namespace TEAMModelBI.Controllers.BITable
             }
         }
 
+        /// <summary>
+        /// 依据人员信息唯一编码修改人员信息表中的醍摩豆id信息相关的事情。
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [AuthToken(Roles = "admin")]
+        [HttpPost("set-usettmdinfo")]
+        public async Task<IActionResult> UpUserTmdInfo(JsonElement jsonElement)
+        {
+            try
+            {
+                var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
+                if (!jsonElement.TryGetProperty("partitionKey", out JsonElement partKey)) return BadRequest();
+                if (!jsonElement.TryGetProperty("rowKey", out JsonElement rowKey)) return BadRequest();
+                if (!jsonElement.TryGetProperty("role", out JsonElement role)) return BadRequest();
+
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                var tableClient = _azureStorage.GetCloudTableClient();
+                var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
+                var table = tableClient.GetTableReference("BIDDUserInfo");
+
+                StringBuilder msg = new($"{_tmdName}[{_tmdId}]将");
+                List<DingDingUserInfo> upUserInfos = new();
+
+                List<DDUserInfo> upUserInfo = new();
+                CoreUser coreUser = new();
+                string oldTmdId = null;
+                string reole = null;
+
+                var tempUser = await table.FindListByDict<DingDingUserInfo>(new Dictionary<string, object> { { "PartitionKey", $"{partKey}" }, { "RowKey", $"{rowKey}" } });
+                if (tempUser.Count > 0)
+                {
+                    foreach (var item in tempUser)
+                    {
+                        oldTmdId = item.tmdId;
+                        reole = item.roles;
+                        coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{item.mobile}" } }, _option.Location, _configuration);
+                        if (!string.IsNullOrEmpty(coreUser.id))
+                        {
+                            item.tmdId = coreUser.id;
+                            item.tmdName = coreUser.name;
+                            item.tmdMobile = coreUser.mobile;
+                            item.picture = coreUser.picture;
+                            item.mail = coreUser.mail;
+                            msg.Append($"{item.name}的{item.tmdId}账号改为新的{coreUser.id}账号;");
+                            upUserInfos.Add(item);
+                        }
+                        else return Ok(new { state = 404, msg = "依据钉钉手机号未找到醍摩豆账号!" });
+                    }
+                }
+
+                if (!string.IsNullOrEmpty(coreUser.id))
+                {
+                    msg.Append("并将学校就的学校信息移植到新的账号,移植的学校:");
+
+                    Teacher teacher = new();
+                    var respone = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync(coreUser.id, new PartitionKey("Base"));
+                    if (respone.Status == 200)
+                    {
+                        using var json = await JsonDocument.ParseAsync(respone.ContentStream);
+                        teacher = json.ToObject<Teacher>();
+                    }
+                    else
+                    {
+                        teacher = new Teacher()
+                        {
+                            id = coreUser.id,
+                            code = "Base",
+                            name = coreUser.name,
+                            picture = coreUser.picture,
+                            createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
+                        };
+                    }
+
+                    List<Task<ItemResponse<BIRelation>>> scRole = new();
+                    await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<BIRelation>(queryText: $"select value(c) from c join a in c.assists join s in c.sales  where c.code='BIRel' and  s.id='{oldTmdId}' or a.id='{oldTmdId}'", requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("BIRel") }))
+                    {
+                        var tempAss = item.assists.Find(f => f.id.Equals($"{oldTmdId}"));
+                        if (tempAss != null)
+                            item.assists.Remove(tempAss);
+                        var tempSa = item.sales.Find(f => f.id.Equals($"{oldTmdId}"));
+                        if (tempSa != null)
+                            item.sales.Remove(tempAss);
+
+                        switch ($"{role}")
+                        {
+                            case "assist":
+                                item.assists.Add(new IdInfo() { id = coreUser.id, name = coreUser.name, picture = coreUser.picture });
+                                break;
+                            case "sales":
+                                item.sales.Add(new IdInfo() { id = coreUser.id, name = coreUser.name, picture = coreUser.picture });
+                                break;
+                        }
+                        item.upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                        scRole.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<BIRelation>(item, item.id, new PartitionKey("BIRel")));
+                    }
+
+                    if (scRole.Count < 256)
+                        await Task.WhenAll(scRole);
+                    else
+                    {
+                        int pages = (scRole.Count + 255) / 256;
+                        for (int i = 0; i < pages; i++)
+                        {
+                            List<Task<ItemResponse<BIRelation>>> tempScRole = scRole.Skip((i) * 256).Take(256).ToList();
+                            await Task.WhenAll(tempScRole);
+                        }
+                    }
+
+                    //List<Task<ItemResponse<SchoolTeacher>>> schoolTeachers = new();
+                    //await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<SchoolTeacher>($"select value(c) from c where c.pk='Teacher' and c.id='{oldTmdId}'"))
+                    //{
+                    //    item.id = coreUser.id;
+                    //    var resp = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{coreUser.id}", new PartitionKey($"{item.code}"));
+                    //    if (resp.Status == 200)
+                    //    {
+                    //        using var json = await JsonDocument.ParseAsync(resp.ContentStream);
+                    //        SchoolTeacher scTeacher = json.ToObject<SchoolTeacher>();
+                    //        if (scTeacher.roles.Contains("sales"))
+                    //            scTeacher.roles.Remove("sales");
+                    //        if (scTeacher.roles.Contains("assist"))
+                    //            scTeacher.roles.Remove("assist");
+                    //        string scId = scTeacher.code.Substring(scTeacher.code.IndexOf("-") + 1);
+
+                    //        Teacher.TeacherSchool isExitId = null;
+                    //        isExitId = teacher.schools.Find(s => s.schoolId.Equals(scId));
+                    //        if (isExitId == null)
+                    //        {
+                    //            ScEasyInfo school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ScEasyInfo>(scId, new PartitionKey("Base"));
+                    //            msg.Append($"{school.name}[{school.id}],");
+                    //            teacher.schools.Add(new Teacher.TeacherSchool() { schoolId = school.id, name = school.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = school.picture, areaId = school.areaId });
+                    //        }
+
+                    //        scTeacher.roles.Add(reole);
+                    //        schoolTeachers.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(scTeacher, scTeacher.id, new PartitionKey($"{scTeacher.code}")));
+                    //    }
+                    //    else
+                    //    {
+                    //        item.name = coreUser.name;
+                    //        string scId = item.code.Substring(item.code.IndexOf("-") + 1);
+                    //        Teacher.TeacherSchool isExitId = null;
+                    //        isExitId = teacher.schools.Find(s => s.schoolId.Equals(scId));
+                    //        if (isExitId == null)
+                    //        {
+                    //            ScEasyInfo school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ScEasyInfo>(scId, new PartitionKey("Base"));
+                    //            msg.Append($"{school.name}[{school.id}],");
+                    //            teacher.schools.Add(new Teacher.TeacherSchool() { schoolId = school.id, name = school.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = school.picture, areaId = school.areaId });
+                    //        }
+
+                    //        schoolTeachers.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<SchoolTeacher>(item, new PartitionKey($"{item.code}")));
+                    //    }
+                    //}
+
+                    //if (schoolTeachers.Count < 256)
+                    //    await Task.WhenAll(schoolTeachers);
+                    //else
+                    //{
+                    //    int pages = (schoolTeachers.Count + 255) / 256;
+                    //    for (int i = 0; i < pages; i++)
+                    //    {
+                    //        List<Task<ItemResponse<SchoolTeacher>>> tempScTeachers = schoolTeachers.Skip((i) * 256).Take(256).ToList();
+                    //        await Task.WhenAll(tempScTeachers);
+                    //    }
+                    //}
+
+                    if (respone.Status == 200)
+                        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey("Base"));
+                    else
+                        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey("Base"));
+                    upUserInfos = await table.SaveOrUpdateAll<DingDingUserInfo>(upUserInfos);
+                }
+
+                //保存操作记录
+                await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "tabledd-update-tmdinfo", msg.ToString(), _dingDing, httpContext: HttpContext);
+
+                foreach (var item in upUserInfos)
+                {
+                    DDUserInfo tempUserInfo = new() 
+                    {
+
+                        partitionKey = item.PartitionKey,
+                        rowKey = item.RowKey,
+                        userId = item.userId,
+                        unionId = item.unionId,
+                        name = item.name,
+                        title = item.title,
+                        stateCode = item.stateCode,
+                        mobile = item.mobile,
+                        jobNumber = item.jobNumber,
+                        pid = item.pid,
+                        deptId = item.deptId,
+                        deptName = item.deptName,
+                        depts = item.depts,
+                        avatar = item.avatar,
+                        isAdmin = item.isAdmin,
+                        tmdId = item.tmdId,
+                        tmdName = item.tmdName,
+                        tmdMobile = item.tmdMobile,
+                        mail = item.mail,
+                        picture = item.picture,
+                        roles = item.roles,
+                        joinTime = item.joinTime,
+                        isDisable = item.isDisable,
+                        permissions = item.permissions,
+                        handleRoles = !string.IsNullOrEmpty($"{item.roles}") ? new List<string>(item.roles.Split(",")) : new List<string>(),
+                        handlePermissions = !string.IsNullOrEmpty($"{item.permissions}") ? new List<string>(item.permissions.Split(",")) : new List<string>(),
+
+                    };
+                    if (!string.IsNullOrEmpty(item.schoolIds))
+                    {
+                        List<string> tempSchoolIds = new(item.schoolIds.Split("|"));
+                        tempUserInfo.handleSchools = await SchoolWay.GetSchoolInfos(cosmosClient, tempSchoolIds);
+                    }
+                    upUserInfo.Add(tempUserInfo);
+                }
+                return Ok(new { state = RespondCode.Ok, upUserInfo });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location}   /tabledd/set-usettmdinfo   \n  {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
         /// <summary>
         /// 获取钉钉用户信息
         /// 并查询本地Table数据表中是否存在
@@ -1440,5 +1785,6 @@ namespace TEAMModelBI.Controllers.BITable
             public List<BaseInfo> handleSchools { get; set; } = new List<BaseInfo>();
         }
 
+
     }
 }

+ 2 - 2
TEAMModelBI/Controllers/BITest/Ies5TestController.cs

@@ -37,9 +37,9 @@ namespace TEAMModelBI.Controllers.BITest
         //读取配置文件
         private readonly IConfiguration _configuration;
         private readonly CoreAPIHttpService _coreAPIHttpService;
-        private readonly HttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClient;
 
-        public Ies5TestController(AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IWebHostEnvironment hostingEnvironment, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, HttpClient httpClient)
+        public Ies5TestController(AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IWebHostEnvironment hostingEnvironment, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, IHttpClientFactory httpClient)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 413 - 151
TEAMModelBI/Controllers/BITest/TestController.cs


+ 5 - 28
TEAMModelBI/Controllers/Census/ActivitySticsController.cs

@@ -183,7 +183,7 @@ namespace TEAMModelBI.Controllers.Census
                 }
             }
             else            
-                scSql = "select value(c.id) from c where c.areaId = null or c.areaId = ''";
+                scSql = "select value(c.id) from c where (c.areaId = null or c.areaId = '' or IS_DEFINED(c.areaId) = false)";
             
             if (setting == null)
             {
@@ -239,7 +239,7 @@ namespace TEAMModelBI.Controllers.Census
                 monthLess = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"{oftenSql} where c.pk='LessonRecord' and {comSql} and c.startTime >= {monthS} and c.startTime <= {monthE}");
 
                 //学时
-                totalTime = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", $"select value(sum(c.totalTime)) from c where c.pk='TeacherTrain' and {comSql}");
+                //totalTime = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", $"select value(sum(c.totalTime)) from c where c.pk='TeacherTrain' and {comSql}");
 
                 //活动
                 string actSpl = BICommonWay.ManyScSql(" and c.school", scIds);
@@ -260,7 +260,7 @@ namespace TEAMModelBI.Controllers.Census
                 //string stSql = $"{oftenSql} join s in c.currency where c.TeacherTrain and {comSql} and s.submitTime = 0 or s.submitTime >= {setting.submitTime}";
                 //submitCount = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", ctSql);
 
-                await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: $"select c.id,c.code,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and {comSql}", requestOptions: new QueryRequestOptions() { })) 
+                await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: $"select c.id,c.code,c.totalTime,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and {comSql}", requestOptions: new QueryRequestOptions() { })) 
                 {
                     using var json = await JsonDocument.ParseAsync(item.ContentStream);
                     if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
@@ -272,6 +272,8 @@ namespace TEAMModelBI.Controllers.Census
                     }
                 }
 
+                //学时
+                totalTime = trains.Select(s => s.totalTime).Sum();
                 trains.ForEach(x =>
                 {
                     //线上研修
@@ -952,31 +954,6 @@ namespace TEAMModelBI.Controllers.Census
             //public int stuCnt { get; set; } = 0;
         }
 
-        public class AreaStudy 
-        {
-            public string id { get; set; }
-
-            public string code { get; set; }
-
-            /// <summary>
-            /// 线上观看视频的学时
-            /// </summary>
-            public long onlineTime { get; set; }
-
-            /// <summary>
-            /// 线下研修学时
-            /// </summary>
-            public long offlineTime { get; set; }
-            /// <summary>
-            /// 课堂实录学时
-            /// </summary>
-            public long classTime { get; set; }
-            /// <summary>
-            /// 必修的
-            /// </summary>
-            public Currency currency { get; set; } = new Currency();
-        }
-
         private class SchoolInfo
         {
             public string id { get; set; }

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

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

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

@@ -14,9 +14,10 @@ using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Context.BI;
 using Azure.Core;
-using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
+using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Context.Constant;
 using DocumentFormat.OpenXml.Wordprocessing;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.Census
 {

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

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

+ 111 - 73
TEAMModelBI/Controllers/Census/PaperController.cs

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

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

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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 959 - 26
TEAMModelBI/Controllers/Census/SchoolController.cs


+ 12 - 4
TEAMModelBI/Controllers/LoginController.cs

@@ -355,7 +355,6 @@ namespace TEAMModelBI.Controllers
                 //    Website = BIConst.Global;
                 //}
 
-                HttpClient httpClient = _http.CreateClient();
                 var table = _azureStorage.GetCloudTableClient().GetTableReference("BIDDUserInfo");
                 var tempUser = await table.FindListByDict<DingDingUserInfo>(new Dictionary<string, object> { { "PartitionKey", $"{partitionKey}" }, { "userId", $"{userId}" } });
 
@@ -560,8 +559,8 @@ namespace TEAMModelBI.Controllers
                 loginSql = $"select value(c) from c where c.mail ={mail}";
             else return Ok(new { state = RespondCode.ParamsError, msg = "手机号/和邮箱为空" });
 
-            List<BusinessUsers> bizUsers = new();
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BusinessUsers>(queryText:loginSql,requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
+            List<BizUsers> bizUsers = new();
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BizUsers>(queryText:loginSql,requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
             {
                 bizUsers.Add(item);
             }
@@ -573,7 +572,16 @@ namespace TEAMModelBI.Controllers
                     var hashedPw = Utils.HashedPassword(password.ToString(), item.salt.ToString());
                     if (hashedPw.Equals(item.pwd))
                     {
-                        businessUsers = item;
+                        businessUsers = new()
+                        {
+                            id = item.id,
+                            code = item.code,
+                            name = item.name,
+                            picture = item.picture,
+                            mobile = item.mobile,
+                            mail = item.mail,
+                            relation = item.relation,
+                        };
                         //string id_token = JwtAuth.CreateAuthTokenBI(_option.HostName, bizUser.RowKey?.ToString(), bizUser.name?.ToString(), bizUser.picture?.ToString(), _option.JwtSecretKey, scope: "company", webSite: Website, expire: 3);
                         openid_token = JwtAuthExtension.CreateBizLoginAuthToken(_option.HostName, businessUsers.id?.ToString(), businessUsers.name?.ToString(), businessUsers.picture?.ToString(), $"{_option.Location}-Open", _option.JwtSecretKey, expire: 3);
 

+ 3 - 29
TEAMModelBI/Controllers/RepairApi/InitialAreaController.cs

@@ -13,7 +13,6 @@ using Azure.Messaging.ServiceBus;
 using TEAMModelBI.Tool.Extension;
 using TEAMModelOS.SDK.Extension;
 using Microsoft.AspNetCore.Hosting;
-using TEAMModelOS.SDK.DI.CoreAPI;
 using TEAMModelOS.SDK.Models;
 using Azure.Cosmos;
 using System;
@@ -24,6 +23,7 @@ using Pipelines.Sockets.Unofficial.Arenas;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
 using TEAMModelBI.Filter;
 using HTEXLib.COMM.Helpers;
+using TEAMModelBI.Models;
 
 namespace TEAMModelBI.Controllers.RepairApi
 {
@@ -36,20 +36,18 @@ namespace TEAMModelBI.Controllers.RepairApi
         private readonly Option _option;
         private readonly AzureStorageFactory _azureStorage;
         private readonly IConfiguration _configuration;
-        private readonly NotificationService _notificationService;
         private readonly AzureServiceBusFactory _serviceBus;
         private readonly IHttpClientFactory _http;
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IWebHostEnvironment _environment; //读取文件
 
-        public InitialAreaController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService, AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment)
+        public InitialAreaController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration,   AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
             _azureStorage = azureStorage;
             _option = option?.Value;
             _configuration = configuration;
-            _notificationService = notificationService;
             _serviceBus = serviceBus;
             _http = http;
             _coreAPIHttpService = coreAPIHttpService;
@@ -285,24 +283,7 @@ namespace TEAMModelBI.Controllers.RepairApi
                 {
                     return Ok(new { state = 201, msg = "能力点复制成功,复制能力点的文件失败," });
                 }
-
-                //发送消息实体
-                Notification notification = new()
-                {
-                    hubName = "hita",
-                    type = "msg",
-                    from = $"BI:{_option.Location}:private",
-                    to = new List<string> { $"{_tmdId}" },
-                    label = $"{partitionCode}_start",
-                    body = new { location = _option.Location, biz = partitionCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
-                    expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
-                };
-
-                var notiUrl = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
-                var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
-                var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
-                var location = _option.Location;
-                await _notificationService.SendNotification(clientID, clientSecret, location, notiUrl, notification); //站内发送消息
+ 
             }
 
             if (AreaS2 != null)
@@ -337,13 +318,6 @@ namespace TEAMModelBI.Controllers.RepairApi
         }
 
 
-        public record CopyStandard
-        {
-            public string id { get; set; }
-            public string standard { get; set; }
-            public string name { get; set; }
-        }
-
 
     }
 }

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

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

+ 573 - 0
TEAMModelBI/Controllers/RepairApi/SchoolRepController.cs

@@ -0,0 +1,573 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using System.Net.Http;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK;
+using TEAMModelOS.Models;
+using System.Threading.Tasks;
+using System.Text.Json;
+using System.IO;
+using TEAMModelBI.Models;
+using System.Collections.Generic;
+using System.Text;
+using TEAMModelOS.SDK.Extension;
+using System;
+using TEAMModelOS.SDK.Models;
+using Azure.Cosmos;
+using System.Linq;
+using TEAMModelOS.SDK.Context.Constant;
+using Pipelines.Sockets.Unofficial.Arenas;
+using TEAMModelBI.Tool;
+using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using DocumentFormat.OpenXml.Math;
+using TEAMModelOS.SDK.Models.Service.BI;
+using TEAMModelBI.Tool.CosmosBank;
+using TEAMModelOS.SDK.Models.Service.BIStatsWay;
+
+namespace TEAMModelBI.Controllers.RepairApi
+{
+    [Route("sccholrep")]
+    [ApiController]
+    public class SchoolRepController : ControllerBase
+    {
+
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly AzureRedisFactory _azureRedis;
+        private readonly IConfiguration _configuration;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly IWebHostEnvironment _environment; //读取文件
+        private readonly IHttpClientFactory _httpClient;
+
+        public SchoolRepController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, AzureRedisFactory azureRedis, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, IHttpClientFactory httpClient, IWebHostEnvironment hostingEnvironment)
+        {
+            _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _azureStorage = azureStorage;
+            _option = option?.Value;
+            _azureRedis = azureRedis;
+            _configuration = configuration;
+            _coreAPIHttpService = coreAPIHttpService;
+            _httpClient = httpClient;
+            _environment = hostingEnvironment;
+        }
+
+        /// <summary>
+        /// 添加新学段的学校
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-allscperiod")]
+        public async Task<IActionResult> SetAllScPeriod(JsonElement jsonElement)
+        {
+            jsonElement.TryGetProperty("Language", out JsonElement Language);
+            jsonElement.TryGetProperty("scId", out JsonElement scId);
+            jsonElement.TryGetProperty("periodName", out JsonElement periodName);
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
+            StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
+            StringBuilder stringBuilder = new();
+            string text;
+            while ((text = streamReader.ReadLine()) != null)
+            {
+                stringBuilder.Append(text.ToString());
+            }
+            streamReader.Close();
+            string input = stringBuilder.ToString();
+            List<SchoolConfig> schoolConfigs = input.ToObject<List<SchoolConfig>>();
+            SchoolConfig schoolConfig = null;
+            string Lang = string.Empty; //語系判斷用字串
+            if (!string.IsNullOrEmpty($"{Language}"))
+                schoolConfig = schoolConfigs.Find(x => x.Lang.Contains($"{Language}"));
+                Lang = $"{Language}";
+
+            if (schoolConfig == null)
+            {
+                //CN站
+                if(_option.Location.Contains("china", StringComparison.OrdinalIgnoreCase)) {
+                    if ($"{Language}".Contains("en"))
+                    {
+                        schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("en-US"));
+                        Lang = "en-US";
+                    }
+                    else
+                    {
+                        schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("zh-CN"));
+                        Lang = "zh-CN";
+                    }
+                }
+                //GL站
+                else
+                {
+                    if ($"{Language}".Contains("tw", StringComparison.OrdinalIgnoreCase))
+                    {
+                        schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("zh-TW"));
+                        Lang = "zh-TW";
+                    }
+                    else
+                    {
+                        schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("en-US"));
+                        Lang = "en-US";
+                    } 
+                }
+            }
+            string campusId = Guid.NewGuid().ToString();
+
+            //默認學段、通識科目、學前、语言 各語系名稱取得
+            string scName = string.Empty;
+            string subjectGeneral = string.Empty;
+            string subjectLanage = string.Empty;
+            string gradePreschool = string.Empty;
+            switch (Lang)
+            {
+                case "zh-CN":
+                    scName = "默认学段";
+                    subjectGeneral = "通识";
+                    subjectLanage = "语言";
+                    gradePreschool = "学前";
+                    break;
+                case "zh-TW":
+                    scName = "預設學段";
+                    subjectGeneral = "通識";
+                    subjectLanage = "語言";
+                    gradePreschool = "學前";
+                    break;
+                case "en-US":
+                    scName = "Default period";
+                    subjectGeneral = "General Studies";
+                    subjectLanage = "Language";
+                    gradePreschool = "Preschool";
+                    break;
+            }
+
+            StringBuilder noPeriodScSql = new("SELECT DISTINCT value(c) FROM c ");
+            List<School> allSc = new();
+            List<string> scidList = new(); //更新的學校ID(回傳值)
+
+            if (!string.IsNullOrEmpty($"{scId}"))
+                noPeriodScSql.Append($" where c.id='{scId}'");
+            else
+                noPeriodScSql.Append($" join sp in c.period where c.code = 'Base' AND ( NOT IS_DEFINED(sp.grades) OR ARRAY_LENGTH(sp.grades) = 0 OR NOT IS_DEFINED(sp.subjects) OR ARRAY_LENGTH(sp.subjects) = 0 )");
+
+            if (!string.IsNullOrEmpty($"{periodName}"))
+                scName = $"{periodName}";
+
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: "select value(c) from c where c.code='Base' and c.period=[]", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+            {
+                allSc.Add(item);
+            }
+
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: noPeriodScSql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+            {
+                allSc.Add(item);
+            }
+
+            foreach (var school in allSc)
+            {
+                if (school.name.Contains("幼儿园") || school.name.Contains("幼稚園") || school.name.Contains("幼兒園") || school.name.Contains("kindergarten", StringComparison.OrdinalIgnoreCase) || school.name.Contains("preschool", StringComparison.OrdinalIgnoreCase))
+                {
+                    List<Subject> newSubjects = new List<Subject>() {
+                        new Subject { id = Guid.NewGuid().ToString(), name = subjectLanage, type = 1 }
+                    };
+                    if (school.period.Count > 0)
+                    {
+                        List<Period> grades = school.period.FindAll(sg => sg.grades.Count == 0);
+                        foreach (Period grade in grades)
+                        {
+                            grade.grades = new List<string>() { gradePreschool };
+                            grade.gradeCount = grade.grades.Count;
+                        }
+                        List<Period> semesters = school.period.FindAll(sg => sg.semesters.Count == 0);
+                        foreach (Period semester in semesters)
+                        {
+                            semester.semesters = new List<Semester>() { 
+                                new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
+                                new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() }
+                            };
+                            semester.semesterCount = semester.semesters.Count;
+                        }
+                        List<Period> subjects = school.period.FindAll(sg => sg.subjects.Count == 0);
+                        foreach (Period subject in subjects)
+                        {
+                            subject.subjects = newSubjects;
+                            subject.subjectCount = subject.subjects.Count;
+                        }
+                    }
+                    else
+                    {
+                        if (school.campuses.Count > 0)
+                            campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
+
+                        school.period.Add(new Period
+                        {
+                            id = Guid.NewGuid().ToString(),
+                            name = scName,
+                            grades = new List<string>() { gradePreschool },
+                            campusId = campusId,
+                            subjects = newSubjects,
+                            semesters = new List<Semester>() { 
+                                new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
+                                new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() }
+                            },
+                            gradeCount = 1,
+                            semesterCount = 2,
+                            subjectCount = newSubjects.Count,
+                        });
+
+                        if (!school.campuses.Select(x => x.id).Contains(campusId))
+                            school.campuses.Add(new Campus { name = school.name, id = campusId });
+                    }
+                }
+                else
+                {
+                    if (school.period.Count > 0)
+                    {
+                        List<Period> grades = school.period.FindAll(sg => sg.grades.Count == 0);
+                        foreach (Period grade in grades)
+                        {
+                            grade.grades = schoolConfig.grades;
+                            grade.gradeCount = schoolConfig.grades.Count;
+                        }
+                        List<Period> semesters = school.period.FindAll(sg => sg.semesters.Count == 0);
+                        foreach (Period semester in semesters)
+                        {
+                            semester.semesters = new List<Semester>() 
+                            { 
+                                new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
+                                new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() }
+                            };
+                            semester.semesterCount = semester.semesters.Count;
+                        }
+                        List<Period> subjects = school.period.FindAll(sg => sg.subjects.Count == 0);
+                        foreach (Period subject in subjects)
+                        {
+                            subject.subjects = (school.type.Equals(2)) ? new List<Subject>() //高教
+                            {
+                                new Subject { id=Guid.NewGuid().ToString(),name=subjectGeneral,type=1 }
+                            } : new List<Subject>() //普教
+                            {
+                                new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
+                                new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
+                                new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
+                            };
+                            subject.subjectCount = subject.subjects.Count;
+                        }
+                    }
+                    else
+                    {
+                        if (school.campuses.Count > 0)
+                            campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
+
+                        school.period.Add(new Period
+                        {
+                            id = Guid.NewGuid().ToString(),
+                            name = scName,
+                            campusId = campusId,
+                            semesters = new List<Semester>() {
+                                new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
+                                new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() }
+                            },
+                            subjects = (school.type.Equals(2)) ? new List<Subject>() { //高教
+                                new Subject { id=Guid.NewGuid().ToString(),name=subjectGeneral,type=1 },
+                            } : new List<Subject>() { //普教
+                                new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
+                                new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
+                                new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
+                            },
+                            grades = schoolConfig.grades,
+                            analysis = new Analysis()
+                            {
+                                type = new List<ExamSimple>() {
+                                    new ExamSimple { id = Guid.NewGuid().ToString(), name = schoolConfig.PresetExam[0].type[0].name },
+                                    new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[1].name },
+                                    new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[2].name },
+                                    new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[3].name }
+                                },
+                                income = schoolConfig.PresetExam[0].income,
+                                eugenics = schoolConfig.PresetExam[0].eugenics,
+                                touch = schoolConfig.PresetExam[0].touch
+                            },
+                            gradeCount = schoolConfig.grades.Count,
+                            semesterCount = schoolConfig.semester.Count,
+                            subjectCount = (school.type.Equals(2)) ? 1 : schoolConfig.PresetSubject.Count
+                        });
+                        if (!school.campuses.Select(x => x.id).Contains(campusId))
+                            school.campuses.Add(new Campus { name = school.name, id = campusId });
+                    }
+                }
+                School rSchool = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey("Base"));
+                scidList.Add(rSchool.id);
+            }
+
+            return Ok(new { state = RespondCode.Ok, ids = scidList });
+        }
+
+        /// <summary>
+        /// 新增学校学段(多个)
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-scperiod")]
+        public async Task<IActionResult> SetScPeriod(JsonElement jsonElement)
+        {
+            if (!jsonElement.TryGetProperty("scId", out JsonElement scId)) return BadRequest();
+            if (!jsonElement.TryGetProperty("periodName", out JsonElement periodName)) return BadRequest();
+
+            List<string> periodNames = $"{periodName}".ToObject<List<string>>();
+            jsonElement.TryGetProperty("Language", out JsonElement Language);
+
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
+            StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
+            StringBuilder stringBuilder = new();
+            string text;
+            while ((text = streamReader.ReadLine()) != null)
+            {
+                stringBuilder.Append(text.ToString());
+            }
+            streamReader.Close();
+            string input = stringBuilder.ToString();
+            List<SchoolConfig> schoolConfigs = input.ToObject<List<SchoolConfig>>();
+            SchoolConfig schoolConfig = null;
+            if (!string.IsNullOrEmpty($"{Language}"))
+                schoolConfig = schoolConfigs.Find(x => x.Lang.Contains($"{Language}"));
+
+            if (schoolConfig == null)
+            {
+                if ($"{Language}".Contains("en"))
+                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("en-US"));
+                else
+                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("zh-CN"));
+            }
+            string campusId = Guid.NewGuid().ToString();
+            School school = null;
+
+            school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{scId}", new PartitionKey("Base"));
+
+            if (school != null)
+            {
+                foreach (var item in periodNames)
+                {
+                    if (school.campuses.Count > 0)
+                        campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
+
+                    school.period.Add(new Period
+                    {
+                        id = Guid.NewGuid().ToString(),
+                        name = item,
+                        campusId = campusId,
+                        semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
+                        new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
+                        subjects = new List<Subject>() {
+                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
+                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
+                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
+                        },
+                        grades = schoolConfig.grades,
+                        analysis = new Analysis()
+                        {
+                            type = new List<ExamSimple>() { new ExamSimple { id = Guid.NewGuid().ToString(), name = schoolConfig.PresetExam[0].type[0].name },
+                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[1].name },
+                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[2].name },
+                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[3].name } },
+                            income = schoolConfig.PresetExam[0].income,
+                            eugenics = schoolConfig.PresetExam[0].eugenics,
+                            touch = schoolConfig.PresetExam[0].touch
+                        }
+                    });
+                }
+
+                if (!school.campuses.Select(x => x.id).Contains(campusId))
+                    school.campuses.Add(new Campus { name = school.name, id = campusId });
+            }
+
+            school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey("Base"));
+
+            return Ok(new { state = RespondCode.Ok, school });
+        }
+
+        /// <summary>
+        /// 学校信息中间件查询和修复接口
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-allscinfos")]
+        public async Task<IActionResult> SetAllScInfos(JsonElement jsonElement)
+        {
+            try
+            {
+                jsonElement.TryGetProperty("scId", out JsonElement scId);
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                List<string> scIds = new();
+                if (!string.IsNullOrEmpty($"{scId}"))
+                    scIds.Add($"{scId}");
+                else
+                    scIds = await CommonFind.FindScIds(cosmosClient, "select value(c.id) from c ", "Base");
+
+                List<BIRelation> scInfos = new();
+                foreach (var itemId in scIds)
+                {
+                    BIRelation bIRelation = null;
+                    var resRel = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(itemId, new PartitionKey("BIRel"));
+                    if (resRel.Status == 200)
+                    {
+                        continue;
+                        //using var fileJson = await JsonDocument.ParseAsync(resRel.ContentStream);
+                        //bIRelation = fileJson.ToObject<BIRelation>();
+                    }
+                    else
+                    {
+                        ScBaseInfo scBaseInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ScBaseInfo>(itemId, new PartitionKey("Base"));
+                        string areaName = null;
+                        if (!string.IsNullOrEmpty(scBaseInfo.areaId))
+                        {
+                            await foreach (var itemName in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<string>(queryText: $"select value(c.name) from c where c.pk='Area' and c.id='{scBaseInfo.areaId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base-Area") }))
+                            {
+                                areaName = itemName;
+                            }
+                        }
+
+                        bIRelation = new BIRelation()
+                        {
+                            id = scBaseInfo.id,
+                            name = scBaseInfo.name,
+                            picture = scBaseInfo.picture,
+                            size = scBaseInfo.size,
+                            createDate = scBaseInfo.createTime,
+                            region = scBaseInfo.region,
+                            province = scBaseInfo.province,
+                            city = scBaseInfo.city,
+                            dist = scBaseInfo.dist,
+                            address = scBaseInfo.address,
+                            areaId = scBaseInfo.areaId,
+                            scale = scBaseInfo.scale,
+                            areaName = areaName,
+                            upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
+                        };
+
+                        var response = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(itemId, new PartitionKey("ProductSum"));
+                        if (response.Status == 200)
+                        {
+                            using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                            if (json.RootElement.TryGetProperty("serial", out JsonElement serial) && !serial.ValueKind.Equals(JsonValueKind.Null))
+                            {
+                                List<string> serials = serial.ToObject<List<SchoolProductSumData>>().Select(x => x.prodCode).ToList();
+                                bIRelation.serial = serials;
+                            }
+                            if (json.RootElement.TryGetProperty("service", out JsonElement service) && !service.ValueKind.Equals(JsonValueKind.Null))
+                            {
+                                List<string> services = service.ToObject<List<SchoolProductSumData>>().Select(x => x.prodCode).ToList();
+                                bIRelation.service = services;
+                            }
+                            if (json.RootElement.TryGetProperty("hard", out JsonElement hard) && !hard.ValueKind.Equals(JsonValueKind.Null))
+                            {
+                                List<string> hards = hard.ToObject<List<SchoolProductSumDataHard>>().Select(x => x.prodCode).ToList();
+                                bIRelation.hard = hards;
+                            }
+                        }
+                        bIRelation = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<BIRelation>(bIRelation, new PartitionKey("BIRel"));
+                    }
+
+                    scInfos.Add(bIRelation);
+                }
+
+                return Ok(new { state = RespondCode.Ok, cnt = scIds.Count, scInfos });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location},/sccholrep/set-allscinfos \n{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
+        /// <summary>
+        /// 修复所有学校统计数据中间件接口
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-allscstats")]
+        public async Task<IActionResult> SetAllScStats(JsonElement jsonElement)
+        {
+            string id = "";
+            try
+            {
+                jsonElement.TryGetProperty("scId", out JsonElement scId);
+                jsonElement.TryGetProperty("year", out JsonElement _year);
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                var redisClinet = _azureRedis.GetRedisClient(8);
+
+                List<string> scIds = new();
+                if (!string.IsNullOrEmpty($"{scId}"))
+                    scIds.Add($"{scId}");
+                else
+                    scIds = await CommonFind.FindScIds(cosmosClient, "select value(c.id) from c ", "Base");
+
+                DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+                int year = dateTime.Year;
+                if (!string.IsNullOrEmpty($"{_year}"))
+                {
+                    year = _year.GetInt32();
+                    dateTime = dateTime.AddYears(-1);
+                }
+
+                List<StatsInfo> statsInfos = new();
+                List<Task<ItemResponse<StatsInfo>>> taskStss = new();
+                foreach (var sc in scIds)
+                {
+                    id = sc;
+                    StatsInfo statsInfo = new();
+                    var scDataStats = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync($"{year}-{sc}", new PartitionKey("Statistics"));
+                    if (scDataStats.Status == 200)
+                    {
+                        using var fileJson = await JsonDocument.ParseAsync(scDataStats.ContentStream);
+                        statsInfo = fileJson.ToObject<StatsInfo>();
+                    }
+                    else
+                    {
+                        statsInfo.id = $"{year}-{sc}";
+                    }
+
+                    statsInfo = await SchoolStatsWay.GetSingleSc(cosmosClient, redisClinet, sc, year);
+                    statsInfo.witRoom = ((int)await SchoolStatsWay.GetShoolWisdomRoomCount(_azureCosmos, _azureRedis, _configuration, _httpClient, _dingDing, statsInfo.schoolId));
+
+                    if (scDataStats.Status == 200)
+                        taskStss.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync<StatsInfo>(statsInfo, $"{year}-{sc}", new PartitionKey("Statistics")));
+                    else
+                        taskStss.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync<StatsInfo>(statsInfo, new PartitionKey("Statistics")));
+
+                    //statsInfo = await StatsWay.upSingleSc(cosmosClient, sc);
+                    statsInfos.Add(statsInfo);
+                }
+
+                if (taskStss.Count < 256)
+                    await Task.WhenAll(taskStss);
+                else
+                {
+                    int pages = (taskStss.Count + 255) / 256;
+                    for (int i = 0; i < pages; i++)
+                    {
+                        List<Task<ItemResponse<StatsInfo>>> temTaskStss = taskStss.Skip(i * 256).Take(256).ToList();
+                        await Task.WhenAll(temTaskStss);
+                    }
+                }
+
+                return Ok(new { state = RespondCode.Ok, statsInfos });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location},/sccholrep/set-allscstats  学校id:{id} \n{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+    }
+}

+ 16 - 16
TEAMModelBI/JsonFile/Preset/LangSchoolConfig.json

@@ -2,34 +2,34 @@
     "Lang": "en-US",
     "semester": [
       {
-        "term": "Next Semester",
+        "term": "Second semester",
         "start": 1,
         "month": 3,
         "day": 1
       },
       {
-        "term": "Last Semester",
+        "term": "First semester",
         "start": 0,
         "month": 9,
         "day": 1
       }
     ],
     "grades": [
-      "First Grade",
-      "Second Grade",
-      "Third Grade"
+      "Grade 1",
+      "Grade 2",
+      "Grade 3"
     ],
     "PresetSubject": [
       {
-        "name": "language",
+        "name": "Science",
         "type": 1
       },
       {
-        "name": "Math",
+        "name": "English",
         "type": 1
       },
       {
-        "name": "English",
+        "name": "Math",
         "type": 1
       }
     ],
@@ -37,7 +37,7 @@
       {
         "type": [
           {
-            "name": "Ordinary Exam"
+            "name": "Regular Exam"
           },
           {
             "name": "Monthly Exam"
@@ -135,15 +135,15 @@
     ],
     "PresetSubject": [
       {
-        "name": "語文",
+        "name": "",
         "type": 1
       },
       {
-        "name": "數學",
+        "name": "",
         "type": 1
       },
       {
-        "name": "英語",
+        "name": "",
         "type": 1
       }
     ],
@@ -151,16 +151,16 @@
       {
         "type": [
           {
-            "name": "平常"
+            "name": "平常"
           },
           {
-            "name": "月"
+            "name": "月"
           },
           {
-            "name": "期中"
+            "name": "期中"
           },
           {
-            "name": "期末"
+            "name": "期末"
           }
         ],
         "income": 30,

+ 6 - 0
TEAMModelBI/LogLang/en-us.json

@@ -0,0 +1,6 @@
+{
+  "update-log-date": "Apply to join school",
+  "BI-NoticeHave": [ "{title}", "{content}", "{agree}", "refuse" ],
+  "BI-NoticeNothing": [ "{title}", "{content}" ],
+  "BI-NoticeSee": [ "{title}", "{content}", "see" ]
+}

+ 4 - 1
TEAMModelBI/LogLang/zh-cn.json

@@ -1,3 +1,6 @@
 {
-  "update-log-date": ["修改"]
+  "update-log-date": "修改",
+  "BI-NoticeHave": [ "{title}", "{content}", "{agree}", "refuse" ],
+  "BI-NoticeNothing": [ "{title}", "{content}" ],
+  "BI-NoticeSee": [ "{title}", "{content}","see" ]
 }

+ 6 - 0
TEAMModelBI/LogLang/zh-tw.json

@@ -0,0 +1,6 @@
+{
+  "update-log-date": "申請加入學校通知",
+  "BI-NoticeHave": [ "{title}", "{content}", "{agree}", "refuse" ],
+  "BI-NoticeNothing": [ "{title}", "{content}" ],
+  "BI-NoticeSee": [ "{title}", "{content}", "see" ]
+}

+ 0 - 1
TEAMModelBI/Models/AssistSchool.cs

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

+ 44 - 0
TEAMModelBI/Models/ForeEndModel.cs

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

+ 33 - 0
TEAMModelBI/Models/RearEndMiddle.cs

@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelBI.Models
+{
+    public class RearEndMiddle
+    {
+    }
+
+    /// <summary>
+    /// 简单信息
+    /// </summary>
+    public record EasyInfo
+    {
+        public string id { get; set; }
+        public string code { get; set; }
+        public string name { get; set; }
+    }
+
+    /// <summary>
+    /// BI学校信息
+    /// </summary>
+    public record BIRelStats : EasyInfo 
+    {
+        public int size { get; set; }
+        public int scale { get; set; }
+        public List<string> serial { get; set; }
+        public List<string> service { get; set; }
+        public List<string> hard { get; set; }
+
+
+    }
+}

+ 11 - 5
TEAMModelBI/Startup.cs

@@ -25,7 +25,7 @@ using TEAMModelOS.SDK.Filter;
 using TEAMModelOS.SDK.Helper.Common.ReflectorExtensions;
 using TEAMModelOS.SDK.Models;
 using VueCliMiddleware;
-using TEAMModelOS.SDK.DI.CoreAPI;
+using System.Net.Http;
 
 namespace TEAMModelBI
 {
@@ -126,10 +126,16 @@ namespace TEAMModelBI
 
             services.AddSnowflakeId(Convert.ToInt64(Configuration.GetValue<string>("Option:LocationNum")), 1);
             services.AddHttpClient();
-            services.AddHttpClient<DingDing>(); 
-            services.AddHttpClient<NotificationService>();
-            services.AddCoreAPIHttpService(Configuration);
-            services.AddHttpClient<CoreAPIHttpService>();
+            services.AddHttpClient<DingDing>();
+            //services.AddCoreAPIHttpService(Configuration);
+            services.AddHttpClient<CoreAPIHttpService>().ConfigureHttpMessageHandlerBuilder(builder =>
+            {
+                builder.PrimaryHandler = new HttpClientHandler
+                {
+                    ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
+                };
+            });
+            services.AddHttpClient<HttpTrigger>();
             services.AddMemoryCache();
             services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = false; });
             services.Configure<SysConfig>(Configuration.GetSection("sysConfig"));  //注册连接

+ 13 - 6
TEAMModelBI/TEAMModelBI.csproj

@@ -45,9 +45,18 @@
 	    <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
 	    <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
 	  </Content>
+	  <Content Update="LogLang\en-us.json">
+	    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+	  </Content>
 	  <Content Update="LogLang\zh-cn.json">
 	    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
 	  </Content>
+	  <Content Update="LogLang\zh-tw.json">
+	    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+	  </Content>
+	</ItemGroup>
+	<ItemGroup>
+	  <Folder Include="wwwroot\" />
 	</ItemGroup>
 	<PropertyGroup>
 		<SpaRoot>ClientApp\</SpaRoot>
@@ -59,9 +68,9 @@
 		<SpaRoot>ClientApp\</SpaRoot>
 		<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
 		<UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-		<Version>1.2210.26</Version>
-		<AssemblyVersion>1.2210.26.1</AssemblyVersion>
-		<FileVersion>1.2210.26.1</FileVersion>
+		<Version>1.2302.17</Version>
+		<AssemblyVersion>1.2302.17.1</AssemblyVersion>
+		<FileVersion>1.2302.17.1</FileVersion>
 		<Description>TEAMModelBI(BI)</Description>
 		<PackageReleaseNotes>BI版本说明版本切换标记2022000908</PackageReleaseNotes>
 		<PackageId>TEAMModelBI</PackageId>
@@ -113,9 +122,7 @@
 	</Target>
 
 	<ProjectExtensions>
-		<VisualStudio>
-			<UserProperties appsettings_1json__JsonSchema="" clientapp_4package_1json__JsonSchema="" />
-		</VisualStudio>
+		<VisualStudio><UserProperties appsettings_1json__JsonSchema="" clientapp_4package_1json__JsonSchema="" loglang_4zh-cn_1json__JsonSchema="https://appliedengdesign.github.io/cnccodes-json-schema/draft/2022-07/schema" /></VisualStudio>
 	</ProjectExtensions>
 </Project>
 

+ 19 - 10
TEAMModelBI/Tool/CommonFind.cs

@@ -1,4 +1,5 @@
 using Azure.Cosmos;
+using DocumentFormat.OpenXml.Spreadsheet;
 using System;
 using System.Collections.Generic;
 using System.Text;
@@ -54,7 +55,7 @@ namespace TEAMModelBI.Tool
         /// <param name="cosmosClient">cosmosDB连接</param>
         /// <param name="tmdId">醍摩豆账户</param>
         /// <returns>返回顾问相关的学校ID集合</returns>
-        public static async Task<List<string>> FindSchoolIds(CosmosClient cosmosClient, string tmdId,string roles= "assist")
+        public static async Task<List<string>> FindSchoolIds(CosmosClient cosmosClient, string tmdId,string roles = "assist", bool isMany = false)
         {
             List<string> schoolIds = new();
             //string schoolSql = $"SELECT DISTINCT REPLACE(c.code,'Teacher-','') AS schoolId,c.code,c.roles,c.id,c.name From c where ARRAY_CONTAINS(c.roles,'assist',true) AND c.status = 'join' AND c.id='{tmdId}'";
@@ -67,8 +68,12 @@ namespace TEAMModelBI.Tool
             //    }
             //}
 
-            string schoolSql = $"SELECT value(REPLACE(c.code, 'Teacher-', '')) FROM c where array_contains(c.roles,'{roles}',true) and c.pk='Teacher' and c.id='{tmdId}'";
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText: schoolSql, requestOptions: new QueryRequestOptions() { }))
+            StringBuilder schoolSql = new($"SELECT value(REPLACE(c.code, 'Teacher-', '')) FROM c where c.pk='Teacher' and c.id='{tmdId}'");
+            if (isMany == true)
+                schoolSql.Append($" and (array_contains(c.roles,'assist',true) or array_contains(c.roles,'sales',true))");
+            else
+                schoolSql.Append($" and array_contains(c.roles,'{roles}',true)");
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText: schoolSql.ToString(), requestOptions: new QueryRequestOptions() { }))
             {
                 schoolIds.Add(item);
             }
@@ -129,16 +134,20 @@ namespace TEAMModelBI.Tool
         public static async Task<List<string>> FindScIds(CosmosClient cosmosClient, string sqlTxt, string code)
         {
             List<string> schoolIds = new();
-
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
             {
-                using var json = await JsonDocument.ParseAsync(item.ContentStream);
-                foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
-                {
-                    schoolIds.Add(obj.GetProperty("id").GetString());
-                }
+                schoolIds.Add(item);
             }
 
+            //await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
+            //{
+            //    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+            //    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+            //    {
+            //        schoolIds.Add(obj.GetProperty("id").GetString());
+            //    }
+            //}
+
             return schoolIds;
         }
 

+ 40 - 27
TEAMModelBI/Tool/CosmosBank/ActivityWay.cs

@@ -19,45 +19,49 @@ namespace TEAMModelBI.Tool.CosmosBank
         public async static Task<int> GetAll(CosmosClient cosmosClient, List<string> scIds = null, List<string> tecIds = null)
         {
             int totals = 0;
-            string sqlTxt = "select count(c.id) as totals from c";
-            foreach (string type in types)
+            try
             {
-                if (scIds.Count > 0)
+                string sqlTxt = "select count(c.id) as totals from c";
+                foreach (string type in types)
                 {
-                    foreach (string sc in scIds)
+                    if (scIds.Count > 0)
                     {
-                        await foreach (var itemTeac in cosmosClient.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{type}-{sc}") }))
+                        foreach (string sc in scIds)
                         {
-                            using var json = await JsonDocument.ParseAsync(itemTeac.ContentStream);
-                            if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetInt32() > 0)
+                            await foreach (var itemTeac in cosmosClient.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{type}-{sc}") }))
                             {
-                                foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                                using var json = await JsonDocument.ParseAsync(itemTeac.ContentStream);
+                                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetInt32() > 0)
                                 {
-                                    totals += obj.GetProperty("totals").GetInt32();
+                                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                                    {
+                                        totals += obj.GetProperty("totals").GetInt32();
+                                    }
                                 }
                             }
                         }
                     }
-                }
 
-                if (tecIds.Count > 0)
-                {
-                    foreach (string sc in scIds)
+                    if (tecIds.Count > 0)
                     {
-                        await foreach (var itemTeac in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{type}-{sc}") }))
+                        foreach (string sc in scIds)
                         {
-                            using var json = await JsonDocument.ParseAsync(itemTeac.ContentStream);
-                            if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetInt32() > 0)
+                            await foreach (var itemTeac in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{type}-{sc}") }))
                             {
-                                foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                                using var json = await JsonDocument.ParseAsync(itemTeac.ContentStream);
+                                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetInt32() > 0)
                                 {
-                                    totals += obj.GetProperty("totals").GetInt32();
+                                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                                    {
+                                        totals += obj.GetProperty("totals").GetInt32();
+                                    }
                                 }
                             }
                         }
                     }
                 }
             }
+            catch { }
             return totals;
         }
 
@@ -72,14 +76,19 @@ namespace TEAMModelBI.Tool.CosmosBank
         public static async Task<int> GetCnt(CosmosClient cosmosClient, string container = "Common", string condSql = null, string code = null) 
         {
             int total = 0;
-            foreach (string type in types)
+            try
             {
-                string sqlTxt = $"select value(count(c.id)) from c where c.pk='{type}' {condSql}";
-                await foreach (var cnt in cosmosClient.GetContainer("TEAMModelOS", container).GetItemQueryIterator<int>(queryText: sqlTxt, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") })) 
+                foreach (string type in types)
                 {
-                    total += cnt;
+                    string sqlTxt = $"select value(count(c.id)) from c where c.pk='{type}' {condSql}";
+                    await foreach (var cnt in cosmosClient.GetContainer("TEAMModelOS", container).GetItemQueryIterator<int>(queryText: sqlTxt, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+                    {
+                        total += cnt;
+                    }
                 }
             }
+            catch { }
+
             return total;
         }
 
@@ -94,17 +103,21 @@ namespace TEAMModelBI.Tool.CosmosBank
         public static async Task<int> GetCnt(CosmosClient cosmosClient, List<string> containers, string condSql = null, string code = null)
         {
             int total = 0;
-            foreach (var container in containers)
+            try
             {
-                foreach (string type in types)
+                foreach (var container in containers)
                 {
-                    string sqlTxt = $"select value(count(c.id)) from c where c.pk='{type}' {condSql}";
-                    await foreach (var cnt in cosmosClient.GetContainer("TEAMModelOS", container).GetItemQueryIterator<int>(queryText: sqlTxt, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+                    foreach (string type in types)
                     {
-                        total += cnt;
+                        string sqlTxt = $"select value(count(c.id)) from c where c.pk='{type}' {condSql}";
+                        await foreach (var cnt in cosmosClient.GetContainer("TEAMModelOS", container).GetItemQueryIterator<int>(queryText: sqlTxt, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+                        {
+                            total += cnt;
+                        }
                     }
                 }
             }
+            catch { }
             return total;
         }
 

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

@@ -4,7 +4,7 @@ using System.Threading.Tasks;
 
 namespace TEAMModelBI.Tool.CosmosBank
 {
-    public class JointlySingleQuery
+    public class JointlySingleQuery1
     {
         /// <summary>
         /// 多个容器返回整数 使用

+ 172 - 117
TEAMModelBI/Tool/CosmosBank/SchoolWay.cs

@@ -8,6 +8,7 @@ using TEAMModelBI.Models;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
 
 namespace TEAMModelBI.Tool.CosmosBank
 {
@@ -19,7 +20,7 @@ namespace TEAMModelBI.Tool.CosmosBank
         /// <param name="cosmosClient"></param>
         /// <param name="schoolIds"></param>
         /// <returns></returns>
-        public async static Task<List<BaseInfo>> GetSchoolInfos(CosmosClient cosmosClient, List<string> schoolIds) 
+        public async static Task<List<BaseInfo>> GetSchoolInfos(CosmosClient cosmosClient, List<string> schoolIds)
         {
             List<BaseInfo> advSchools = new();
             foreach (var item in schoolIds)
@@ -43,138 +44,192 @@ namespace TEAMModelBI.Tool.CosmosBank
         /// <param name="schoolIds"></param>
         /// <param name="busy"></param>
         /// <returns></returns>
-        public async static Task<List<string>> SchoolAdviser(CosmosClient cosmosClient, DingDingUserInfo ddUserInfo,List<string> schoolIds ,string busy) 
+        public async static Task<List<string>> SchoolAdviser(CosmosClient cosmosClient, DingDingUserInfo ddUserInfo, List<string> schoolIds, string role, string busy)
         {
-            Teacher teacher = null;
-            bool isReadTec = false;
-            bool isAddUpd = false;
             List<string> noSchool = new();
-             var tecResponse = await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(ddUserInfo.tmdId, new PartitionKey($"Base"));
-            if (tecResponse.Status == 200)
-            {
-                JsonDocument jsonDocument = JsonDocument.Parse(tecResponse.Content);
-                teacher = jsonDocument.RootElement.ToObject<Teacher>();
-            }
-            else 
-            {
-                teacher = new Teacher()
-                {
-                    id = ddUserInfo.tmdId,
-                    name = ddUserInfo.tmdName,
-                    picture = ddUserInfo.picture,
-                    size = 1,
-                    code = "Base",
-                    pk = "Base",
-                };
-                isAddUpd = true;
-            }
-            List<Task<ItemResponse<SchoolTeacher>>> addSchoolTeache = new();
-            List<Task<ItemResponse<SchoolTeacher>>> updSchoolTeache = new();
-
-            foreach (var schoolId in schoolIds)
+            foreach (var item in schoolIds)
             {
-                School school = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>(schoolId, new PartitionKey("Base"));
-                var tempSc = teacher.schools.Find(x => x.schoolId == schoolId);
-                if (tempSc == null)
+                BIRelation bIRelation = new();
+                var resBiRel = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(item, new PartitionKey($"BIRel"));
+                if (resBiRel.Status == 200)
                 {
-                    teacher.schools.Add(new Teacher.TeacherSchool { schoolId = school.id, name = school.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = school.picture, areaId = school.areaId });
-                    isReadTec = true;
+                    JsonDocument jsonD = JsonDocument.Parse(resBiRel.Content);
+                    bIRelation = jsonD.RootElement.ToObject<BIRelation>();
                 }
-                SchoolTeacher schoolTeacher = new();
-                var stResponse  = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(ddUserInfo.tmdId, new PartitionKey($"Teacher-{schoolId}"));
-                if (stResponse.Status == 200)
-                {
-                    JsonDocument tempJson = JsonDocument.Parse(stResponse.Content);
-                    schoolTeacher = tempJson.RootElement.ToObject<SchoolTeacher>();
 
-                    if ($"{busy}".Equals("add"))
-                    {
-                        if (!schoolTeacher.roles.Contains("assist"))
-                        {
-                            schoolTeacher.roles.Add("assist");
-                            addSchoolTeache.Add(cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, schoolTeacher.id, new PartitionKey($"Teacher-{schoolId}")));
-                        }
-                        else
-                            noSchool.Add(schoolId);
-                    }
-                    if ($"{busy}".Equals("del"))
-                    {
-                        if (schoolTeacher.roles.Contains("assist"))
-                        {
-                            schoolTeacher.roles.Remove("assist");
-                            teacher.schools.Remove(teacher.schools.Find(x => x.schoolId == schoolId));
-                            updSchoolTeache.Add(cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, schoolTeacher.id, new PartitionKey($"Teacher-{schoolId}")));
-                        }
-                        else
-                            noSchool.Add(schoolId);
-                    }
-                }
-                else 
-                {                
-                    schoolTeacher = new SchoolTeacher()
-                    {
-                        id = ddUserInfo.tmdId,
-                        name = ddUserInfo.tmdName,
-                        picture = ddUserInfo.picture,
-                        job = "顾问",
-                        subjectIds = new List<string>(),
-                        roles = new List<string> { "assist" },
-                        permissions = new List<string>(),
-                        status = "join",
-                        code = $"Teacher-{schoolId}",
-                        pk = "Teacher",
-                        createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
-                    };
-
-                    addSchoolTeache.Add(cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code)));
-                }
-            }
-            if (isReadTec == true)
-            {
-                if (isAddUpd == true)
+                if (role.Equals("assist"))
                 {
-                    await cosmosClient.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey($"Base"));
-                }
-                else
-                {
-                    await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey("Base"));
-                }
-            }
-            if (updSchoolTeache.Count > 0)
-            {
-                if (updSchoolTeache.Count < 256)
-                {
-                    await Task.WhenAll(updSchoolTeache);
-                }
-                else
-                {
-                    int pages = (updSchoolTeache.Count + 255) / 256;
-                    for (int i = 0; i < pages; i++)
+                    switch ($"{busy}")
                     {
-                        List<Task<ItemResponse<SchoolTeacher>>> tempAbility = updSchoolTeache.Skip((i) * 256).Take(256).ToList();
-                        await Task.WhenAll(tempAbility);
+                        case "add":
+                            var addAss = bIRelation.assists.Find(f => f.id.Equals(ddUserInfo.tmdId));
+                            if (addAss == null)
+                                bIRelation.assists.Add(new IdInfo() { id = ddUserInfo.tmdId, name = ddUserInfo.tmdName, picture = ddUserInfo.picture });
+                            break;
+                        case "del":
+                            var delAss = bIRelation.assists.Find(f => f.id.Equals(ddUserInfo.tmdId));
+                            if (delAss != null)
+                                bIRelation.assists.Remove(new IdInfo() { id = ddUserInfo.tmdId, name = ddUserInfo.tmdName, picture = ddUserInfo.picture });
+                            break;
                     }
                 }
-            }
-
-            if (addSchoolTeache.Count > 0)
-            {
-                if (addSchoolTeache.Count < 256)
-                {
-                    await Task.WhenAll(addSchoolTeache);
-                }
-                else
+                if (role.Equals("sales"))
                 {
-                    int pages = (addSchoolTeache.Count + 255) / 256;
-                    for (int i = 0; i < pages; i++)
+                    switch ($"{busy}")
                     {
-                        List<Task<ItemResponse<SchoolTeacher>>> tempAbility = addSchoolTeache.Skip((i) * 256).Take(256).ToList();
-                        await Task.WhenAll(tempAbility);
+                        case "add":
+                            var tempSa = bIRelation.sales.Find(f => f.id.Equals(ddUserInfo.tmdId));
+                            if (tempSa == null)
+                                bIRelation.sales.Add(new IdInfo() { id = ddUserInfo.tmdId, name = ddUserInfo.tmdName, picture = ddUserInfo.picture });
+                            break;
+                        case "del":
+                            var delSa = bIRelation.sales.Find(f => f.id.Equals(ddUserInfo.tmdId));
+                            if (delSa != null)
+                                bIRelation.sales.Remove(new IdInfo() { id = ddUserInfo.tmdId, name = ddUserInfo.tmdName, picture = ddUserInfo.picture });
+                            break;
                     }
                 }
+                bIRelation.upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<BIRelation>(bIRelation, bIRelation.id, new PartitionKey("BIRel"));
             }
 
-            return noSchool; 
+            return noSchool;
+
+            //List<string> noSchool = new();
+            //Teacher teacher = null;
+            //bool isReadTec = false;
+            //bool isAddUpd = false;
+            //string joinStatus = "";
+            //if (role.Equals("assist"))
+            //    joinStatus = "顾问";
+            //if (role.Equals("sales"))
+            //    joinStatus = "销售";
+            //var tecResponse = await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(ddUserInfo.tmdId, new PartitionKey($"Base"));
+            //if (tecResponse.Status == 200)
+            //{
+            //    JsonDocument jsonDocument = JsonDocument.Parse(tecResponse.Content);
+            //    teacher = jsonDocument.RootElement.ToObject<Teacher>();
+            //}
+            //else 
+            //{
+            //    teacher = new Teacher()
+            //    {
+            //        id = ddUserInfo.tmdId,
+            //        name = ddUserInfo.tmdName,
+            //        picture = ddUserInfo.picture,
+            //        size = 1,
+            //        code = "Base",
+            //        pk = "Base",
+            //    };
+            //    isAddUpd = true;
+            //}
+            //List<Task<ItemResponse<SchoolTeacher>>> addSchoolTeache = new();
+            //List<Task<ItemResponse<SchoolTeacher>>> updSchoolTeache = new();
+
+            //foreach (var schoolId in schoolIds)
+            //{
+            //    School school = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>(schoolId, new PartitionKey("Base"));
+            //    var tempSc = teacher.schools.Find(x => x.schoolId == schoolId);
+            //    if (tempSc == null)
+            //    {
+            //        teacher.schools.Add(new Teacher.TeacherSchool { schoolId = school.id, name = school.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = school.picture, areaId = school.areaId });
+            //        isReadTec = true;
+            //    }
+            //    SchoolTeacher schoolTeacher = new();
+            //    var stResponse  = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(ddUserInfo.tmdId, new PartitionKey($"Teacher-{schoolId}"));
+            //    if (stResponse.Status == 200)
+            //    {
+            //        JsonDocument tempJson = JsonDocument.Parse(stResponse.Content);
+            //        schoolTeacher = tempJson.RootElement.ToObject<SchoolTeacher>();
+
+            //        if ($"{busy}".Equals("add"))
+            //        {
+            //            if (!schoolTeacher.roles.Contains($"{role}"))
+            //            {
+            //                schoolTeacher.roles.Add($"{role}");
+            //                addSchoolTeache.Add(cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, schoolTeacher.id, new PartitionKey($"Teacher-{schoolId}")));
+            //            }
+            //            else
+            //                noSchool.Add(schoolId);
+            //        }
+            //        if ($"{busy}".Equals("del"))
+            //        {
+            //            if (schoolTeacher.roles.Contains($"{role}"))
+            //            {
+            //                schoolTeacher.roles.Remove($"{role}");
+            //                teacher.schools.Remove(teacher.schools.Find(x => x.schoolId == schoolId));
+            //                updSchoolTeache.Add(cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, schoolTeacher.id, new PartitionKey($"Teacher-{schoolId}")));
+            //            }
+            //            else
+            //                noSchool.Add(schoolId);
+            //        }
+            //    }
+            //    else 
+            //    {                
+            //        schoolTeacher = new SchoolTeacher()
+            //        {
+            //            id = ddUserInfo.tmdId,
+            //            name = ddUserInfo.tmdName,
+            //            picture = ddUserInfo.picture,
+            //            job = joinStatus,
+            //            subjectIds = new List<string>(),
+            //            roles = new List<string> { $"{role}" },
+            //            permissions = new List<string>(),
+            //            status = "join",
+            //            code = $"Teacher-{schoolId}",
+            //            pk = "Teacher",
+            //            createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
+            //        };
+
+            //        addSchoolTeache.Add(cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code)));
+            //    }
+            //}
+            //if (isReadTec == true)
+            //{
+            //    if (isAddUpd == true)
+            //    {
+            //        await cosmosClient.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey($"Base"));
+            //    }
+            //    else
+            //    {
+            //        await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey("Base"));
+            //    }
+            //}
+            //if (updSchoolTeache.Count > 0)
+            //{
+            //    if (updSchoolTeache.Count < 256)
+            //    {
+            //        await Task.WhenAll(updSchoolTeache);
+            //    }
+            //    else
+            //    {
+            //        int pages = (updSchoolTeache.Count + 255) / 256;
+            //        for (int i = 0; i < pages; i++)
+            //        {
+            //            List<Task<ItemResponse<SchoolTeacher>>> tempAbility = updSchoolTeache.Skip((i) * 256).Take(256).ToList();
+            //            await Task.WhenAll(tempAbility);
+            //        }
+            //    }
+            //}
+
+            //if (addSchoolTeache.Count > 0)
+            //{
+            //    if (addSchoolTeache.Count < 256)
+            //    {
+            //        await Task.WhenAll(addSchoolTeache);
+            //    }
+            //    else
+            //    {
+            //        int pages = (addSchoolTeache.Count + 255) / 256;
+            //        for (int i = 0; i < pages; i++)
+            //        {
+            //            List<Task<ItemResponse<SchoolTeacher>>> tempAbility = addSchoolTeache.Skip((i) * 256).Take(256).ToList();
+            //            await Task.WhenAll(tempAbility);
+            //        }
+            //    }
+            //}
+
+            //return noSchool; 
         }
 
     }

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

@@ -0,0 +1,496 @@
+using Azure.Cosmos;
+using DocumentFormat.OpenXml.Bibliography;
+using DocumentFormat.OpenXml.Math;
+using DocumentFormat.OpenXml.Office2010.Excel;
+using Microsoft.OData.Edm;
+using NUnit.Framework.Constraints;
+using OpenXmlPowerTools;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelBI.Models;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Cosmos.BI.BITable;
+using TEAMModelOS.SDK.Models.Service.BI;
+using TEAMModelOS.SDK.Models.Service.BIStatsWay;
+using static TEAMModelBI.Tool.CosmosBank.StatsWay;
+
+namespace TEAMModelBI.Tool.CosmosBank
+{
+    public static class StatsWay
+    {
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="scId"></param>
+        /// <returns></returns>
+        public static async Task<StatsInfo> upSingleSc(CosmosClient cosmosClient, string scId)
+        {
+
+            StatsInfo statsInfo = new() { id = $"{scId}" };
+
+            DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+            var (dayS, dayE) = TimeHelper.GetStartOrEnd(dateTime);  //今天开始时间    13位
+            var (lastWeekS, lastWeekE) = TimeHelper.GetStartOrEnd(dateTime, "lastweek");   //计算上周开始/结束时间
+            var (weekS, weekE) = TimeHelper.GetStartOrEnd(dateTime, "week");             //计算本周开始/结束时间
+
+            var (lastTermS, lastTermE) = TimeHelper.GetStartOrEnd(dateTime, "lastterm");   //计算上学期开始/结束时间
+            var (termS, termE) = TimeHelper.GetStartOrEnd(dateTime, "term");   //计算本学期开始/结束时间
+
+            var (lastMthS, LastmthE) = TimeHelper.GetStartOrEnd(dateTime, "lastMonth");  //上月开始/结束时间
+            var (mthS, mthE) = TimeHelper.GetStartOrEnd(dateTime, "month");  //本月开始/结束时间
+
+            var (lastYearS, lastYearE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year - 1}-1-1"), "year"); //计算去年开始/结束时间
+            var (yearS, yearE) = TimeHelper.GetStartOrEnd(dateTime, "year");         //计算今年开始/结束时间
+
+            string currSql = "select value(count(c.id)) from c";
+            string dayWhereSql = $"c.createTime >= {dayS} and c.createTime <= {dayE}";
+            string weekWhereSql = $"c.createTime >= {weekS} and c.createTime <= {weekE}";
+            string monthWhereSql = $"c.createTime >= {mthS} and c.createTime <= {mthE}";
+
+            ScBase scBase = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<ScBase>(statsInfo.id, new PartitionKey("Base"));
+            statsInfo.name = scBase.name;
+            statsInfo.picture = scBase.picture;
+            statsInfo.size = scBase.size;
+            statsInfo.scCreateTime = scBase.createTime;
+            statsInfo.areaId = scBase.areaId;
+
+            string tchSql = $"{currSql} where ARRAY_CONTAINS(c.roles, 'teacher', true) AND c.status = 'join'";
+            statsInfo.tch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", tchSql, $"Teacher-{scBase.id}");
+            statsInfo.dayTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and {dayWhereSql} ", $"Teacher-{scBase.id}");
+            statsInfo.weekTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {weekWhereSql}", $"Teacher-{scBase.id}");
+            statsInfo.monthTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {monthWhereSql}", $"Teacher-{scBase.id}");
+
+            statsInfo.stu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", currSql, $"Base-{scBase.id}");
+            statsInfo.dayStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {dayWhereSql}", $"Base-{scBase.id}");
+            statsInfo.weekStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {weekWhereSql}", $"Base-{scBase.id}");
+            statsInfo.monthStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {monthWhereSql}", $"Base-{scBase.id}");
+
+            statsInfo.room = await JointlySingleQuery.GetValueInt(cosmosClient, "School", currSql, $"Room-{scBase.id}");
+            statsInfo.witRoom = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{currSql} where (c.serial != null or c.serial != '' or IS_DEFINED(c.serial) = true)", $"Room-{scBase.id}");
+            statsInfo.resourceCnt = await JointlySingleQuery.GetValueInt(cosmosClient, "School", currSql, $"Bloblog-{scBase.id}");
+
+            statsInfo.lesson = await GetLessStats(cosmosClient, statsInfo.id);
+            statsInfo.activity = await GetActStats(cosmosClient, statsInfo.id);
+            statsInfo.study = await GetStudyStats(cosmosClient, statsInfo.id);
+
+            return statsInfo;
+        }
+
+
+        /// <summary>
+        /// 课例
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        public static async Task<LessonStats> GetLessStats(CosmosClient cosmosClient, string id) 
+        {
+            LessonStats lessStats = new();
+
+            DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+
+            var (lastDayS, lastdayE) = TimeHelper.GetStartOrEnd(dateTime.AddDays(-1));   //昨天开始时间
+            var (dayS, dayE) = TimeHelper.GetStartOrEnd(dateTime);  //今天开始时间   
+
+            var (lastWeekS, lastWeekE) = TimeHelper.GetStartOrEnd(dateTime, "lastweek");   //计算上周开始/结束时间
+            var (weekS, weekE) = TimeHelper.GetStartOrEnd(dateTime, "week");             //计算本周开始/结束时间
+
+            var (lastTermS, lastTermE) = TimeHelper.GetStartOrEnd(dateTime, "lastterm");   //计算上学期开始/结束时间
+            var (termS, termE) = TimeHelper.GetStartOrEnd(dateTime, "term");   //计算本学期开始/结束时间
+
+            var (lastMthS, LastmthE) = TimeHelper.GetStartOrEnd(dateTime, "lastMonth");  //上月开始/结束时间
+            var (mthS, mthE) = TimeHelper.GetStartOrEnd(dateTime, "month");  //本月开始/结束时间
+
+            var (lastYearS, lastYearE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year - 1}-1-1"), "year"); //计算去年开始/结束时间
+            var (yearS, yearE) = TimeHelper.GetStartOrEnd(dateTime, "year");         //计算今年开始/结束时间
+
+            string currSql = "select value(count(c.id)) from c  where c.pk='LessonRecord'";
+            lessStats.all = await JointlySingleQuery.GetValueInt(cosmosClient, "School", code: $"LessonRecord-{id}", $"{currSql}");
+            lessStats.open = await JointlySingleQuery.GetValueInt(cosmosClient, "School", code: $"LessonRecord-{id}", $"{currSql} and c.upload = 0");
+            lessStats.less = await JointlySingleQuery.GetValueInt(cosmosClient, "School", code: $"LessonRecord-{id}", $"{currSql} and c.upload = 1");
+
+            List<LessRelStats> lessRelStats = new();
+            string sql = $"select c.id,c.code,c.startTime,c.clientInteractionCount from c where c.pk='LessonRecord' and c.startTime >= {lastYearS} and c.startTime <= {yearE}";
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<LessRelStats>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonRecord-{id}") })) 
+            {
+                lessRelStats.Add(item);
+            }
+
+            lessStats.lastDay = lessRelStats.FindAll(f => f.startTime >= lastDayS && f.startTime <= lastdayE).ToList().Count;
+            lessStats.day = lessRelStats.FindAll(f => f.startTime >= dayS && f.startTime <= dayE).ToList().Count;
+            lessStats.lastWeek = lessRelStats.FindAll(f => f.startTime >= lastWeekS && f.startTime <= lastWeekE).ToList().Count;
+            lessStats.week = lessRelStats.FindAll(f => f.startTime >= weekS && f.startTime <= weekE).ToList().Count;
+            lessStats.lastTerm = lessRelStats.FindAll(f => f.startTime >= lastTermS && f.startTime <= lastTermE).ToList().Count;
+            lessStats.term = lessRelStats.FindAll(f => f.startTime >= termS && f.startTime <= termE).ToList().Count;
+
+            lessStats.lastDayInter = lessRelStats.FindAll(f => f.startTime >= lastDayS && f.startTime <= lastdayE).ToList().Select(s=>s.clientInteractionCount).Sum();
+            lessStats.dayInter = lessRelStats.FindAll(f => f.startTime >= dayS && f.startTime <= dayS).ToList().Select(s => s.clientInteractionCount).Sum();
+            lessStats.lastMonthInter = lessRelStats.FindAll(f => f.startTime >= lastWeekS && f.startTime <= lastWeekE).ToList().Select(s => s.clientInteractionCount).Sum();
+            lessStats.monthInter = lessRelStats.FindAll(f => f.startTime >= weekS && f.startTime <= weekS).ToList().Select(s => s.clientInteractionCount).Sum();
+            lessStats.lastYearInter = lessRelStats.FindAll(f => f.startTime >= lastTermS && f.startTime <= lastTermE).ToList().Select(s => s.clientInteractionCount).Sum();
+            lessStats.yearInter = lessRelStats.FindAll(f => f.startTime >= termS && f.startTime <= termE).ToList().Select(s => s.clientInteractionCount).Sum();
+
+            DateTimeOffset lyearDay = new(DateTimeOffset.UtcNow.Year - 1, DateTimeOffset.UtcNow.Month, DateTimeOffset.UtcNow.Day, DateTimeOffset.UtcNow.Hour, DateTimeOffset.UtcNow.Minute, DateTimeOffset.UtcNow.Second, TimeSpan.Zero);
+            List<StartEndTime> leveryDay = TimeHelper.GetYearEveryDay(lyearDay);
+            List<StartEndTime> everyDay = TimeHelper.GetYearEveryDay(DateTimeOffset.UtcNow);
+
+            //for (int i = 0; i < leveryDay.Count; i++)
+            //{
+            //    if (lessStats.LastYear.Count == 366)
+            //        lessStats.LastYear[i] = (double)lessRelStats.FindAll(f => (f.startTime >= leveryDay[i].start && f.startTime <= leveryDay[i].end)).Count;
+            //    else
+            //        lessStats.LastYear.Add((double)lessRelStats.FindAll(f => (f.startTime >= leveryDay[i].start && f.startTime <= leveryDay[i].end)).Count);
+            //}
+
+            for (int i = 0; i < everyDay.Count; i++)
+            {
+                if (lessStats.year.Count == 366)
+                    lessStats.year[i] = lessRelStats.FindAll(f => (f.startTime >= everyDay[i].start && f.startTime <= everyDay[i].end)).Count;
+                else
+                    lessStats.year.Add(lessRelStats.FindAll(f => (f.startTime >= everyDay[i].start && f.startTime <= everyDay[i].end)).Count);
+            }
+
+            //string lastDaySql = $"{currSql} and c.startTime >= {lastDayS} and c.startTime <= {lastDayS}";
+            //lessStats.lastDay = await JointlySingleQuery.GetValueInt(cosmosClient, "School", lastDaySql, code: $"LessonRecord-{id}");
+
+            //string daySql = $"{currSql} and c.startTime >= {dayS} and c.startTime <= {dayE}";
+            //lessStats.day = await JointlySingleQuery.GetValueInt(cosmosClient, "School", daySql, code: $"LessonRecord-{id}");
+
+            //string lastWeekSql = $"{currSql}  and c.startTime >= {lastWeekS} and c.startTime <= {lastWeekE}";
+            //lessStats.lastWeek = await JointlySingleQuery.GetValueInt(cosmosClient, "School", lastWeekSql, code: $"LessonRecord-{id}");
+
+            //string weekSql = $"{currSql}  and c.startTime >= {weekS} and c.startTime <= {weekE}";
+            //lessStats.week = await JointlySingleQuery.GetValueInt(cosmosClient, "School", weekSql, code: $"LessonRecord-{id}");
+
+            //string lastTermSql = $"{currSql} and c.startTime >= {lastTermS} and c.startTime <= {lastTermE}";
+            //lessStats.lastTerm = await JointlySingleQuery.GetValueInt(cosmosClient, "School", lastTermSql, code: $"LessonRecord-{id}");
+
+            //string termSql = $"{currSql} and c.startTime >= {termS} and c.startTime <= {termE}";
+            //lessStats.term = await JointlySingleQuery.GetValueInt(cosmosClient, "School", termSql, code: $"LessonRecord-{id}");
+
+
+            //string InterSql = "select value(sum(c.clientInteractionCount)) from c where c.pk='LessonRecord'";
+            //string lastDayInterSql = $"{InterSql} and c.startTime >= {lastDayS} and c.startTime <= {lastdayE}";
+            //lessStats.lastDayInter = await JointlySingleQuery.GetValueInt(cosmosClient, "School", lastDayInterSql, code: $"LessonRecord-{id}");
+
+            //string dayInterSql = $"{InterSql} and c.startTime >= {dayS} and c.startTime <= {dayE}";
+            //lessStats.dayInter = await JointlySingleQuery.GetValueInt(cosmosClient, "School", dayInterSql, code: $"LessonRecord-{id}");
+
+            //string lastMthInterSql = $"{InterSql} and c.startTime >= {lastMthS} and c.startTime <= {LastmthE}";
+            //lessStats.lastMonthInter = await JointlySingleQuery.GetValueInt(cosmosClient, "School", lastMthInterSql, code: $"LessonRecord-{id}");
+
+            //string mthInterSql = $"{InterSql} and c.startTime >= {mthS} and c.startTime <= {mthE}";
+            //lessStats.monthInter = await JointlySingleQuery.GetValueInt(cosmosClient, "School", mthInterSql, code: $"LessonRecord-{id}");
+
+            //string lastYearInterSql = $"{InterSql} and c.startTime >= {lastYearS} and c.startTime <= {lastYearE}";
+            //lessStats.lastYearInter = await JointlySingleQuery.GetValueInt(cosmosClient, "School", lastYearInterSql, code: $"LessonRecord-{id}");
+
+            //string yearInterSql = $"{InterSql} and c.startTime >= {yearS} and c.startTime <= {yearE}";
+            //lessStats.yearInter = await JointlySingleQuery.GetValueInt(cosmosClient, "School", yearInterSql, code: $"LessonRecord-{id}");
+
+
+            return lessStats;
+        }
+
+
+        /// <summary>
+        /// 统计学校活动
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="scId"></param>
+        /// <returns></returns>
+        public static async Task<ActivityStats> GetActStats(CosmosClient cosmosClient, string scId) 
+        {
+            ActivityStats actStats = new();
+
+            DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+
+            var (lastDayS, lastdayE) = TimeHelper.GetStartOrEnd(dateTime.AddDays(-1));   //昨天开始时间
+            var (dayS, dayE) = TimeHelper.GetStartOrEnd(dateTime);  //今天开始时间   
+
+            var (lastWeekS, lastWeekE) = TimeHelper.GetStartOrEnd(dateTime, "lastweek");   //计算上周开始/结束时间
+            var (weekS, weekE) = TimeHelper.GetStartOrEnd(dateTime, "week");             //计算本周开始/结束时间
+
+            var (lastTermS, lastTermE) = TimeHelper.GetStartOrEnd(dateTime, "lastterm");   //计算上学期开始/结束时间
+            var (termS, termE) = TimeHelper.GetStartOrEnd(dateTime, "term");   //计算本学期开始/结束时间
+
+            var (lastMonthS, lastMonthE) = TimeHelper.GetStartOrEnd(dateTime, "lastMonth");   //上月开始/结束时间
+            var (monthS, monthE) = TimeHelper.GetStartOrEnd(dateTime, "month");   //本月开始/结束时间
+
+            var (lastYearS, lastYearE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year - 1}-1-1"), "year"); //计算去年开始/结束时间
+            var (yearS, yearE) = TimeHelper.GetStartOrEnd(dateTime, "year");         //计算今年开始/结束时间
+
+            string currSql = "select value(count(c.id)) from c ";
+            string yearSql = $"select c.id,c.code,c.createTime from c  where c.createTime >= {lastYearS} and c.createTime <= {yearE}";
+            int exam = 0;
+            int survey = 0;
+            int vote = 0;
+            int homework = 0;
+
+            int lastDay = 0;
+            int dayCnt = 0;
+            int lastWeek = 0;
+            int week = 0;
+            int lastTerm = 0;
+            int term = 0;
+            int lastMonth = 0;
+            int month = 0;
+
+            DateTimeOffset lyearDay = new(DateTimeOffset.UtcNow.Year - 1, DateTimeOffset.UtcNow.Month, DateTimeOffset.UtcNow.Day, DateTimeOffset.UtcNow.Hour, DateTimeOffset.UtcNow.Minute, DateTimeOffset.UtcNow.Second, TimeSpan.Zero);
+            List<StartEndTime> leveryDay = TimeHelper.GetYearEveryDay(lyearDay);
+            List<StartEndTime> everyDay = TimeHelper.GetYearEveryDay(DateTimeOffset.UtcNow);
+            List<ArtRelStats> examSts = new();
+            List<ArtRelStats> surveySts = new();
+            List<ArtRelStats> voteSts = new();
+            List<ArtRelStats> homeworkSts = new();
+
+            foreach (var artType in StaticValue.activityTypes)
+            {
+                switch (artType)
+                {
+                    case "Exam":
+                        exam = await JointlySingleQuery.GetValueInt(cosmosClient, "Common", currSql, $"Exam-{scId}");
+                        await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ArtRelStats>(queryText: yearSql, requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{scId}")}))
+                        {
+                            examSts.Add(item);
+                        }
+                        break;
+                    case "Survey":
+                        survey = await JointlySingleQuery.GetValueInt(cosmosClient, "Common", currSql, $"Survey-{scId}");
+                        await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ArtRelStats>(queryText: yearSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Survey-{scId}") }))
+                        {
+                            surveySts.Add(item);
+                        }
+
+                        break;
+                    case "Vote":
+                        vote = await JointlySingleQuery.GetValueInt(cosmosClient, "Common", currSql, $"Vote-{scId}");
+                        await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ArtRelStats>(queryText: yearSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{scId}") }))
+                        {
+                            voteSts.Add(item);
+                        }
+                        break;
+                    case "Homework":
+                        homework = await JointlySingleQuery.GetValueInt(cosmosClient, "Common", currSql, $"Homework-{scId}");
+                        await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ArtRelStats>(queryText: yearSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Homework-{scId}") }))
+                        {
+                            homeworkSts.Add(item);
+                        }
+                        break;
+                }
+            }
+
+
+            List<ArtRelStats> tempAll = new();
+            if (examSts.Count > 0) 
+            {
+                tempAll.AddRange(examSts);
+                lastDay += examSts.FindAll(f => f.createTime >= lastDayS && f.createTime <= lastdayE).ToList().Count;
+                dayCnt += examSts.FindAll(f => f.createTime >= dayS && f.createTime <= dayE).ToList().Count;
+                lastWeek += examSts.FindAll(f => f.createTime >= lastWeekS && f.createTime <= lastWeekE).ToList().Count;
+                week += examSts.FindAll(f => f.createTime >= weekS && f.createTime <= weekE).ToList().Count;
+                lastTerm += examSts.FindAll(f => f.createTime >= lastTermS && f.createTime <= lastTermE).ToList().Count;
+                term += examSts.FindAll(f => f.createTime >= termS && f.createTime <= termE).ToList().Count;
+                lastMonth += examSts.FindAll(f => f.createTime >= lastMonthS && f.createTime <= lastMonthE).ToList().Count;
+                month += examSts.FindAll(f => f.createTime >= monthS && f.createTime <= monthE).ToList().Count;
+            }
+            
+            if (surveySts.Count > 0)
+            {
+                tempAll.AddRange(surveySts);
+                lastDay += surveySts.FindAll(f => f.createTime >= lastDayS && f.createTime <= lastdayE).ToList().Count;
+                dayCnt += surveySts.FindAll(f => f.createTime >= dayS && f.createTime <= dayE).ToList().Count;
+                lastWeek += surveySts.FindAll(f => f.createTime >= lastWeekS && f.createTime <= lastWeekE).ToList().Count;
+                week += surveySts.FindAll(f => f.createTime >= weekS && f.createTime <= weekE).ToList().Count;
+                lastTerm += surveySts.FindAll(f => f.createTime >= lastTermS && f.createTime <= lastTermE).ToList().Count;
+                term += surveySts.FindAll(f => f.createTime >= termS && f.createTime <= termE).ToList().Count;
+                lastMonth += examSts.FindAll(f => f.createTime >= lastMonthS && f.createTime <= lastMonthE).ToList().Count;
+                month += examSts.FindAll(f => f.createTime >= monthS && f.createTime <= monthE).ToList().Count;
+            }
+
+            if (voteSts.Count > 0)
+            {
+                tempAll.AddRange(voteSts);
+                lastDay += voteSts.FindAll(f => f.createTime >= lastDayS && f.createTime <= lastdayE).ToList().Count;
+                dayCnt += voteSts.FindAll(f => f.createTime >= dayS && f.createTime <= dayE).ToList().Count;
+                lastWeek += voteSts.FindAll(f => f.createTime >= lastWeekS && f.createTime <= lastWeekE).ToList().Count;
+                week += voteSts.FindAll(f => f.createTime >= weekS && f.createTime <= weekE).ToList().Count;
+                lastTerm += voteSts.FindAll(f => f.createTime >= lastTermS && f.createTime <= lastTermE).ToList().Count;
+                term += voteSts.FindAll(f => f.createTime >= termS && f.createTime <= termE).ToList().Count;
+                lastMonth += examSts.FindAll(f => f.createTime >= lastMonthS && f.createTime <= lastMonthE).ToList().Count;
+                month += examSts.FindAll(f => f.createTime >= monthS && f.createTime <= monthE).ToList().Count;
+            }
+
+            if (homeworkSts.Count > 0)
+            {
+                tempAll.AddRange(homeworkSts);
+                lastDay += homeworkSts.FindAll(f => f.createTime >= lastDayS && f.createTime <= lastdayE).ToList().Count;
+                dayCnt += homeworkSts.FindAll(f => f.createTime >= dayS && f.createTime <= dayE).ToList().Count;
+                lastWeek += homeworkSts.FindAll(f => f.createTime >= lastWeekS && f.createTime <= lastWeekE).ToList().Count;
+                week += homeworkSts.FindAll(f => f.createTime >= weekS && f.createTime <= weekE).ToList().Count;
+                lastTerm += homeworkSts.FindAll(f => f.createTime >= lastTermS && f.createTime <= lastTermE).ToList().Count;
+                term += homeworkSts.FindAll(f => f.createTime >= termS && f.createTime <= termE).ToList().Count;
+                lastMonth += examSts.FindAll(f => f.createTime >= lastMonthS && f.createTime <= lastMonthE).ToList().Count;
+                month += examSts.FindAll(f => f.createTime >= monthS && f.createTime <= monthE).ToList().Count;
+            }
+
+            if (tempAll.Count > 0) 
+            {
+                //for (int i = 0; i < leveryDay.Count; i++)
+                //{
+                //    if (actStats.LastYear.Count == 366)
+                //        actStats.LastYear[i] = (double)tempAll.FindAll(f => (f.createTime >= leveryDay[i].start && f.createTime <= leveryDay[i].end)).Count;
+                //    else
+                //        actStats.LastYear.Add((double)tempAll.FindAll(f => (f.createTime >= leveryDay[i].start && f.createTime <= leveryDay[i].end)).Count);
+                //}
+
+                for (int i = 0; i < everyDay.Count; i++)
+                {
+                    if (actStats.year.Count == 366)
+                        actStats.year[i] = tempAll.FindAll(f => (f.createTime >= everyDay[i].start && f.createTime <= everyDay[i].end)).Count;
+                    else
+                        actStats.year.Add(tempAll.FindAll(f => (f.createTime >= everyDay[i].start && f.createTime <= everyDay[i].end)).Count);
+                }
+            }
+
+            //string lastDaySql = $"c.createTime >= {lastDayS} and c.createTime <= {lastdayE}";
+            //string daySql = $"c.createTime >= {dayS} and c.createTime <= {dayE}";
+            //string lastWeekSql = $"c.createTime >= {lastWeekS} and c.createTime <= {lastWeekE}";
+            //string weekSql = $"c.createTime >= {weekS} and c.createTime <= {weekE}";
+            //string lastTermSql = $"c.createTime >= {lastTermS} and c.createTime <= {lastTermE}";
+            //string termSql = $"c.createTime >= {termS} and c.createTime <= {termE}";
+            //foreach (var type in StaticValue.activityTypes)
+            //{
+            //    switch (type)
+            //    {
+            //        case "Exam":
+            //            exam += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Exam'", code: $"Exam-{scId}");
+            //            lastDay += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Exam' and {lastDaySql}", code: $"Exam-{scId}");
+            //            dayCnt += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Exam' and {daySql}", code: $"Exam-{scId}");
+            //            lastWeek+= await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Exam' and {lastWeekSql}", code: $"Exam-{scId}");
+            //            week += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Exam' and {weekSql}", code: $"Exam-{scId}");
+            //            lastTerm += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Exam' and {lastTermSql}", code: $"Exam-{scId}");
+            //            term += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Exam' and {termSql}", code: $"Exam-{scId}");                        
+            //            break;
+            //        case "Survey":
+            //            survey += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Survey'", code: $"Survey-{scId}");
+            //            lastDay += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Survey' and {lastDaySql}", code: $"Survey-{scId}");
+            //            dayCnt += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Survey' and {daySql}", code: $"Survey-{scId}");
+            //            lastWeek += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Survey' and {lastWeekSql}", code: $"Survey-{scId}");
+            //            week += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Survey' and {weekSql}", code: $"Survey-{scId}");
+            //            lastTerm += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Survey' and {lastTermSql}", code: $"Survey-{scId}");
+            //            term += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Survey' and {termSql}", code: $"Survey-{scId}");
+                        
+            //            break;
+            //        case "Vote":
+            //            vote += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Vote'", code: $"Vote-{scId}");
+            //            lastDay += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Vote' and {lastDaySql}", code: $"Vote-{scId}");
+            //            dayCnt += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Vote' and {daySql}", code: $"Vote-{scId}");
+            //            lastWeek += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Vote' and {lastWeekSql}", code: $"Vote-{scId}");
+            //            week += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Vote' and {weekSql}", code: $"Vote-{scId}");
+            //            lastTerm += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Vote' and {lastTermSql}", code: $"Vote-{scId}");
+            //            term += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Vote' and {termSql}", code: $"Vote-{scId}");                        
+            //            break;
+            //        case "Homework":
+            //            homework += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Homework'", code: $"Homework-{scId}");
+            //            lastDay += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Homework' and {lastDaySql}", code: $"Homework-{scId}");
+            //            dayCnt += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Homework' and {daySql}", code: $"Homework-{scId}");
+            //            lastWeek += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Homework' and {lastWeekSql}", code: $"Homework-{scId}");
+            //            week += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Homework' and {weekSql}", code: $"Homework-{scId}");
+            //            lastTerm += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Homework' and {lastTermSql}", code: $"Homework-{scId}");
+            //            term += await JointlySingleQuery.GetValueInt(cosmosClient, "Common", $"{currSql} where c.pk='Homework' and {termSql}", code: $"Homework-{scId}");                        
+            //            break;
+            //    }
+            //}
+            actStats.all = (exam + survey + vote + homework);
+            actStats.exam = exam;
+            actStats.survey = survey;
+            actStats.vote = vote;
+            actStats.homework = homework;
+            actStats.lastDay = lastDay;
+            actStats.dayCnt = dayCnt;
+            actStats.lastWeek = lastWeek;
+            actStats.week = week;
+            actStats.lastTerm = lastTerm;
+            actStats.term = term;
+            actStats.lastMonth = lastMonth;
+            actStats.month = month;
+            actStats.upTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+
+            return actStats;
+        }
+
+        /// <summary>
+        /// 研修
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="scId"></param>
+        /// <returns></returns>
+        public static async Task<StudyStats> GetStudyStats(CosmosClient cosmosClient, string scId) 
+        {
+            StudyStats studyStats = new();
+
+
+            List<AreaStudy> trains = new();
+
+            School school = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>($"{scId}", new PartitionKey("Base"));
+            //cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText:$"select value(c.areaId) from c where c.id='{scId}'", requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")});
+
+            AreaSetting setting = null;
+            var responSett = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"{school.areaId}", new PartitionKey("AreaSetting"));
+            if (responSett.Status == 200)
+            {
+                using var fileJson = await JsonDocument.ParseAsync(responSett.ContentStream);
+                setting = fileJson.ToObject<AreaSetting>();
+            }
+            if (setting == null)
+            {
+                setting = new AreaSetting
+                {
+                    allTime = 50,
+                    classTime = 5,
+                    submitTime = 15,
+                    onlineTime = 20,
+                    offlineTime = 10,
+                    lessonMinutes = 45,
+                };
+            }
+
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<AreaStudy>(queryText: $"select c.id,c.code,c.totalTime,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and c.school='{scId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{scId}") }))
+            {
+                trains.Add(item);
+            }
+
+            studyStats.learnTime = trains.Select(s => s.totalTime).Sum();
+            trains.ForEach(x =>
+            {
+                //线上研修
+                if (x.onlineTime == 0) studyStats.online++; else if (x.onlineTime >= setting.onlineTime) studyStats.online++; else studyStats.online++;
+
+                //线下研修
+                if (x.offlineTime == 0) studyStats.offline++; else if (x.onlineTime >= setting.offlineTime) studyStats.offline++; else studyStats.offline++;
+
+                //课堂实录
+                if (x.classTime == 0) studyStats.classRoom++; else if (x.classTime >= setting.classTime) studyStats.classRoom++; else studyStats.classRoom++;
+
+                //认证材料
+                if (x.currency.submitTime == 0) studyStats.submit++; else if (x.currency.submitTime >= setting.submitTime) studyStats.submit++; else studyStats.submit++;
+
+                if (x.currency.submitTime == 0 && x.classTime == 0 && x.offlineTime == 0 && x.onlineTime == 0) studyStats.notStarted++;
+                else if (x.currency.submitTime >= setting.submitTime && x.classTime >= setting.classTime && x.onlineTime >= setting.offlineTime && x.onlineTime >= setting.onlineTime) studyStats.finish++;
+                else studyStats.ongoing++;
+            });
+
+            return studyStats;
+        }
+
+
+    }
+}

+ 47 - 12
TEAMModelBI/Tool/TimeHelper.cs

@@ -1,13 +1,15 @@
-using System;
+using DocumentFormat.OpenXml.Bibliography;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 using TEAMModelBI.Models;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
 
 namespace TEAMModelBI.Tool
 {
-    public static class TimeHelper
+    public static class TimeHelper1
     {
         /// <summary>
         /// 平年
@@ -88,16 +90,16 @@ namespace TEAMModelBI.Tool
         /// <param name="date"></param>
         /// <param name="dateLenth"></param>
         /// <returns></returns>
-        public static async Task<List<MonthStartEnd>> GetYearSataMthCtMth(DateTimeOffset date,bool dateLenth = true) 
+        public static async Task<List<StartEndTime>> GetYearSataMthCtMth(DateTimeOffset date,bool dateLenth = true) 
         {
             int year = date.Year;
             int mth = date.Month;
             int day = date.Day;
 
-            List<MonthStartEnd> monthStartEnds = new();
+            List<StartEndTime> monthStartEnds = new();
             for (int i = 1; i <= mth; i++)
             {
-                MonthStartEnd monthStartEnd = new() { yearMonth = $"{year}-{i}" };
+                StartEndTime monthStartEnd = new() { date = $"{year}-{i}" };
                 //DateTime dt = DateTime.Parse($"{year}-{i}");
                 DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
                 long start = dtNew.ToUnixTimeMilliseconds();
@@ -131,12 +133,12 @@ namespace TEAMModelBI.Tool
         /// <param name="year">年份</param>
         /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
         /// <returns></returns>
-        public static List<MonthStartEnd> GetYearMonthlyStartEnd(int year, bool dateLenth = true)
+        public static List<StartEndTime> GetYearMonthlyStartEnd(int year, bool dateLenth = true)
         {
-            List<MonthStartEnd> monthStartEnds = new();
+            List<StartEndTime> monthStartEnds = new();
             for (int i = 1; i <= 12; i++)
             {
-                MonthStartEnd monthStartEnd = new MonthStartEnd() { yearMonth = $"{year}-{i}" };
+                StartEndTime monthStartEnd = new StartEndTime() { date = $"{year}-{i}" };
                 //DateTime dt = DateTime.Parse($"{year}-{i}");
                 DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
                 long start = dtNew.ToUnixTimeMilliseconds();
@@ -160,17 +162,17 @@ namespace TEAMModelBI.Tool
         /// <param name="yearMonth">日期</param>
         /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
         /// <returns></returns>
-        public static List<MonthStartEnd> monthsOfYear(string yearMonth, bool dateLenth = true)
+        public static List<StartEndTime> monthsOfYear(string yearMonth, bool dateLenth = true)
         {
-            List<MonthStartEnd> monthStartEnds = new();
+            List<StartEndTime> monthStartEnds = new();
             DateTime dateTime = DateTime.Parse(yearMonth);
 
             int year = dateTime.Year;
             int month = dateTime.Month;
-            List<string> months = new List<string>();
+            List<string> months = new();
             while (year > dateTime.Year - 1 || month > dateTime.Month)
             {
-                MonthStartEnd monthStartEnd = new MonthStartEnd() { yearMonth = $"{year}-{month}" };
+                StartEndTime monthStartEnd = new() { date = $"{year}-{month}" };
 
                 DateTimeOffset dtNew = new(year, month, 1, 0, 0, 0, TimeSpan.Zero);
                 long start = dateLenth ? dtNew.ToUnixTimeMilliseconds() : dtNew.ToUnixTimeSeconds();
@@ -330,6 +332,11 @@ namespace TEAMModelBI.Tool
                             }
                         }
                         break;
+                    //上个月
+                    case "lastMonth":
+                        tempStrart = new DateTimeOffset(year, month - 1, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month - 1, DateTime.DaysInMonth(year, month - 1), 23, 59, 59, TimeSpan.Zero);
+                        break;
                     //本月1号至当天
                     case "monthDay":
                         tempStrart = new DateTimeOffset(year, month, 1, 0, 0, 0, TimeSpan.Zero);
@@ -417,5 +424,33 @@ namespace TEAMModelBI.Tool
             return days;
         }
 
+
+        public static List<YearMonth> GetYearMonth(List<double> doubles, int year = 0,int month = 0) 
+        {
+            List<YearMonth> months = new();
+            DateTimeOffset dateTime = DateTimeOffset.Now;
+            if (year == 0) 
+                year = dateTime.Year;
+            if(month == 0)
+                month = dateTime.Month;
+
+            List<int> isLeapYear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? isLeapYear = leapY : isLeapYear = flatY;
+            double[] array = doubles.ToArray();
+            double ser = doubles.Sum();
+            int moth = 1;
+            int primaryD = 0;
+            for (int i = 0; i < isLeapYear.Count; i++)
+            {
+                if (month < moth)
+                    break;
+                double[] temp = new double[isLeapYear[i]];
+                Array.ConstrainedCopy(array, primaryD, temp, 0, isLeapYear[i]);
+                months.Add(new YearMonth() { id = $"{year}-{moth}", cnt = temp.Sum() });
+                moth += 1;
+                primaryD += isLeapYear[i];
+            }
+
+            return months;
+        }
     }
 }

+ 6 - 2
TEAMModelOS.FunctionV4/CosmosDB/CommonTrigger.cs

@@ -59,12 +59,16 @@ namespace TEAMModelOS.FunctionV4
                         if (!string.IsNullOrWhiteSpace($"{jsond}"))
                         {
                             if ($"{jsond}".Equals("Receiver", StringComparison.OrdinalIgnoreCase)
-                                ||$"{jsond}".Equals("Notice", StringComparison.OrdinalIgnoreCase)
+                                || $"{jsond}".Equals("Notice", StringComparison.OrdinalIgnoreCase)
                                 || $"{jsond}".Equals("ExamClassResult", StringComparison.OrdinalIgnoreCase))
                             {
                                 ///通知接收者的变更
                                 continue;
                             }
+                            //else if ($"{jsond}".Equals("StatsNotice", StringComparison.OrdinalIgnoreCase)) 
+                            //{
+                            //    var sert = 012;
+                            //}
                             else
                             {
                                 TriggerData data = element.ToObject<TriggerData>();
@@ -76,7 +80,7 @@ namespace TEAMModelOS.FunctionV4
                                 switch (data.pk)
                                 {
                                     case "Exam":
-                                        await TriggerExam.Trigger(_coreAPIHttpService,_azureCosmos, _serviceBus, _azureStorage, _dingDing, client, element, data);
+                                        await TriggerExam.Trigger(_coreAPIHttpService, _azureCosmos, _serviceBus, _azureStorage, _dingDing, client, element, data);
                                         break;
                                     case "Vote":
                                         await TriggerVote.Trigger(_coreAPIHttpService, _serviceBus, _azureStorage, _dingDing, client, element, data, _azureRedis, _configuration);

+ 0 - 0
TEAMModelOS.FunctionV4/CosmosDB/TriggerArt.cs


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels