Bläddra i källkod

Merge branch 'develop6.0-tmd' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop6.0-tmd

zhouj1203@hotmail.com 3 år sedan
förälder
incheckning
693b2a9828
61 ändrade filer med 979 tillägg och 497 borttagningar
  1. 181 0
      TEAMModelAPI/Controllers/School/CourseController.cs
  2. 28 4
      TEAMModelAPI/Controllers/School/ExamController.cs
  3. 72 39
      TEAMModelAPI/Controllers/School/GroupListController.cs
  4. 7 74
      TEAMModelAPI/Controllers/School/SchoolController.cs
  5. 1 0
      TEAMModelBI/ClientApp/package.json
  6. 1 1
      TEAMModelBI/ClientApp/src/components/echarts/baseBar.vue
  7. 7 4
      TEAMModelBI/ClientApp/src/components/echarts/customBar.vue
  8. 5 4
      TEAMModelBI/ClientApp/src/components/echarts/customPie.vue
  9. 0 6
      TEAMModelBI/ClientApp/src/language/lang/lang/zh-cn.js
  10. 1 1
      TEAMModelBI/ClientApp/src/language/lang/zh-cn.js
  11. 1 1
      TEAMModelBI/ClientApp/src/language/lang/zh-tw.js
  12. 2 0
      TEAMModelBI/ClientApp/src/main.js
  13. 1 0
      TEAMModelBI/ClientApp/src/view/home.vue
  14. 2 20
      TEAMModelBI/ClientApp/src/view/index/dashboard.vue
  15. 1 1
      TEAMModelBI/ClientApp/src/view/index/operateLog.vue
  16. 14 0
      TEAMModelBI/ClientApp/src/view/login.vue
  17. 1 1
      TEAMModelBI/ClientApp/src/view/teachermanage/areamanage.vue
  18. 56 29
      TEAMModelBI/ClientApp/src/view/teachermanage/classpower.vue
  19. 81 63
      TEAMModelBI/ClientApp/src/view/teachermanage/impower.vue
  20. 1 1
      TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue
  21. 10 3
      TEAMModelBI/ClientApp/src/view/teachermanage/school.vue
  22. 43 10
      TEAMModelBI/ClientApp/src/view/teachermanage/setschool.vue
  23. 1 1
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  24. 3 3
      TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj
  25. 14 9
      TEAMModelOS.SDK/Models/Cosmos/School/Course.cs
  26. BIN
      TEAMModelOS/ClientApp/src/assets/image/none.png
  27. 6 5
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  28. 2 2
      TEAMModelOS/ClientApp/src/common/QrcodeModal.vue
  29. 5 1
      TEAMModelOS/ClientApp/src/components/research-dashboard/RightBotR.vue
  30. 5 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/cusMgt.js
  31. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js
  32. 5 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/cusMgt.js
  33. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/learnActivity.js
  34. 5 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/cusMgt.js
  35. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/learnActivity.js
  36. 0 27
      TEAMModelOS/ClientApp/src/router/routes.js
  37. 1 0
      TEAMModelOS/ClientApp/src/store/module/user.js
  38. 4 4
      TEAMModelOS/ClientApp/src/view/areatrain/TrainDetail.vue
  39. 8 0
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.less
  40. 47 26
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue
  41. 10 6
      TEAMModelOS/ClientApp/src/view/classrecord/eventchart/DataCount.vue
  42. 3 2
      TEAMModelOS/ClientApp/src/view/homepage/AcCountPie.vue
  43. 16 3
      TEAMModelOS/ClientApp/src/view/homepage/HomePage.less
  44. 77 39
      TEAMModelOS/ClientApp/src/view/homepage/HomePage.vue
  45. 4 4
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.vue
  46. 3 3
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue
  47. 26 20
      TEAMModelOS/ClientApp/src/view/login/Index.vue
  48. 3 3
      TEAMModelOS/ClientApp/src/view/login/page/Student.vue
  49. 1 1
      TEAMModelOS/ClientApp/src/view/newcourse/EvDetail.vue
  50. 1 0
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.less
  51. 27 23
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue
  52. 6 2
      TEAMModelOS/ClientApp/src/view/research-center/ResearchCenter.vue
  53. 32 9
      TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.less
  54. 122 24
      TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.vue
  55. 4 4
      TEAMModelOS/ClientApp/src/view/train/TrainDetail.vue
  56. 1 1
      TEAMModelOS/ClientApp/src/view/user/BandPhone.vue
  57. 2 1
      TEAMModelOS/Controllers/Student/TmdUserController.cs
  58. 1 1
      TEAMModelOS/Controllers/System/CoreController.cs
  59. 12 1
      TEAMModelOS/Controllers/Teacher/TeacherCommonController.cs
  60. 3 3
      TEAMModelOS/TEAMModelOS.csproj
  61. 0 1
      TEAMModelOS/appsettings.Development.json

+ 181 - 0
TEAMModelAPI/Controllers/School/CourseController.cs

@@ -0,0 +1,181 @@
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK;
+using TEAMModelOS.SDK.DI;
+using System.Text.Json;
+using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Extension;
+using Azure.Cosmos;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Options;
+using System.IO;
+using System.Dynamic;
+using System.Net.Http;
+using System.Net;
+using Newtonsoft.Json;
+using System.Linq;
+using StackExchange.Redis;
+using static TEAMModelOS.SDK.Models.Teacher;
+using Microsoft.Extensions.Configuration;
+using TEAMModelOS.Filter;
+using Microsoft.AspNetCore.Authorization;
+using HTEXLib.COMM.Helpers;
+using TEAMModelOS.SDK.Models.Service;
+namespace TEAMModelAPI.Controllers
+{
+    [ProducesResponseType(StatusCodes.Status200OK)]
+    [ProducesResponseType(StatusCodes.Status400BadRequest)]
+    [ApiController]
+    [Route("school")]
+    public class CourseController : ControllerBase
+    {
+        public AzureCosmosFactory _azureCosmos;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly AzureRedisFactory _azureRedis;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly IConfiguration _configuration;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly AzureServiceBusFactory _serviceBus;
+        public CourseController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, AzureServiceBusFactory serviceBus)
+        {
+            _azureCosmos = azureCosmos;
+            _azureStorage = azureStorage;
+            _azureRedis = azureRedis;
+            _dingDing = dingDing;
+            _option = option?.Value;
+            _configuration = configuration;
+            _coreAPIHttpService = coreAPIHttpService;
+            _serviceBus = serviceBus;
+        }
+        /// <summary>
+        ///  获取指定学段作息
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-period-timetable")]
+        [ApiToken(Auth = "1301", Name = "试卷和评测的条件信息", RW = "R", Limit = false)]
+        public async Task<IActionResult> GetPaperExamCondition(JsonElement json)
+        {
+            json.TryGetProperty("periodId", out JsonElement _periodId);
+            var (id, school) = HttpContext.GetApiTokenInfo();
+            School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
+            var period = data.period.Find(x => x.id.Equals($"{_periodId}"));
+            if (period != null)
+            {
+                return Ok(new { period.subjects, period.timetable, period.grades, period.majors });
+            }
+            else
+            {
+                return Ok(new { error = 1, msg = "学段不存在!" });
+            }
+        }
+       
+
+        [ProducesDefaultResponseType]
+        [HttpPost("upsert-course-info")]
+        [ApiToken(Auth = "1302", Name = "课程详细信息", RW = "R", Limit = false)]
+        public async Task<IActionResult> UpsertCourseInfo(JsonElement json)
+        {
+            var (id, school) = HttpContext.GetApiTokenInfo();
+            if (!json.TryGetProperty("course", out JsonElement _course)) { return Ok(new { error = 1, msg = "课程对象不存在" }); }
+            var courseDto = _course.ToObject<CourseDto>();
+            Course course = null;
+            if (courseDto != null && courseDto.Valid().isVaild) {
+                School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
+                var period = data.period.Find(x => x.id.Equals($"{courseDto.periodId}"));
+                if (period != null)
+                {
+                    var subject = period.subjects.Find(x => x.id.Equals($"{courseDto.subjectId}"));
+                    if (subject != null)
+                    {
+                        if (string.IsNullOrWhiteSpace(courseDto?.id))
+                        {
+                            course = new Course
+                            {
+                                pk = "Course",
+                                id = Guid.NewGuid().ToString(),
+                                code = $"Course-{school}",
+                                name = courseDto.name,
+                                subject = new SubjectSimple { id = subject.id, name = subject.name  },
+                                period= new PeriodSimple { id = period.id, name = period.name },
+
+                            };
+                        }
+                        else
+                        {
+
+                        }
+                        return Ok(new { period.subjects, period.timetable, period.grades, period.majors });
+                    }
+                    else {
+                        return Ok(new { error = 2, msg = "科目不存在!" });
+                    }
+                }
+                else
+                {
+                    return Ok(new { error = 2, msg = "学段不存在!" });
+                }
+            }
+            else
+            {
+                return Ok(new { error = 3, msg = courseDto.Valid() });
+            }
+            
+        }
+        [ProducesDefaultResponseType]
+        [HttpPost("get-course-list")]
+        [ApiToken(Auth = "1303", Name = "获取课程列表信息", RW = "R", Limit = false)]
+        public async Task<IActionResult> GetCourseList(JsonElement json)
+        {
+            var client = _azureCosmos.GetCosmosClient();
+            var (id, school) = HttpContext.GetApiTokenInfo();
+            json.TryGetProperty("periodId", out JsonElement periodId);
+            json.TryGetProperty("subjectId", out JsonElement subjectId);
+            StringBuilder sql = new StringBuilder($"SELECT c.id,c.name,c.subject,c.period,c.scope,c.no,c.school FROM c where 1=1 ");
+            if (!string.IsNullOrWhiteSpace($"{periodId}"))
+            {
+                sql.Append($" and c.period.id='{periodId}'");
+            }
+            if (!string.IsNullOrWhiteSpace($"{subjectId}"))
+            {
+                sql.Append($" and c.subject.id='{subjectId}'");
+            }
+            List<dynamic> courses = new List<dynamic>();
+            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").
+                    GetItemQueryIterator<dynamic>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{school}") }))
+            {
+                courses.Add(item);
+            }
+            return Ok(new { courses });
+        }
+
+        [ProducesDefaultResponseType]
+        [HttpPost("get-course-info")]
+        [ApiToken(Auth = "1304", Name = "课程详细信息", RW = "R", Limit = false)]
+        public async Task<IActionResult> GetCourseInfo(JsonElement json)
+        {
+            var (id, school) = HttpContext.GetApiTokenInfo();
+            json.TryGetProperty("courseId", out JsonElement courseId);
+            Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School")
+               .ReadItemStreamAsync($"{courseId}", new PartitionKey($"Course-{school}"));
+            if (response.Status == 200)
+            {
+                JsonDocument document = JsonDocument.Parse(response.Content);
+                Course course = document.RootElement.Deserialize<Course>();
+                return Ok(new { course.name, course.id, course.subject, course.period, course.scope, course.school, course.no, course.desc, course.schedule });
+            }
+            else
+            {
+                return Ok(new { error = 1, msg = "课程不存在!" });
+            }
+        }
+
+
+    }
+}

+ 28 - 4
TEAMModelAPI/Controllers/School/ExamController.cs

@@ -53,10 +53,34 @@ namespace TEAMModelAPI.Controllers
             _option = option?.Value;
             _configuration = configuration;
         }
-
+        /// <summary>
+        ///  获取试卷和评测的条件信息
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-paper-exam-condition")]
+        [ApiToken(Auth = "1101", Name = "试卷和评测的条件信息", RW = "R", Limit = false)]
+        public async Task<IActionResult> GetPaperExamCondition(JsonElement json)
+        {
+            json.TryGetProperty("periodId", out JsonElement _periodId);
+            var (id, school) = HttpContext.GetApiTokenInfo();
+            School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
+            var exmaType = new { type = new List<string> { "regular", "simulation", "normal" } };//regula ,正规考,  simulation 模拟靠考,normal 普通考
+            var exmaMode = new { type = new List<string> { "0", "1", "2" } };//0 线上评测,  1 课中评测 ,2 阅卷评测
+            var period = data.period.Find(x => x.id.Equals($"{_periodId}"));
+            if (period != null)
+            {
+                return Ok(new { period.subjects, period.analysis, period.grades, exmaType, exmaMode });
+            }
+            else
+            {
+                return Ok(new { error = 1, msg = "学段不存在!" });
+            }
+        }
         [ProducesDefaultResponseType]
         [HttpGet("import-exam")]
-        [ApiToken(Auth = "201", Name = "汇入评测基础数据", Limit = false)]
+        [ApiToken(Auth = "1102", Name = "汇入评测基础数据", Limit = false)]
         public async Task<IActionResult> importExam(JsonElement request)
         {
             //获取评测的ID
@@ -78,7 +102,7 @@ namespace TEAMModelAPI.Controllers
         }
         [ProducesDefaultResponseType]
         [HttpGet("upsert-record")]
-        [ApiToken(Auth = "202", Name = "批量汇入作答数据", Limit = false)]
+        [ApiToken(Auth = "1103", Name = "批量汇入作答数据", Limit = false)]
         public async Task<IActionResult> upsertRecord(JsonElement request)
         {
 
@@ -341,7 +365,7 @@ namespace TEAMModelAPI.Controllers
         }
         [ProducesDefaultResponseType]
         [HttpGet("parse-word")]
-        [ApiToken(Auth = "203", Name = "录入试卷数据", Limit = false)]
+        [ApiToken(Auth = "1104", Name = "录入试卷数据", Limit = false)]
         public async Task<IActionResult> ParseWord([FromForm] FileDto fileDto)
         {
             if (!FileType.GetExtention(fileDto.file.FileName).ToLower().Equals("docx"))

+ 72 - 39
TEAMModelAPI/Controllers/School/GroupListController.cs

@@ -63,7 +63,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-group-list")]
-        [ApiToken(Auth = "109", Name = "学校名单列表", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1201", Name = "学校名单列表", RW = "R", Limit = false)]
         public async Task<IActionResult> GetGroupList(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -157,10 +157,9 @@ namespace TEAMModelAPI.Controllers
                 groupLists = groupLists.Select(x => new { x.id, x.type, x.name, x.periodId, x.school, x.scope, x.year })
             });
         }
-
         [ProducesDefaultResponseType]
         [HttpPost("get-group-members")]
-        [ApiToken(Auth = "110", Name = "获取名单详细信息和成员信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1202", Name = "获取名单详细信息和成员信息", RW = "R", Limit = false)]
         public async Task<IActionResult> GetGroupMembers(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -170,8 +169,6 @@ namespace TEAMModelAPI.Controllers
             (List<RMember> members, List<RGroupList> groups) = await GroupListService.GetStutmdidListids(_coreAPIHttpService, client, _dingDing, listids, $"{school}");
             return Ok(new { groups = groups.Select(x => new { x.name, x.no, x.periodId, x.school, x.type, x.year, x.tcount, x.scount, x.leader, x.members, x.id }), members });
         }
-
-
         /// <summary>
         /// 导入行政班学生
         /// </summary>
@@ -179,7 +176,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("import-class-members")]
-        [ApiToken(Auth = "111", Name = "导入行政班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1203", Name = "导入行政班学生", RW = "W", Limit = false)]
         public async Task<IActionResult> ImportClassMembers(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -213,7 +210,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("update-class-members")]
-        [ApiToken(Auth = "112", Name = "更新行政班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1204", Name = "更新行政班学生", RW = "W", Limit = false)]
         public async Task<IActionResult> UpdateClassMembers(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -249,7 +246,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("remove-class-members")]
-        [ApiToken(Auth = "113", Name = "移除行政班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1205", Name = "移除行政班学生", RW = "W", Limit = false)]
         public async Task<IActionResult> RemoveClassMembers(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -285,49 +282,85 @@ namespace TEAMModelAPI.Controllers
         }
 
         /// <summary>
-        /// 创建或更新教学班
+        /// 创建或更新教学班基本信息
         /// </summary>
         /// <param name="request"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("upsert-teach-group")]
-        [ApiToken(Auth = "114", Name = "创建或更新教学班", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1206", Name = "创建或更新教学班", RW = "W", Limit = false)]
         public async Task<IActionResult> UpsertTeachGroup(JsonElement json) {
             var (id, school) = HttpContext.GetApiTokenInfo();
             if (!json.TryGetProperty("groupList", out JsonElement _groupList)) { return Ok(new { error=1,msg="名单对象不存在"}); }
             var list= _groupList.ToObject<GroupListDto>();
-            if (list != null  && list.Valid().isVaild) {
-                if (string.IsNullOrWhiteSpace(list.id))
+            GroupList groupList = null;
+          
+            if (list != null && list.Valid().isVaild)
+            {
+                School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
+                Period period = data.period.Find(x => x.id.Equals($"{list.periodId}"));
+                if (period != null)
                 {
-                    GroupList groupList = new GroupList()
+                    if (string.IsNullOrWhiteSpace(list.id))
                     {
-                        id=Guid.NewGuid ().ToString(),
-                        code=$"GroupList-{school}",
-                        name=list.name,
-                        periodId=list.periodId,
-                        scope="school",
-                        school=school,
-                        type="teach",
-                        year=list.year,
-                        froms=3
-                    };
-                    groupList = await GroupListService.CheckListNo(groupList, _azureCosmos, _dingDing, _option);
-                    
-                }
-                else {
-                    Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{list.id}", new PartitionKey($"GroupList-{school}"));
-                    if (response.Status==200)
-                    {
-                        JsonDocument jsonDocument = JsonDocument.Parse(response.Content);
-                        var groupList = jsonDocument.RootElement.ToObject<GroupList>();
-                        groupList.name=string.IsNullOrWhiteSpace(list.name)?groupList.name: list.name;
-                        
+                        groupList = new GroupList()
+                        {
+                            pk = "GroupList",
+                            id = Guid.NewGuid().ToString(),
+                            code = $"GroupList-{school}",
+                            name = list.name,
+                            periodId = list.periodId,
+                            scope = "school",
+                            school = school,
+                            type = "teach",
+                            year = list.year,
+                            froms = 3
+                        };
+                        groupList = await GroupListService.CheckListNo(groupList, _azureCosmos, _dingDing, _option);
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(groupList, new PartitionKey(groupList.code));
                     }
-                    else { 
+                    else
+                    {
+                        Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{list.id}", new PartitionKey($"GroupList-{school}"));
+                        if (response.Status == 200)
+                        {
+                            JsonDocument jsonDocument = JsonDocument.Parse(response.Content);
+                            groupList = jsonDocument.RootElement.ToObject<GroupList>();
+                            groupList.name = string.IsNullOrWhiteSpace(list.name) ? groupList.name : list.name;
+                            groupList.periodId = string.IsNullOrWhiteSpace(list.periodId) ? groupList.periodId : list.periodId;
+                            groupList.school = school;
+                            groupList.scope = "school";
+                            groupList.froms = 3;
+                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(groupList, groupList.id, new PartitionKey(groupList.code));
+                        }
+                        else
+                        {
+                            groupList = new GroupList()
+                            {
+                                id = Guid.NewGuid().ToString(),
+                                code = $"GroupList-{school}",
+                                name = list.name,
+                                periodId = list.periodId,
+                                scope = "school",
+                                school = school,
+                                type = "teach",
+                                year = list.year,
+                                froms = 3
+                            };
+                            groupList = await GroupListService.CheckListNo(groupList, _azureCosmos, _dingDing, _option);
+                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(groupList, new PartitionKey(groupList.code));
+                        }
                     }
                 }
+                else {
+                    return Ok(new { error = 2, msg ="学段不存在!" });
+                }
+            }
+            else
+            {
+                return Ok(new { error = 3, msg = list.Valid() });
             }
-            return Ok();
+            return Ok(new { groupList });
         }
 
         /// <summary>
@@ -337,7 +370,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("import-teach-members")]
-        [ApiToken(Auth = "115", Name = "导入教学班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1207", Name = "导入教学班学生", RW = "W", Limit = false)]
         public async Task<IActionResult> ImportTeachMembers(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -407,7 +440,7 @@ namespace TEAMModelAPI.Controllers
                 }
                 else
                 {
-                    return Ok(new { error = valid, msg = "名单列表格式错误!" });
+                    return Ok(new { error = 3, msg = valid });
                 }
             }
             else
@@ -423,7 +456,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("remove-teach-members")]
-        [ApiToken(Auth = "116", Name = "移除教学班学生", RW = "W", Limit = false)]
+        [ApiToken(Auth = "1208", Name = "移除教学班学生", RW = "W", Limit = false)]
         public async Task<IActionResult> RemoveTeachMembers(JsonElement json) {
             var (id, school) = HttpContext.GetApiTokenInfo();
             json.TryGetProperty("stuids", out JsonElement _stuids);

+ 7 - 74
TEAMModelAPI/Controllers/School/SchoolController.cs

@@ -59,7 +59,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpGet("get-school-info")]
-        [ApiToken(Auth = "101",Name = "学校基础信息", RW = "R", Limit =false)]
+        [ApiToken(Auth = "1001",Name = "学校基础信息", RW = "R", Limit =false)]
         public async Task<IActionResult> GetSchoolInfo()
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -81,7 +81,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpGet("get-teacher-list")]
-        [ApiToken(Auth = "102", Name = "学校教师列表", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1002", Name = "学校教师列表", RW = "R", Limit = false)]
         public async Task<IActionResult> GetTeacherList()
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -102,7 +102,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-teacher-info")]
-        [ApiToken(Auth = "103", Name = "学校教师信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1003", Name = "学校教师信息", RW = "R", Limit = false)]
         public async Task<IActionResult> GetTeacherInfo(JsonElement json )
         {
             json.TryGetProperty("tmdid", out JsonElement _tmdid);
@@ -138,50 +138,7 @@ namespace TEAMModelAPI.Controllers
             }
         }
        
-        [ProducesDefaultResponseType]
-        [HttpPost("get-course-list")]
-        [ApiToken(Auth = "104", Name = "获取课程列表信息",RW ="R", Limit = false)]
-        public async Task<IActionResult> GetCourseList(JsonElement json) {
-            var client = _azureCosmos.GetCosmosClient();
-            var (id, school) = HttpContext.GetApiTokenInfo();
-            json.TryGetProperty("periodId", out JsonElement periodId);
-            json.TryGetProperty("subjectId", out JsonElement subjectId);
-            StringBuilder sql = new StringBuilder($"SELECT c.id,c.name,c.subject,c.period,c.scope,c.no,c.school FROM c where 1=1 ");
-            if (!string.IsNullOrWhiteSpace($"{periodId}")) {
-                sql.Append($" and c.period.id='{periodId}'");
-            }
-            if (!string.IsNullOrWhiteSpace($"{subjectId}"))
-            {
-                sql.Append($" and c.subject.id='{subjectId}'");
-            }
-            List<dynamic> courses = new List<dynamic>();
-            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").
-                    GetItemQueryIterator<dynamic>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{school}") }))
-            {
-                courses.Add(item);
-            }
-            return Ok(new { courses });
-        }
-       
-        [ProducesDefaultResponseType]
-        [HttpPost("get-course-info")]
-        [ApiToken(Auth = "105", Name = "课程详细信息", RW = "R", Limit = false)]
-        public async Task<IActionResult> GetCourseInfo(JsonElement json)
-        {
-            var (id, school) = HttpContext.GetApiTokenInfo();
-            json.TryGetProperty("courseId", out JsonElement courseId);
-            Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School")
-               .ReadItemStreamAsync($"{courseId}", new PartitionKey($"Course-{school}"));
-            if (response.Status == 200)
-            {
-                JsonDocument document= JsonDocument.Parse(response.Content);
-                Course course= document.RootElement.Deserialize<Course>();
-                return Ok(new { course.name,course.id, course.subject, course .period, course .scope, course.school, course .no, course .desc, course.schedule});
-            }
-            else {
-                return Ok(new { error=1,msg="课程不存在!"});
-            }
-        }
+      
         /// <summary>
         /// 获取物理教室列表
         /// </summary>
@@ -189,7 +146,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-room-list")]
-        [ApiToken(Auth = "106", Name = "获取物理教室列表", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1004", Name = "获取物理教室列表", RW = "R", Limit = false)]
         public async Task<IActionResult> GetRoomList(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -216,7 +173,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-room-info")]
-        [ApiToken(Auth = "107", Name = "获取物理教室详细信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "1005", Name = "获取物理教室详细信息", RW = "R", Limit = false)]
         public async Task<IActionResult> GetRoomInfo(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -235,30 +192,6 @@ namespace TEAMModelAPI.Controllers
             }
         }
 
-        /// <summary>
-        ///  获取试卷和评测的条件信息
-        /// </summary>
-        /// <param name="request"></param>
-        /// <returns></returns>
-        [ProducesDefaultResponseType]
-        [HttpPost("get-paper-exam-condition")]
-        [ApiToken(Auth = "108", Name = "试卷和评测的条件信息", RW = "R", Limit = false)]
-        public async Task<IActionResult> GetPaperExamCondition(JsonElement json)
-        {
-            json.TryGetProperty("periodId", out JsonElement _periodId);
-            var (id, school) = HttpContext.GetApiTokenInfo();
-            School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
-            var exmaType = new { type = new List<string> { "regular", "simulation", "normal" } };//regula ,正规考,  simulation 模拟靠考,normal 普通考
-            var exmaMode = new { type = new List<string> { "0", "1", "2" } };//0 线上评测,  1 课中评测 ,2 阅卷评测
-            var period = data.period.Find(x => x.id.Equals($"{_periodId}"));
-            if (period != null)
-            {
-                return Ok(new { period.subjects, period.analysis, period.grades, exmaType, exmaMode });
-            }
-            else
-            {
-                return Ok(new { error = 1, msg = "学段不存在!" });
-            }
-        }
+        
     }
 }

+ 1 - 0
TEAMModelBI/ClientApp/package.json

@@ -13,6 +13,7 @@
         "@lywzx/vue.access.control": "^1.0.10",
         "axios": "^0.20.0-0",
         "bootstrap": "^4.5.3",
+        "c-scrollbar": "^1.0.2",
         "clipboard": "^2.0.10",
         "core-js": "^3.7.0",
         "echarts": "^5.2.2",

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

@@ -84,7 +84,7 @@ class InitChart {
                 },
             },
             grid: {
-                left: '0%',
+                left: '10%',
                 top: '15%',
                 right: '0%',
                 bottom: '0%',

+ 7 - 4
TEAMModelBI/ClientApp/src/components/echarts/customBar.vue

@@ -82,7 +82,7 @@ class InitChart {
             //图标位置
             grid: {
                 top: '10%',
-                left: '27%',
+                left: '30%',
                 bottom: '10%',
             },
             xAxis: {
@@ -103,11 +103,14 @@ class InitChart {
                         show: false,
                     },
                     axisLabel: {
-                        color: '#fff',
+                        color: '#ccc',
+                        textStyle: {
+                            fontSize: 10,
+                        },
                         rich: {
                             lg: {
                                 backgroundColor: '#339911',
-                                color: '#fff',
+                                color: '#ccc',
                                 borderRadius: 15,
                                 // padding: 5,
                                 align: 'center',
@@ -136,7 +139,7 @@ class InitChart {
                     yAxisIndex: 0,
                     data: data,
                     barCategoryGap: 50,
-                    barWidth: 16,
+                    barWidth: 14,
                     itemStyle: {
                         normal: {
                             barBorderRadius: 20,

+ 5 - 4
TEAMModelBI/ClientApp/src/components/echarts/customPie.vue

@@ -81,11 +81,11 @@ class InitChart {
             },
             legend: {
                 top: '85%',
-                itemWidth: 10,
-                itemHeight: 10,
+                itemWidth: 6,
+                itemHeight: 6,
                 textStyle: {
                     color: 'rgba(255,255,255,.5)',
-                    fontSize: '10',
+                    fontSize: '9',
                 },
             },
             tooltip: {
@@ -99,13 +99,14 @@ class InitChart {
                     name: '数据占比',
                     type: 'pie',
                     // 如果radius是百分比则必须加引号
-                    radius: ['10%', '60%'],
+                    radius: ['20%', '55%'],
                     center: ['50%', '45%'],
                     roseType: 'radius',
                     data: data.various,
                     // 修饰饼形图文字相关的样式 label对象
                     label: {
                         fontSize: 12,
+                        color: 'rgba(255,255,255,.5)',
                     },
                     // 修饰引导线样式
                     labelLine: {

+ 0 - 6
TEAMModelBI/ClientApp/src/language/lang/lang/zh-cn.js

@@ -1,6 +0,0 @@
-const zh_cn = {
-    login: {
-        title: '钉钉扫码登录',
-    },
-}
-export default zh_cn

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

@@ -179,7 +179,7 @@ const zh_cn = {
             spacesize: '空间大小',
             assis: '关联管家',
             operate: '操作',
-            operatecontent: '编辑'
+            operatecontent: '编 辑'
         },
         createSchools: {
             title: '创建学校',

+ 1 - 1
TEAMModelBI/ClientApp/src/language/lang/zh-tw.js

@@ -179,7 +179,7 @@ const zh_tw = {
             spacesize: '空間大小',
             assis: '關聯管家',
             operate: '操作',
-            operatecontent: '編輯'
+            operatecontent: '編 輯'
         },
         createSchools: {
             title: '創建學校',

+ 2 - 0
TEAMModelBI/ClientApp/src/main.js

@@ -15,6 +15,7 @@ import JsonViewer from "vue3-json-viewer"
 import Export2Excel from "@/until/excel/Export2Excel";
 import "vue3-json-viewer/dist/index.css";
 import i18n from './language/i18n'
+import CScrollbar from 'c-scrollbar';
 
 const app = createApp(App)
 app.config.globalProperties.$api = axios
@@ -29,4 +30,5 @@ app.use(Blob)
 app.use(JsonViewer)
 app.use(Export2Excel)
 app.use(i18n)
+app.use(CScrollbar)
 app.mount('#app')

+ 1 - 0
TEAMModelBI/ClientApp/src/view/home.vue

@@ -112,6 +112,7 @@ a:hover {
 ::-webkit-scrollbar-thumb {
     -webkit-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.3);
     background-color: rgba(221, 222, 224); /*滚动条的背景颜色*/
+    border-radius: 5px;
 }
 .el-loading-spinner {
     margin-top: 0 !important;

+ 2 - 20
TEAMModelBI/ClientApp/src/view/index/dashboard.vue

@@ -497,7 +497,7 @@ ul > li {
     background-size: 100% 100%;
 }
 .headers h1 {
-    font-size: 2.475rem;
+    font-size: 2.275rem;
     color: #fff;
     text-align: center;
     line-height: 5rem;
@@ -643,7 +643,7 @@ ul > li {
     height: 2.5rem;
     line-height: 2.5rem;
     text-align: center;
-    font-size: 1.025rem;
+    font-size: 0.955rem;
     color: rgba(255, 255, 255, 0.7);
     padding-top: 0.525rem;
 }
@@ -727,22 +727,4 @@ ul > li {
         transform: translate(-50%, -50%) rotate(-360deg);
     }
 }
-</style>
-<style>
-.dashebordbox .el-loading-spinner .circular {
-    width: 42px;
-    height: 42px;
-    animation: loading-rotate 1s linear infinite;
-    display: none;
-}
-.dashebordbox .el-loading-spinner {
-    background: url('../../assets/img/loading2.gif') no-repeat;
-    background-size: 48px 48px;
-    width: 100px;
-    height: 100px;
-    position: relative;
-    top: 50%;
-    left: 45%;
-    display: block;
-}
 </style>

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

@@ -71,7 +71,7 @@
             </div> -->
         </div>
         <div class="recordbox">
-            <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" @selection-change="handleSelectionChange" :empty-text='$t(`commonMsg.nodataTable`)' v-loading="loading" element-loading-text="数据加载中...">
+            <el-table ref="multipleTableRef" :data="tableData" height="80vh" style="width: 100%" @selection-change="handleSelectionChange" :empty-text='$t(`commonMsg.nodataTable`)' v-loading="loading" element-loading-text="数据加载中...">
                 <el-table-column prop="index" :label="$t(`log.tables.serialnum`)" sortable align="center" />
                 <el-table-column property="name" :label="$t(`log.tables.name`)" align="center" />
                 <el-table-column property="tmdId" :label="$t(`log.tables.id`)" align="center" />

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

@@ -301,5 +301,19 @@ export default {
     height: 45px;
     border-radius: 30px;
 }
+.el-loading-spinner {
+    margin-top: 0 !important;
+    transform: translateY(-50%);
+}
+.el-loading-text {
+    padding-top: 50px;
+    background-image: url('../assets/img/loading2.gif') !important;
+    background-repeat: no-repeat;
+    background-position: top center;
+    background-size: 75px auto;
+}
+.el-loading-spinner .circular {
+    display: none;
+}
 </style>
 

+ 1 - 1
TEAMModelBI/ClientApp/src/view/teachermanage/areamanage.vue

@@ -57,7 +57,7 @@
                 <el-table-column prop="standardName" :label="$t(`areaManages.areaTable.project`)" align="center" />
                 <el-table-column :label="$t(`areaManages.areaTable.operate`)" align="center" v-if="PowerShow">
                     <template #default="scope">
-                        <el-button size="mini" @click="operation(scope.$index, scope.row,true)">{{$t(`areaManages.areaTable.operate`)}}</el-button>
+                        <el-button size="mini" @click="operation(scope.$index, scope.row,true)" type="primary">{{$t(`areaManages.areaTable.operate`)}}</el-button>
                     </template>
                 </el-table-column>
             </el-table>

+ 56 - 29
TEAMModelBI/ClientApp/src/view/teachermanage/classpower.vue

@@ -63,42 +63,46 @@
                             </el-dropdown>
                         </div>
                         <div class="serialnumList">
-                            <div class="serialnumList-item" v-for="(item,index) in powerList" :key="index" :class="{'active':pithCode.pithState===index}">
-                                <p><span :class="item.deviceMax > 1 ? 'serialnumList-item-tag':'serialnumList-item-taginfo'">{{item.typename}}</span><span class="serialnumList-item-num">{{item.serial}}</span></p>
-                                <div class="serialnumList-item-details">
-                                    <span class="details-endtime-title">{{$t(`schoolManages.serial.overdueTime`)}}:</span><span class="details-endtime-content" :class="!item.state ? 'expiretext':''">{{item.etime}}</span><span class="expire" v-show="item.state===false">({{$t(`schoolManages.serial.seletct.overdue`)}})</span>
-                                    <span class="details-use-title">{{$t(`schoolManages.serial.usables`)}}:</span><span class="details-use-content">{{item.usedata}}/{{item.deviceMax}}</span>
+                            <c-scrollbar ref="scrollbarRef" width="100%" height="61vh" trigger="hover" direction="y">
+                                <div class="serialnumList-item" v-for="(item,index) in powerList" :key="index" :class="{'active':pithCode.pithState===index}">
+                                    <p><span :class="item.deviceMax > 1 ? 'serialnumList-item-tag':'serialnumList-item-taginfo'">{{item.typename}}</span><span class="serialnumList-item-num">{{item.serial}}</span></p>
+                                    <div class="serialnumList-item-details">
+                                        <span class="details-endtime-title">{{$t(`schoolManages.serial.overdueTime`)}}:</span><span class="details-endtime-content" :class="!item.state ? 'expiretext':''">{{item.etime}}</span><span class="expire" v-show="item.state===false">({{$t(`schoolManages.serial.seletct.overdue`)}})</span>
+                                        <span class="details-use-title">{{$t(`schoolManages.serial.usables`)}}:</span><span class="details-use-content">{{item.usedata}}/{{item.deviceMax}}</span>
+                                    </div>
+                                    <div class="serialnumList-item-details secondinfo">
+                                        <span>{{$t(`schoolManages.serial.card.socrates`)}}</span>
+                                        <span>{{$t(`schoolManages.serial.card.distance`)}}</span>
+                                        <span>{{$t(`schoolManages.serial.card.recorded`)}}</span>
+                                    </div>
+                                    <div class="pitchon">
+                                        <span class="pitchon-affirm" v-if="pithCode.pithState ===-1 && item.state===true" @click="pitcheEcod(item,index)">{{$t(`schoolManages.serial.choice`)}}</span>
+                                        <span class="pitchon-close" v-if="item.pitch ===true" @click="pithCode.pithState=-1,item.pitch=false">取消</span>
+                                        <span class="pitchon-confirmed" v-if="item.pitch ===true">{{$t(`schoolManages.serial.pitch`)}}</span>
+                                    </div>
                                 </div>
-                                <div class="serialnumList-item-details secondinfo">
-                                    <span>{{$t(`schoolManages.serial.card.socrates`)}}</span>
-                                    <span>{{$t(`schoolManages.serial.card.distance`)}}</span>
-                                    <span>{{$t(`schoolManages.serial.card.recorded`)}}</span>
-                                </div>
-                                <div class="pitchon">
-                                    <span class="pitchon-affirm" v-if="pithCode.pithState ===-1 && item.state===true" @click="pitcheEcod(item,index)">{{$t(`schoolManages.serial.choice`)}}</span>
-                                    <span class="pitchon-close" v-if="item.pitch ===true" @click="pithCode.pithState=-1,item.pitch=false">取消</span>
-                                    <span class="pitchon-confirmed" v-if="item.pitch ===true">{{$t(`schoolManages.serial.pitch`)}}</span>
-                                </div>
-                            </div>
+                            </c-scrollbar>
                         </div>
                     </div>
                 </pane>
                 <pane size="75" min-size="10" max-size="85">
                     <div class="classgradeList">
-                        <div class="classgradeList-list">
-                            <div class="classgradeList-item" v-for="(item,index) in classRoom" :key="item.id" :class="item.serial !==null ? 'alreadyBind':''">
-                                <p class="classgradeList-item-name" :class="item.serial !==null ? 'alreadyBindc':''">{{item.name}}</p>
-                                <p class="classgradeList-item-type" v-if="item.openType==='1' ">{{$t(`schoolManages.serial.classType.common`)}}</p>
-                                <p class="classgradeList-item-type" v-else-if="item.openType ==='2'">{{$t(`schoolManages.serial.classType.specialty`)}}</p>
-                                <p class="classgradeList-item-bind" v-if="item.serial ===null">{{$t(`schoolManages.serial.notbind`)}}</p>
-                                <p class="classgradeList-item-alreadybind" v-else-if="item.serial !==null">{{item.serial}}</p>
-                                <div class="classgradeList-item-hover">
-                                    <span v-if="pithCode.pithState ===-1 && item.serial===null">{{$t(`schoolManages.serial.choiceHint`)}}</span>
-                                    <span v-if="pithCode.pithState !==-1 && pithCode.present && item.serial ===null" @click="bindClass(item,index)">{{$t(`schoolManages.serial.bind`)}}</span>
-                                    <span v-if="item.serial !== null" @click="relieveBind(item,index)">{{$t(`schoolManages.serial.relievebind`)}}</span>
+                        <c-scrollbar ref="scrollbarRef" width="100%" height="61vh" trigger="hover" direction="y">
+                            <div class="classgradeList-list">
+                                <div class="classgradeList-item" v-for="(item,index) in classRoom" :key="item.id" :class="item.serial !==null ? 'alreadyBind':''">
+                                    <p class="classgradeList-item-name" :class="item.serial !==null ? 'alreadyBindc':''">{{item.name}}</p>
+                                    <p class="classgradeList-item-type" v-if="item.openType==='1' ">{{$t(`schoolManages.serial.classType.common`)}}</p>
+                                    <p class="classgradeList-item-type" v-else-if="item.openType ==='2'">{{$t(`schoolManages.serial.classType.specialty`)}}</p>
+                                    <p class="classgradeList-item-bind" v-if="item.serial ===null">{{$t(`schoolManages.serial.notbind`)}}</p>
+                                    <p class="classgradeList-item-alreadybind" v-else-if="item.serial !==null">{{item.serial}}</p>
+                                    <div class="classgradeList-item-hover">
+                                        <span v-if="pithCode.pithState ===-1 && item.serial===null">{{$t(`schoolManages.serial.choiceHint`)}}</span>
+                                        <span v-if="pithCode.pithState !==-1 && pithCode.present && item.serial ===null" @click="bindClass(item,index)">{{$t(`schoolManages.serial.bind`)}}</span>
+                                        <span v-if="item.serial !== null" @click="relieveBind(item,index)">{{$t(`schoolManages.serial.relievebind`)}}</span>
+                                    </div>
                                 </div>
                             </div>
-                        </div>
+                        </c-scrollbar>
                     </div>
                 </pane>
             </splitpanes>
@@ -574,7 +578,30 @@ export default {
 }
 .stretchbox .splitpanes__pane {
     background-color: #fff !important;
-    overflow: auto;
+    /* overflow: auto; */
+}
+@media screen and (max-width: 1367px) {
+    .serialnumList-item-num {
+        display: block;
+    }
+    .secondinfo span {
+        margin-right: 5px !important;
+    }
+    .details-endtime-title {
+        margin-left: 15px;
+    }
+    .details-use-title {
+        display: inline-block;
+    }
+    .classpower {
+        height: 73vh !important;
+    }
+    .classpower-top {
+        height: 120px !important;
+    }
+    .classgradeList .c-scrollbar {
+        height: 54vh !important;
+    }
 }
 </style>
 

+ 81 - 63
TEAMModelBI/ClientApp/src/view/teachermanage/impower.vue

@@ -2,69 +2,73 @@
     <div class="impowerbox">
         <div class="impowerbox-left">
             <div class="impowerbox-list">
-                <div class="impowerbox-list-item" v-for="item in viewProduct" :key="item.id">
-                    <div class="impowerbox-list-item-img">
-                        <img :src="item.img">
-                    </div>
-                    <div class="impowerbox-list-item-content">
-                        <p class="item-content-title">{{item.name}}</p>
-                        <div class="item-content-box">
-                            <p class="introducebox"><span class="item-content-box-type">{{$t(`schoolManages.service.introductory`)}}:</span></p>
-                            <p><span class="item-content-box-brief">{{item.title}}</span></p>
-                            <p><span class="item-content-box-type">{{$t(`schoolManages.service.type`)}}:</span><span class="item-content-box-typename">{{item.type===1 ? $t(`schoolManages.service.software`):item.type ===2 ? $t(`schoolManages.service.servicetype`):item.type ===3 ? $t(`schoolManages.service.hardware`):''}}</span></p>
-                            <!-- <p><span class="item-content-box-type">购买时间:</span><span class="item-content-box-typename">2021-09-08</span></p>
+                <c-scrollbar ref="scrollbarRef" width="100%" height="73vh" trigger="hover" direction="y">
+                    <div class="impowerbox-list-item" v-for="item in viewProduct" :key="item.id">
+                        <div class="impowerbox-list-item-img">
+                            <img :src="item.img">
+                        </div>
+                        <div class="impowerbox-list-item-content">
+                            <p class="item-content-title">{{item.name}}</p>
+                            <div class="item-content-box">
+                                <p class="introducebox"><span class="item-content-box-type">{{$t(`schoolManages.service.introductory`)}}:</span></p>
+                                <p><span class="item-content-box-brief">{{item.title}}</span></p>
+                                <p><span class="item-content-box-type">{{$t(`schoolManages.service.type`)}}:</span><span class="item-content-box-typename">{{item.type===1 ? $t(`schoolManages.service.software`):item.type ===2 ? $t(`schoolManages.service.servicetype`):item.type ===3 ? $t(`schoolManages.service.hardware`):''}}</span></p>
+                                <!-- <p><span class="item-content-box-type">购买时间:</span><span class="item-content-box-typename">2021-09-08</span></p>
                             <p><span class="item-content-box-type">到期时间:</span><span class="item-content-box-typename">2022-07-08</span></p> -->
+                            </div>
+                        </div>
+                        <span class="item-content-buyicon">{{$t(`schoolManages.service.buy`)}}</span>
+                        <div class="impowerbox-list-item-state">
+                            {{$t(`schoolManages.service.serve`)}}
                         </div>
                     </div>
-                    <span class="item-content-buyicon">{{$t(`schoolManages.service.buy`)}}</span>
-                    <div class="impowerbox-list-item-state">
-                        {{$t(`schoolManages.service.serve`)}}
-                    </div>
-                </div>
+                </c-scrollbar>
             </div>
         </div>
         <div class="impowerbox-right">
             <div class="productList">
                 <p class="productList-title"> {{$t(`schoolManages.service.title`)}}:</p>
                 <p class="productList-typename"> {{$t(`schoolManages.service.software`)}}:</p>
-                <div class="productList-item" v-for="item in viewProductList.software" :key="item.id">
-                    <svg class="producticon" aria-hidden="true" v-if="item.state >0">
-                        <use xlink:href="#icon-ruanjian--copy"></use>
-                    </svg>
-                    <svg class="producticon" aria-hidden="true" v-else>
-                        <use xlink:href="#icon-ruanjian-"></use>
-                    </svg>
-                    <span class="productList-text" :class="item.state <=0 ? 'notreach':''">{{item.name}}</span>
-                    <svg class="producticon dependright" aria-hidden="true" v-show="item.state >0">
-                        <use xlink:href="#icon-gouxuan"></use>
-                    </svg>
-                </div>
-                <p class="productList-typename"> {{$t(`schoolManages.service.servicetype`)}}:</p>
-                <div class="productList-item" v-for="item in viewProductList.service" :key="item.id">
-                    <svg class="producticon" aria-hidden="true" v-if="item.state >0">
-                        <use xlink:href="#icon-jishufuwu"></use>
-                    </svg>
-                    <svg class="producticon" aria-hidden="true" v-else>
-                        <use xlink:href="#icon-jishufuwu-copy"></use>
-                    </svg>
-                    <span class="productList-text" :class="item.state <=0 ? 'notreach':''">{{item.name}}</span>
-                    <svg class="producticon dependright" aria-hidden="true" v-show="item.state >0">
-                        <use xlink:href="#icon-gouxuan"></use>
-                    </svg>
-                </div>
-                <p class="productList-typename"> {{$t(`schoolManages.service.hardware`)}}:</p>
-                <div class="productList-item" v-for="item in viewProductList.hardware" :key="item.id">
-                    <svg class="producticon" aria-hidden="true" v-if="item.state >0">
-                        <use xlink:href="#icon-sharpicons_monitor-copy"></use>
-                    </svg>
-                    <svg class="producticon" aria-hidden="true">
-                        <use xlink:href="#icon-sharpicons_monitor-copy-copy"></use>
-                    </svg>
-                    <span class="productList-text" :class="item.state <=0 ? 'notreach':''">{{item.name}}</span>
-                    <svg class="producticon dependright" aria-hidden="true" v-show="item.state >0">
-                        <use xlink:href="#icon-gouxuan"></use>
-                    </svg>
-                </div>
+                <c-scrollbar ref="scrollbarRef" width="100%" height="66vh" trigger="hover" direction="y">
+                    <div class="productList-item" v-for="item in viewProductList.software" :key="item.id">
+                        <svg class="producticon" aria-hidden="true" v-if="item.state >0">
+                            <use xlink:href="#icon-ruanjian--copy"></use>
+                        </svg>
+                        <svg class="producticon" aria-hidden="true" v-else>
+                            <use xlink:href="#icon-ruanjian-"></use>
+                        </svg>
+                        <span class="productList-text" :class="item.state <=0 ? 'notreach':''">{{item.name}}</span>
+                        <svg class="producticon dependright" aria-hidden="true" v-show="item.state >0">
+                            <use xlink:href="#icon-gouxuan"></use>
+                        </svg>
+                    </div>
+                    <p class="productList-typename"> {{$t(`schoolManages.service.servicetype`)}}:</p>
+                    <div class="productList-item" v-for="item in viewProductList.service" :key="item.id">
+                        <svg class="producticon" aria-hidden="true" v-if="item.state >0">
+                            <use xlink:href="#icon-jishufuwu"></use>
+                        </svg>
+                        <svg class="producticon" aria-hidden="true" v-else>
+                            <use xlink:href="#icon-jishufuwu-copy"></use>
+                        </svg>
+                        <span class="productList-text" :class="item.state <=0 ? 'notreach':''">{{item.name}}</span>
+                        <svg class="producticon dependright" aria-hidden="true" v-show="item.state >0">
+                            <use xlink:href="#icon-gouxuan"></use>
+                        </svg>
+                    </div>
+                    <p class="productList-typename"> {{$t(`schoolManages.service.hardware`)}}:</p>
+                    <div class="productList-item" v-for="item in viewProductList.hardware" :key="item.id">
+                        <svg class="producticon" aria-hidden="true" v-if="item.state >0">
+                            <use xlink:href="#icon-sharpicons_monitor-copy"></use>
+                        </svg>
+                        <svg class="producticon" aria-hidden="true">
+                            <use xlink:href="#icon-sharpicons_monitor-copy-copy"></use>
+                        </svg>
+                        <span class="productList-text" :class="item.state <=0 ? 'notreach':''">{{item.name}}</span>
+                        <svg class="producticon dependright" aria-hidden="true" v-show="item.state >0">
+                            <use xlink:href="#icon-gouxuan"></use>
+                        </svg>
+                    </div>
+                </c-scrollbar>
             </div>
         </div>
     </div>
@@ -99,7 +103,7 @@ export default {
                 type: 1,
                 name: 'HiTeach STD',
                 prodcode: 'J223IZ6M',
-                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据,加速教师专业成长,体现随时随地拥有专属议课专家在身边指导的优点,摆脱过去专家评课带有主观因素影响的缺点。',
+                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据。',
                 img: require('@/assets/img/module1.jpg'),
                 state: 0,
             },
@@ -108,7 +112,7 @@ export default {
                 type: 1,
                 name: 'HiTeach TBL',
                 prodcode: '3222C6D2',
-                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据,加速教师专业成长,体现随时随地拥有专属议课专家在身边指导的优点,摆脱过去专家评课带有主观因素影响的缺点。',
+                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据。',
                 img: require('@/assets/img/module1.jpg'),
                 state: 0,
             },
@@ -117,7 +121,7 @@ export default {
                 type: 1,
                 name: 'HiTeach PRO',
                 prodcode: 'J223IZAM',
-                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据,加速教师专业成长,体现随时随地拥有专属议课专家在身边指导的优点,摆脱过去专家评课带有主观因素影响的缺点。',
+                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据。',
                 img: require('@/assets/img/module1.jpg'),
                 state: 0,
             },
@@ -126,7 +130,7 @@ export default {
                 type: 1,
                 name: 'HiTeach Lite',
                 prodcode: '3222NIYD',
-                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据,加速教师专业成长,体现随时随地拥有专属议课专家在身边指导的优点,摆脱过去专家评课带有主观因素影响的缺点。',
+                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据。',
                 img: require('@/assets/img/module1.jpg'),
                 state: 0,
             },
@@ -135,7 +139,7 @@ export default {
                 type: 1,
                 name: 'HiTeach Mobile',
                 prodcode: '3222DNG2',
-                title: '是醍摩豆研发多年的智慧教学系统,借助网路的普及(尤其是5G时代),可以自动整合学生的智慧型手机,不需要安装与设定,只要请学生拿起手机,在浏览器输入webirs.cc,并输入云端教室编号完成连线,就能进行即时反馈与图文互动,既简单又方便。',
+                title: '借助网路的普及(尤其是5G时代),不需要安装与设定,只要请学生拿起手机,并输入云端教室编号完成连线,就能进行即时反馈与图文互动,既简单又方便。',
                 img: require('@/assets/img/module1.jpg'),
                 state: 0,
             },
@@ -144,7 +148,7 @@ export default {
                 type: 1,
                 name: 'HiTeach Premium',
                 prodcode: '3222IAVN',
-                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据,加速教师专业成长,体现随时随地拥有专属议课专家在身边指导的优点,摆脱过去专家评课带有主观因素影响的缺点。',
+                title: '一体整合各课堂间软、硬体,让老师体验在同一系统内实践现代化智慧课堂;内建自动化数据采集系统完整采收课间的教学行为大数据,即时分析、制表,提供教师专业且客观的行为数据。',
                 img: require('@/assets/img/module1.jpg'),
                 state: 0,
             },
@@ -171,7 +175,7 @@ export default {
                 type: 2,
                 name: proxy.$t(`schoolManages.service.serveData.class`),
                 prodcode: 'IPDYZYLC',
-                title: '老师利用IES智慧教学服务即可统整智慧教室教学各阶段所需的教学资源,包含云端课程、学生名单、教材、题库、课堂笔记、评量成绩、课堂影片等,并可根据学生的课堂互动数据,产出学习历程、成绩与诊断分析报告。',
+                title: '各阶段所需的教学资源,包含云端课程、学生名单、教材、题库、课堂笔记、评量成绩、课堂影片等,并可根据学生的课堂互动数据,产出学习历程、成绩与诊断分析报告。',
                 img: require('@/assets/img/module1.jpg'),
                 state: 0,
             },
@@ -207,7 +211,7 @@ export default {
                 type: 2,
                 name: proxy.$t(`schoolManages.service.serveData.teachresearch`),
                 prodcode: 'VLY6J6N6',
-                title: '通过课堂教学观摩、研讨、学习、交流活动,提升教师队伍整体素质以及区域教研能力与水平,引导广大教师钻研智慧课堂教学,更新教育理念,创新教学方法,优化教学过程。',
+                title: '通过课堂教学观摩、研讨、学习、交流活动,提升教师队伍整体素质以及区域教研能力与水平,更新教育理念,创新教学方法,优化教学过程。',
                 img: require('@/assets/img/module3.jpg'),
                 state: 0,
             },
@@ -317,7 +321,7 @@ export default {
 .impowerbox-left {
     width: 75%;
     box-shadow: 1px 1px 5px #ccc;
-    overflow-y: auto;
+    /* overflow-y: auto; */
     padding-bottom: 5px;
 }
 .impowerbox-right {
@@ -327,6 +331,7 @@ export default {
     margin-left: 1%;
     line-height: 20px;
     box-shadow: 1px 1px 5px #ccc;
+    /* overflow-y: auto; */
 }
 .impowerbox-list {
     position: relative;
@@ -338,6 +343,7 @@ export default {
     display: flex;
     flex-direction: row;
     flex-wrap: wrap;
+    text-align: left;
 }
 .impowerbox-list-item {
     width: 28%;
@@ -361,6 +367,7 @@ export default {
     font-size: 20px;
     font-weight: 700;
     margin-top: 10px;
+    text-align: center;
 }
 .item-content-box {
     padding: 15px 10px 15px 25px;
@@ -478,4 +485,15 @@ export default {
     height: 20px;
     color: #8d8d8d;
 }
+@media screen and (max-width: 1367px) {
+    .impowerbox {
+        height: 73vh !important;
+    }
+    .impowerbox-list .c-scrollbar {
+        height: 65vh !important;
+    }
+    .impowerbox-right .c-scrollbar {
+        height: 56vh !important;
+    }
+}
 </style>

+ 1 - 1
TEAMModelBI/ClientApp/src/view/teachermanage/manage.vue

@@ -178,7 +178,7 @@ export default {
                           res.ddUserInfos[i].userstate = res.ddUserInfos[i].tmdId == '' ? false : true
                       }
                       tableData.value = res.ddUserInfos
-                      //   loading.value = false
+                      loading.value = false
                   })
             // const proxys = proxy
             // let valname = val

+ 10 - 3
TEAMModelBI/ClientApp/src/view/teachermanage/school.vue

@@ -80,7 +80,7 @@
                 <!-- <el-table-column prop="state" label="状态" width="110" align="center" /> -->
                 <el-table-column :label="$t(`schoolManages.tables.operate`)" align="center" v-if="PowerShow">
                     <template #default="scope">
-                        <el-button type="text" size="small" @click.prevent="deleteRow(scope.$index, scope.row)">{{$t(`schoolManages.tables.operatecontent`)}}</el-button>
+                        <el-button type="primary" size="default" @click.prevent="deleteRow(scope.$index, scope.row)">{{$t(`schoolManages.tables.operatecontent`)}}</el-button>
                     </template>
                 </el-table-column>
             </el-table>
@@ -185,7 +185,7 @@
 import { reactive, ref, getCurrentInstance, toRef } from 'vue'
 import option from '@/static/region.json'
 import { useStore } from 'vuex'
-import { ElMessage } from 'element-plus'
+import { ElMessage, ElLoading } from 'element-plus'
 import { useRouter } from 'vue-router'
 import SetSchool from './setschool.vue'
 import Impower from './impower.vue'
@@ -548,13 +548,20 @@ export default {
                     }
                 }
             }
+            const loadinginfo = ElLoading.service({
+                lock: true,
+                text: '正在保存,请稍后...',
+                background: 'rgba(0, 0, 0, 0.7)',
+            })
             proxy.$api
                 .updateSchoolphase(newData)
                 .then((res) => {
                     res.state === 200 ? (ElMessage.success('保存成功'), (studyPhase.value = res.schoolInfo.id), (changebtns.value = false)) : ElMessage.error('保存失败')
+                    loadinginfo.close()
                 })
                 .catch((res) => {
                     ElMessage.error(proxy.$t(`commonMsg.apiError`))
+                    loadinginfo.close()
                 })
         }
         getAllschool()
@@ -619,7 +626,7 @@ export default {
     width: 96%;
     max-height: 80vh;
     margin: 0 auto;
-    overflow-y: auto;
+    /* overflow-y: auto; */
 }
 /*编辑页面样式*/
 .redactbox {

+ 43 - 10
TEAMModelBI/ClientApp/src/view/teachermanage/setschool.vue

@@ -1188,6 +1188,7 @@ export default {
 .phasebox {
     width: 100%;
     line-height: 20px;
+    height: 82vh;
 }
 .left-pane,
 .right-pane {
@@ -1195,7 +1196,7 @@ export default {
     text-align: left;
     display: inline-block;
     line-height: 20px;
-    height: 80vh;
+    height: 82vh;
     vertical-align: top;
 }
 .left-pane {
@@ -1204,9 +1205,13 @@ export default {
 .center-pane {
     width: 50%;
     display: inline-block;
-    height: 80vh;
+    height: 83vh;
     border-right: 1px solid #ccc;
     text-align: left;
+    overflow-y: auto;
+}
+.center-pane:hover {
+    overflow-y: auto;
 }
 .pane-title {
     width: 100%;
@@ -1333,7 +1338,7 @@ export default {
     margin: 10px;
     overflow: hidden;
     display: inline-block;
-    width: 98%;
+    width: 97%;
     border: 1px solid #d5d5d5;
 }
 .semesterbox-title {
@@ -1396,11 +1401,11 @@ export default {
 }
 .set-time-enrollment {
     line-height: 20px;
-    margin-top: 0.5%;
+    margin-top: 1%;
 }
 .set-time-enrollment-star {
     line-height: 20px;
-    margin-top: 0.5%;
+    margin-top: 1%;
 }
 .set-time-enrollment span {
     font-size: 12px;
@@ -1432,7 +1437,7 @@ export default {
     padding-left: 2%;
 }
 .set-time-start {
-    width: 25%;
+    width: 27%;
 }
 .set-time-start span {
     margin-left: 10%;
@@ -1542,6 +1547,9 @@ export default {
     display: inline-block;
     border: 1px solid #d5d5d5;
 }
+.classbox {
+    width: 48%;
+}
 .classbox .semesterbox-title::before {
     background: #7c4dff;
 }
@@ -1765,7 +1773,7 @@ export default {
     overflow: hidden;
     display: inline-block;
     border: 1px solid #d5d5d5;
-    width: 98%;
+    width: 97%;
 }
 .exam-type-item {
     background: #80b2c9;
@@ -1781,7 +1789,7 @@ export default {
     padding-right: 10px;
 }
 .exam-type-title {
-    width: 10%;
+    width: 13%;
     line-height: 25px;
     height: 40px;
 }
@@ -1805,7 +1813,7 @@ export default {
     cursor: pointer;
 }
 .exam-type-content {
-    width: 90%;
+    width: 85%;
     min-height: 40px;
 }
 .exam-type-title,
@@ -1822,7 +1830,7 @@ export default {
 .passbox {
     margin-bottom: 10px;
     display: flex;
-    width: 30%;
+    width: 45%;
 }
 .satisfybox-icon,
 .satisfybox-title,
@@ -1916,6 +1924,9 @@ export default {
     width: 50%;
     margin-bottom: 15px;
 }
+.settimebox:hover {
+    overflow-y: auto;
+}
 </style>
 <style>
 .pitch .el-card__body {
@@ -2047,4 +2058,26 @@ export default {
 .conductbox .el-form {
     margin-top: 2%;
 }
+@media screen and (max-width: 1367px) {
+    .settimebox .el-card__body {
+        width: 200px;
+    }
+}
+@media screen and (max-width: 1367px) {
+    .settime-icon div {
+        margin-bottom: 50%;
+    }
+}
+@media screen and (max-width: 1367px) {
+    .classbox,
+    .subjectbox {
+        width: 98% !important;
+    }
+    .phasebox {
+        height: 78vh !important;
+    }
+    .center-pane {
+        height: 79vh !important;
+    }
+}
 </style>

+ 1 - 1
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -1139,7 +1139,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-更新课堂记录出错\n{ex.Message}\n{ex.StackTrace}\n{data}\n{code}\n", GroupNames.成都开发測試群組);
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-更新课堂记录出错\n{ex.Message}\n{ex.StackTrace}\n{data}\n{code}\n{updates}\n", GroupNames.成都开发測試群組);
             }
         }
 

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

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

+ 14 - 9
TEAMModelOS.SDK/Models/Cosmos/School/Course.cs

@@ -83,15 +83,7 @@ namespace TEAMModelOS.SDK.Models
 
     }
 
-    public class Customize
-    {
-        public string id { get; set; }
-        public string name { get; set; }
-        public Teachers teacher { get; set; } = new Teachers();
-        public string scope { get; set; }
-        public string code { get; set; }
-
-    }
+    
     public class TimeInfo
     {
         public string id { get; set; }
@@ -122,4 +114,17 @@ namespace TEAMModelOS.SDK.Models
         public string id { get; set; }
         public string name { get; set; }
     }
+
+    public class CourseDto
+    {
+        public string id { get; set; }
+        [Required(ErrorMessage = "{0} 课程的名称必须填写")]
+        public string name { get; set; }
+        public string desc { get; set; }
+        public string no { get; set; }
+        [Required(ErrorMessage = "{0} 课程的科目id必须填写")]
+        public string subjectId { get; set; }
+        [Required(ErrorMessage = "{0} 课程的学段id必须填写")]
+        public string periodId { get; set; }
+    }
 }

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


+ 6 - 5
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -167,12 +167,13 @@ export default {
                     icon: 'iconfont icon-data-count',
                     name: this.$t('system.menu.researchBoard'),
                     router: '/home/Dashboard',
-                    tag: this.$t('system.preview'),
+                    tag: '',
                     role: 'teacher|admin',
                     permission: '',
                     menuName: 'Dashboard',
                     child: [],
-                    isShow: this.$store.state.config.srvAdrType != 'product' && this.checkHost()
+                    // isShow: this.$store.state.config.srvAdrType != 'product' && this.checkHost()
+                    isShow: this.checkHost()
                 },
                 // 学校管理
                 {
@@ -371,7 +372,7 @@ export default {
                     tag: this.$t('system.preview'),
                     permission: '',
                     subName: 'research',
-                    isShow: this.$store.state.config.srvAdrType != 'product' && this.checkHost(),
+                    isShow: this.checkHost(),
                     child: [
                         {
                             icon: 'iconfont icon-course-videos',
@@ -381,13 +382,13 @@ export default {
                             role: 'teacher|admin',
                             permission: '',
                             menuName: 'courseCenter',
-                            isShow: true
+                            isShow: this.$store.state.config.srvAdrType != 'product'
                         },
                         {
                             icon: 'iconfont icon-data-count',
                             name: this.$t('system.menu.cusVideoMgt'),
                             router: '/home/ResearchMgt',
-                            tag: this.$t('system.preview'),
+                            tag: '',
                             role: 'teacher|admin',
                             permission: '',
                             menuName: 'ResearchMgt',

+ 2 - 2
TEAMModelOS/ClientApp/src/common/QrcodeModal.vue

@@ -65,13 +65,13 @@ export default {
                             width: 280, // 设置宽度,单位像素
                             height: 280, // 设置高度,单位像素
                             // text: encodeURI(url), // 编码处理
-                            text: shortUrl.result, // 编码处理
+                            text: shortUrl.result || encodeURI(this.config.url), // 编码处理
                             correctLevel: QRCode.CorrectLevel.Q //解决编码后网址太长的问题
                         })
                         this.joinQRcode = qrcode
                     } else {
                         this.joinQRcode.clear()
-                        this.joinQRcode.makeCode(shortUrl.result)
+                        this.joinQRcode.makeCode(shortUrl.result || encodeURI(this.config.url))
                     }
                     let dom = document.getElementById('qrcode')
                     if (dom) dom.title = ''

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

@@ -6,7 +6,11 @@
 			<dv-decoration-3 class="dv-dec-3" />
 		</p>
 		<div class="bg-color-black">
-			<TechBar></TechBar>
+			<!-- <TechBar></TechBar> -->
+			<div style="width: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;margin-top: 50px;">
+				<img src="../../assets/image/none.png" width="200px">
+				<span>暂无数据</span>
+			</div>
 		</div>
 	</div>
 </template>

+ 5 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/cusMgt.js

@@ -117,6 +117,7 @@ export default {
     inviteInfo5:'快速加入教師個人課程鏈接:',
     inviteInfo6:'或登入醍摩豆雲平臺IES學習主頁,輸入課程碼加入課程:',
     inviteInfo7:'輸入課程邀請碼,加入課程 :',
+    inviteInfo8:'教師:',
     createTips1: 'Note: You (have joined a school) can select students from your school to join the course, or allow students to join the course by entering the course invitation code, scanning the course QR code, or using the invitation link.',
     createTips2: 'Note: You (not yet a member of a school) can allow students to join the course by entering the course invitation code, scanning the course QR code, or using the invitation link.',
     renameListTitle: 'Edit List Name',
@@ -363,7 +364,10 @@ export default {
         rcdLabel: 'Interaction Records',
         enote: 'E-Note',
         sokrateRpt: 'Sokrates Report',
-        dataCount: 'Data Statistics',
+        dataCount:'统计数据',
+        videoData:'視頻數據',
+        exportData:'導出數據',
+        noVideo:'當前課堂記錄沒有視頻數據',
         allRcd: 'All Records',
         qustion: 'Pop Quiz',
         message: 'HiMessage',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js

@@ -69,7 +69,7 @@ export default {
         shareText2:'活動名稱:',
         shareText3:'活動類型:',
         shareText4:'學科:',
-        shareText5:'課程:',
+        shareText5:'課程名稱:',
         shareText6:'快速登入醍摩豆雲平臺IES學習主頁,進行線上活動',
         shareText7:'或登入醍摩豆雲平臺IES學習主頁,進行線上活動:',
         shareText8:'掃碼進行線上活動',

+ 5 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/cusMgt.js

@@ -117,6 +117,7 @@ export default {
     inviteInfo5:'快速加入教师个人课程链接:',
     inviteInfo6:'或登入醍摩豆云平台IES学习主页,输入课程码加入课程:',
     inviteInfo7:'输入课程邀请码,加入课程 :',
+    inviteInfo8:'教师 :',
     createTips1:'温馨提示:您(已加入学校)可以挑选学校学生加入课程或让学生通过输入课程邀请码、扫描课程二维码、课程链接方式主动加入课程。',
     createTips2:'温馨提示:您(暂未加入学校)可让学生通过输入课程邀请码、扫描课程二维码、课程链接方式主动加入课程。',
     renameListTitle:'修改名称',
@@ -363,7 +364,10 @@ export default {
         rcdLabel:'互动记录',
         enote:'电子笔记',
         sokrateRpt:'苏格拉底报告',
-        dataCount:'数据统计',
+        dataCount:'统计数据',
+        videoData:'视频数据',
+        exportData:'导出数据',
+        noVideo:'当前课堂记录没有视频数据',
         allRcd:'所有记录',
         qustion:'即问即答',
         message:'飞讯',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/learnActivity.js

@@ -70,7 +70,7 @@ export default {
         shareText2:'活动名称:',
         shareText3:'活动类型:',
         shareText4:'学科:',
-        shareText5:'课程:',
+        shareText5:'课程名称:',
         shareText6:'快速登入醍摩豆云平台IES学习主页,进行线上活动',
         shareText7:'或登入醍摩豆云平台IES学习主页,进行线上活动:',
         shareText8:'扫码进行线上活动',

+ 5 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/cusMgt.js

@@ -117,6 +117,7 @@ export default {
     inviteInfo5:'快速加入教師個人課程鏈接:',
     inviteInfo6:'或登入醍摩豆雲平臺IES學習主頁,輸入課程碼加入課程:',
     inviteInfo7:'輸入課程邀請碼,加入課程 :',
+    inviteInfo8:'教師:',
     createTips1: '溫馨提示:您(已加入學校)可以挑選學校學生加入課程或讓學生通過輸入課程邀請碼、掃描課程二維碼、課程鏈接方式主動加入課程。 ',
     createTips2: '溫馨提示:您(暫未加入學校)可讓學生通過輸入課程邀請碼、掃描課程二維碼、課程鏈接方式主動加入課程。 ',
     renameListTitle: '修改名稱',
@@ -363,7 +364,10 @@ export default {
         rcdLabel: '互動記錄',
         enote: '電子筆記',
         sokrateRpt: '蘇格拉底報告',
-        dataCount: '數據統計',
+        dataCount: '統計數據',
+        videoData:'視頻數據',
+        exportData:'導出數據',
+        noVideo:'當前課堂記錄沒有視頻數據',
         allRcd: '所有記錄',
         qustion: '即問即答',
         message: '飛訊',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/learnActivity.js

@@ -70,7 +70,7 @@ export default {
         shareText2:'活動名稱:',
         shareText3:'活動類型:',
         shareText4:'學科:',
-        shareText5:'課程:',
+        shareText5:'課程名稱:',
         shareText6:'快速登入醍摩豆雲平臺IES學習主頁,進行線上活動',
         shareText7:'或登入醍摩豆雲平臺IES學習主頁,進行線上活動:',
         shareText8:'掃碼進行線上活動',

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

@@ -33,50 +33,32 @@ export const routes = [{
 		{
 			name: 'login',
 			path: '/',
-			meta: {
-				middleware: ['login?']
-			},
 			component: resolve => require(['@/view/login/Index.vue'], resolve)
 		},
 		{
 			name: 'loginTeacher',
 			path: 'teacher',
-			meta: {
-				middleware: ['login?']
-			},
 			component: resolve => require(['@/view/login/page/Teacher.vue'], resolve)
 		},
 		{
 			name: 'loginStudent',
 			path: 'student',
-			meta: {
-				middleware: ['login?']
-			},
 			component: resolve => require(['@/view/login/page/Student.vue'], resolve)
 		},
 		// 金牛区登录页
 		{
 			name: 'jinniu',
 			path: '/jinniu',
-			meta: {
-				middleware: ['login?']
-			},
 			component: resolve => require(['@/view/login/jinniu/Index.vue'], resolve)
 		},
 		{
 			name: 'jinniuTeacher',
 			path: 'jinniuteacher',
-			meta: {
-				middleware: ['login?']
-			},
 			component: resolve => require(['@/view/login/jinniu/Teacher.vue'], resolve)
 		},
 		{
 			name: 'jinniuStudent',
 			path: 'jinniustudent',
-			meta: {
-				middleware: ['login?']
-			},
 			component: resolve => require(['@/view/login/jinniu/Student.vue'], resolve)
 		},
 
@@ -88,9 +70,6 @@ export const routes = [{
 	children: [{
 		name: 'regist',
 		path: '/regist',
-		meta: {
-			middleware: ['login?']
-		},
 		component: resolve => require(['@/view/regist/Index.vue'], resolve)
 	}]
 },
@@ -101,9 +80,6 @@ export const routes = [{
 	children: [{
 		name: 'bandphone',
 		path: '/bandphone',
-		meta: {
-			middleware: ['login?']
-		},
 		component: resolve => require(['@/view/user/BandPhone.vue'], resolve)
 	}]
 },
@@ -113,9 +89,6 @@ export const routes = [{
 	children: [{
 		name: 'forgotpw',
 		path: '/forgotpw',
-		meta: {
-			middleware: ['login?']
-		},
 		component: resolve => require(['@/view/forgotPw/Index.vue'], resolve)
 	}]
 },

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

@@ -801,6 +801,7 @@ export default {
                 userAccess.roles = info.roles
                 userAccess.permissions = info.permissions
                 sessionStorage.setItem('userAccess', encodeURIComponent(JSON.stringify(userAccess), "utf-8"))
+                localStorage.setItem('t_access', encodeURIComponent(JSON.stringify(userAccess), "utf-8"))
 
                 return true
             } else {

+ 4 - 4
TEAMModelOS/ClientApp/src/view/areatrain/TrainDetail.vue

@@ -892,12 +892,12 @@ export default {
                     let qrcode = new QRCode('fullqrcode', {
                         width: 320, // 设置宽度,单位像素
                         height: 320, // 设置高度,单位像素
-                        text: shortUrl.result // 设置二维码内容或跳转地址
+                        text: shortUrl.result || encodeURI(url) // 设置二维码内容或跳转地址
                     })
                     this.fullQR = qrcode
                 } else {
                     this.fullQR.clear()
-                    this.fullQR.makeCode(shortUrl.result)
+                    this.fullQR.makeCode(shortUrl.result || encodeURI(url))
                 }
                 let dom = document.getElementById('fullqrcode')
                 if (dom) dom.title = ''
@@ -914,12 +914,12 @@ export default {
                     let qrcode = new QRCode('sign-qr-code', {
                         width: 150, // 设置宽度,单位像素
                         height: 150, // 设置高度,单位像素
-                        text: shortUrl.result // 设置二维码内容或跳转地址
+                        text: shortUrl.result || encodeURI(url)// 设置二维码内容或跳转地址
                     })
                     this.signQRcode = qrcode
                 } else {
                     this.signQRcode.clear()
-                    this.signQRcode.makeCode(shortUrl.result)
+                    this.signQRcode.makeCode(shortUrl.result || encodeURI(url))
                 }
                 let dom = document.getElementById('qrcode')
                 if (dom) dom.title = ''

+ 8 - 0
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.less

@@ -67,6 +67,7 @@
     box-shadow: 0px 0px 10px 2px #d8d8d8;
     height: 450px;
     display: flex;
+    position: relative;
     background: #fff;
 }
 .courseware-wrap {
@@ -398,4 +399,11 @@
     right: 5px;
     bottom: 5px;
     z-index: 9999;
+}
+.no-video-tips{
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    color: #ff9900;
+    width: 100%;
 }

+ 47 - 26
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue

@@ -29,10 +29,15 @@
                         <!-- <span class="e-note-tag" @click="viewReport">
                             {{$t('cusMgt.rcd.sokrateRpt')}}
                         </span> -->
+                        <!-- 表格下载 -->
+                        <span class="e-note-tag" @click="downloadData">
+                            <Icon type="md-download" />
+                            {{$t('cusMgt.rcd.exportData')}}
+                        </span>
                         <!-- 数据统计 -->
-                        <span class="e-note-tag" @click="viewData">
-                            <Icon type="md-podium" />
-                            {{$t('cusMgt.rcd.dataCount')}}
+                        <span class="e-note-tag" v-show="hasVideo" @click="isShowVd = !isShowVd">
+                            <Icon :type="isShowVd ? 'md-podium' : 'logo-youtube'" />
+                            {{isShowVd ? $t('cusMgt.rcd.dataCount') : $t('cusMgt.rcd.videoData')}}
                         </span>
                     </div>
                 </div>
@@ -48,15 +53,18 @@
                             <Page :total="pageList.length" :current="curPage" :page-size="1" size="small" @on-change="getCurHTEX" />
                         </div>
                     </div>
-                    <video-player2 v-if="hasVideo || isShowVd" @on-vd-error="videoError" class="video-player-box" :markers="markers" ref="videoPlayer" :options="playerOptions" :playsinline="true" @getCurPage="getCurPage">
+                    <video-player2 v-if="hasVideo" v-show="isShowVd" @on-vd-error="videoError" class="video-player-box" :markers="markers" ref="videoPlayer" :options="playerOptions" :playsinline="true" @getCurPage="getCurPage">
                     </video-player2>
-                    <div v-else class="video-player-box" style="padding:25px 0px">
-                        <DataCount></DataCount>
+                    <div v-show="!isShowVd" class="video-player-box" style="padding:25px 0px">
+                        <Alert v-show="!hasVideo" class="no-video-tips" type="warning" show-icon>
+                            {{$t('cusMgt.rcd.noVideo')}}
+                        </Alert>
+                        <DataCount :rcdInfo="recordInfo"></DataCount>
                     </div>
-                    <i-switch v-show="hasVideo" v-model="isShowVd" class="toggle-view" true-color="#19be6b" false-color="#2b85e4">
+                    <!-- <i-switch v-show="hasVideo" v-model="isShowVd" class="toggle-view" true-color="#19be6b" false-color="#2b85e4">
                         <Icon type="logo-youtube" slot="open"></Icon>
                         <Icon type="md-podium" slot="close"></Icon>
-                    </i-switch>
+                    </i-switch> -->
                 </div>
 
                 <div class="cus-data-wrap">
@@ -118,9 +126,6 @@
         </div>
         <!--返回顶部-->
         <BackToTop @on-to-top="handleToTop"></BackToTop>
-        <Modal v-model="dataStatus" :title="$t('cusMgt.rcd.dataCount')" :width="800" footer-hide>
-            <DataCount></DataCount>
-        </Modal>
     </div>
 </template>
 <script>
@@ -136,9 +141,8 @@ export default {
     },
     data() {
         return {
-            isShowVd:false,
-            hasVideo:true,
-            dataStatus: false,
+            isShowVd: true,
+            hasVideo: true,
             eventClick: false,
             sokratesRecords: [],
             pageList: [],
@@ -183,8 +187,26 @@ export default {
         }
     },
     methods: {
-        videoError(){
-            this.hasVideo = false 
+        //下载统计表格
+        downloadData() {
+            let blobInfo = this.recordInfo.scope === 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile
+            let url = `${blobInfo.blob_uri}/records/${this.recordInfo.id}/IES/summary.xlsx?${blobInfo.blob_sas}`
+
+            const downloadRes = async () => {
+                let response = await fetch(url); // 内容转变成blob地址
+                let blob = await response.blob(); // 创建隐藏的可下载链接
+                let objectUrl = window.URL.createObjectURL(blob);
+                let a = document.createElement('a');
+                a.href = objectUrl;
+                a.download = this.recordInfo.name + '.xlsx';
+                a.click()
+                a.remove();
+            }
+            downloadRes();
+        },
+        videoError() {
+            this.hasVideo = false
+            this.isShowVd = false
         },
         //返回顶部
         handleToTop() {
@@ -212,8 +234,8 @@ export default {
         getPageList() {
             this.pageList = []
             this.markers = []
-            let userProfile = this.$store.state.user.userProfile
-            let url = `${userProfile.blob_uri}/records/${this.recordInfo.id}/Sokrates/SokratesRecords.json?${userProfile.blob_sas}`
+            let blobInfo = this.recordInfo.scope == 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile
+            let url = `${blobInfo.blob_uri}/records/${this.recordInfo.id}/Sokrates/SokratesRecords.json?${blobInfo.blob_sas}`
             this.$tools.getFile(url).then(
                 res => {
                     this.sokratesRecords = JSON.parse(res)
@@ -222,7 +244,7 @@ export default {
                     pgids.forEach((item, index) => {
                         let page = {}
                         page.id = item
-                        page.img = `${userProfile.blob_uri}/records/${this.recordInfo.id}/Memo/${item}.jpg?${userProfile.blob_sas}`
+                        page.img = `${blobInfo.blob_uri}/records/${this.recordInfo.id}/Memo/${item}.jpg?${blobInfo.blob_sas}`
                         page.page = index + 1
                         //当前页面对应的sokrates
                         page.pageData = this.sokratesRecords.filter(record => record.Pgid === item && record.Event != 'PgJump' && record.Event != 'PgAdd' && record.Event != 'DiscussStart')
@@ -253,10 +275,6 @@ export default {
                 query: { id: this.recordInfo.id, name: this.recordInfo.name }
             })
         },
-        //查看数据统计
-        viewData() {
-            this.dataStatus = true
-        },
         //查看电子笔记
         viewENote() {
             if (this.recordInfo.eNote) {
@@ -349,9 +367,9 @@ export default {
         } else {
             sessionStorage.setItem('record', JSON.stringify(this.recordInfo))
             //对接Blob数据
-            let userProfile = this.$store.state.user.userProfile
-            this.videoUrl = `${userProfile.blob_uri}/records/${this.recordInfo.id}/Record/CourseRecord.mp4?${userProfile.blob_sas}`
-            this.videoPoster = `${userProfile.blob_uri}/records/${this.recordInfo.id}/Record/CoverImage.jpg?${userProfile.blob_sas}`
+            let blobInfo = this.recordInfo.scope == 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile
+            this.videoUrl = `${blobInfo.blob_uri}/records/${this.recordInfo.id}/Record/CourseRecord.mp4?${blobInfo.blob_sas}`
+            this.videoPoster = `${blobInfo.blob_uri}/records/${this.recordInfo.id}/Record/CoverImage.jpg?${blobInfo.blob_sas}`
             this.playerOptions.poster = this.videoPoster
             this.playerOptions.sources.push({
                 src: this.videoUrl
@@ -393,4 +411,7 @@ export default {
 .video-player-box .vjs-volume-panel {
     display: none;
 }
+.video-player-box .ivu-alert {
+    border-radius: 0px;
+}
 </style>

+ 10 - 6
TEAMModelOS/ClientApp/src/view/classrecord/eventchart/DataCount.vue

@@ -10,12 +10,19 @@
 <script>
 import CountTo from 'vue-count-to'
 export default {
+    props: {
+        rcdInfo: {
+            type: Object,
+            default: () => {
+                return undefined
+            }
+        }
+    },
     components: {
         CountTo
     },
     data() {
         return {
-            baseData: {},
             colorList: ['#2d8cf0', '#2d8cf0', '#2db7f5', '#2db7f5', '#2db7f5', '#19be6b', '#2db7f5', '#2db7f5', '#2db7f5', '#ed4014'],
             dataList: [
                 {
@@ -73,11 +80,8 @@ export default {
         }
     },
     created() {
-        //Base.json Blob尚未上传,暂时从本地读取
-        this.baseData = require("../data/Base.json")
-        console.log(this.baseData)
-        if (this.baseData.summary) {
-            const summary = this.baseData.summary
+        if (this.rcdInfo) {
+            const summary = this.rcdInfo
             // 出席人数
             this.dataList[0].value = summary.attendCount
             this.dataList[0].info = `(${summary.attendCount}/${summary.clientCount} ${summary.attendRate}%)`

+ 3 - 2
TEAMModelOS/ClientApp/src/view/homepage/AcCountPie.vue

@@ -36,7 +36,7 @@ export default {
                         padding: [5, 0, 5, 0]
                     },
                     icon: 'circle',
-                    bottom: 10
+                    bottom: 20
                 },
                 grid: {
                     left: '10px',
@@ -56,6 +56,7 @@ export default {
                         label:{
                             show:false
                         },
+                        center:['50%','40%'],
                         data: []
                     }
                 ]
@@ -98,7 +99,7 @@ export default {
                 this.option.title = []
                 this.option.title.push({
                     text: '{name|' + title + '}\n{val|' + this.total + '}',
-                    top: '38%',
+                    top: '30%',
                     left: 'center',
                     textStyle: {
                         rich: {

+ 16 - 3
TEAMModelOS/ClientApp/src/view/homepage/HomePage.less

@@ -360,8 +360,9 @@
     .cus-count-item{
         padding: 10px 15px;
         // width: 120px;
-        flex:0.2;
+        // flex:0.2;
         min-width: 60px;
+        width: calc(25% - 22px);
         height: 80px;
         border-radius: 5px;
         background: #54aded;
@@ -370,14 +371,26 @@
         border: 1px solid #f0f0f0;
     }
     .tag-label{
-        color: #fff;
+        color: #4b4646;
     }
     .count-num{
         font-size: 30px;
         font-weight: 600;
-        color: white;
+        color: #4b4646;
     }
 }
+.cus-count-item-bg3{
+    background: #87c1fd !important;
+    // background-image: linear-gradient(120deg, #5ab7bf 0%, #95c6f2 100%) !important;
+}
+.cus-count-item-bg1{
+    background: #96c3d7 !important;
+    // background-image: linear-gradient(120deg, #5cadff 0%, #2db7f5 100%) !important;
+}
+.cus-count-item-bg2{
+    background: #b8ced7 !important;
+    // background-image: linear-gradient(120deg, #54adff 0%, #00b2c1 100%) !important;
+}
 .cus-chart-wrap{
     padding: 0px;
     display: flex;

+ 77 - 39
TEAMModelOS/ClientApp/src/view/homepage/HomePage.vue

@@ -4,10 +4,17 @@
         <vuescroll>
             <div class="chart-box">
                 <div class="chart-box-column1">
-                    <!-- 我的课表 -->
-                    <div class="cus-table-box">
+                    <!-- TODO 我的课表 此部分暂时去掉-->
+                    <div class="cus-table-box" v-if="!checkHost()">
                         <MinTable @tmwCus="getTmwCus"></MinTable>
                     </div>
+                    <!-- 活动统计 -->
+                    <div class="ac-count-box" v-else style="width:100%;height:360px;margin-bottom:15px">
+                        <p class="chart-title">
+                            {{$t('home.acCount')}}
+                        </p>
+                        <AcCountPie style="margin-top:-20px;" :count="acCount"></AcCountPie>
+                    </div>
                     <!-- 第三方平台连接 -->
                     <div class="recent-box" style="height:389px" v-if="checkHost()">
                         <p class="text-title">{{$t('platform.ptText')}}</p>
@@ -21,38 +28,72 @@
                             </vuescroll>
                         </div>
                     </div>
-                    <!-- 活动统计 -->
-                    <div class="ac-count-box" v-else style="width:100%">
-                        <p class="chart-title">
-                            {{$t('home.acCount')}}
-                        </p>
-                        <AcCountPie style="margin-top:-20px;" :count="acCount"></AcCountPie>
-                    </div>
+
                 </div>
                 <div class="chart-box-column2">
-                    <!-- 课堂数据 -->
-                    <div class="class-chart-box" v-if="checkHost()">
+                    <!-- 数据统计 -->
+                    <div class="class-chart-box" v-if="checkHost()" style="padding:35px 30px">
+                        <!-- 课堂记录统计 -->
                         <div class="cus-count-wrap">
-                            <div class="cus-count-item">
+                            <div class="cus-count-item cus-count-item-bg3">
                                 <p class="tag-label">{{$t('home.cusTotal')}}</p>
                                 <countTo :startVal='0' :endVal='recordCount.total || 0' :duration='1500' class="count-num"></countTo>
                             </div>
 
-                            <div class="cus-count-item">
+                            <div class="cus-count-item cus-count-item-bg3">
                                 <p class="tag-label">{{$t('home.semesterCount')}}</p>
                                 <countTo :startVal='0' :endVal='recordCount.semester || 0' :duration='1500' class="count-num"></countTo>
                             </div>
-                            <div class="cus-count-item">
+                            <div class="cus-count-item cus-count-item-bg3">
                                 <p class="tag-label">{{$t('home.weekCount')}}</p>
                                 <countTo :startVal='0' :endVal='recordCount.week || 0' :duration='1500' class="count-num"></countTo>
                             </div>
-                            <div class="cus-count-item">
+                            <div class="cus-count-item cus-count-item-bg3">
                                 <p class="tag-label">{{$t('home.dayCount')}}</p>
                                 <countTo :startVal='0' :endVal='recordCount.today || 0' :duration='1500' class="count-num"></countTo>
                             </div>
                         </div>
-                        <Divider dashed />
-                        <div class="cus-chart-wrap">
+                        <!-- 课程班级名单统计 -->
+                        <div class="cus-count-wrap" style="margin-top:25px">
+                            <div class="cus-count-item cus-count-item-bg1">
+                                <p class="tag-label">学校课程</p>
+                                <countTo :startVal='0' :endVal='countData.schoolCourseCount  || 0' :duration='1500' class="count-num"></countTo>
+                            </div>
+                            <div class="cus-count-item cus-count-item-bg1">
+                                <p class="tag-label">任教班级</p>
+                                <countTo :startVal='0' :endVal='countData.classIdsCount   || 0' :duration='1500' class="count-num"></countTo>
+                            </div>
+                            <div class="cus-count-item cus-count-item-bg1">
+                                <p class="tag-label">个人课程</p>
+                                <countTo :startVal='0' :endVal='countData.privateCourseCount   || 0' :duration='1500' class="count-num"></countTo>
+                            </div>
+                            <div class="cus-count-item cus-count-item-bg1">
+                                <p class="tag-label">个人名单</p>
+                                <countTo :startVal='0' :endVal='countData.stulistsCount   || 0' :duration='1500' class="count-num"></countTo>
+                            </div>
+                        </div>
+                        <!-- 资源统计 -->
+                        <div class="cus-count-wrap" style="margin-top:25px">
+                            <div class="cus-count-item cus-count-item-bg2">
+                                <p class="tag-label">课纲数量</p>
+                                <countTo :startVal='0' :endVal='countData.privateSyllabusCount  || 0' :duration='1500' class="count-num"></countTo>
+                            </div>
+                            <div class="cus-count-item cus-count-item-bg2">
+                                <p class="tag-label">试卷数量</p>
+                                <countTo :startVal='0' :endVal='countData.privatePaperCount   || 0' :duration='1500' class="count-num"></countTo>
+                            </div>
+                            <div class="cus-count-item cus-count-item-bg2">
+                                <p class="tag-label">题目数量</p>
+                                <countTo :startVal='0' :endVal='countData.privateItemCount  || 0' :duration='1500' class="count-num"></countTo>
+                            </div>
+                            <div class="cus-count-item cus-count-item-bg2">
+                                <p class="tag-label">资源数量</p>
+                                <countTo :startVal='0' :endVal='countData.privateBloblogCount  || 0' :duration='1500' class="count-num"></countTo>
+                            </div>
+                        </div>
+                        <!-- 暂时隐藏 -->
+                        <!-- <Divider dashed /> -->
+                        <div class="cus-chart-wrap" style="display:none">
                             <!-- 最高T分 -->
                             <TechScore class="class-chart" :tScore="recordData.max || 0"></TechScore>
                             <!-- 课例趋势图 -->
@@ -64,7 +105,8 @@
                     <!-- 研修数据 && 活动统计-->
                     <div style="display: flex;">
                         <!-- 研修数据 -->
-                        <div class="train-chart-box" :style="{width:!checkHost() ? '100%' : 'calc(70% - 15px)',marginRight:!checkHost() ? '0px' : '15px'}" v-show="$store.state.config.srvAdr == 'China'">
+                        <!-- <div class="train-chart-box" :style="{width:!checkHost() ? '100%' : 'calc(70% - 15px)',marginRight:!checkHost() ? '0px' : '15px'}" v-show="$store.state.config.srvAdr == 'China'"> -->
+                        <div class="train-chart-box" style="width:100%;margin-right:0px" v-show="$store.state.config.srvAdr == 'China'">
                             <p class="chart-title">
                                 {{$t('system.menu.trainCount')}}
                             </p>
@@ -118,12 +160,12 @@
                             </div>
                         </div>
                         <!-- 活动统计 -->
-                        <div class="ac-count-box" v-if="checkHost()">
+                        <!-- <div class="ac-count-box" v-if="checkHost()">
                             <p class="chart-title">
                                 {{$t('home.acCount')}}
                             </p>
                             <AcCountPie style="margin-top:-20px;" :count="acCount"></AcCountPie>
-                        </div>
+                        </div> -->
                     </div>
 
                 </div>
@@ -209,6 +251,7 @@ export default {
     inject: ['reload'],
     data() {
         return {
+            countData:{},
             platformList: [],
             areaSas: '',
             schoolSas: '',
@@ -319,8 +362,8 @@ export default {
     },
     methods: {
         openPlatform(index) {
-			let url = this.platformList[index].url
-			window.open(/^(http:|https:)/i.test(url) ? url : "http://" + url)
+            let url = this.platformList[index].url
+            window.open(/^(http:|https:)/i.test(url) ? url : "http://" + url)
         },
         //查看课堂记录统计数据
         getTeacherRecordData() {
@@ -356,7 +399,7 @@ export default {
         },
         //查询学时数据
         getStudyTime() {
-            if(!this.$store.state.userInfo.hasSchool) return
+            if (!this.$store.state.userInfo.hasSchool) return
             let req = {
                 tmdid: this.$store.state.userInfo.TEAMModelId,
                 school: this.$store.state.userInfo.schoolCode,
@@ -435,7 +478,7 @@ export default {
         },
         //查询学校公告
         findNotice() {
-            if(!this.$store.state.userInfo.hasSchool) return
+            if (!this.$store.state.userInfo.hasSchool) return
             let params = {
                 code: this.$store.state.userInfo.schoolCode,
                 type: "school",
@@ -496,7 +539,7 @@ export default {
         },
         // 查询学校资源平台
         getSchoolSetting() {
-            if(!this.$store.state.userInfo.hasSchool) return
+            if (!this.$store.state.userInfo.hasSchool) return
             let params = {
                 schoolId: this.$store.state.userInfo.schoolCode
             }
@@ -580,7 +623,7 @@ export default {
                     if (res.goingDatas) {
                         this.goingList = res.goingDatas
                     }
-
+                    this.countData = res
                 },
                 err => {
                     // this.$Message.error('API error!')
@@ -596,6 +639,14 @@ export default {
         },
     },
     created() {
+        // privateCourseCount  私人课程数量
+        // schoolCourseCount 所在学校教学课程数量
+        // classIdsCount  行政班教学数量
+        // teachIdsCount  教学班教学数量 
+        // stulistsCount  个人课程名单数量
+        // privateItemCount 个人题目数量
+        // privatePaperCount  个人试卷数量
+        // privateSyllabusCount 个人课纲数量
         this.areaSas = this.$store.state.user.userProfile.osblob_sas
         this.schoolSas = this.$store.state.user.schoolProfile.blob_sas
         this.getAreaSource()
@@ -612,14 +663,6 @@ export default {
         }
     },
     mounted() {
-        //      this.$EventBus.$off('onGlobalLoading')
-        //      this.$EventBus.$on('onGlobalLoading', (data) => {
-        // if(!data){
-        // 	this.getAcCount()	
-        // }else{
-        // 	this.isLoading = data
-        // }
-        //      })
     },
     computed: {
         //暂时只验证加入学校, 手机号需要对接API
@@ -635,11 +678,6 @@ export default {
         }
     },
     watch: {
-        // '$store.state.userInfo.schoolCode': {
-        //     handler(n, o) {
-        //         this.getAcCount()
-        //     }
-        // }
     }
 }
 </script>

+ 4 - 4
TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.vue

@@ -277,8 +277,8 @@ export default {
             let evType = this.getModeLabel(this.evaListShow[this.curEvaIndex].source)
             let soc = this.evaListShow[this.curEvaIndex].owner === 'school' ? this.$t('learnActivity.mgtScEv.shareText4') : this.$t('learnActivity.mgtScEv.shareText5')
             let socName = this.evaListShow[this.curEvaIndex].subjects.map(item => item.name).join('、')
-            let shortUrl = await this.$api.getShortUrl(encodeURI(this.shareUrl)) //暂不替换,等路由处理好了再替换
-            let shareText = `${this.$t('learnActivity.mgtScEv.shareText1')}\n\n${this.$t('learnActivity.mgtScEv.shareText2')}${evName}\n${this.$t('learnActivity.mgtScEv.shareText3')}${evType}\n${soc}${socName}\n\n${this.$t('learnActivity.mgtScEv.shareText6')}\n${shortUrl.result}\n\n${this.$t('learnActivity.mgtScEv.shareText7')}\nURL:https://${window.location.host}/login/student`
+            let shortUrl = await this.$api.getShortUrl(encodeURI(this.shareUrl)) //暂不替换,等路由处理好了再替换 
+            let shareText = `${this.$t('learnActivity.mgtScEv.shareText1')}\n\n${soc}${socName}\n${this.$t('learnActivity.mgtScEv.shareText3')}${evType}\n${this.$t('cusMgt.inviteInfo8')}${this.$store.state.userInfo.name}\n${this.$t('learnActivity.mgtScEv.shareText2')}${evName}\n\n${this.$t('learnActivity.mgtScEv.shareText6')}\n${shortUrl.result || encodeURI(this.shareUrl)}\n\n${this.$t('learnActivity.mgtScEv.shareText7')}\nURL:https://${window.location.host}/login/student`
             this.$copyText(shareText).then(
                 ok => {
                     this.$Message.success(this.$t("settings.copyModal1"))
@@ -297,13 +297,13 @@ export default {
                     let qrcode = new QRCode('qrcode', {
                         width: 280, // 设置宽度,单位像素
                         height: 280, // 设置高度,单位像素
-                        text: shortUrl.result, // 编码处理
+                        text: shortUrl.result || encodeURI(this.shareUrl), // 编码处理
                         correctLevel: QRCode.CorrectLevel.Q //解决编码后网址太长的问题
                     })
                     this.shareQRcode = qrcode
                 } else {
                     this.shareQRcode.clear()
-                    this.shareQRcode.makeCode(shortUrl.result)
+                    this.shareQRcode.makeCode(shortUrl.result || encodeURI(this.shareUrl))
                 }
                 let dom = document.getElementById('qrcode')
                 if (dom) dom.title = ''

+ 3 - 3
TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue

@@ -273,7 +273,7 @@ export default {
             let soc = this.evaListShow[this.curEvaIndex].owner === 'school' ? this.$t('learnActivity.mgtScEv.shareText4') : this.$t('learnActivity.mgtScEv.shareText5')
             let socName = this.evaListShow[this.curEvaIndex].subjects.map(item => item.name).join('、')
             let shortUrl = await this.$api.getShortUrl(encodeURI(this.shareUrl))
-            let shareText = `${this.$t('learnActivity.mgtScEv.shareText1')}\n\n${this.$t('learnActivity.mgtScEv.shareText2')}${evName}\n${this.$t('learnActivity.mgtScEv.shareText3')}${evType}\n${soc}${socName}\n\n${this.$t('learnActivity.mgtScEv.shareText6')}\n${shortUrl.result}\n\n${this.$t('learnActivity.mgtScEv.shareText7')}\nURL:https://${window.location.host}/login/student`
+            let shareText = `${this.$t('learnActivity.mgtScEv.shareText1')}\n\n${soc}${socName}\n${this.$t('learnActivity.mgtScEv.shareText3')}${evType}\n${this.$t('cusMgt.inviteInfo8')}${this.$store.state.userInfo.name}\n${this.$t('learnActivity.mgtScEv.shareText2')}${evName}\n\n${this.$t('learnActivity.mgtScEv.shareText6')}\n${shortUrl.result || encodeURI(this.shareUrl)}\n\n${this.$t('learnActivity.mgtScEv.shareText7')}\nURL:https://${window.location.host}/login/student`
             this.$copyText(shareText).then(
                 ok => {
                     this.$Message.success(this.$t("settings.copyModal1"))
@@ -292,13 +292,13 @@ export default {
                     let qrcode = new QRCode('qrcode', {
                         width: 280, // 设置宽度,单位像素
                         height: 280, // 设置高度,单位像素
-                        text: shortUrl.result, // 编码处理
+                        text: shortUrl.result || encodeURI(this.shareUrl), // 编码处理
                         correctLevel: QRCode.CorrectLevel.Q //解决编码后网址太长的问题
                     })
                     this.shareQRcode = qrcode
                 } else {
                     this.shareQRcode.clear()
-                    this.shareQRcode.makeCode(shortUrl.result)
+                    this.shareQRcode.makeCode(shortUrl.result || encodeURI(this.shareUrl))
                 }
                 let dom = document.getElementById('qrcode')
                 if (dom) dom.title = ''

+ 26 - 20
TEAMModelOS/ClientApp/src/view/login/Index.vue

@@ -454,25 +454,30 @@ export default {
             this.$Spin.show(); //開啟加載畫面
             let redirect_uri = window.location.origin + '/login'
             this.$api.OauthLogin(this.userOauth.state, this.userOauth.code, redirect_uri).then(res => {
-                
-                //TODO 大陆站微信登陆需要验证是否启用
+
                 let tokenData = jwtDecode(res.id_token)
-                localStorage.setItem("access_token",res.access_token)
+                localStorage.setItem("access_token", res.access_token)
+                /**
+                 * TODO
+                 * 先暂时不处理微信绑定手机号验证,等后续确认
+                 */
                 //token解析出来为字符串,所以需要对比字符串‘false’
-                if (tokenData.isMobile === 'false' && this.$store.state.config.srvAdr == 'China') {
-                    //未启用,前往绑定手机号
-                    this.$router.push({
-                        path: '/bandphone',
-                        query: {
-                            loginType: this.userOauth.state,
-                            id: tokenData.sub
-                        }
-                    })
-                    this.$Spin.hide(); //關閉加載畫面
-                } else {
-                    //已启用,正常登录
-                    this.loginProcess(res, this.defaultSchool.code)
-                }
+                // if (tokenData.isMobile === 'false' && this.$store.state.config.srvAdr == 'China') {
+                //     //未启用,前往绑定手机号
+                //     this.$router.push({
+                //         path: '/bandphone',
+                //         query: {
+                //             loginType: this.userOauth.state,
+                //             id: tokenData.sub
+                //         }
+                //     })
+                //     this.$Spin.hide(); //關閉加載畫面
+                // } else {
+                //     //已启用,正常登录
+                //     this.loginProcess(res, this.defaultSchool.code)
+                // }
+                this.loginProcess(res, this.defaultSchool.code)
+                this.$Spin.hide(); //關閉加載畫面
             })
         },
         SSOLogin: function (code) { // 快速登入
@@ -494,8 +499,9 @@ export default {
             let identity = sessionStorage.getItem('identity')
             // 登录学生端
             if (identity === 'student') {
-                this.$loginTools.stuLoginById(item)
-				// await this.$api.login.studLoginbyID(item).then(res => {
+                localStorage.setItem("access_token", item.access_token)
+                this.$loginTools.stuLoginById(item.id_token)
+                // await this.$api.login.studLoginbyID(item).then(res => {
                 //     result = res
                 // })
                 // //設定權限並登入 学生端默认权限
@@ -513,7 +519,7 @@ export default {
             }
             // 登录教师端
             else {
-				this.$loginTools.teacherLogin(item, schoolCode)
+                this.$loginTools.teacherLogin(item, schoolCode)
                 // await this.$api.login.teacherLogin(item, schoolCode).then(res => {
                 //     result = res
                 // })

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

@@ -473,8 +473,8 @@
 				let redirect_uri = window.location.origin + '/login';
 				this.$api.BuildOauthUrl(provider, redirect_uri).then(res => {
 					window.location.href = res
-				})
-			},
+                })
+            },
 			SSOLogin: function(code) { // 快速登入
 				this.$Spin.show(); //開啟加載畫面
 				this.$api.SSOLogin(code).then(async res => {
@@ -482,7 +482,7 @@
 					if (!res.error) {
 						// 登入大雲開始
 						localStorage.setItem("access_token", res.access_token)
-						this.$loginTools.stuLoginById(result.id_token)
+                        this.$loginTools.stuLoginById(res.id_token)
 					} else {
 						this.$Message.warning(this.$t('login.sse.error.text1'));
 					}

+ 1 - 1
TEAMModelOS/ClientApp/src/view/newcourse/EvDetail.vue

@@ -88,7 +88,7 @@ export default {
         findExamInfo(examId, code) {
             let requestData = {
                 id: examId,
-                code: code
+                code: code.includes('Exam-') ? code : 'Exam-' + code
             }
             this.isLoading = true
             this.pageLoading = true

+ 1 - 0
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.less

@@ -249,6 +249,7 @@
     // color:white;
     font-size:14px;
     padding-right:30px;
+    margin-top: -30px;
 }
 .action-icon {
     margin-right: 10px;

+ 27 - 23
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue

@@ -156,6 +156,7 @@
                                             <p slot="title" class="record-name" style="padding-left:10px">
                                                 {{item.name}}
                                                 <Icon type="md-create" class="edit-ev-name" @click.stop="editRecordName(index)" :title="$t('cusMgt.edRdName')" />
+                                                <Icon type="md-trash" class="edit-ev-name" @click.stop="delRecord(item.id)" :title="$t('cusMgt.delRcd')" />
                                             </p>
                                             <div slot="description" style="padding-left:10px;margin-top:10px">
                                                 <!-- 出席人数 -->
@@ -197,12 +198,21 @@
                                                     <span class="record-info-value">{{handleDuration(item.duration)}}</span>
                                                 </span>
                                                 <!-- 时间 -->
-                                                <span>{{$jsFn.timeFormat(item.startTime)}}</span>
+                                                <span class="record-info" style="float:right">
+                                                    <span>
+                                                        <Icon type="md-time" color="#70B1E7" />
+                                                    </span>
+                                                    <span class="record-info-value">
+                                                        {{$jsFn.timeFormat(item.startTime)}}
+                                                    </span>
+                                                </span>
                                                 <div class="record-action-wrap">
                                                     <!-- <Icon class="action-icon" custom="iconfont icon-video" :title="$t('cusMgt.socrateMv')" @click.stop="viewVideo(item)" />
                                                     <Icon class="action-icon" type="md-share" :title="$t('cusMgt.share')" v-show="$store.state.config.srvAdrType != 'product'" @click.stop="shareRecord" /> -->
                                                     <!-- <Icon class="action-icon" type="md-trash" :size="15" :title="$t('cusMgt.delRcd')" @click.stop="delRecord(item.id)" /> -->
-                                                    <span class="action-text" @click.stop="delRecord(item.id)">删除</span>
+                                                    <!-- <span class="action-text" @click.stop="delRecord(item.id)">
+                                                        <Icon type="md-trash" :size="15" :title="$t('cusMgt.delRcd')"/>
+                                                    </span> -->
                                                 </div>
                                             </div>
                                         </ListItemMeta>
@@ -255,12 +265,12 @@
                                                     <span class="ev-attr-wrap">
                                                         <span class="attr-label">
                                                             <Icon type="md-time" size="16" />
-                                                            {{$t('cusMgt.acTime')}}:
+                                                            <!-- {{$t('cusMgt.acTime')}}: -->
                                                         </span>
                                                         <span class="attr-value">
-                                                            {{dateFormat(item.startTime)}}
-                                                            -
-                                                            {{dateFormat(item.endTime)}}
+                                                            {{$jsFn.timeFormat(item.startTime)}}
+                                                            <!-- -
+                                                            {{dateFormat(item.endTime)}} -->
                                                         </span>
                                                     </span>
                                                 </p>
@@ -1497,7 +1507,7 @@ export default {
                 // 处理分享内容
                 try {
                     let shortUrl = await this.$api.getShortUrl(encodeURI(this.inviteUrl))
-                    let shareText = `${this.$t('cusMgt.inviteInfo1')}\n\n${this.$t('cusMgt.inviteInfo2')}${cusName}\n${this.$t('cusMgt.inviteInfo3')}${listName}\n${this.$t('cusMgt.inviteInfo4')}${tName}\n\n${this.$t('cusMgt.inviteInfo5')}\n${shortUrl.result}\n\n${this.$t('cusMgt.inviteInfo6')}\nURL:https://${loginUrl}/login/student\n${this.$t('cusMgt.inviteInfo7')}${this.stuListNo}`
+                    let shareText = `${this.$t('cusMgt.inviteInfo1')}\n\n${this.$t('cusMgt.inviteInfo2')}${cusName}\n${this.$t('cusMgt.inviteInfo3')}${listName}\n${this.$t('cusMgt.inviteInfo4')}${tName}\n\n${this.$t('cusMgt.inviteInfo5')}\n${shortUrl.result || encodeURI(this.inviteUrl)}\n\n${this.$t('cusMgt.inviteInfo6')}\nURL:https://${loginUrl}/login/student\n${this.$t('cusMgt.inviteInfo7')}${this.stuListNo}`
                     this.qrConfig.shareContent = shareText
                 } catch (e) {
                     this.qrConfig.shareContent = ''
@@ -1613,12 +1623,7 @@ export default {
             this.$router.push({
                 name: 'classRecord',
                 params: {
-                    record: {
-                        id: this.recordList[index].id,
-                        name: this.recordList[index].name,
-                        startTime: this.recordList[index].startTime,
-                        eNote: this.recordList[index].eNote
-                    }
+                    record: this.recordList[index]
                 }
             })
         },
@@ -1962,18 +1967,17 @@ export default {
                 this.$api.lessonRecord.getLessonList(params).then(
                     res => {
                         this.recordList = res.lessonRecords
-                        let privateSas = {}
-                        let blobInfo = this.$store.state.user.userProfile
-                        privateSas.sas = '?' + blobInfo.blob_sas
-                        privateSas.url = blobInfo.blob_uri.slice(0, blobInfo.blob_uri.lastIndexOf(this.$store.state.userInfo.TEAMModelId) - 1)
-                        privateSas.name = this.$store.state.userInfo.TEAMModelId
+                        let sasInfo = {}
+                        let blobInfo = this.listType === 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile
+                        sasInfo.sas = '?' + blobInfo.blob_sas
+                        sasInfo.name = this.listType === 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
+                        sasInfo.url = blobInfo.blob_uri.slice(0, blobInfo.blob_uri.lastIndexOf(sasInfo.name) - 1)
                         this.recordList.forEach(item => {
-                            item.sokrateImg = `${privateSas.url}/${privateSas.name}/records/${item.id}/Sokrates/SokratesResults/event.png${privateSas.sas}`
-                            item.eNote = `${privateSas.url}/${privateSas.name}/records/${item.id}/Note.pdf${privateSas.sas}`
-                            item.video = `${privateSas.url}/${privateSas.name}/records/${item.id}/Record/CourseRecord.mp4${privateSas.sas}`
-                            item.poster = `${privateSas.url}/${privateSas.name}/records/${item.id}/Record/CoverImage.jpg${privateSas.sas}`
+                            item.sokrateImg = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Sokrates/SokratesResults/event.png${sasInfo.sas}`
+                            item.eNote = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Note.pdf${sasInfo.sas}`
+                            item.video = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Record/CourseRecord.mp4${sasInfo.sas}`
+                            item.poster = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Record/CoverImage.jpg${sasInfo.sas}`
                         })
-                        // this.filterRecordList(this.curClassIndex)
                     },
                     err => {
                         this.$Message.error(this.$t('cusMgt.rcdErr'))

+ 6 - 2
TEAMModelOS/ClientApp/src/view/research-center/ResearchCenter.vue

@@ -201,6 +201,7 @@
 				introVideos: [],
 				doubleGreenVideos:[],
 				todayVideos:[],
+				schoolSas:null
 			}
 		},
 		created() {
@@ -211,8 +212,9 @@
 		},
 		methods: {
 			/* 获取最新课例统计数据 */
-			getDashboardData(){
+			async getDashboardData(){
 				let semesterRange = this.$tools.getSemesterTimeRange()
+				this.schoolSas = await this.$tools.getSchoolSas()
 				this.$api.lessonRecord.getDashboardData({
 					"stime": semesterRange.st,
 					"etime": semesterRange.et,
@@ -332,7 +334,8 @@
 				list.forEach(item => {
 					let container = item.scope === 'school' ? item.school : item.tmdid
 					let blobHost = this.$evTools.getBlobHost()
-					item.poster = blobHost + '/' + container + '/records/' + item.id + '/Record/CoverImage.jpg'
+					item.videoPath = blobHost + '/' + container + '/records/' + item.id + '/Record/CourseRecord.mp4'  + this.schoolSas.sas
+					item.poster = blobHost + '/' + container + '/records/' + item.id + '/Record/CoverImage.jpg' + this.schoolSas.sas
 					item.subject = this.curPeriod.subjects.find(i => i.id === item.subjectId).name
 					item.grade = item.grade.map(i => this.curPeriod.grades[+i]).join(',')
 				})
@@ -380,6 +383,7 @@
 						}else{
 							this.isReachBottom = true
 						}
+						console.log(this.listVideos);
 						this.listVideos = this.listVideos.concat(this.getFullInfo(res.lessonRecords))
 						this.continuationToken = res.continuationToken
 					}

+ 32 - 9
TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.less

@@ -1,20 +1,37 @@
 .research-mgmt-container{
 	padding: 5px 25px;
 	
+	.analysis-box{
+		padding: 10px 0;
+		font-size: 14px;
+		.analysis-item{
+			margin-right: 40px;
+			&-title{
+				&::before{
+					content: "";
+					width: 3px;
+					height: 10px;
+					border-radius: 4px;
+					background-color: #736d6d;
+					display: inline-block;
+					margin-right: 5px;
+				}
+			}
+			
+			&-value{
+				font-size: 24px;
+				font-weight: bold;
+				color: red;
+				margin-left: 10px;
+			}
+		}
+	}
+	
 	.title{
 		font-size: 24px;
 		font-weight: bold;
 		margin-left: -5px;
 		margin-bottom: 10px;
-		// &::before{
-		// 	content: "";
-		// 	width: 5px;
-		// 	height: 15px;
-		// 	border-radius: 4px;
-		// 	background-color: #38b894;
-		// 	display: inline-block;
-		// 	margin-right: 5px;
-		// }
 	}
 	
 	.filter-box{
@@ -41,6 +58,11 @@
 				margin-right: 10px;
 			}
 		}
+		
+		.export-btn{
+			margin-left: 20px;
+			text-decoration: underline;
+		}
 	}
 	
 	.tools-bar{
@@ -59,6 +81,7 @@
 	
 	.table-box{
 		overflow: auto;
+		margin-top: 20px;
 		.action-icon{
 			margin-right: 10px;
 			font-size: 18px;

+ 122 - 24
TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.vue

@@ -1,6 +1,13 @@
 <template>
 	<div class="research-mgmt-container">
 		<!-- <p class="title">课例管理</p> -->
+		<div class="analysis-box">
+			<span class="analysis-item" v-for="(item,index) in analysisArr" :key="index">
+				<span class="analysis-item-title">{{ item }}</span>
+				<span class="analysis-item-value">0</span>
+			</span>
+			
+		</div>
 		<div class="filter-box">
 			<div style="display: flex;">
 				<div class="filter-item">
@@ -32,26 +39,24 @@
 				</div>
 				<div style="margin-right: 10px;">
 					<span>共查询到 <span style="font-size: 18px;font-weight: bold;color: #28b989;">{{ totalNum.count }}
-						</span>条课例数据</span>
+						</span>条课堂记录</span>
+					<span class="tool-item" style="margin-left: 20px;cursor: pointer;" @click="downloadTable()">
+						<Icon type="md-download" />
+						<span>导出数据</span>
+					</span>	
 				</div>
 			</div>
 
 		</div>
-		<div class="tools-bar">
+		<!-- <div class="tools-bar">
 			<div class="tool-item" @click="onAddVideo">
-				<!-- <Button type="success" icon="md-add">添加课例</Button> -->
 				<Icon type="md-add" />
 				<span>添加课例</span>
 			</div>
 			<div class="tool-item">
-				<!-- <Button type="info" icon="md-download">导出数据</Button> -->
 				<Icon type="md-download" />
 				<span>导出数据</span>
 			</div>
-			<!-- 			<div class="tool-item">
-				<Icon type="ios-trash" />
-				<span>批量删除</span>
-			</div> -->
 			<div class="tool-item" @click="onTagMgClick">
 				<Icon type="md-settings" />
 				<span>类别管理</span>
@@ -60,19 +65,17 @@
 				<Icon type="ios-paper-plane" />
 				<span>分享至公开课</span>
 			</div>
-		</div>
+		</div> -->
 		<div class="table-box">
-			<Scroll :on-reach-bottom="getMore" height="750" :distance-to-edge="[15, 15]">
-				<Table stripe :columns="tableColumn" :data="tableData" :loading="tableLoading">
+			<Scroll :on-reach-bottom="getMore" height="700" :distance-to-edge="[15, 15]">
+				<Table stripe :columns="tableColumnNew" :data="tableData" :loading="tableLoading">
 					<template slot-scope="{ row,index }" slot="tmdname">
 						<span>
-							<!-- <Tag color="#dfa718" v-if="index === 0">公开课</Tag> -->
 							{{ row.tmdname || row.tmdid }}
 						</span>
 					</template>
 					<template slot-scope="{ row,index }" slot="name">
 						<span>
-							<!-- <Tag color="#dfa718" v-if="index === 0">公开课</Tag> -->
 							{{ row.name }}
 						</span>
 					</template>
@@ -85,12 +88,16 @@
 					<template slot-scope="{ row }" slot="grade">
 						<span>{{ row.grade.map(i => curPeriod.grades[+i]).join(',') }}</span>
 					</template>
+					<template slot-scope="{ row }" slot="startTime">
+						<span>{{ $tools.formatTime(row.startTime) }}</span>
+					</template>
 					<template slot-scope="{ row }" slot="action">
-						<Icon class="action-icon" type="ios-paper-plane" color="#27a3cf"/>
+						<!-- <Icon class="action-icon" type="ios-paper-plane" color="#27a3cf"/>
 						<Icon class="action-icon" type="md-play" color="#34cf97" @click="doPlay(row)" />
-						<!-- <Icon class="action-icon" type="md-podium" color="#3197e5" @click="showAnalysis(row)" /> -->
 						<Icon class="action-icon" type="md-create" color="#3197e5" @click="doEdit(row)" />
-						<Icon class="action-icon" type="md-trash" color="#e25255" @click="doDelete(row)" />
+						<Icon class="action-icon" type="md-trash" color="#e25255" @click="doDelete(row)" /> -->
+						<Button size="small" type="success" style="margin-right: 5px;" @click="downloadTable">下载总表</Button>
+						<Button size="small" type="primary" @click="downloadTable">预览笔记</Button>
 					</template>
 				</Table>
 			</Scroll>
@@ -141,6 +148,7 @@
 		},
 		data() {
 			return {
+				analysisArr:['课堂记录总数','教师数','累计任务数','累计作品数','累计互动总数','本学期新增课堂记录数'],
 				isEdit: false,
 				editLoading: false,
 				tagLoading: false,
@@ -151,7 +159,7 @@
 				categoryModal: false,
 				formModal: false,
 				tableLoading: false,
-				tableHeight: document.documentElement.clientHeight * 0.58,
+				tableHeight: document.documentElement.clientHeight * 0.48,
 				curEditTag: '',
 				curEditIndex: -1,
 				curPage: 1,
@@ -220,6 +228,90 @@
 						className: "table-action"
 					}
 				],
+				tableColumnNew:[
+					{
+						title: '班级',
+						key: 'className',
+						ellipsis:true,
+					},
+					{
+						title: '教师名称',
+						key: 'tmdname',
+						ellipsis:true,
+					},
+					{
+						title: '课堂名称',
+						key: 'name',
+						ellipsis:true,
+					},
+					{
+						title: '日期',
+						slot: 'startTime',
+						ellipsis:true,
+						width:200
+					},
+					{
+						title: '出席率',
+						key: 'attendCount',
+						ellipsis:true,
+					},
+					{
+						title: '小组数',
+						key: 'groupCount',
+						ellipsis:true,
+					},
+					{
+						title: '总计分',
+						key: 'totalPoint',
+						ellipsis:true,
+					},
+					{
+						title: '任务总数',
+						key: 'collateTaskCount',
+						ellipsis:true,
+					},
+					{
+						title: '作品总数',
+						key: 'collateCount',
+						ellipsis:true,
+					},
+					{
+						title: '推送总数',
+						key: 'pushCount',
+						ellipsis:true,
+					},
+					{
+						title: '总互动分',
+						key: 'score',
+						ellipsis:true,
+					},
+					{
+						title: '互动题数',
+						key: 'interactionCount',
+						ellipsis:true,
+					},
+					{
+						title: '互动总数',
+						key: 'clientInteractionCount',
+						ellipsis:true,
+					},
+					{
+						title: '测验总题数',
+						key: 'examQuizCount',
+						ellipsis:true,
+					},
+					{
+						title: '测验得分率',
+						key: 'examPointRate',
+						ellipsis:true,
+					},
+					{
+						title: '操作',
+						slot: 'action',
+						className: "table-action",
+						width:200
+					}
+				],
 				originList: []
 			}
 		},
@@ -228,6 +320,9 @@
 			this.initTags()
 		},
 		methods: {
+			downloadTable(){
+				this.$Message.warning('暂未处理')
+			},
 			/* 修改课堂记录基础信息 */
 			onEditLesson() {
 				console.log()
@@ -309,9 +404,10 @@
 			getMore() {
 				this.filterParams.continuationToken = this.continuationToken
 				if (this.continuationToken) {
-					this.$api.lessonRecord.getLessonList(this.filterParams).then(res => {
+					this.$api.lessonRecord.getLessonList(this.filterParams).then(async res => {
 						if (!res.error && res.lessonRecords) {
-							this.tableData = this.tableData.concat(this.getFullInfo(res.lessonRecords))
+							let schoolSas = await this.$tools.getSchoolSas()
+							this.tableData = this.tableData.concat(this.getFullInfo(res.lessonRecords,schoolSas))
 							this.continuationToken = res.continuationToken
 						}
 					})
@@ -320,7 +416,7 @@
 				}
 			},
 			/* 替换课例数据的科目学段等信息 */
-			getFullInfo(list) {
+			getFullInfo(list,schoolSas) {
 				let tchList = []
 				this.$nextTick(() => {
 					tchList = this.$refs.tchSelect.teacherList
@@ -331,8 +427,8 @@
 					}
 					let container = item.scope === 'school' ? item.school : item.tmdid
 					let blobHost = this.$evTools.getBlobHost()
-					item.poster = blobHost + '/' + container + '/records/' + item.id + '/Record/CoverImage.jpg'
-					item.videoPath = blobHost + '/' + container + '/records/' + item.id + '/Record/CourseRecord.mp4'
+					item.poster = blobHost + '/' + container + '/records/' + item.id + '/Record/CoverImage.jpg' + schoolSas.sas
+					item.videoPath = blobHost + '/' + container + '/records/' + item.id + '/Record/CourseRecord.mp4' + schoolSas.sas
 				})
 				return list
 			},
@@ -342,12 +438,14 @@
 				this.isReachBottom = false
 				this.filterParams.continuationToken = null
 				this.totalNum = await this.$api.lessonRecord.getLessonCount(this.filterParams)
-				this.$api.lessonRecord.getLessonList(this.filterParams).then(res => {
+				this.$api.lessonRecord.getLessonList(this.filterParams).then(async res => {
 					if (!res.error && res.lessonRecords) {
-						this.tableData = this.getFullInfo(res.lessonRecords)
+						let schoolSas = await this.$tools.getSchoolSas()
+						this.tableData = this.getFullInfo(res.lessonRecords,schoolSas)
 						this.isReachBottom = true
 						this.continuationToken = res.continuationToken
 						this.tableLoading = false
+						console.log(this.tableData)
 					}
 				})
 				this.filterParams.continuationToken = this.continuationToken

+ 4 - 4
TEAMModelOS/ClientApp/src/view/train/TrainDetail.vue

@@ -1421,13 +1421,13 @@ export default {
                     let qrcode = new QRCode('fullqrcode', {
                         width: 320, // 设置宽度,单位像素
                         height: 320, // 设置高度,单位像素
-                        text: shortUrl.result, // 设置二维码内容或跳转地址
+                        text: shortUrl.result || encodeURI(url), // 设置二维码内容或跳转地址
                         correctLevel: QRCode.CorrectLevel.L //解决编码后网址太长的问题
                     })
                     this.fullQR = qrcode
                 } else {
                     this.fullQR.clear()
-                    this.fullQR.makeCode(shortUrl.result)
+                    this.fullQR.makeCode(shortUrl.result || encodeURI(url))
                 }
                 let dom = document.getElementById('fullqrcode')
                 if (dom) dom.title = ''
@@ -1444,13 +1444,13 @@ export default {
                     let qrcode = new QRCode('sign-qr-code', {
                         width: 150, // 设置宽度,单位像素
                         height: 150, // 设置高度,单位像素
-                        text: shortUrl.result, // 设置二维码内容或跳转地址
+                        text: shortUrl.result || encodeURI(url), // 设置二维码内容或跳转地址
                         correctLevel: QRCode.CorrectLevel.L //解决编码后网址太长的问题
                     })
                     this.signQRcode = qrcode
                 } else {
                     this.signQRcode.clear()
-                    this.signQRcode.makeCode(shortUrl.result)
+                    this.signQRcode.makeCode(shortUrl.result || encodeURI(url))
                 }
                 let dom = document.getElementById('qrcode')
                 if (dom) dom.title = ''

+ 1 - 1
TEAMModelOS/ClientApp/src/view/user/BandPhone.vue

@@ -304,7 +304,7 @@ export default {
                     }
                     try {
                         let res = await this.$api.SendPinCode(data)
-                        //账号已存在
+                        //账号已存在 需要传hasUser才可能返回2 现在这种方式不会走这个判断
                         if (res.error === 2) {
                             data.hasUser = true
                             res = await this.$api.SendPinCode(data)

+ 2 - 1
TEAMModelOS/Controllers/Student/TmdUserController.cs

@@ -156,7 +156,8 @@ namespace TEAMModelOS.Controllers
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                request.TryGetProperty("id_token", out JsonElement id_token);
+                await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}{ex.StackTrace}\n{id_token}", GroupNames.醍摩豆服務運維群組);
                 return BadRequest();
             }
         }

+ 1 - 1
TEAMModelOS/Controllers/System/CoreController.cs

@@ -225,7 +225,7 @@ namespace TEAMModelOS.Controllers
             try
             {
                 var uri = new Uri(url.GetString());
-                string md5url = Md5Hash.GetMd5String(uri.AbsolutePath);
+                string md5url = Md5Hash.GetMd5String(uri.OriginalString);
 
                 char[] chars = new char[]
                {

+ 12 - 1
TEAMModelOS/Controllers/Teacher/TeacherCommonController.cs

@@ -197,7 +197,18 @@ namespace TEAMModelOS.Controllers
             {
                 privateSyllabusCount = item;
             }
-            return Ok(new { totalCount = count, goingDatas = datas, privateCourseCount, schoolCourseCount , classIdsCount= classIds.Count(), teachIdsCount= teachIds.Count(),   stulistsCount = stulists.Count(), privateItemCount , privatePaperCount, privateSyllabusCount });
+            List<string> bloblogTypes = new List<string>() ;
+            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<string>(
+                "select   value( c.type)     from c  "
+                , requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Bloblog-{id}") }))
+            {
+                bloblogTypes.Add(item);
+            }
+            var bloblogTypeCount= bloblogTypes.GroupBy(x => x).Select(y => new { type = y, count = y.ToList().Count });
+            return Ok(new { totalCount = count, goingDatas = datas, privateCourseCount, schoolCourseCount , classIdsCount= classIds.Count(), teachIdsCount= teachIds.Count(),   stulistsCount = stulists.Count(), 
+                privateItemCount , privatePaperCount, privateSyllabusCount, privateBloblogCount= bloblogTypes.Count,
+                bloblogTypeCount
+            });
         }
 
 

+ 3 - 3
TEAMModelOS/TEAMModelOS.csproj

@@ -32,9 +32,9 @@
     <SpaRoot>ClientApp\</SpaRoot>
     <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
     <UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-    <Version>5.2203.17</Version>
-    <AssemblyVersion>5.2203.17.1</AssemblyVersion>
-    <FileVersion>5.2203.17.1</FileVersion>
+    <Version>5.2203.18</Version>
+    <AssemblyVersion>5.2203.18.1</AssemblyVersion>
+    <FileVersion>5.2203.18.1</FileVersion>
     <Description>TEAMModelOS(IES5)</Description>
     <PackageReleaseNotes>6.0版本说明</PackageReleaseNotes>
     <PackageId>TEAMModelOS</PackageId>

+ 0 - 1
TEAMModelOS/appsettings.Development.json

@@ -21,7 +21,6 @@
   },
   "Azure": {
     "Storage": {
-      //"ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelstorage;AccountKey=Yq7D4dE6cFuer2d2UZIccTA/i0c3sJ/6ITc8tNOyW+K5f+/lWw9GCos3Mxhj47PyWQgDL8YbVD63B9XcGtrMxQ==;EndpointSuffix=core.chinacloudapi.cn",
       "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn"
     },
     "Cosmos": {