JAELYS 4 years ago
parent
commit
62b1da058a
100 changed files with 84071 additions and 1060 deletions
  1. 1 1
      TEAMModelFunction/TriggerCorrect.cs
  2. 29 6
      TEAMModelFunction/TriggerExam.cs
  3. 4 1
      TEAMModelOS.SDK/DI/DingDing/DingDing.cs
  4. 171 0
      TEAMModelOS.SDK/Extension/CoreTokenExtensions.cs
  5. 4 1
      TEAMModelOS.SDK/Models/Cosmos/Common/Bloblog.cs
  6. 16 7
      TEAMModelOS.SDK/Models/Cosmos/Common/Inner/SyllabusTree.cs
  7. 14 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Syllabus.cs
  8. 12 0
      TEAMModelOS.SDK/Models/Cosmos/Common/TmdInfo.cs
  9. 3 16
      TEAMModelOS.SDK/Models/Cosmos/Common/Volume.cs
  10. 0 111
      TEAMModelOS.SDK/Models/Cosmos/Teacher/Favorite.cs
  11. 127 0
      TEAMModelOS.SDK/Models/Cosmos/Teacher/Share.cs
  12. 77 0
      TEAMModelOS.SDK/Models/Service/NotificationService.cs
  13. 3 0
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  14. 14827 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.js
  15. 1 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.js.map
  16. 313 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.sandbox.js
  17. 1 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.sandbox.js.map
  18. 65293 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.worker.js
  19. 1 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.worker.js.map
  20. 1 1
      TEAMModelOS/ClientApp/public/web/viewer.html
  21. 5 5
      TEAMModelOS/ClientApp/public/web/viewer.js
  22. 1 1
      TEAMModelOS/ClientApp/public/web/viewer.js.map
  23. 73 9
      TEAMModelOS/ClientApp/src/api/blob.js
  24. 2 0
      TEAMModelOS/ClientApp/src/api/index.js
  25. 6 1
      TEAMModelOS/ClientApp/src/api/schoolSetting.js
  26. 7 0
      TEAMModelOS/ClientApp/src/api/service.js
  27. BIN
      TEAMModelOS/ClientApp/src/assets/image/1-1.jpg
  28. BIN
      TEAMModelOS/ClientApp/src/assets/login/1-1.jpg
  29. BIN
      TEAMModelOS/ClientApp/src/assets/login/1-2.png
  30. BIN
      TEAMModelOS/ClientApp/src/assets/login/1-3.png
  31. BIN
      TEAMModelOS/ClientApp/src/assets/login/1-4.png
  32. BIN
      TEAMModelOS/ClientApp/src/assets/login/1-5.png
  33. BIN
      TEAMModelOS/ClientApp/src/assets/login/1-7.png
  34. BIN
      TEAMModelOS/ClientApp/src/assets/login/2-1.png
  35. BIN
      TEAMModelOS/ClientApp/src/assets/login/2-2.jpg
  36. BIN
      TEAMModelOS/ClientApp/src/assets/login/3-1.jpg
  37. BIN
      TEAMModelOS/ClientApp/src/assets/login/3-2.png
  38. BIN
      TEAMModelOS/ClientApp/src/assets/mark/img0.jpg
  39. BIN
      TEAMModelOS/ClientApp/src/assets/mark/img1.jpg
  40. BIN
      TEAMModelOS/ClientApp/src/assets/mark/img2.jpg
  41. 62 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/event-list-new.css
  42. 76 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/event-list-new.less
  43. 97 55
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-test.css
  44. 5 5
      TEAMModelOS/ClientApp/src/common/BaseAreaPicker.vue
  45. 5 31
      TEAMModelOS/ClientApp/src/common/BaseLayout.less
  46. 73 23
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  47. 120 34
      TEAMModelOS/ClientApp/src/common/BaseNotification.vue
  48. 0 1
      TEAMModelOS/ClientApp/src/common/BaseSelectSchool.vue
  49. 63 8
      TEAMModelOS/ClientApp/src/common/UploadModal.vue
  50. 41 30
      TEAMModelOS/ClientApp/src/components/app-root.vue
  51. 1 3
      TEAMModelOS/ClientApp/src/components/evaluation/ExerciseList.vue
  52. 1 1
      TEAMModelOS/ClientApp/src/components/public/frontEndMain/Index.less
  53. 146 109
      TEAMModelOS/ClientApp/src/components/public/frontEndMain/Index.vue
  54. 2 4
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/StudentScore.vue
  55. 152 52
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue
  56. 1 1
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperView.vue
  57. 70 7
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue
  58. 6 5
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseList.vue
  59. 144 144
      TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue
  60. 3 2
      TEAMModelOS/ClientApp/src/components/syllabus/InviteTeacher.less
  61. 188 16
      TEAMModelOS/ClientApp/src/components/syllabus/InviteTeacher.vue
  62. 6 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/home.js
  63. 4 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/stuAccount.js
  64. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/system.js
  65. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/teachContent.js
  66. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/updModal.js
  67. 6 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/home.js
  68. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/index.js
  69. 28 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/settings.js
  70. 4 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/stuAccount.js
  71. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/studentWeb.js
  72. 61 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/syllabus.js
  73. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/system.js
  74. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/teachContent.js
  75. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/totalAnalysis.js
  76. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/updModal.js
  77. 6 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/home.js
  78. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/index.js
  79. 35 7
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/settings.js
  80. 4 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/stuAccount.js
  81. 61 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/syllabus.js
  82. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/system.js
  83. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachContent.js
  84. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/updModal.js
  85. 992 0
      TEAMModelOS/ClientApp/src/static/countries.js
  86. 1 1
      TEAMModelOS/ClientApp/src/store/module/serviceDriveAuth.js
  87. 1 1
      TEAMModelOS/ClientApp/src/store/module/studentWeb.js
  88. 0 47
      TEAMModelOS/ClientApp/src/utils/html2pdf.js
  89. 10 21
      TEAMModelOS/ClientApp/src/view/Home.vue
  90. 51 32
      TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue
  91. 8 4
      TEAMModelOS/ClientApp/src/view/answersheet/SheetBaseInfo.vue
  92. 2 1
      TEAMModelOS/ClientApp/src/view/evaluation/bank/ExerciseList.vue
  93. 3 3
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseFilter.vue
  94. 5 1
      TEAMModelOS/ClientApp/src/view/evaluation/index/index.vue
  95. 0 182
      TEAMModelOS/ClientApp/src/view/homepage/CoursePlan.vue
  96. 65 8
      TEAMModelOS/ClientApp/src/view/homepage/HomePage.less
  97. 63 37
      TEAMModelOS/ClientApp/src/view/homepage/HomePage.vue
  98. 370 0
      TEAMModelOS/ClientApp/src/view/homepage/MinTable.vue
  99. 8 10
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue
  100. 0 0
      TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkData.vue

+ 1 - 1
TEAMModelFunction/TriggerCorrect.cs

@@ -134,7 +134,7 @@ namespace TEAMModelFunction
                                     foreach (string stuId in examClass.studentIds)
                                     {
                                         int index = examClass.studentIds.IndexOf(stuId);
-                                        tasks.Add(redisClient.HashSetAsync($"Exam:Scoring:{eid}-{subjectId}", stuId, new { tmdId = "" , ans = examClass.studentAnswers[index][0], score = examClass.studentScores[index] }.ToJsonString()));
+                                        tasks.Add(redisClient.HashSetAsync($"Exam:Scoring:{eid}-{subjectId}", stuId, new { tmdId = "" , ans = examClass.studentAnswers[index].Count > 0 ? examClass.studentAnswers[index][0] : "", score = examClass.studentScores[index] }.ToJsonString()));
                                     }
 
                                 }

+ 29 - 6
TEAMModelFunction/TriggerExam.cs

@@ -206,11 +206,31 @@ namespace TEAMModelFunction
                                         var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.school}"));
                                         if (sresponse.Status == 200)
                                         {
+
                                             using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
                                             Class classroom = json.ToObject<Class>();
+                                            School sc = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>(info.school, new Azure.Cosmos.PartitionKey("Base"));
+                                            foreach (Period period in sc.period)
+                                            {
+                                                if (period.id.Equals(classroom.periodId))
+                                                {
+                                                    foreach (Semester semester in period.semesters)
+                                                    {
+                                                        if (semester.start == 1)
+                                                        {
+                                                            int year = DateTimeOffset.UtcNow.Year;
+                                                            int month = DateTimeOffset.UtcNow.Month;
+                                                            int day = DateTimeOffset.UtcNow.Day;
+                                                            int time =  month > semester.month ?  0 :  1;
+                                                            int eyear = classroom.year - time;
+                                                            result.gradeId = (year - eyear).ToString();
+                                                        }
+                                                    }
+                                                }
+                                            }
                                             //result.info.id = classroom.id;
                                             result.info.name = classroom.name;
-                                            result.gradeId = classroom.gradeId;
+                                            //result.gradeId = classroom.year.ToString();
                                             //处理班级人数
                                             await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id from c where c.classId = '{classroom.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Base-{info.school}") }))
                                             {
@@ -535,7 +555,8 @@ namespace TEAMModelFunction
                 int plcount = 0;
                 //存放并去重知识点
                 HashSet<string> kname = new HashSet<string>();
-                if (info.papers[no].knowledge.Count > 0) {
+                if (info.papers[no].knowledge.Count > 0)
+                {
                     info.papers[no].knowledge.ForEach(kno =>
                     {
                         kno.ForEach(k =>
@@ -631,7 +652,7 @@ namespace TEAMModelFunction
                         //await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(classResult, classResult.id, new Azure.Cosmos.PartitionKey($"{classResult.code}"));
                     }
                 }
-                
+
             }
             catch (Exception ex)
             {
@@ -672,7 +693,8 @@ namespace TEAMModelFunction
                             int phCount = 0;
                             int plCount = 0;
                             int pCount = 0;
-                            if (info.papers[no].field.Count > 0) {
+                            if (info.papers[no].field.Count > 0)
+                            {
                                 foreach (int str in info.papers[no].field)
                                 {
                                     if (str == knowledgeName[i])
@@ -720,7 +742,7 @@ namespace TEAMModelFunction
                                 pl.Add(plCount);
                                 double per = classResult.studentIds.Count > 0 ? Math.Round(score / classResult.studentIds.Count, 2) : 0;
                                 persent.Add(allScore > 0 ? per / allScore : 0);
-                            }                           
+                            }
                         }
                         classResult.fphc = ph;
                         classResult.fplc = pl;
@@ -858,7 +880,8 @@ namespace TEAMModelFunction
                         csRate.Add(classResult.studentIds.Count > 0 ? Math.Round(classSrate * 1.0 / classResult.studentIds.Count, 2) : 0 / allScore);
 
                     }
-                    else {
+                    else
+                    {
                         csRate.Add(0);
                     }
 

+ 4 - 1
TEAMModelOS.SDK/DI/DingDing/DingDing.cs

@@ -99,7 +99,10 @@ namespace TEAMModelOS.SDK.DI
         [Description("82aba2fccfa8442c575db3ac0442fa5aea90cd7574bb9a71d5abf210ea72a3aa,SEC3f38eca87cd4fd10505d136f91071a2e8b14cd863bd6bbafb24c612fc751a59a")]
         成都开发測試群組,
         [Description("1a316ce4edc2db88231d40d80072b00f2751d7d9e2e5871c5dc061885b01c48d,SECff60201ac9b219943b9f8fc397fda1a617d0cbc140850f5ea9cb4f131479d39a")]
-        醍摩豆服務運維群組
+        醍摩豆服務運維群組,
+        [Description("a83ea4ead63bf1b4e087723b3a7ccdf7f4c96708a22493f489bb928999f50d87,SECf1d22db7d00580dc7c0e597e31112a25ae1025500fc998b5b30961d91e115271")]
+        AI智慧學校申請通知群
+
     }
 
 

+ 171 - 0
TEAMModelOS.SDK/Extension/CoreTokenExtensions.cs

@@ -0,0 +1,171 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using Microsoft.IdentityModel.Tokens;
+using Microsoft.Identity.Client;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using Azure.Security.KeyVault.Secrets;
+using Azure.Core;
+using Azure.Identity;
+using System.Net.Http;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public static class CoreTokenExtensions
+    {       //var issuer = Configuration.GetValue<string>("JwtSettings:Issuer");
+            //var signKey = Configuration.GetValue<string>("JwtSettings:SignKey");
+        private const string issuer = "account.teammodel";
+        //Azure AD 租用戶識別碼(國際、大陸)
+        private static List<string> tenantids = new List<string> { "73a2bcc5-fe99-4566-aa8a-07e7bb287df1", "4807e9cf-87b8-4174-aa5b-e76497d7392b" };
+        private static ConcurrentDictionary<string, KeyVaultSecret> KeyVaultSecrets { get; } = new ConcurrentDictionary<string, KeyVaultSecret>();
+              
+
+        #region  Access Token
+        /// <summary>
+        /// 產生AccessToken
+        /// </summary>
+        /// <param name="clientID"></param>
+        /// <param name="location">服務位置,Global or China ...</param>
+        /// <returns></returns>
+        public static async ValueTask<AuthenticationResult> CreateAccessToken(string clientID, string clientSecret, string location)
+        {
+            //從金鑰庫取出秘密,此作法讓所有端直接刷新金鑰,無需傳送秘密,SPA更適用
+            var secret = clientSecret ?? (await GetClientIDSecret(clientID, location)).Value;
+
+            var sts = Enum.Parse<STSEndpoint>(location, true);
+
+            IConfidentialClientApplication app;
+            app = ConfidentialClientApplicationBuilder.Create(clientID)
+                                                      .WithClientSecret(secret)
+                                                      .WithAuthority(new Uri(sts.GetDescriptionText()))
+                                                      .Build();
+            var scope = ((STSScope)sts).GetDescriptionText();
+            var result = await app.AcquireTokenForClient(new[] { scope }).ExecuteAsync();
+            return result;
+        }
+
+        /// <summary>
+        /// 驗證是否為公司Azure發行金鑰,支援大陸國際
+        /// </summary>
+        /// <param name="token"></param>
+        /// <returns></returns>
+        public static bool ValidateAccessToken(JwtSecurityToken token)
+        {
+            try
+            {
+                if (token.Payload.TryGetValue("tid", out var value) && value is string tokenTenantId)
+                {
+                    return tenantids.Contains(tokenTenantId);
+                }
+                return false;
+            }
+            catch (Exception)
+            {
+                return false;
+            }
+        }
+
+        public static bool ValidateIdToken(string token, string salt)
+        {
+            try
+            {
+                var handler = new JwtSecurityTokenHandler();
+                var validationParameters = new TokenValidationParameters
+                {
+                    RequireExpirationTime = true,
+                    ValidateIssuer = false,
+                    ValidateAudience = false,
+                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
+                    ValidateLifetime = false,
+                    //LifetimeValidator = LifetimeValidator,
+                    ClockSkew = TimeSpan.Zero                    
+                };
+                ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
+                return true;
+            }
+            catch(Exception ex)
+            {
+                Trace.WriteLine(ex.Message);
+                return false;
+            }
+        }
+        #endregion
+
+        private static async ValueTask<KeyVaultSecret> GetClientIDSecret(string clientID, string location)
+        {   //Azure 金鑰庫處理
+            var s = await Task.Run(() =>
+            {
+                var secret = KeyVaultSecrets.GetOrAdd(clientID, (x) =>
+                {
+                    try
+                    {
+                        var sts = Enum.Parse<CoreServiceClient>(location, true);
+                        var scrtetstring = sts.GetDescriptionText().Split(",");
+                        //TODO 之後驗證端點用KnownAuthorityHosts取代,此SDK版本無支援
+                        var secret = new ClientSecretCredential(scrtetstring[0], scrtetstring[1], scrtetstring[2], new TokenCredentialOptions() { AuthorityHost = new Uri(scrtetstring[3]) });
+                        var client = new SecretClient(new Uri(((KeyVaultEndpoint)sts).GetDescriptionText()), secret);
+                        var clientSecret = client.GetSecretAsync(clientID).ConfigureAwait(false);
+                        return clientSecret.GetAwaiter().GetResult();
+                    }
+                    catch
+                    {
+                        return null;
+                    }
+                });
+                return secret;
+            });
+            return s;
+        }
+
+        public static bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
+        {
+            return true;
+            //if (expires != null)
+            //{
+            //    if (DateTime.UtcNow < expires)
+            //    {
+            //        return true;
+            //    }
+            //}
+
+            //return false;
+        }
+
+        private enum STSEndpoint
+        {
+            [Description("https://login.chinacloudapi.cn/4807e9cf-87b8-4174-aa5b-e76497d7392b")]
+            China,
+            [Description("https://login.microsoftonline.com/73a2bcc5-fe99-4566-aa8a-07e7bb287df1")]
+            Global
+        }
+
+        private enum STSScope
+        {
+            [Description("api://72643704-b2e7-4b26-b881-bd5865e7a7a5/.default")]
+            China,
+            [Description("api://8768b06f-c5c5-4b0c-abfb-d7ded354626d/.default")]
+            Global
+        }
+
+        private enum KeyVaultEndpoint
+        {
+            [Description("https://corekeyvaultcn.vault.azure.cn/")]
+            China,
+            [Description("https://corekeyvaultjp.vault.azure.net/")]
+            Global
+        }
+
+        private enum CoreServiceClient
+        {
+            [Description("4807e9cf-87b8-4174-aa5b-e76497d7392b,72643704-b2e7-4b26-b881-bd5865e7a7a5,tRYbDXtotEOe2Bbmo=[3h9Hbu_Trt:c6,https://login.partner.microsoftonline.cn")]
+            China,
+            [Description("73a2bcc5-fe99-4566-aa8a-07e7bb287df1,8768b06f-c5c5-4b0c-abfb-d7ded354626d,7=O./yws0L89WcEsece:9/4deJHP4E=F,https://login.microsoftonline.com/")]
+            Global
+        }
+    }
+}

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

@@ -13,10 +13,13 @@ namespace TEAMModelOS.SDK.Models
         public string url { get; set; }
         public long  time { get; set; }
         public long  size { get; set; }
-        public string period { get; set; }
+        public List<string> periodId { get; set; } = new List<string>() { "" };
+        public List<string> subjectId { get; set; } = new List<string>() { "" };
+        public List<string> gradeId { get; set; } = new List<string>() { "" };
         /// <summary>
         /// audio 音频,video 视频 ,doc文档,image图片,other 其他,res教材,thum缩略图
         /// </summary>
         public string type { get; set; }
+
     }
 }

+ 16 - 7
TEAMModelOS.SDK/Models/Cosmos/Common/Inner/SyllabusTree.cs

@@ -10,14 +10,23 @@ namespace TEAMModelOS.SDK.Models
         }
         public List<SyllabusTree> children { get; set; }
     }
-    public class SyllabusTreeNode{
-        public string id { get; set; }
-       // public string code { get; set; }
-        public string scope { get; set; }
-        public SyllabusTreeNode() {
+    public class SyllabusTreeNode {
+
+        public SyllabusTreeNode(){
             trees = new List<SyllabusTree>();
         }
-        public List<SyllabusTree> trees { get; set; }
-    }
+        /// <summary>
+        /// 课纲章节id
+        /// </summary>
+        public string  id { get; set; }
+        /// <summary>
+        /// 册别的id
+        /// </summary>
+        public string volumeId { get; set; }
+       // public string code { get; set; }
+        public string scope { get; set; }
+        public  List<SyllabusTree>  trees  { get; set; }
 
+        public List<SyllabusAuth> auth { get; set; } = new List<SyllabusAuth>();
+    }
 }

+ 14 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Syllabus.cs

@@ -20,5 +20,19 @@ namespace TEAMModelOS.SDK.Models
         [Required(ErrorMessage = "{0} 必须填写")]
         public List<Tnode> children { get; set; }
         public string volumeId { get; set; }
+        public List<SyllabusAuth> auth { get; set; }
+        public string scope { get; set; }
+}
+
+    /// <summary>
+    /// 只要创建课纲的creatorId 才能编辑课纲的分享,共编权限 25600 74200  27500 2000
+    /// ,共编者 谁创建的节点只能谁删除,而且删除时能删除子节点(包含不是自己创建的)。
+    /// </summary>
+    public class SyllabusAuth
+    {
+        public string tmdid { get; set; }
+        public string tmdname { get; set; }
+        public bool coedit { get; set; }
+        public bool share { get; set; }
     }
 }

+ 12 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/TmdInfo.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models
+{
+    public  class TmdInfo
+    {
+        public string tmdid { get; set; }
+        public string tmdname { get; set; }
+    }
+}

+ 3 - 16
TEAMModelOS.SDK/Models/Cosmos/Common/Volume.cs

@@ -82,22 +82,9 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
         /// </summary>
         [Required(ErrorMessage = "scope 必须设置")]
         public string scope { get; set; }
-        public List<SyllabusAuth> auth { get; set; } = new List<SyllabusAuth>();
-    }
 
-    /// <summary>
-    /// 只要创建课纲的creatorId 才能编辑课纲的分享,共编权限 25600 74200  27500 2000
-    /// ,共编者 谁创建的节点只能谁删除,而且删除时能删除子节点(包含不是自己创建的)。
-    /// </summary>
-    public class SyllabusAuth
-    {
-        public string tmdid { get; set; }
-        public string name { get; set; }
-        public bool coedit { get; set; }
-        public bool share { get; set; }
-        /// <summary>
-        ///分享的节点 all  或者節點id
-        /// </summary>
-        public List<string> snodes { get; set; } = new List<string>();
+        public List<string> syllabusIds { get; set; } = new List<string>();
+
     }
+
 }

+ 0 - 111
TEAMModelOS.SDK/Models/Cosmos/Teacher/Favorite.cs

@@ -36,115 +36,4 @@ namespace TEAMModelOS.SDK.Models.Cosmos
         [Required(ErrorMessage = "引用来源课纲code 必须设置")]
         public string fromCode { get; set; }
     }
-
-    /*
-     {
-        "id":"课纲册别id",
-        "code":"Share-接收者tmdid",
-        "issuer":"分享者tmdid",
-        "createTime":分享时间,
-        "scode":"引用来源课纲册别code",
-        "scope":"school/private",
-        "school":"hbcn",
-        "issuer":"颁发权限的id"
-    }
-     */
-    /// <summary>
-    /// 主动分享给谁, 分享功能只会发生在个人课纲中
-    /// </summary>
-    public class Share : CosmosEntity {
-        public Share(){
-            pk = "Share";
-        }
-
-        public string scode { get; set; }
-        /// <summary>
-        /// 权限颁发者
-        /// </summary>
-        public string issuer { get; set; }
-        public long  createTime { get; set; }
-        /// <summary>
-        /// 学校编码或教师tmdid
-        /// </summary>
-        [Required(ErrorMessage = "school 必须设置")]
-        public string school { get; set; }
-        /// <summary>
-        /// school|private
-        /// </summary>
-        [Required(ErrorMessage = "scope 必须设置")]
-        public string scope { get; set; }
-        /// <summary>
-        /// 共编
-        /// </summary>
-        public bool coedit { get; set; }
-        /// <summary>
-        /// 分享
-        /// </summary>
-        public bool share { get; set; }
-        /// <summary>
-        /// 课纲名称
-        /// </summary>
-        public string sname { get; set; }
-    }
-         
-    /// <summary>
-    /// 主动分享给谁,当接收者接收并完成相关资源复制后则删除本条数据。
-    /// </summary>
-    public class ShareData
-    {
-        /// <summary>
-        /// 学校编码
-        /// </summary>
-        [Required(ErrorMessage = "school 必须设置")]
-        public string school { get; set; }
-        /// <summary>
-        /// school|private
-        /// </summary>
-        [Required(ErrorMessage = "scope 必须设置")]
-        public string scope { get; set; }
-        /// <summary>
-        /// add/edit/del
-        /// </summary>
-        [Required(ErrorMessage = "opt 必须设置")]
-        public string opt { get; set; }
-
-        [Required(ErrorMessage = "tmdid 必须设置")]
-        public string tmdid { get; set; }
-        /// <summary>
-        /// tmdname
-        /// </summary>
-        public string name { get; set; }
-        /// <summary>
-        /// 课纲册别的id
-        /// </summary>
-        [Required(ErrorMessage = "sid 必须设置")]
-        public string sid { get; set; }
-        /// <summary>
-        /// 课纲册别的分区键
-        /// </summary>
-        [Required(ErrorMessage = "socde 必须设置")]
-        public string scode { get; set; }
-        /// <summary>
-        /// 课纲册别的名称
-        /// </summary>
-        [Required(ErrorMessage = "sname 必须设置")]
-        public string sname { get; set; }
-        /// <summary>
-        /// 共编权限
-        /// </summary>
-        public bool coedit { get; set; } = false;
-        /// <summary>
-        /// 分享权限
-        /// </summary>
-        public bool share { get; set; } = false;
-        /// <summary>
-        /// 分享的节点 all  或者節點id
-        /// </summary>
-        public List<string> snodes { get; set; } = new List<string>();
-        /// <summary>
-        /// 共编 分享权限颁发者
-        /// </summary>
-        [Required(ErrorMessage = "issuer 必须设置")]
-        public string issuer { get; set; }
-    }
 }

+ 127 - 0
TEAMModelOS.SDK/Models/Cosmos/Teacher/Share.cs

@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models
+{
+    /*
+     {
+        "id":"课纲册别id",
+        "code":"Share-接收者tmdid",
+        "issuer":"分享者tmdid",
+        "createTime":分享时间,
+        "scode":"引用来源课纲册别code",
+        "scope":"school/private",
+        "school":"hbcn",
+        "issuer":"颁发权限的id"
+    }
+     */
+    /// <summary>
+    /// 主动分享给谁, 分享功能只会发生在个人课纲中
+    /// </summary>
+    public class Share : CosmosEntity
+    {
+        /// <summary>
+        /// id 为章节id, code为Share-tmdid
+        /// </summary>
+        public Share()
+        {
+            pk = "Share";
+        }
+        /// <summary>
+        /// 权限颁发者
+        /// </summary>
+        public string issuer { get; set; }
+        public long createTime { get; set; }
+        /// <summary>
+        /// 学校编码或教师tmdid
+        /// </summary>
+        [Required(ErrorMessage = "school 必须设置")]
+        public string school { get; set; }
+        /// <summary>
+        /// school|private
+        /// </summary>
+        [Required(ErrorMessage = "scope 必须设置")]
+        public string scope { get; set; }
+        /// <summary>
+        /// 共编
+        /// </summary>
+        public bool coedit { get; set; }
+        /// <summary>
+        /// 分享
+        /// </summary>
+        public bool share { get; set; }
+        /// <summary>
+        /// 册别id
+        /// </summary>
+        public string volumeId { get; set; }
+        /// <summary>
+        /// 课纲章节的name
+        /// </summary>
+        [Required(ErrorMessage = "syllabusName 必须设置")]
+        public string syllabusName { get; set; }
+        /// <summary>
+        /// 册别名称
+        /// </summary>
+        public string volumeName { get; set; }
+    }
+    /// <summary>
+    /// 主动分享给谁,当接收者接收并完成相关资源复制后则删除本条数据。
+    /// </summary>
+    public class ShareData
+    {
+        /// <summary>
+        /// 学校编码
+        /// </summary>
+        [Required(ErrorMessage = "school 必须设置")]
+        public string school { get; set; }
+        /// <summary>
+        /// school|private
+        /// </summary>
+        [Required(ErrorMessage = "scope 必须设置")]
+        public string scope { get; set; }
+        /// <summary>
+        /// add/edit/del
+        /// </summary>
+        [Required(ErrorMessage = "opt 必须设置")]
+        public string opt { get; set; }
+
+        [Required(ErrorMessage = "tmdid 必须设置")]
+        public List<TmdInfo> tmdInfo { get; set; } = new List<TmdInfo>();
+        
+        /// <summary>
+        /// 共编权限
+        /// </summary>
+        public bool coedit { get; set; } = false;
+        /// <summary>
+        /// 分享权限
+        /// </summary>
+        public bool share { get; set; } = false;
+        /// <summary>
+        /// 课纲章节的id
+        /// </summary>
+        [Required(ErrorMessage = "syllabusId 必须设置")]
+        public string syllabusId { get; set; }
+        /// <summary>
+        /// 课纲章节的name
+        /// </summary>
+        [Required(ErrorMessage = "syllabusName 必须设置")]
+        public string syllabusName { get; set; }
+        /// <summary>
+        /// 册别名称
+        /// </summary>
+        public string volumeName { get; set; }
+        /// <summary>
+        /// 册别id
+        /// </summary>
+        public string volumeId { get; set; }
+        /// <summary>
+        /// 共编 分享权限颁发者
+        /// </summary>
+        [Required(ErrorMessage = "issuer 必须设置")]
+        public string issuer { get; set; }
+    }
+
+
+}

+ 77 - 0
TEAMModelOS.SDK/Models/Service/NotificationService.cs

@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Json;
+using System.Text;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Extension;
+
+namespace TEAMModelOS.SDK.Models.Service
+{
+    public class NotificationService
+    {
+        private readonly HttpClient _httpClient;
+        public NotificationService(HttpClient httpClient)
+        {
+            _httpClient = httpClient;
+        }
+        public    async Task<int> SendNotification(string clientID, string clientSecret, string location, string url, Notification notification) {
+            if (location.Contains("China")) {
+                location = "China";
+            }
+            else if (location.Contains("Global"))
+            {
+                location = "Global";
+            }
+            var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
+            _httpClient.DefaultRequestHeaders.Add("Authorization",$"Bearer {token.AccessToken}" );
+            HttpResponseMessage responseMessage = await _httpClient.PostAsJsonAsync(url, notification);
+            if (responseMessage.StatusCode == HttpStatusCode.OK)
+            {
+                return 200;
+            }
+            else if (responseMessage.StatusCode == HttpStatusCode.Unauthorized)
+            {
+                return 401;
+            }
+            else {
+                return 500;
+            }
+        }
+    }
+
+    public class Notification {
+        /// <summary>
+        /// App name (hita) 小寫
+        /// </summary>
+        public string hubName { get; set; }
+        /// <summary>
+        /// 通知訊息種類,分為msg,info及notice。       
+        /// msg : 一般訊息,會存Redis,拿了就刪。
+        /// info : 公告訊息或給多人讀取的訊息,會存Redis,拿了不刪,只能等時間到期或透過API刪除。
+        /// notice : 屬於系統層級訊息,不存Redis,直接裸送訊息。
+        /// </summary>
+        public string type { get; set; }
+        /// <summary>
+        /// 送訊息的來源端 格式為"{服務}:{類別}: ..." 如"ies5:hbrd","ies5:hbrd:hb0901"
+        /// </summary>
+        public string from { get; set; }
+        /// <summary>
+        /// 接收對象或手機註冊的tag,ID或服務等...
+        /// </summary>
+        public List<string> to { get; set; }
+        /// <summary>
+        /// 	標題。
+        /// </summary>
+        public string label { get; set; }
+        /// <summary>
+        /// 正文。
+        /// </summary>
+        public string body { get; set; }
+        /// <summary>
+        /// 該訊息到期時間(UTC),單位為秒,且必須大於現在時間。
+        /// </summary>
+        public long expires { get; set; }
+    }
+}

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

@@ -13,7 +13,9 @@
   <ItemGroup>
     <PackageReference Include="AspectCore.Extensions.Reflection" Version="2.2.0" />
     <PackageReference Include="Azure.Cosmos" Version="4.0.0-preview3" />
+    <PackageReference Include="Azure.Identity" Version="1.4.0" />
     <PackageReference Include="Azure.Messaging.ServiceBus" Version="7.1.1" />
+    <PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.1.0" />
     <PackageReference Include="Azure.Storage.Blobs.Batch" Version="12.5.1" />
     <PackageReference Include="Azure.Storage.Queues" Version="12.6.1" />
     <PackageReference Include="ClouDASLibx" Version="1.2.7" />
@@ -22,6 +24,7 @@
     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.10" />
     <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
     <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="5.0.4" />
+    <PackageReference Include="Microsoft.Identity.Client" Version="4.32.1" />
     <PackageReference Include="StackExchange.Redis" Version="2.2.4" />
     <PackageReference Include="SvgNet" Version="2.1.1" />
     <PackageReference Include="System.Drawing.Common" Version="5.0.2" />

File diff suppressed because it is too large
+ 14827 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.js


File diff suppressed because it is too large
+ 1 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.js.map


File diff suppressed because it is too large
+ 313 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.sandbox.js


File diff suppressed because it is too large
+ 1 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.sandbox.js.map


File diff suppressed because it is too large
+ 65293 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.worker.js


File diff suppressed because it is too large
+ 1 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.worker.js.map


+ 1 - 1
TEAMModelOS/ClientApp/public/web/viewer.html

@@ -34,7 +34,7 @@ See https://github.com/adobe-type-tools/cmap-resources
 
 <!-- This snippet is used in production (included from viewer.html) -->
 <link rel="resource" type="application/l10n" href="locale/locale.properties">
-<script src="../build/pdf.js"></script>
+<script src="../pdfBuild/pdf.js"></script>
 
 
   <script src="viewer.js"></script>

+ 5 - 5
TEAMModelOS/ClientApp/public/web/viewer.js

@@ -206,7 +206,7 @@ const defaultOptions = {
     kind: OptionKind.WORKER
   },
   workerSrc: {
-    value: "../build/pdf.worker.js",
+    value: "../pdfBuild/pdf.worker.js",
     kind: OptionKind.WORKER
   }
 };
@@ -220,7 +220,7 @@ const defaultOptions = {
     kind: OptionKind.VIEWER
   };
   defaultOptions.sandboxBundleSrc = {
-    value: "../build/pdf.sandbox.js",
+    value: "../pdfBuild/pdf.sandbox.js",
     kind: OptionKind.VIEWER
   };
 }
@@ -3921,10 +3921,10 @@ function apiPageModeToSidebarView(mode) {
 
 let pdfjsLib;
 
-if (typeof window !== "undefined" && window["pdfjs-dist/build/pdf"]) {
-  pdfjsLib = window["pdfjs-dist/build/pdf"];
+if (typeof window !== "undefined" && window["pdfjs-dist/pdfBuild/pdf"]) {
+  pdfjsLib = window["pdfjs-dist/pdfBuild/pdf"];
 } else {
-  pdfjsLib = require("../build/pdf.js");
+  pdfjsLib = require("../pdfBuild/pdf.js");
 }
 
 module.exports = pdfjsLib;

File diff suppressed because it is too large
+ 1 - 1
TEAMModelOS/ClientApp/public/web/viewer.js.map


+ 73 - 9
TEAMModelOS/ClientApp/src/api/blob.js

@@ -1,10 +1,26 @@
 import { fetch, post } from '@/api/http'
+import { GLOBAL } from '@/static/Global.js';
+//获取文件后缀和类型
+function getExAndType(fileName) {
+    let ex = fileName.substring(fileName.lastIndexOf('.') + 1)
+    let type = 'other'
+    ex = ex.toUpperCase()
+    for (let key in GLOBAL.CONTENT_TYPES) {
+        if (GLOBAL.CONTENT_TYPES[key].indexOf(ex) != -1) {
+            type = key
+            break
+        }
+    }
+    return {
+        ex, type
+    }
+}
 export default {
-    getBlobSAS: function(data) {
+    getBlobSAS: function (data) {
         return post('/api/File/getBlobSAS', data)
     },
     //最开始使用的blob授权API
-    getContainerSAS: function(data) {
+    getContainerSAS: function (data) {
         return post('/api/File/getContainerSAS', data)
     },
     //获取blob容器读写创建
@@ -12,31 +28,79 @@ export default {
         return post('/blob/sas-rcwld', data)
     },
     //获取blob容器只读创建
-    blobSasR: function(data) {
+    blobSasR: function (data) {
         return post('/blob/sas-r', data)
     },
     //单文件只读权限
-    urlSasR: function(data) {
+    urlSasR: function (data) {
         return post('/blob/sas-url-r', data)
     },
     //获取容器空间
     getContainerSize: function (data) {
         return post('/blob/get-blobsize', data)
     },
-	// 删除blob指定目录下的所有文件
-	deletePrefix: function (data) {
+    // 删除blob指定目录下的所有文件
+    deletePrefix: function (data) {
         return post('/blob/delete-prefix', data)
     },
     // 批量删除blob
-	deleteBlobs: function (data) {
+    deleteBlobs: function (data) {
         return post('/blob/delete-blobs', data)
     },
     // 上传文件之前需要先检查文件是否存在
-	checkBlobs: function (data) {
+    checkBlobs: function (data) {
         return post('/blob/check-blobsize', data)
     },
     // 上传文件之后需要更新blob空间
-	updateSize: function (data) {
+    updateSize: function (data) {
         return post('/blob/update-blobsize', data)
+    },
+    /**
+     * 上传文件之后保存文件的描述信息
+     * opt: add 更新
+     * opt: del 删除
+     **/
+    upsertBlobInfo: function (data) {
+        return post('/blob/bloblog-opt', data)
+    },
+    /**
+     * 查询资源信息
+     * 这里统一将返回数据处理成原来前端直接listBlob返回的数据格式
+     * @returns 
+     */
+    listBlobInfo: function (data, host, container) {
+        return new Promise((r, j) => {
+            post('/blob/bloblog-list', data).then(
+                res => {
+                    console.log(res)
+                    let blobs = []
+                    res.bloblogs.forEach(item => {
+                        let blobName = item.url
+                        let info = getExAndType(item.url)
+                        let i = {
+                            url: host + '/' +container + '/' + item.url,
+                            blob: '/' + item.url,
+                            name: blobName.substring(blobName.lastIndexOf('/') + 1),
+                            size: item.size,
+                            createTime: item.time,
+                            extension: info.ex,
+                            type: info.type,
+                            periodId: item.periodId,
+                            subjectId: item.subjectId,
+                            gradeId: item.gradeId,
+                            id: item.id
+                        }
+                        blobs.push(i)
+                    })
+                    r(blobs)
+                },
+                err => {
+                    j(err)
+                }
+            )
+
+        })
+
+        // return post('/blob/bloblog-list', data)
     }
 }

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

@@ -29,6 +29,7 @@ import spaceAuth from './spaceAuth'
 import room from './room'
 import mark from './mark'
 import openMgmt from './openMgmt';
+import service from './service';
 
 export default {
     accessToken,
@@ -59,6 +60,7 @@ export default {
     room,
     mark,
     openMgmt,
+	service,
 
     // 获取登录跳转链接
     getLoginLink: function (data) {

+ 6 - 1
TEAMModelOS/ClientApp/src/api/schoolSetting.js

@@ -73,5 +73,10 @@ export default {
     //根据私有班级id集合查询班级详细信息
     getClassByIds: function (data) {
         return post('/school/classroom/name', data)
-    }
+    },
+	
+	// 申请建立学校
+	applySchool:function (data) {
+        return post('/core/apply-school', data)
+    },
 }

+ 7 - 0
TEAMModelOS/ClientApp/src/api/service.js

@@ -0,0 +1,7 @@
+import { fetch, post } from '@/api/http'
+export default {
+	/* 获取端外通知 */
+    getNotification: function (data) {
+        return post('https://api2.teammodel.net/service/getnotification', data)
+    },
+}

BIN
TEAMModelOS/ClientApp/src/assets/image/1-1.jpg


BIN
TEAMModelOS/ClientApp/src/assets/login/1-1.jpg


BIN
TEAMModelOS/ClientApp/src/assets/login/1-2.png


BIN
TEAMModelOS/ClientApp/src/assets/login/1-3.png


BIN
TEAMModelOS/ClientApp/src/assets/login/1-4.png


BIN
TEAMModelOS/ClientApp/src/assets/login/1-5.png


BIN
TEAMModelOS/ClientApp/src/assets/login/1-7.png


BIN
TEAMModelOS/ClientApp/src/assets/login/2-1.png


BIN
TEAMModelOS/ClientApp/src/assets/login/2-2.jpg


BIN
TEAMModelOS/ClientApp/src/assets/login/3-1.jpg


BIN
TEAMModelOS/ClientApp/src/assets/login/3-2.png


BIN
TEAMModelOS/ClientApp/src/assets/mark/img0.jpg


BIN
TEAMModelOS/ClientApp/src/assets/mark/img1.jpg


BIN
TEAMModelOS/ClientApp/src/assets/mark/img2.jpg


+ 62 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/event-list-new.css

@@ -0,0 +1,62 @@
+.list-new {
+  display: flex;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+  padding: 15px 10px 15px 25px;
+}
+.list-new:hover {
+  background: linear-gradient(-270deg, #fafafa, #d4ede1);
+  color: #03966a;
+  cursor: pointer;
+}
+.list-new-icon {
+  width: 10%;
+  margin-right: 30px;
+}
+.list-new-icon .svg-icon {
+  width: 40px;
+  height: 40px;
+}
+.list-new-test {
+  width: 70%;
+  font-weight: bolder;
+  font-size: 14px;
+  line-height: 22px;
+  margin-right: 20px;
+  clear: both;
+}
+.list-new-test .list-item-typeMark {
+  text-align: center;
+  background-color: #dfdfdf;
+  border-radius: 10px;
+  padding: 1px 10px;
+  margin: 0 8px 0 -10px;
+}
+.list-new-test .list-item-time {
+  color: #8f8787;
+  font-size: 12px;
+}
+.list-new-test .isScore {
+  float: right;
+}
+.list-new-type {
+  width: 15%;
+  display: flex;
+  justify-content: center;
+  flex-direction: column;
+}
+.list-new-type .list-new-unDone {
+  font-size: 10px;
+  font-weight: bolder;
+  padding: 5px;
+  border-radius: 4px;
+  text-align: center;
+  border: 1px solid;
+}
+.list-new-type .isAllowRetry {
+  color: #fff;
+  background-color: #64ae16;
+  border: none;
+}
+.list-new-type .isWrongPra {
+  margin-top: 10px;
+}

+ 76 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/event-list-new.less

@@ -0,0 +1,76 @@
+.list-new{
+    display: flex;
+    border-bottom: 1px solid rgba(0,0,0,.1);
+    padding: 15px 10px 15px 25px;
+
+    &:hover{
+        background: linear-gradient(-270deg, #fafafa, #d4ede1);
+        color: #03966a;
+        cursor: pointer;
+    }
+
+    &-icon{
+        width: 10%;
+        margin-right: 30px;
+
+        .svg-icon{
+            width: 40px;
+            height: 40px;
+        }
+    }
+
+    &-test{
+        width: 70%;
+        font-weight: bolder;
+        font-size: 14px;
+        line-height: 22px;
+        margin-right: 20px;
+        clear: both;
+
+        .list-item-typeMark{
+            text-align: center;
+            background-color: #dfdfdf;
+            border-radius: 10px;
+            padding: 1px 10px;
+            margin: 0 8px 0 -10px;
+        }
+
+        .list-item-time {
+            color: #8f8787;
+            font-size: 12px;
+        }
+
+        .isScore{
+            float: right;
+        }
+    }
+
+    &-type{
+        width: 15%;
+        display: flex;
+        justify-content: center;
+        flex-direction: column;
+
+        .list-new-unDone{
+            font-size: 10px;
+            font-weight: bolder;
+            // color: #fff;
+            padding: 5px;
+            border-radius: 4px;
+            text-align: center;
+            border: 1px solid;
+
+            
+        }
+        
+        .isAllowRetry{
+            color: #fff;
+            background-color: #64ae16;
+            border: none;
+        }
+
+        .isWrongPra{
+            margin-top: 10px;
+        }
+    }
+}

+ 97 - 55
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-test.css

@@ -1,13 +1,14 @@
 .lesson-test-pop {
   position: fixed;
   width: 100%;
-  height: 100%;
+  /* height: 100%; */
   overflow-y: scroll;
   overflow-x: hidden;
   background-color: #f9f9f9;
   z-index: 10;
   top: 0px;
   left: 0px;
+  font-size: 18px;
 }
 .que-box {
     margin-top:10px;
@@ -29,6 +30,15 @@
     padding-top: 3px;
     height: 30px;
 }
+.has-right-ans{
+    background-color: #4fd5a3;
+}
+.has-wrong-ans{
+    background-color: #ff5508;
+}
+.has-no-ans{
+    background-color: #b7b7b7;
+}
 .has-ans {
     border: 1px solid rgba(117, 117, 117, 0.726);
     margin-left: 5px;
@@ -44,7 +54,7 @@
 }
 .ans-box :hover {
     color: #24b880;
-    font-size: 16px;
+    /* font-size: 16px; */
     padding: 2px 5px;
 }
 .has-ans :hover {
@@ -74,18 +84,22 @@
 
 .lesson-test-pop .warmMessage {
     z-index: 999;
+    font-size: 14px;
+}
+.lesson-test-pop .warmMessage h3{
+  font-size: 16px;
+}
+.lesson-test-pop .testTitle .ques-filter {
+    position: absolute;
+    right: 10%;
+    top: 3px;
 }
-    .lesson-test-pop .testTitle .ques-filter {
-        position: absolute;
-        right: 10%;
-        top: 3px;
-    }
 
 .lesson-test-pop .testTitle .ques-filter .filter-text {
   padding: 2px 7px;
   border-radius: 4px;
   color: #515a6e;
-  font-size: 14px;
+  /* font-size: 14px; */
   font-weight: bolder;
   background-color: rgba(0, 0, 0, 0.1);
 }
@@ -161,10 +175,10 @@
   position: relative;
   display: block;
   overflow: auto;
-  height: 95.5vh;
+  height: 96vh;
   background-color: #ffffff;
   left: 0px;
-  font-size: 20px;
+  /* font-size: 20px; */
 }
 
 .lesson-test-pop .questionContent {
@@ -177,34 +191,34 @@
   text-align: center;
   max-width: 100px;
   margin-bottom: 5px;
-  /*margin-top:20px;*/
+  /*margin-top: 20px;*/
 }
 .lesson-test-pop .questioDes {
-    margin-top:20px;
+    margin-top: 20px;
     font-weight: 900;
-    font-size: 20px;
-    /* height:500px; */
-    overflow-y:scroll;
-    /*border:2px solid red;*/
+    /* font-size: 20px; */
+    /* height: 500px; */
+    overflow-y: scroll;
+    /* border: 2px solid red; */
 }
 .lesson-test-pop .que-item {
-    display:flex;
+    display: flex;
     width: 100%;
     /* max-height: 450px; */
     /* overflow-y: scroll; */
-    /*border:1px solid blue;*/
+    /* border: 1px solid blue; */
 }
 
 .lesson-test-pop .que-items {
     width: 100%;
-    /*border:1px solid lightblue;*/
+    /* border: 1px solid lightblue; */
     /* max-height: 200px; */
-    margin-left:10px;
+    margin-left: 10px;
     /*max-height: 200px;*/
-    overflow-y: scroll;
+    /* overflow-y: scroll; */
 }
 .lesson-test-pop .questionNo {
-    margin-bottom:5px;
+    margin-bottom: 5px;
     font-weight: 900;
 }
 .lesson-test-pop .answers{
@@ -247,7 +261,7 @@
 }
 
 .compose-content {
-    /*margin-top: 30px;*/
+    /* margin-top: 30px; */
     width: 100%;
     /* height: 200px; */
     z-index: 0;
@@ -324,11 +338,12 @@
   /* float: left;
   right: -10px; */
   margin-top: 20px;
-  margin-bottom: 100px;
+  /* margin-bottom: 100px; */
   right: 10px;
   font-weight: 900;
   display: flex;
-  flex-wrap:wrap;
+  flex-wrap: wrap;
+  font-size: 14px;
 }
 .lesson-test-pop .pageCtl2 button {
   text-align: center;
@@ -357,7 +372,7 @@
 .lesson-test-pop .analysis{
   margin-top: 20px;
   z-index: 2;
-  font-size: 20px;
+  /* font-size: 20px; */
   transition: opacity 0.2s ease-in;
   opacity: 0;
 }
@@ -458,13 +473,13 @@
   border-collapse: collapse;
   font-weight: 500;
   cursor: pointer;
-  font-size: 14px;
+  /* font-size: 14px; */
   padding: 2px 10px;
   height: 30px;
 }
 .lesson-test-pop .ansSheet .ansSheetQno:hover {
   color: #24b880;
-  font-size: 16px;
+  /* font-size: 16px; */
   padding: 2px 10px;
   background-color: #ececec;
 }
@@ -513,6 +528,9 @@
   }
 }
 @media screen and (max-width: 1366px) {
+    /* .lesson-test-pop{
+      font-size: 18px;
+    } */
     .lesson-test-pop .testTitle .ques-filter {
         right: 15%;
     }
@@ -543,8 +561,8 @@
         margin-top: 50px;
     }
     .compose-box {
-        background-color: #24b880;
-        color: white;
+        /* background-color: #24b880;
+        color: white; */
         width: 95%;
         border-radius: 6px;
     }
@@ -557,7 +575,7 @@
     .compose-content {
         margin-top: 30px;
         width: 95%;
-        height: 200px;
+        /* height: 200px; */
         margin-bottom:30px;
         z-index: 0;
     }
@@ -578,10 +596,13 @@
         position: relative;
         display: block;
         overflow: auto;
-        height: 95vh;
+        height: 97vh;
         background-color: #ffffff;
         left: 0px;
     }
+    .lesson-test-pop .que-box{
+        max-height: 760px;
+    }
     .lesson-test-pop .pageCtl2 {
         position: relative;
         /* float: right;
@@ -595,6 +616,20 @@
         margin: 0 10px 10px 10px;
     }
 }
+@media screen and (max-width: 1024px) {
+    .lesson-test-pop{
+        font-size: 14px;
+    }
+    .lesson-test-pop .ans-box{
+        font-size: 13px;
+    }
+    .lesson-test-pop .pageCtl2{
+      font-size: 12px;
+    }
+    .lesson-test-pop .que-box{
+      max-height: 450px;
+    }
+}
 @media screen and (max-width: 991px) {
     .lesson-test-pop .testTitle .ques-filter {
         right: 25%;
@@ -616,35 +651,48 @@
         left: 65%;
     }
 
-    .lesson-test-pop .questionArea {
+    /* .lesson-test-pop .questionArea {
         height: auto;
-    }
+    } */
 
-    .lesson-test-pop .ansArea {
+    /* .lesson-test-pop .ansArea {
         position: relative;
-    }
+    } */
 }
-@media screen and (max-width: 767px) {
+@media screen and (max-width: 768px) {
+    .lesson-test-pop{
+      font-size: 14px;
+    }
     .lesson-test-pop .testTitle .ques-filter {
         left: 38%;
     }
-}
-@media screen and (max-width: 767px) {
     .lesson-test-pop .ansSheet {
-        font-size: 10px;
-        width: 80%;
+      /* font-size: 10px; */
+      width: 80%;
     }
-}
-@media screen and (max-width: 767px) {
     .lesson-test-pop .questionDesImg {
-        width: 40%;
-        margin-top: 20px;
+      width: 40%;
+      margin-top: 20px;
     }
-}
-@media screen and (max-width: 767px) {
     .lesson-test-pop .myProgressBar {
-        right: 30%;
+      right: 30%;
+    }
+    .lesson-test-pop .questionArea {
+      /* font-size: 18px; */
     }
+    .lesson-test-pop .questioDes {
+        /* overflow-y: scroll; */
+        /* font-size: 18px; */
+    }
+}
+@media screen and (max-width: 767px) {
+    
+}
+@media screen and (max-width: 767px) {
+    
+}
+@media screen and (max-width: 767px) {
+    
 }
 @media screen and (max-width: 680px) {
     .lesson-test-pop .myProgressBar {
@@ -652,11 +700,5 @@
     }
 }
 @media screen and (max-width: 767px) {
-    .lesson-test-pop .questionArea {
-        font-size: 18px;
-    }
-    .lesson-test-pop .questioDes {
-        /* overflow-y: scroll; */
-        font-size: 18px;
-    }
+    
 }

+ 5 - 5
TEAMModelOS/ClientApp/src/common/BaseAreaPicker.vue

@@ -38,12 +38,12 @@
 </script>
 <style>
 	.distpicker-address-wrapper select {
-		background-color: #575757;
-		color: #cacaca;
+		background-color: #575757 !important;
+		color: #cacaca !important;
 		margin: 5px 0;
-		font-size: 14px;
-		height: 35px;
-		border: 0;
+		font-size: 14px !important;
+		height: 35px !important;
+		border: 0 !important;
 		display: inline-block;
 		position: relative;
 		outline: none;

+ 5 - 31
TEAMModelOS/ClientApp/src/common/BaseLayout.less

@@ -38,7 +38,7 @@
         top: 70px;
         bottom: 0px;
         width: 100%;
-        padding-left: 191px;
+        padding-left: 192px;
         overflow-y: auto;
         background: var(--body-bg);
         transition: padding-left 0.4s;
@@ -128,14 +128,14 @@
     width: 100%;
     text-align: right;
     cursor: pointer;
-    transition: background 1s;
+    transition: background 0.5s;
     padding-right: 5px;
-    padding-top: 5px;
-    padding-bottom: 5px;
+    padding-top: 1px;
+    padding-bottom: 1px;
     background:var(--side-bg);
     &:hover {
         background: #404040;
-        transition: background 1s;
+        transition: background 0.5s;
     }
 
     &:hover .collapse-icon {
@@ -148,33 +148,7 @@
     transform: translateX(-18px);
     transition:transform 0.2s;
 }
-.sub-item-wrap {
-    position: relative;
-}
-
-.sub-item-wrap::before {
-    content: '';
-    z-index: -1;
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    pointer-events: none;
-    background-image: linear-gradient(270deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
-    transform-origin: center right;
-    transform: scaleX(0);
-}
 
-.sub-item-wrap-active {
-    z-index: 1;
-}
-
-.sub-item-wrap-active::before {
-    transform-origin: center left;
-    transform: scaleX(1);
-    transition: transform 0.3s ease-in-out;
-}
 .menu-item-text {
     display: inline-block;
     overflow: hidden;

+ 73 - 23
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -31,11 +31,11 @@
                                         <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
                                         <span>{{item.name}}</span>
                                     </template>
-                                    <MenuItem class="sub-item-wrap sub-item-wrap-active" :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll">
+                                    <MenuItem :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll">
                                     <Tooltip :content="menuItem.name" placement="right" transfer v-show="isCollapsed">
                                         <Icon class="sub-menu-icon" :custom="menuItem.icon" size="16" />
                                     </Tooltip>
-                                    <Icon v-show="!isCollapsed" class="sub-menu-icon" :custom="menuItem.icon" size="16"/>
+                                    <Icon v-show="!isCollapsed" class="sub-menu-icon" :custom="menuItem.icon" size="16" />
                                     <span>
                                         {{menuItem.name}}
                                         <span style="color: aqua;margin-left: 2px;font-size: 12px;vertical-align: text-top;">
@@ -49,7 +49,13 @@
                                     <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
                                 </Tooltip>
                                 <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
-                                <span>{{item.name}}</span>
+                                <span>
+                                    {{item.name}}
+                                    <span style="color: aqua;margin-left: 2px;font-size: 12px;vertical-align: text-top;">
+                                        {{item.tag}}
+                                    </span>
+                                </span>
+
                                 </MenuItem>
                             </div>
                         </div>
@@ -64,7 +70,7 @@
                                     <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
                                     <span>{{item.name}}</span>
                                 </template>
-                                <MenuItem class="sub-item-wrap sub-item-wrap-active" :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll && menuItem.isShow">
+                                <MenuItem :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll && menuItem.isShow">
                                 <Tooltip :content="menuItem.name" placement="right" transfer v-show="isCollapsed">
                                     <Icon class="sub-menu-icon" :custom="menuItem.icon" size="18" />
                                 </Tooltip>
@@ -82,11 +88,15 @@
                                 <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
                             </Tooltip>
                             <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
-                            <span>{{item.name}}</span>
+                            <span>
+                                {{item.name}}
+                                <span style="color: aqua;margin-left: 2px;font-size: 12px;margin-top:3px">
+                                    {{item.tag}}
+                                </span>
+                            </span>
                             </MenuItem>
                         </div>
                     </MenuGroup>
-
                 </vuescroll>
             </Menu>
             <p class="copyright-info" v-show="!isCollapsed">
@@ -461,7 +471,7 @@ export default {
                     icon: 'iconfont icon-task',
                     name: this.$t('system.menu.taskList'),
                     router: '/home/taskList',
-                    tag: '',
+                    tag: '预览',
                     role: 'teacher',
                     permission: '',
                     child: [],
@@ -488,7 +498,7 @@ export default {
             if (cloudSetting.menuStatus == 'close') {
                 this.isCollapsed = true
             }
-			this.isShowLogo = cloudSetting.logoStatus === 'open'
+            this.isShowLogo = cloudSetting.logoStatus === 'open'
         }
     },
     mounted() {
@@ -549,7 +559,30 @@ export default {
     font-size: 12px;
     line-height: 30px;
     height: 30px;
+    position: relative;
+    color: white;
+}
+.ivu-menu-item-group{
+    position: relative;
+}
+.biz-menu .ivu-menu-vertical .ivu-menu-item-group::after {
+    content: "";
+    width: 100%;
+    height: 1px;
+    background: #303030;
+    position: absolute;
+    right: 0px;
+    bottom: -10px;
+    box-shadow:0px 12px 8px -12px #000;
+}
+.biz-menu  .ivu-menu-item-group:nth-child(2)::after {
+    background: transparent;
 }
+.biz-menu  .ivu-menu-item-group:nth-child(2) {
+    margin-top: 30px;
+}
+
+
 .biz-menu .ivu-menu-item-group:first-child {
     margin-top: 0px;
 }
@@ -561,7 +594,8 @@ export default {
 }
 
 .biz-menu .ivu-menu-light {
-    background: var(--side-bg);
+    // background: var(--side-bg);
+    background: #1d1e23;
     color: var(--primary-textColor);
 }
 
@@ -572,7 +606,8 @@ export default {
 .biz-menu
     .ivu-menu-light.ivu-menu-vertical
     .ivu-menu-item-active:not(.ivu-menu-submenu) {
-    background: #101117;
+    background: #33343a;
+    color: white;
     z-index: 2;
 }
 
@@ -585,8 +620,8 @@ export default {
 .menu-item span {
     display: inline-block;
     white-space: nowrap;
-    font-size: 16px;
-    position: absolute;
+    font-size: 15px;
+    // position: absolute;
     width: ~"calc(100% - 50px)";
     max-width: 150px;
     vertical-align: top;
@@ -596,22 +631,25 @@ export default {
 }
 
 .menu-item i {
+    margin-right: 10px;
     transform: translateX(0px);
     transition: font-size 0.5s ease, transform 0.5s ease;
-    vertical-align: sub;
     font-size: 16px;
-    /*color: var(--primary-text-color);*/
 }
 
 .menu-item .ivu-menu .ivu-menu-item {
     color: #cccccc;
 }
 .menu-item .ivu-menu-item {
-    color: hsla(0,0%,100%,.7);
+    color: hsla(0, 0%, 100%, 0.7);
+    display: flex;
+    align-items: center;
 }
 
 .menu-item .ivu-menu-submenu-title {
-    color: hsla(0,0%,100%,.7);
+    color: hsla(0, 0%, 100%, 0.7);
+    display: flex;
+    align-items: center;
 }
 
 .collapsed-menu i {
@@ -623,10 +661,8 @@ export default {
 
 .biz-menu .ivu-icon-ios-arrow-down:before {
     position: absolute;
-    top: -5px;
-    font-size: 12px;
-    opacity: 0.8;
-    color: hsla(0,0%,100%,.7);
+    top: -6px;
+    font-size: 15px;
 }
 
 .collapsed-menu .ivu-icon-ios-arrow-down:before {
@@ -661,25 +697,39 @@ export default {
 
 .biz-menu .ivu-menu-vertical .ivu-menu-item,
 .biz-menu .ivu-menu-vertical .ivu-menu-submenu-title {
-    padding: 10px 24px;
+    padding: 13px 24px;
+}
+.biz-menu .ivu-menu-submenu .ivu-menu-item {
+    background: #101117;
+    display: flex;
+    align-items: center;
 }
 
 .biz-menu
     .ivu-menu-light.ivu-menu-vertical
     .ivu-menu-item-active:not(.ivu-menu-submenu) {
-    color: #1cc0f3;
+    color: #ffffff;
 }
 
 .biz-menu
     .ivu-menu-light.ivu-menu-vertical
     .ivu-menu-item-active:not(.ivu-menu-submenu):after {
+    // background: transparent;
     background: #1cc0f3;
+    width: 1px;
 }
 
 // .ivu-menu-submenu-title:hover .ivu-menu-submenu-title-icon::before,.ivu-menu-submenu-title:hover span, .ivu-menu-submenu-title:hover .ivu-icon{
 //     color: #fff;
 // }
-.ivu-menu-submenu-title:hover .ivu-menu-submenu-title-icon::before{
+.ivu-menu-submenu-title:hover .ivu-menu-submenu-title-icon::before {
     color: rgb(45, 183, 245);
 }
+.ivu-menu-item:hover,
+.ivu-menu-submenu-title:hover {
+    color: white !important;
+    .ivu-icon-ios-arrow-down:before {
+        color: white !important;
+    }
+}
 </style>

+ 120 - 34
TEAMModelOS/ClientApp/src/common/BaseNotification.vue

@@ -1,69 +1,155 @@
 <template>
 	<div class="base-notification">
 		<Poptip :title="$t('utils.newNotice')" class="dark-iview-poptip">
-			<Icon type="md-notifications" />
-			<!-- <div slot="content" class="notice-wrap">
-				<div class="notice-item">
-					<p class="item-name">青城山学校</p>
-					<p class="item-content">活动[2020下学期国文期末考]达成率已达100%</p>
-					<span class="item-time">2020-08-14 18:22</span>
+			<Badge :count="msgArr.length">
+				<Icon type="md-notifications" />
+			</Badge>
+			<div slot="content" class="notice-wrap">
+				<div class="notice-item" v-for="(item,index) in msgArr" :key="index" @click="doClickMsg(item)">
+					<p class="item-name">{{ getMsgType(item) }}</p>
+					<p class="item-content">{{ getMsgContent(item) }}</p>
+					<!-- <span class="item-time">{{ item.expires }}</span> -->
 				</div>
-				<div class="notice-item">
-					<p class="item-name">成都市高新区芳草小学</p>
-					<p class="item-content">已成功加入</p>
-					<span class="item-time">2020-08-14 18:22</span>
-				</div>
-				<div class="notice-item">
-					<p class="item-name">成都市泡桐树小学</p>
-					<p class="item-content">活动[2020下学期国文期末考]达成率已达100%</p>
-					<span class="item-time">2020-08-14 18:22</span>
-				</div>
-			</div> -->
+			</div>
 		</Poptip>
 	</div>
 </template>
 
 <script>
+	export default {
+		props: {
+			msgs: {
+				type: Array,
+				default: () => []
+			}
+		},
+		data() {
+			return {
+				msgArr: [],
+				msgTypes: {
+					'request_school': '申请通知',
+					'invite_school': '邀请通知',
+				}
+			}
+		},
+		created() {
+
+		},
+		methods: {
+			getBodyJson(str) {
+				let reg = /\\/g;
+				//使用replace方法将全部匹配正则表达式的转义符替换为空
+				let replaceAfter = str.replace(reg, '').replace(/=/g, ':');
+				return replaceAfter
+			},
+			getMsgType(msg) {
+				return this.msgTypes[msg.label]
+			},
+			getMsgContent(msg) {
+				let body = JSON.parse(this.getBodyJson(msg.body))
+				console.log(body)
+				switch (msg.label) {
+					case 'request_school':
+						return `${body.tmdname}(${body.tmdid}) 申请加入 ${body.schoolname}`
+						break;
+					case 'invite_school':
+						return `${body.tmdname}(${body.tmdid}) 邀请您加入 ${body.schoolname}`
+						break;
+					case 'request-join_school':
+						return `${body.schoolname} 已同意您的加入请求`
+						break;
+					case 'invite-join_school':
+						return `${body.tmdname}(${body.tmdid}) 已接受您的加入 ${body.schoolname} 的邀请`
+						break;
+					case 'remove_school':
+						return `${body.schoolname} 已将您移除`
+						break;
+					default:
+						break;
+				}
+			},
+			doClickMsg(msg) {
+				switch (msg.label) {
+					case 'request_school':
+						this.$router.push('teachermgmt')
+						break;
+					case 'invite_school':
+						this.$router.push('settings')
+						break;
+					default:
+						break;
+				}
+			}
+		},
+		watch: {
+			msgs: {
+				handler(n, o) {
+					this.msgArr = n
+					console.log(this.msgArr)
+				}
+			}
+		}
+	}
 </script>
 
 <style lang="less">
-	.base-notification{
-		.ivu-icon{
+	.base-notification {
+		font-family: 'NotoSerif', '微软正黑体', 'Microsoft JhengHei UI', 'Microsoft JhengHei', Sans-serif;
+
+		.ivu-icon {
 			font-size: 22px;
 			color: #d0d0d0;
 			cursor: pointer;
 		}
-		
-		.dark-iview-poptip .ivu-poptip-popper{
+
+		.dark-iview-poptip .ivu-poptip-popper {
 			padding: 0;
 			top: 40px !important;
+			z-index: 9999;
+		}
+
+		.ivu-badge-count {
+			width: 16px;
+			height: 16px;
+			display: inline-block;
+			border-radius: 50%;
+			color: white;
+			border: none;
+			font-size: 12px;
+			line-height: 16px;
+			text-align: center;
+			margin-left: 10px;
+			min-width: 16px;
+			box-shadow: none;
+			padding: 0;
 		}
-		
-		.notice-wrap{
+
+		.notice-wrap {
 			display: flex;
 			flex-direction: column;
-			
-			.notice-item{
+
+			.notice-item {
 				position: relative;
 				padding: 10px;
-				color:#d0d0d0;
+				color: #d0d0d0;
 				border-bottom: 1px solid #424242;
-				
-				&:last-child{
+				cursor: pointer;
+
+				&:last-child {
 					border: none;
 				}
-				
-				.item-name{
+
+				.item-name {
 					font-size: 16px;
 					font-weight: bold;
-					color:#fff;
+					color: #fff;
 					margin: 10px 0;
 				}
-				
-				.item-time{
+
+				.item-time {
 					margin-top: 5px;
 					font-size: 12px;
-					color:#777777;
+					color: #777777;
 					float: right;
 				}
 			}

+ 0 - 1
TEAMModelOS/ClientApp/src/common/BaseSelectSchool.vue

@@ -42,7 +42,6 @@
 			this.defaultLogo = require('@/assets/icon/default_school.png')
 			// 获取本地存储中的 用户信息
 			let user = JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"));
-			console.log(user)
 			let schoolProfile = localStorage.school_profile ? JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")) :undefined;
 			this.user.schools = user.schools
 			let joinSchools = user.schools && user.schools.length ?  user.schools.filter(i => i.status === 'join') : null

+ 63 - 8
TEAMModelOS/ClientApp/src/common/UploadModal.vue

@@ -1,18 +1,22 @@
 <template>
-    <Modal v-model="uploadStatus" :ok-text="textLoading ? $t('updModal.uploading') : isComplete ? $t('updModal.complete'):$t('updModal.comfirmUpd')" :cancel-text="$t('updModal.cancelUpd')" :title="$t('teachContent.btnUpload')" class="upload-modal dark-iview-modal" width="800" :mask-closable="false" :closable="false" @on-ok="modalOk" @on-cancel="modalCancel" :loading="modalLoading">
+    <Modal v-model="uploadStatus" :ok-text="textLoading ? $t('updModal.uploading') : isComplete ? $t('updModal.complete'):$t('updModal.comfirmUpd')" :cancel-text="$t('updModal.cancelUpd')" :title="$t('teachContent.btnUpload')" class="upload-modal dark-iview-modal" width="900" :mask-closable="false" :closable="false" @on-ok="modalOk" @on-cancel="modalCancel" :loading="modalLoading">
         <div class="upload-file-box">
-            <!-- <p>上传到:{{pdInfo.filterPeriodName}}</p> -->
-            <ResBelong v-show="routerScope == 'school'" showLabel class="upd-to-pd" :pdId="pdId"></ResBelong>
+            <ResBelong @tag-change="getResTags" v-show="routerScope == 'school'" showLabel class="upd-to-pd" :pdId="pdId"></ResBelong>
             <Upload type="drag" action="" :show-upload-list="false" multiple :before-upload="customUpload" class="upload-wrap" :disabled="textLoading">
                 <Icon class="upload-icon" custom="iconfont icon-upload" v-show="!uploadedList.length" />
                 <p class="upload-text" :style="{marginTop: uploadedList.length ? '25px':'0px'}">
                     <Icon size="24" style="font-size: 22px;vertical-align: baseline;margin-right: 5px;" custom="iconfont icon-upload" v-show="uploadedList.length" />
                     {{$t('teachContent.uploadText')}}
                 </p>
-                <p class="upload-text" style="font-size:12px;">{{$t('updModal.tips1')}}</p>
-                <p class="upload-text" :style="{fontSize:'12px',marginBottom: uploadedList.length ? '25px':'50px'}">
+                <p class="upload-text" style="font-size:12px;">
+                    {{$t('updModal.tips1')}}
+                </p>
+                <p class="upload-text" style="font-size:12px;">
                     {{$t('updModal.tips3')}}
                 </p>
+                <p class="upload-text" :style="{fontSize:'12px',marginBottom: uploadedList.length ? '25px':'50px'}">
+                    {{$t('updModal.tips2')}}
+                </p>
             </Upload>
             <div class="upload-file-box">
                 <div class="upload-file-item" v-for="(item,index) in uploadedList" :key="index">
@@ -80,7 +84,12 @@ export default {
             textLoading: false,
             modalLoading: false,
             isComplete: false, //是否完成上传
-            loadingCount: 0
+            loadingCount: 0,
+            tags: {
+                period: '',
+                gradeId: [],
+                subjectId: []
+            }
         }
     },
     props: {
@@ -132,6 +141,13 @@ export default {
         }
     },
     methods: {
+        //资源标签:学段、学科、年级
+        getResTags(data) {
+            console.log(data)
+            this.tags.period = data.period
+            this.tags.subjectId = data.subjects
+            this.tags.gradeId = data.grades
+        },
         //删除文件
         deleteFile(index) {
             this.containerClient.deleteBlob(this.uploadedList[index].blob).then(
@@ -268,6 +284,40 @@ export default {
         modalOk() {
             //已完成上传操作,关闭对话框、emit
             if (this.isComplete) {
+                //保存Blob描述信息
+                //API设计可以优化,如果API参数为对象数据,这里可以避免for循环里面发起请求影响性能
+                if (this.routerScope == 'school') {
+                    this.uploadedList.forEach(item => {
+                        item.periodId = this.tags.period
+                        item.gradeId = this.tags.gradeId.map(item => item + '')
+                        item.subjectId = this.tags.subjectId
+                        let requestData = {
+                            periodId: this.tags.period,
+                            gradeId: this.tags.gradeId.map(item => item + ''),
+                            subjectId: this.tags.subjectId,
+                            scope: 'school',
+                            name: this.$store.state.userInfo.schoolCode,
+                            url: item.blob.substring(1, item.blob.length),
+                            opt: 'add'
+                        }
+                        this.$api.blob.upsertBlobInfo(requestData)
+                    })
+                }
+                //个人资源不用关联学段、学科、年级等信息
+                else {
+                    this.uploadedList.forEach(item => {
+                        let requestData = {
+                            periodId: [],
+                            gradeId: [],
+                            subjectId: [],
+                            scope: 'private',
+                            name: this.$store.state.userInfo.TEAMModelId,
+                            url: item.blob.substring(1, item.blob.length),
+                            opt: 'add'
+                        }
+                        this.$api.blob.upsertBlobInfo(requestData)
+                    })
+                }
                 this.$emit("successData", this.uploadedList)
                 this.uploadedList = []
             } else { //还未上传文件,则上传文件
@@ -362,7 +412,6 @@ export default {
                 this.textLoading = false
                 this.isComplete = true
                 this.modalLoading = false
-
             }
         },
         //处理图片缩略图
@@ -409,12 +458,18 @@ export default {
             }
         }
         // 使用组件接收的值
-        else{
+        else {
             this.routerScope = this.scope
         }
 
     },
     watch: {
+        pdId: {
+            handler(n, o) {
+                this.tags.period = this.pdId
+            },
+            immediate: true
+        },
         urlString: {
             handler(v, o) {
                 if (this.urlString && this.containerName && this.sasString) {

+ 41 - 30
TEAMModelOS/ClientApp/src/components/app-root.vue

@@ -1,43 +1,54 @@
 <template>
     <div id="app" class="container-fluid">
-        <router-view v-if="isRouterAlive"/>
+        <router-view v-if="isRouterAlive" />
     </div>
 </template>
 
 <script>
-    import NavMenu from './nav-menu'
+import NavMenu from './nav-menu'
 
-    export default {
-        components: {
-            'nav-menu': NavMenu,
-        },
-        provide () {    //父组件中通过provide来提供变量,在子组件中通过inject来注入变量。                                             
-            return {
-                reload: this.reload                                              
-            }
-        },
-        methods: {
-            reload() {
-                this.isRouterAlive = false
-                this.$nextTick(function () {
-                    this.isRouterAlive = true
-                })
-            }
-        },
-        data() {
-            return {
-                isRouterAlive:true
-            }
-        },
-        created() {
+export default {
+    components: {
+        'nav-menu': NavMenu,
+    },
+    provide() {    //父组件中通过provide来提供变量,在子组件中通过inject来注入变量。                                             
+        return {
+            reload: this.reload
+        }
+    },
+    methods: {
+        reload() {
+            this.isRouterAlive = false
+            this.$nextTick(function () {
+                this.isRouterAlive = true
+            })
+        }
+    },
+    data() {
+        return {
+            isRouterAlive: true
+        }
+    },
+    created() {
+    },
+    watch: {
+        '$i18n.locale': {
+            handler(n, o) {
+                document.title = this.$t('system.title')
+            },
+            immediate: true
         }
     }
+}
 </script>
 
 <style scoped>
-    #app, body, html {
-        width: 100%;
-        height: 100%;
-        font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI','Microsoft YaHei','微软雅黑', 'Microsoft JhengHei';
-    }
+#app,
+body,
+html {
+    width: 100%;
+    height: 100%;
+    font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI",
+        "Microsoft YaHei", "微软雅黑", "Microsoft JhengHei";
+}
 </style>

+ 1 - 3
TEAMModelOS/ClientApp/src/components/evaluation/ExerciseList.vue

@@ -202,7 +202,6 @@
 			};
 		},
 		created() {
-			console.log('接收到的',this.analysisJson)
 			this.pageSize = this.isAnalysis ? 999 : 5
 			this.pageChange(1)
 		},
@@ -365,7 +364,6 @@
 		},
 		mounted() {
 			this.selectList = this.selQue
-			console.log(this.optionRate)
 		},
 		computed: {
 			curScope() {
@@ -401,7 +399,7 @@
 			optionRate:{
 				handler(n,o){
 					if(n){
-						console.log(n)
+						// console.log(n)
 					}
 				},
 				immediate:true,

+ 1 - 1
TEAMModelOS/ClientApp/src/components/public/frontEndMain/Index.less

@@ -1,7 +1,7 @@
 .login{
     width: 100%;
     height: 100%;
-    background-image: url('../../../assets/image/lgoin_bg.jpg');
+    // background-image: url('../../../assets/login/1-1.jpg');
     background-repeat: no-repeat;
     background-attachment: fixed;
     background-position: center;

File diff suppressed because it is too large
+ 146 - 109
TEAMModelOS/ClientApp/src/components/public/frontEndMain/Index.vue


+ 2 - 4
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/StudentScore.vue

@@ -94,7 +94,7 @@
                         <span>{{$t("studentWeb.exam.studentScore.comIndex")}}</span>
                     </li>
                 </ul>
-                <ul v-for="(item,index) in scoreInfo.averageMap">
+                <ul v-for="(item, index) in scoreInfo.averageMap" :key="index">
                     <li class="sub-item">
                         <div class="sub-show"><span>{{item.name}}</span></div>
                     </li>
@@ -214,7 +214,6 @@
     </div>
 </template>
 <script>
-
     export default {
         props: {
             stuData: {
@@ -389,7 +388,6 @@
         },
         mounted() {
             this.getPaperData()
-
         },
         watch: {
             stuData() {
@@ -397,7 +395,7 @@
                     this.stuScore = []
                     this.getPaperData()
                 }
-                deep:true
+                deep: true
             }
         }
     }

File diff suppressed because it is too large
+ 152 - 52
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue


+ 1 - 1
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperView.vue

@@ -43,7 +43,7 @@
                     </div>
                 </TabPane>
                 <!-- 成绩分析 -->
-                <TabPane :label="$t('studentWeb.exam.gradeReport')" v-if="isTestOver" name="analyse">
+                <TabPane :label="$t('studentWeb.exam.gradeReport')" v-if="isTestOver && $store.getters.getItemTitle.owner == 'school'" name="analyse">
                     <div class="title-rect-group">
                         <!-- <div class="title-rect" /> -->
                         <h2 class="title-rect-name">{{$t("studentWeb.exam.gradeAnalyse")}}</h2>

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

@@ -81,7 +81,70 @@
                     <br />
                     {{ $t("studentWeb.empty") }}
                 </div>
-                <div :id="`event${item.id}`"
+                <div v-if="isListNoItem == false">
+                    <div :id="`event${item.id}`"
+                         class="list-new"
+                         @click="sentSelectedEventTitle(item)"
+                         :class="{ 'list-item-selected': selectedCondition(item) }"
+                         v-for="(item, index) in eventShow"
+                         :key="index"
+                    >
+                        <div class="list-new-icon">
+                            <svg-icon v-if="item.eventType == 'HomeWork'" icon-class="doc" />
+                            <svg-icon v-if="item.eventType == 'Preview'"  icon-class="selflearninginTime" />
+                            <svg-icon v-if="item.eventType == 'Exam'" icon-class="multiTest" />
+                            <svg-icon v-if="item.eventType == 'Vote'" icon-class="vote" />
+                            <svg-icon v-if="item.eventType == 'Survey'" icon-class="quesnaire" />
+                        </div>
+                        <div v-if="item.eventType == 'Exam'" class="list-new-test">
+                            <p class="list-item-title">
+                                <span class="list-item-typeMark">{{item.owner == 'school' ? $t('studentWeb.public.schoolExam'):$t('studentWeb.public.privateExam')}}</span>
+                                <span>{{ item.name }}</span>
+                            </p>
+                            <!-- 暂时不改 -->
+                            <!-- <p class="list-item-time isScore" v-show="timeStatus(item) == 'finish'">
+                                得分率:20%
+                            </p> -->
+                            <p class="list-item-time">
+                                {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
+                            </p>
+                        </div>
+                        <div v-if="item.eventType == 'Vote'" class="list-new-test">
+                            <p class="list-item-title">
+                                <span class="list-item-typeMark">{{item.owner == 'school' ? $t('studentWeb.public.schoolVote'):$t('studentWeb.public.privateVote')}}</span>
+                                <span>{{ item.name }}</span>
+                            </p>
+                            <p class="list-item-time">
+                                {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
+                            </p>
+                        </div>
+                        <div v-if="item.eventType == 'Survey'" class="list-new-test">
+                            <p class="list-item-title">
+                                <span class="list-item-typeMark">{{item.owner == 'school' ? $t('studentWeb.public.schoolSurvey'):$t('studentWeb.public.privateSurvey')}}</span>
+                                <span>{{ item.name }}</span>
+                            </p>
+                            <p class="list-item-time">
+                                {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
+                            </p>
+                        </div>
+                        <div class="list-new-type">
+                            <div class="list-new-unDone isAllowRetry" v-show="timeStatus(item) == 'going'">
+                                <span>{{$t("studentWeb.public.going")}}</span>
+                            </div>
+                            <div class="list-new-unDone" v-show="timeStatus(item) == 'finish'">
+                                <span class="isOvertime">{{$t("studentWeb.public.finish")}}</span>
+                            </div>
+                            <!-- 暂时不改 -->
+                            <!-- <div class="list-new-unDone isWrongPra" v-show="timeStatus(item) == 'finish' && item.eventType == 'Exam'">
+                                <span class="">{{$t("studentWeb.exam.report.wrongPractice")}}</span>
+                            </div> -->
+                        </div>
+                            
+                    </div>
+                </div>
+
+
+                <!-- <div :id="`event${item.id}`"
                      class="list-item"
                      @click="sentSelectedEventTitle(item)"
                      :class="{ 'list-item-selected': selectedCondition(item) }"
@@ -106,9 +169,9 @@
                             <p class="list-item-time">
                                 {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
                             </p>
-                            <!-- <p class="list-item-time" v-show="timeStatus(item) == 'finish'">
+                            <p class="list-item-time" v-show="timeStatus(item) == 'finish'">
                                 得分率:20%
-                            </p> -->
+                            </p>
                         </li>
                         <li class="list-item-info"
                             v-if="item.eventType == 'Vote'">
@@ -136,11 +199,11 @@
                         <li class="list-item-unDone" v-show="timeStatus(item) == 'finish'">
                             <div class="isOvertime">{{$t("studentWeb.public.finish")}}</div>
                         </li>
-                        <!-- <li class="list-item-unDone" v-show="timeStatus(item) == 'finish' && item.eventType == 'Exam'">
+                        <li class="list-item-unDone" v-show="timeStatus(item) == 'finish' && item.eventType == 'Exam'">
                             <div class="">{{$t("studentWeb.exam.report.wrongPractice")}}</div>
-                        </li> -->
+                        </li>
                     </ul>
-                </div>
+                </div> -->
                 <div class="list-end"></div>
             </div>
         </div>
@@ -299,7 +362,6 @@
                 //選中第一個
                 let currentfilterArray = [];
                 this.eventShow.length = 0
-                console.log(this.eventTypeCheckers);
                 for (let i = 0; i < this.eventList.length; i++) {
                     if (this.eventPageType.includes(this.eventList[i].eventType)) {
                         // 沒有篩選類型+沒有篩選狀態的情況
@@ -555,4 +617,5 @@
 
 <style scoped>
     @import "~@/assets/student-web/component_styles/event-list.css";
+    @import "~@/assets/student-web/component_styles/event-list-new.css";
 </style>

+ 6 - 5
TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseList.vue

@@ -295,13 +295,13 @@ export default {
   name: "CourseList",
   data() {
     return {
-      currentView:'table',
+      currentView: 'table',
       messageOpen: false,
       timetitle:
         localStorage.getItem("lang") == "tw"
           ? ["時間", "一", "二", "三", "四", "五"]
           : ["time", "Mon", "Tue", "Wed", "Thu", "Fri"],
-        courseList: this.$api.studentWeb.courseList
+      courseList: this.$api.studentWeb.courseList //moke数据
     };
   },
   created() {
@@ -310,12 +310,12 @@ export default {
     }
   },
   methods: {
-    changeView(type){
+    changeView(type) {
       this.currentView=type
     },
     sentFirstItemActive() {
-        let tempArr = [];
-        console.log(this.$api.studentWeb.courseList)
+      let tempArr = [];
+      console.log(this.$api.studentWeb.courseList)
       for (let i = 0; i < this.courseList.length; i++) {
         if (this.courseList[i].courseType != "臨時") {
           tempArr.push(this.courseList[i]);
@@ -323,6 +323,7 @@ export default {
       }
       this.sentSelectedEventTitle(tempArr[0]);
     },
+    // 跳转到当前课程
     sentSelectedEventTitle: function (item) {
       this.$router.push("/courseList#" + item.courseID);
       //改變ItemName的狀態 vuex mutations

+ 144 - 144
TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue

@@ -1,18 +1,21 @@
 <template>
 	<div class="syllabus-tree-main">
 		<vuescroll>
-			<el-tree :data="treeDatas" :props="defaultProps" class="tree" node-key="id"  default-expand-all highlight-current
-				@node-drop="handleDrop" @node-click="onNodeClick" :draggable="editable" :expand-on-click-node="false">
+			<el-tree :data="treeDatas" :props="defaultProps" :allow-drop="allowDrop" class="tree" node-key="id"
+				default-expand-all highlight-current @node-drop="handleDrop" @node-click="onNodeClick"
+				:draggable="editable" :expand-on-click-node="false" ref="tree">
 				<span class="custom-tree-node" slot-scope="{ node, data }">
 					<span class="tree-node-lable">
 						{{data.title}}
-						<Icon type="md-cube" title="有关联资源" v-if="data.rnodes && data.rnodes.length"/>
+						<!-- {{data.id}} -->
+						<Icon type="md-cube" :title="$t('syllabus.tree.hasResource')" v-if="data.rnodes && data.rnodes.length" />
 					</span>
 					<span class="custom-tree-tools" v-if="editable">
-						<Icon type="md-create" size="16" title="编辑" @click="onEditItem(node,data,$event)" />
-						<Icon type="md-add" size="16" title="添加" @click="onAddNode(data,$event)" />
-						<Icon type="md-remove" size="16" title="删除" @click="remove(node,data)" />
-						<Icon type="md-share" v-if="isFirstLevel(data.pid)" @click="doShare(data)"/>
+						<Icon type="md-create" size="16" :title="$t('syllabus.tree.edit')" @click="onEditItem(node,data,$event)" />
+						<Icon type="md-add" size="16" :title="$t('syllabus.tree.add')" @click="onAddNode(node,data,$event)" />
+						<Icon type="md-remove" size="16" :title="$t('syllabus.tree.remove')" @click="remove(node,data)" />
+						<Icon type="md-share" v-if="isFirstLevel(data)" :title="isSchool ? $t('syllabus.tree.coEdit') : $t('syllabus.tree.share')"
+							@click="doShare(data)" />
 					</span>
 				</span>
 			</el-tree>
@@ -20,14 +23,15 @@
 
 		<!-- 新增或者编辑弹窗 -->
 		<Modal v-model="isEditOrAdd" width="500" footer-hide class="tree-modal">
-			<div class="modal-header" slot="header">{{ isEditItem ? '编辑节点':'新增节点'}}</div>
+			<div class="modal-header" slot="header">{{ isEditItem ? $t('syllabus.tree.editTitle'):$t('syllabus.tree.addTitle')}}</div>
 			<div class="modal-content">
-				<p class="node-title">父节点</p>
+				<p class="node-title">{{ $t('syllabus.tree.parent') }}</p>
 				<Input v-model="nodeInfo.parent" style="width: 100%" disabled />
-				<p class="node-title">节点名称</p>
-				<Input v-model="nodeInfo.title" placeholder="请输入节点名称..." style="width: 100%" />
+				<p class="node-title">{{ $t('syllabus.tree.nodeName') }}</p>
+				<Input v-model="nodeInfo.title" :placeholder="$t('syllabus.tree.place1')" style="width: 100%" />
 			</div>
-			<Button @click="onSubmitNode" class="modal-btn" style="width: 88%;margin-left: 6%;margin-bottom: 20px;">确认</Button>
+			<Button @click="onSubmitNode" class="modal-btn"
+				style="width: 88%;margin-left: 6%;margin-bottom: 20px;">{{ $t('syllabus.tree.confirm') }}</Button>
 		</Modal>
 	</div>
 </template>
@@ -65,7 +69,8 @@
 				currentParentData: null,
 				currentResources: [],
 				currentItems: [],
-				curNode:null,
+				curNode: null,
+				curData:null,
 				nodeInfo: {
 					id: null,
 					title: '',
@@ -79,22 +84,50 @@
 					pid: '',
 					code: '',
 					status: 1,
-					parent: ''
-				}
+					parent: '',
+					rnodes:[]
+				},
+				isSchool: false,
+				flatArr:[]
 			}
 		},
+		created() {
+			this.isSchool = this.$route.name === 'syllabus'
+		},
 		methods: {
 			onNodeClick(data, node) {
-				console.log(data, node)
-				this.curNode = data
-				this.$emit('onNodeClick',data)
+				this.curNode = node
+				this.curData = data
+				this.$emit('onNodeClick', {
+					data:data,
+					node:node
+				})
+			},
+
+			doShare(data) {
+				this.$emit('doShare', data)
 			},
 			
-			doShare(data){
-				this.$emit('doShare',data)
+			/* 禁止一级节点往下级进行拖拽 */
+			allowDrop(draggingNode, dropNode, dropType) {
+				if (draggingNode.level === dropNode.level) {
+					if(draggingNode.level === 1){
+						return dropType === 'prev' || dropType === 'after'
+					}else{
+						return dropType === 'prev' || dropType === 'after' ||  dropType === 'inner'
+					}
+				} else {
+					// 如果是二三级拖到其他级别 则正常拖拽 但是不能拖到第一级
+					if(draggingNode.level !== 1 && dropNode.level !== 1){
+						return dropType === 'prev' || dropType === 'after' ||  dropType === 'inner'
+					}
+					
+				}
 			},
 			// 拖拽完成回调
 			handleDrop(draggingNode, dropNode, dropType) {
+				this.$emit('addModifyId',this.getChapterIdById(draggingNode.data.id))
+				this.$emit('addModifyId',this.getChapterIdById(dropNode.data.id))
 				switch (dropType) {
 					case 'before':
 						draggingNode.data.pid = dropNode.data.pid
@@ -109,35 +142,58 @@
 						break
 				}
 				this.$parent.hasModify = true
+
 			},
 
 			// 删除节点操作
 			remove(node, data) {
+				let isFirstLevel = this.isFirstLevel(data)
 				this.$Modal.confirm({
-					title: '删除节点',
-					content: '<p>确认删除该节点?</p>',
-					okText: '确认',
-					cancelText: '取消',
+					title: this.$t('syllabus.tree.removeTitle'),
+					content: this.$t('syllabus.tree.removeConfirm'),
 					onOk: () => {
 						const parent = node.parent
 						const children = parent.data.children || parent.data
 						const index = children.findIndex(d => d.id === data.id)
-						children.splice(index, 1)
-						this.$Message.success('删除成功')
-						this.$parent.hasModify = true
+						// 如果是删除的第一层的节点 则直接访问API进行删除 如果不是 则记录子节点的PID
+						if(isFirstLevel){
+							this.$api.syllabus.DeleteTree({
+								id:data.id,
+								code:this.volume.id,
+								scope:this.volume.scope
+							}).then(res => {
+								if (!res.error) {
+									if(res.code === 404){
+										this.$parent.modifyIdArr  = this.$parent.modifyIdArr.filter(i => i !== data.id)
+									}
+									children.splice(index, 1)
+									this.$Message.success(this.$t('syllabus.tree.removeSucTip'))
+								} else {
+									this.$Message.warning(res.error);
+								}
+							}).catch(err => {
+								this.$Message.error(err);
+							})
+						}else{
+							children.splice(index, 1)
+							this.$Message.success(this.$t('syllabus.tree.removeSucTip'))
+							this.$parent.hasModify = true
+							this.$emit('addModifyId',this.getChapterIdById(data.id))
+						}
 					}
 				})
 			},
 
 			// 点击添加展开弹窗
-			onAddNode(data, e) {
+			onAddNode(node,data, e) {
 				e.stopPropagation() // 防止点击事件穿透到父层
 				this.isEditItem = false
 				this.isEditOrAdd = true
-
 				this.currentParentData = data // 当前点击节点即为父节点
 				this.nodeInfo.parent = data.title
+				this.nodeInfo.id = data.id
 				this.nodeInfo.title = ''
+				this.curNode = node
 			},
 
 			// 编辑节点操作
@@ -145,73 +201,27 @@
 				e.stopPropagation() // 防止点击事件穿透到父层
 				this.isEditOrAdd = true
 				this.isEditItem = true
-
 				this.currentEditData = data
 				this.nodeInfo.parent = node.parent.data.title || this.volume.name
 				this.nodeInfo.title = node.data.title
+				this.nodeInfo.id = node.data.id
+				this.curNode = node
 			},
-
-
-			onRelatedContent(node, data, e) {
-				e.stopPropagation() // 防止点击事件穿透到父层
-				this.isRelatedContent = true
-				this.currentEditData = data
-			},
-
-			onShowContent(val, data) {
-				console.log(data)
-				this.contentIndex = val
-				this.currentItems = []
-				this.currentResources = []
-				// data.items.length && this.findQuestionById(data.items)
-				data.resources.length && this.findResourceById(data.resources)
-				this.isShowContent = true
-			},
-
-			/**
-			 * 通过id查询内容信息
-			 * */
-			findResourceById(ids) {
-
-				this.$api.learnActivity.FindSyllabusResourceById(ids).then(
-					res => {
-						if (!res.error) {
-							this.currentResources = res.result.data
-						} else {
-							this.$Message.error("API ERROR")
-						}
-					},
-					err => {
-						this.$Message.error("API ERROR")
-
-					}
-				)
-
-			},
-			/**
-			 * 通过id查询题目信息
-			 * */
-			findQuestionById(ids) {
-				this.$api.learnActivity.FindQuestionById(ids).then(
-					res => {
-						if (!res.error) {
-							this.currentItems = res.result.data
-						} else {
-							this.$Message.error("API ERROR")
-						}
-					},
-					err => {
-						this.$Message.error("API ERROR")
-
-					}
-				)
+			
+			/* 根据节点获取它所在的章节信息 */
+			getChapterByNode(node){
+				console.log(node)
+				if(node.level === 1){
+					return node
+				}else{
+					return this.getChapterByNode(node.parent)
+				}
 			},
 
-
 			// 提交编辑或者新增
 			onSubmitNode() {
 				if (!this.nodeInfo.title) {
-					this.$Message.warning('节点名称不能为空')
+					this.$Message.warning(this.$t('syllabus.tree.nodeNameTip'))
 					return
 				}
 				if (this.isEditItem) {
@@ -231,55 +241,54 @@
 					}
 					this.currentParentData.children.push(newChild)
 				}
-
 				this.isEditOrAdd = false
 				this.$parent.hasModify = true
-				this.$Message.success(this.isEditItem ? '编辑成功' : '添加成功')
-			},
-
-
-			/**
-			 * 选择关联题目
-			 * @param val 当前已选题目
-			 */
-			onSelectQuestion(val) {
-				this.questionList = val.questions
-			},
-
-			/**
-			 * 选择关联内容
-			 * @param val 当前已选内容
-			 */
-			onSelectFile(val) {
-				this.fileList = val.files
-				console.log(val)
+				this.$emit('addModifyId',this.getChapterIdById(this.curData.id))
+				this.$Message.success(this.isEditItem ? this.$t('syllabus.tree.editSucTip') : this.$t('syllabus.tree.addSucTip'))
 			},
-
-			/** 保存内容与题目关联 */
-			onSaveNode() {
-				this.isLoading = true
-				this.currentEditData.items = this.currentEditData.items ? [...new Set(this.currentEditData.items.concat(
-					this.questionList.map(item => item.id)))] : [...new Set(this.questionList.map(item => item.id))]
-				this.currentEditData.resources = this.currentEditData.resources ? [...new Set(this.currentEditData
-					.resources.concat(this.fileList.map(item => item.url)))] : [...new Set(this.fileList.map(item =>
-					item.url))]
-				this.$api.syllabus.SaveOrUpdateAsNodes([this.currentEditData]).then(res => {
-					if (!res.error && res) {
-						this.isRelatedContent = false
-						this.$emit('onTreeUpdate')
-						this.isLoading = false
-						this.$parent.hasModify = true
-					} else {
-						this.$Message.warning('获取数据失败')
-					}
+			
+			/* 获取整个树的章节与子节点归属 */
+			getAllChild(arr){
+				let result = []
+				arr.forEach(item => {
+					result.push({
+						chapterId:item.id,
+						children:this.flatChildren(item.children)
+					})
 				})
+				this.flatArr = result
 			},
+			
+			/* 递归拉平所有children */
+			flatChildren(children){
+				let result = []
+				const fn = (source)=>{
+				    source.forEach(i => {
+				    	result.push(i.id)
+				    	if(i.children.length){
+				    		fn(i.children)
+				    	}
+				    })
+				}
+				fn(children)
+				return result
+			},
+			
+			/* 根据某个节点ID换取它对应的章节ID */
+			getChapterIdById(id){
+				if(this.flatArr.map(i => i.chapterId).includes(id)){
+					return id
+				}else{
+					let targetChapter = this.flatArr.find(i => i.children.includes(id))
+					return targetChapter.chapterId
+				}
+			}
 
 		},
-		computed:{
-			isFirstLevel(){
-				return pid => {
-					return pid === this.volume.id
+		computed: {
+			isFirstLevel() {
+				return data => {
+					return data.pid === this.volume.id
 				}
 			},
 		},
@@ -288,21 +297,12 @@
 			treeData: {
 				handler: function(n, o) {
 					// 以下为拼接树形数据以及册别数据
-					// let defaultTree = []
-					// let volumeParent = {
-					//     title: this.volume.name,
-					//     id: this.volume.id,
-					//     code: this.volume.code,
-					//     pid: 'Root',
-					//     children: []
-					// }
-					// volumeParent.children = n
-					// defaultTree.push(volumeParent)
-					this.treeDatas = n
-					this.$nextTick().then(() =>{
+					this.treeDatas = n.map(i => i.trees[0])
+					this.getAllChild(this.treeDatas)
+					this.$nextTick().then(() => {
 						const firstNode = document.querySelector('.el-tree-node')
 						firstNode.click();
-					  })
+					})
 				},
 				immediate: true
 			},
@@ -358,7 +358,7 @@
 	}
 
 	.tree /deep/ .el-tree-node:before {
-		border-left: 1px dashed #343434;
+		border-left: 1px dashed #626262;
 		bottom: 0px;
 		height: 100%;
 		top: -20px;
@@ -366,7 +366,7 @@
 	}
 
 	.tree /deep/ .el-tree-node:after {
-		border-top: 1px dashed #343434;
+		border-top: 1px dashed #626262;
 		height: 20px;
 		top: 20px;
 		width: 12px;

+ 3 - 2
TEAMModelOS/ClientApp/src/components/syllabus/InviteTeacher.less

@@ -18,11 +18,12 @@
 	}
 	
 	.teacher-wrap{
-		margin-top: 30px;
-		
 		.dark-iview-table .ivu-table td{
 			border-color: #494949;
 			color: #c4c4c4 !important;
 		}
 	}
+
+	
+	
 }

+ 188 - 16
TEAMModelOS/ClientApp/src/components/syllabus/InviteTeacher.vue

@@ -4,8 +4,12 @@
 			<span>当前选择章节:</span>
 			<span class="node-name">{{ nodeInfo.title }}</span>
 		</div>
+		<div class="search-wrap" v-if="isSchool">
+			<Input v-model="searchVal"  placeholder="输入教师名字或ID查询..."
+			icon="ios-close-circle-outline" @on-click="onCloseSearch" @on-change="onSearchChange"/>
+		</div>
 		<div class="teacher-wrap">
-			<Table class="dark-iview-table" :columns="teacherCol" :data="teacherList" height="500">
+			<Table class="dark-iview-table" :columns="teacherCol" :data="teacherList" height="400" v-if="isSchool">
 				<template slot-scope="{ row }" slot="name">
 					<div style="display: flex;align-items: center;">
 						<PersonalPhoto :name="row.name" :picture="row.picture" />
@@ -14,10 +18,24 @@
 				</template>
 				<template slot-scope="{ row }" slot="action">
 					<div style="display: flex;align-items: center;">
-						
+						<i-switch true-color="#13ce66"></i-switch>
 					</div>
 				</template>
 			</Table>
+			<div class="search-id-wrap" v-else>
+				<div class="id-search">
+					<Input v-model="searchIdVal" placeholder="搜索教师..." search @on-search="onIdSearch"/>
+					<p v-html="$t('teachermgmt.addTeacher.content')"></p>
+					<p v-if="curTeacher && curTeacher.id" class="search-result-text">搜索结果</p>
+					<div v-if="curTeacher && curTeacher.id" class="search-result-wrap">
+						<PersonalPhoto :name="curTeacher.name" :picture="curTeacher.picture" />
+						<p class="t-name">{{ curTeacher.name }}</p>
+						<p class="t-id">{{ curTeacher.id }}</p>
+					</div>
+					<p v-if="!curTeacher && hasSearchResult" class="search-none">暂未查询到相关结果</p>
+					<p v-if="hasSearchResult" class="re-search" @click="onReSearch">重新搜索</p>
+				</div>
+			</div>
 		</div>
 	</div>
 </template>
@@ -40,31 +58,54 @@
 		},
 		data() {
 			return {
+				isSchool:false,
+				hasSearchResult:false,
+				searchVal:'',
+				searchIdVal:'',
 				nodeInfo: {
 					title: ''
 				},
+				curTeacher:{
+					name:'',
+					picture:'',
+					id:'',
+					job:''
+				},
 				teacherCol: [{
-						title: '姓名',
+						title: this.$t('teachermgmt.table.th2'),
 						key: 'name',
 						slot: 'name'
 					},
 					{
-						title: '醍摩豆ID',
+						title: this.$t('teachermgmt.table.th1'),
 						key: 'id'
 					},
 					{
-						title: '权限',
-						key: 'size'
+					  title: this.$t('teachermgmt.table.th3'),
+					  key: 'job',
+					  render: (h, params) => {
+					    if (typeof params.row.job === 'undefined' || params.row.job == null || params.row.job === '') {
+					      return h('span', this.$t('teachermgmt.job.teacher'))
+					    } else {
+					      return h('span', params.row.job)
+					    }
+					  }
 					},
 					{
-						title: '操作',
-						slot:'action'
+						title: '是否共编',
+						key:'action',
+						slot: 'action'
 					}
 				],
-				teacherList: []
+				teacherList: [],
+				originList:[]
 			}
 		},
+		created() {
+			this.isSchool = this.$route.name === 'syllabus'
+		},
 		methods: {
+			/* 获取学校所有教师列表 */
 			getAllTeacher() {
 				this.$store.dispatch('user/getSchoolTeacher').then(
 					res => {
@@ -72,22 +113,52 @@
 							this.$Message.error('無法取得使用者資料')
 						} else {
 							this.teacherList = this.$store.state.user.schoolUserList.filter(i => i.status === 'join')
-							console.log(this.teacherList)
+							this.originList = JSON.parse(JSON.stringify(this.teacherList))
 						}
 					},
 					err => {
 						this.$Message.error('user/setSchoolTeacher API error!')
 					}
 				)
+			},
+			/* 搜索词汇发生变化 */
+			onSearchChange(){
+				this.teacherList = this.originList.filter(i => i.name.indexOf(this.searchVal) > -1 || i.id.indexOf(this.searchVal) > -1)
+			},
+			/* 关闭搜索 */
+			onCloseSearch(){
+				this.searchVal = ''
+				this.teacherList = JSON.parse(JSON.stringify(this.originList))
+			},
+			/* 根据ID邮箱手机号搜索教师信息 */
+			onIdSearch(){
+				this.$store.dispatch('user/getUserFromCoreId', [this.searchIdVal]).then(
+				    (res) => {
+				        if (res.code == 1) {
+				            this.curTeacher = res.data.length ? res.data[0] : null
+				        } else {
+				            this.$Message.error('user/getUserFromCoreId API error!')
+				        }
+						this.hasSearchResult = true
+				    },
+				    (err) => {
+				        this.$Message.error('user/getUserFromCoreId API error!')
+				    }
+				)
+			},
+			/* 重新搜索 */
+			onReSearch(){
+				this.searchIdVal = ''
+				this.curTeacher = null
+				this.hasSearchResult = false
 			}
 		},
 		mounted() {
-			this.getAllTeacher()
+			this.isSchool && this.getAllTeacher()
 		},
 		watch: {
 			node: {
 				handler(n, o) {
-					console.log('xxxxxxx', n)
 					if (n) {
 						this.nodeInfo = n
 					}
@@ -100,12 +171,113 @@
 
 <style lang="less" scoped src="./InviteTeacher.less"></style>
 <style lang="less">
-	.teacher-wrap {
-		.dark-iview-table .ivu-table td {
-			border-color: #494949;
-			color: #c4c4c4 !important;
+	.it-container{
+		.teacher-wrap {
+			.dark-iview-table .ivu-table td {
+				border-color: #494949;
+				color: #c4c4c4 !important;
+			}
 		}
 		
+		.search-wrap{
+			.ivu-input-wrapper{
+				width: 300px;
+				line-height: 35px;
+			}
+			.ivu-input{
+				background-color: #474747;
+				border-color: #515151;
+				font-size: 12px;
+				color: #ddd;
+				margin: 20px 0;
+				border-radius: 50px;
+				padding-left: 10px;
+				height: 35px;
+			}
+			
+			.ivu-input-icon{
+				line-height: 75px;
+			}
+		}
 		
+		.search-id-wrap{
+			margin-top: 20px;
+			color: #adadad;
+			.point{
+				color: #F1F1F1;
+				font-weight: bold;
+				font-size: 16px;
+				margin: 0 10px;
+			}
+			
+			.id-search{
+				height: 400px;
+				width: 100%;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				
+				.ivu-input-wrapper{
+					width: 500px;
+					line-height: 35px;
+				}
+				.ivu-input{
+					background-color: #474747;
+					border-color: #515151;
+					font-size: 14px;
+					color: #ddd;
+					margin: 20px 0;
+					border-radius: 50px;
+					padding-left: 20px;
+					height: 45px;
+				}
+				
+				.ivu-input-icon{
+					line-height: 86px;
+					margin-right: 10px;
+				}
+			}
+			
+			.search-result-text{
+				margin-top: 60px;
+				margin-bottom: 10px;
+			}
+			
+			.search-result-wrap{
+				background-color: #4e4e4e;
+				padding: 20px;
+				border-radius: 10px;
+				display: flex;
+				flex-direction: column;
+				justify-content: center;
+				align-items: center;
+				.avatar , .fakeAvatar{
+					width: 60px !important;
+					height: 60px !important;
+					border-radius: 50%;
+				}
+				.t-name{
+					color: #fff;
+					font-size: 16px;
+					font-weight: bold;
+					margin: 10px 0;
+				}
+			}
+			
+			.search-none{
+				color: #ff4f80;
+				font-size: 16px;
+				font-weight: bold;
+				margin-top: 80px;
+			}
+			
+			.re-search{
+				margin: 20px 0;
+				text-decoration: underline;
+				color: #FFFCFC;
+				font-size: 14px;
+				cursor: pointer;
+			}
+		}
 	}
 </style>

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

@@ -30,5 +30,10 @@ export default{
     verifySchool:'加入学校',
     toSchool:'加入学校>>>',
     schoolSuccess:'您已加入学校!',
-    hasJoin:'已加入'
+    hasJoin:'已加入',
+    myCourse:'我的課表',
+    tmwCus:'明日課程',
+    course:'課程:',
+    className:'班級:',
+    tmwNoCus:'明天沒有課程安排'
 }

+ 4 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/stuAccount.js

@@ -37,6 +37,9 @@ export default {
   delOk:'删除成功',
   isBottom:'已经到底了',
   edit:'修改',
+  adminClass:'行政班管理',
+  teachClass:'教學班管理',
+  stuMgt:'學生管理',
 
   // AddStudent.vue
   accountInfo: '账号资讯',
@@ -90,6 +93,7 @@ export default {
   idWarning:'警告:Excel 內账号重复!',
   gradeWarning:'警告:年级错误',
   setNoErr:"错误:座位号已在校內重复",
+  downloadText:'(下載名單模板)',
 
   // Authorization.vue
   authTitle: '服务授权管理',

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

@@ -1,11 +1,13 @@
 export default {
+    preview:'P',
+    title:'TEAM Model Cloud',
     loading:'加载中',
     menu:{
         school:'学校',
         private:'个人',
         noSchool1:'学校暂未购买服务',
         noSchool2:'暂未加入学校',
-        copyright:'©2021 Powered by 醍摩豆',
+        copyright:'©2021 HABOOK Group',
         schoolMgt:'学校管理',
         schoolRes:'校本资源',
         baseSetting:'基础设置',

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

@@ -52,6 +52,8 @@ export default {
   delBatchTips2:'请先选择需要删除的文件!',
   specialChart:'不能包含特殊字符',
   noData:'暂无数据',
-  uploadTo:'上传至:',
+  applyPd:'适用学段:',
+  applySub:'适用学科:',
+   applyGrade:'适用年级:',
   public:'公共资源'
 }

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

@@ -4,7 +4,7 @@
     comfirmUpd:'确认上传',
     cancelUpd:'取消上传',
     tips1:'* 上传相同名字的文件会自动覆盖',
-    tips2:'* 勾选',
+    tips2:'您可以为资源设置适用学段、学科和年级',
     tips3:'支持PPTX文档转换成HTEX教材',
     fileType1:'教材',
     fileType2:'图片',

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

@@ -30,5 +30,10 @@ export default{
     verifySchool:'暂未加入学校',
     toSchool:'加入学校>>>',
     schoolSuccess:'您已加入学校!',
-    hasJoin:'已加入'
+    hasJoin:'已加入',
+    myCourse:'我的课表',
+    tmwCus:'明日课程',
+    course:'课程:',
+    className:'班级:',
+    tmwNoCus:'明天没有课程安排'
 }

+ 2 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/index.js

@@ -32,6 +32,7 @@ import http from './http'
 import utils from './utils'
 import knowledge from './knowledge'
 import task from './task'
+import syllabus from './syllabus'
 export default {
   schoolBaseInfo,
   classMgmt,
@@ -67,6 +68,7 @@ export default {
   utils,
   knowledge,
   task,
+  syllabus,
   test: '测试',
   formConfigP: {
     input: '请输入',

+ 28 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/settings.js

@@ -44,6 +44,9 @@ export default {
 	status1:'已加入',
 	status2:'收到邀请',
 	status3:'申请中',
+	searchTip:'请输入<span>学校名称</span>或者<span>学校代码</span>进行搜索',
+	searchNone:'* 如未搜索到您想要的学校,可点击下方申请建立您的学校',
+	applyBtn:'申请建立学校',
 	openList: '开放平台应用列表',
 	openInfo: '应用信息',
 	openName: '应用名称',
@@ -75,4 +78,29 @@ export default {
 	copyModal2: "复制失败",
 	openModal1: "应用列表获取失败",
 	openModal2: "api列表获取失败",
+	applyForm:{
+		title:'申请建立AI智慧学校',
+		name:'学校/机构名称',
+		id:'学校/机构简码',
+		code:'学校/机构代码',
+		address:'学校/机构地址',
+		manager:'学校/机构负责人',
+		cellphone:'学校/机构联系电话',
+		content:'备注信息',
+		place1:'选择学校所在地区',
+		place2:'请输入学校详细地址',
+		place3:'请输入您的手机号,邮箱等联系方式',
+		place4:'可填写您的备注信息',
+		place5:'请输入管理员的称呼',
+		place6:'请选择学校所在地区',
+		submit:'提交申请',
+		submitSuc:'已成功提交申请!',
+		errTip1:'请选择正确的地区!',
+		errTip2:'请将信息填写完整!',
+		rule1:'学校名称不能为空',
+		rule2:'管理员信息不能为空',
+		rule3:'联系方式不能为空',
+		rule4:'学校地址不能为空',
+		applyTip:'* 提交申请后,将会于5个工作日内审核完毕,并通知申请人。'
+	}
 }

+ 4 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/stuAccount.js

@@ -37,6 +37,9 @@ export default {
   delOk:'删除成功',
   isBottom:'已经到底了',
   edit:'修改',
+  adminClass:'行政班管理',
+  teachClass:'教学班管理',
+  stuMgt:'学生管理',
 
   // AddStudent.vue
   accountInfo: '账号资讯',
@@ -90,6 +93,7 @@ export default {
   idWarning:'警告:Excel 內账号重复!',
   gradeWarning:'警告:年级错误',
   setNoErr:"错误:座位号已在校內重复",
+  downloadText:'(下载名单模板)',
 
   // Authorization.vue
   authTitle: '服务授权管理',

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

@@ -311,7 +311,9 @@ export default {
             exitWrongDe: "系统检测您尚未「结束练习」,如您选择「确定」,",
             exitWrongDes: "则目前作答将不保存,下次需重新练习",
             endPractice: "结束练习提示",
-            endPracticeDe: "您将离开错题练习页面",
+            endPracticeDe: "是否继续练习?",
+            endPracticeBtn1: "继续练习",
+            endPracticeBtn2: "结束练习",
             qNo: '题号:',
             correction: '正解',
             queNo: '题目:',

+ 61 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/syllabus.js

@@ -0,0 +1,61 @@
+export default{
+	praviteSyllabus:'个人课纲',
+	btnSave:'存储变更',
+	volumeList:'册别清单',
+	place1:'输入册别名称...',
+	syllabusMenu:'课纲目录',
+	relate:'关联资源',
+	addResource:'添加资源',
+	type1:'内容资源',
+	type2:'试题资源',
+	type3:'试卷资源',
+	type4:'本地文件',
+	type5:'超链接',
+	preview:'查看',
+	remove:'删除',
+	upload:'上传本地文件',
+	editVolume:'编辑册别',
+	addVolume:'新增册别',
+	grade:'年级',
+	semester:'学期',
+	name:'名称',
+	place2:'非必填,默认由年级+科目+学期组成...',
+	place3:'填写册别名称',
+	confirm:'确认',
+	addLink:'添加超链接',
+	linkName:'超链接标题',
+	linkUrl:'超链接地址',
+	chooseCoTeacher:'选择共编教师',
+	chooseShareTeacher:'选择分享教师',
+	score:'配分',
+	count:'题数',
+	deleteVolume:'删除册别',
+	deleteConfirm:'确认删除该册别?',
+	deleteSuc:'删除成功',
+	deleteFail:'删除失败',
+	uploadSuc:'上传成功',
+	removeConfirm:'确定要移除该资源吗?',
+	doSuc:'操作成功',
+	isExistVolume:'已存在相同册别',
+    tree:{
+		hasResource:'有关联资源',
+		edit:'编辑',
+		add:'添加',
+		remove:'删除',
+		coEdit:'共编该章节',
+		share:'分享该章节',
+		editTitle:'编辑节点',
+		addTitle:'新增节点',
+		parent:'父节点',
+		nodeName:'节点名称',
+		place1:'请输入节点名称...',
+		confirm:'确认',
+		removeTitle:'删除节点',
+		removeConfirm:'确认删除该节点?',
+		cancel:'取消',
+		removeSucTip:'删除成功',
+		nodeNameTip:'节点名称不能为空',
+		editSucTip:'编辑成功',
+		addSucTip:'添加成功',
+	}
+}

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

@@ -1,11 +1,13 @@
 export default {
+    preview:'预览',
+    title:'醍摩豆云平台',
     loading:'加载中',
     menu:{
         school:'学校',
         private:'个人',
         noSchool1:'学校暂未购买服务',
         noSchool2:'暂未加入学校',
-        copyright:'©2021 Powered by 醍摩豆',
+        copyright:'©2021 HABOOK Group',
         schoolMgt:'学校管理',
         schoolRes:'学校资源',
         baseSetting:'基础设置',

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

@@ -52,6 +52,8 @@ export default {
   delBatchTips2:'请先选择需要删除的文件!',
   specialChart:'不能包含特殊字符',
   noData:'暂无数据',
-  uploadTo:'上传至:',
+  applyPd:'适用学段:',
+  applySub:'适用学科:',
+  applyGrade:'适用年级:',
   public:'公共资源'
 }

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

@@ -39,7 +39,7 @@ export default {
 	condition8: '发布年份',
     // totalIndex.vue
     ti_title1: '基本数据统计',
-    ti_title2: '评测数据统计',
+    ti_title2: '学情分析',
     ti_title3: '学科对比统计',
     ti_title4: '年级优生率统计',
     ti_title5: '评测列表数据',

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

@@ -4,7 +4,7 @@
     comfirmUpd:'确认上传',
     cancelUpd:'取消上传',
     tips1:'* 上传相同名字的文件会自动覆盖',
-    tips2:'* 勾选',
+    tips2:'您可以为资源设置适用学段、学科和年级',
     tips3:'支持PPTX文档转换成HTEX教材',
     fileType1:'教材',
     fileType2:'图片',

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

@@ -30,5 +30,10 @@ export default {
     verifySchool:'加入學校',
     toSchool:'加入學校>>>',
     schoolSuccess:'您已加入學校! ',
-    hasJoin:'已加入'
+    hasJoin:'已加入',
+    myCourse:'我的課表',
+    tmwCus:'明日課程',
+    course:'課程:',
+    className:'班級:',
+    tmwNoCus:'明天沒有課程安排'
 }

+ 2 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/index.js

@@ -32,6 +32,7 @@ import http from './http'
 import utils from './utils'
 import knowledge from './knowledge'
 import task from './task'
+import syllabus from './syllabus'
 export default {
   
   schoolBaseInfo,
@@ -68,6 +69,7 @@ export default {
   utils,
   knowledge,
   task,
+  syllabus,
   test: '測試',
   formConfigP: {
     input: '請輸入',

+ 35 - 7
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/settings.js

@@ -12,10 +12,10 @@ export default {
 	menuTips: '選擇左側Menu在網站載入時的預設顯示模式',
 	menuOpen: '預設展開顯示',
 	menuClose: '預設關閉顯示',
-	logoSetting:'Logo顯示設定',
-	logoTips:'選擇是否隱藏左上角平臺Logo',
-	logoOpen:'預設顯示',
-	logoHide:'預設隱藏',
+	logoSetting: 'Logo顯示設定',
+	logoTips: '選擇是否隱藏左上角平臺Logo',
+	logoOpen: '預設顯示',
+	logoHide: '預設隱藏',
 	defaultSchool: '預設學校',
 	curSchool: '當前學校',
 	courseNum: '課程數',
@@ -24,8 +24,8 @@ export default {
 	requestStatus: '送出加入邀請',
 	goSchool: '前往學校',
 	agreeJoin: '同意加入',
-	cancelAdd:'拒絕加入',
-	undoJoin:'撤銷申請',
+	cancelAdd: '拒絕加入',
+	undoJoin: '撤銷申請',
 	requestJoin: '申請加入',
 	inputSearch: '輸入要檢索的學校名稱',
 	modalTip1: '注意',
@@ -37,13 +37,16 @@ export default {
 	columnTool: '操作',
 	modalTip4: '溫馨提示',
 	modalTip5: '確認加入',
-	modalTip6:'確認取消加入',
+	modalTip6: '確認取消加入',
 	submitSucTips: '提交成功',
 	submitFailTips: '操作失敗',
 	joinSucTips: '加入成功!',
 	status1: '已加入',
 	status2: '收到邀請',
 	status3: '申請中',
+	searchTip:'請輸入<span>學校名稱</span>或者<span>學校程式碼</span>進行搜尋',
+	searchNone:'*如未搜尋到您想要的學校,可點擊下方申請建立您的學校',
+	applyBtn:'申請建立學校',
 	openList: '開放平臺清單',
 	openInfo: '平臺資訊',
 	openName: '應用名稱',
@@ -57,6 +60,31 @@ export default {
 	apiMethod: '請求方法',
 	openKeep: '儲存平臺',
 	unedit: '取消編輯',
+	applyForm:{
+	title:'申請建立AI智慧學校',
+	name:'學校/機構名稱',
+	id:'學校/機构簡碼',
+	code:'學校/機构程式碼',
+	address:'學校/機构地址',
+	manager:'學校/機构負責人',
+	cellphone:'學校/機构聯繫電話',
+	content:'備註資訊',
+	place1:'選擇學校所在地區',
+	place2:'請輸入學校詳細地址',
+	place3:'請輸入您的手機號,郵箱等聯繫方式',
+	place4:'可填寫您的備註資訊',
+	place5:'請輸入管理員的稱呼',
+	place6:'請選擇學校所在地區',
+	submit:'提交申請',
+	submitSuc:'已成功提交申請!',
+	errTip1:'請選擇正確的地區!',
+	errTip2:'請將資訊填寫完整!',
+	rule1:'學校名稱不能為空',
+	rule2:'管理員資訊不能為空',
+	rule3:'聯繫方式不能為空',
+	rule4:'學校地址不能為空',
+	applyTip:'*提交申請後,將會於5個工作日內稽核完畢,並通知申請人。'
+	}
 	delModal1: '您確定刪除',
 	delModal2: '嗎?',
 	delModal3: '刪除成功',

+ 4 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/stuAccount.js

@@ -37,6 +37,9 @@ export default {
   delOk: '刪除成功',
   isBottom: '已經到底了',
   edit:'修改',
+  adminClass:'行政班管理',
+  teachClass:'教學班管理',
+  stuMgt:'學生管理',
 
   //AddStudent.vue
   accountInfo: '帳號資訊',
@@ -90,6 +93,7 @@ export default {
   idWarning:'警告:Excel 內帳號重複! ',
   gradeWarning:'警告:年級錯誤',
   setNoErr:"錯誤:座位號已在校內重複",
+  downloadText:'(下載名單模板)',
 
   //Authorization.vue
   authTitle: '服務授權管理',

+ 61 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/syllabus.js

@@ -0,0 +1,61 @@
+export default {
+	praviteSyllabus: '個人課綱',
+	btnSave: '存儲變更',
+	volumeList: '册別清單',
+	place1: '輸入册別名稱…',
+	syllabusMenu: '課綱目錄',
+	relate: '關聯資源',
+	addResource: '添加資源',
+	type1: '內容資源',
+	type2: '試題資源',
+	type3: '試卷資源',
+	type4: '本地檔案',
+	type5: '超連結',
+	preview: '查看',
+	remove: '删除',
+	upload: '上傳本地檔案',
+	editVolume: '編輯册別',
+	addVolume: '新增册別',
+	grade: '年級',
+	semester: '學期',
+	name: '名稱',
+	place2: '非必填,默認由年級+科目+學期組成…',
+	place3: '填寫册別名稱',
+	confirm: '確認',
+	addLink: '添加超連結',
+	linkName: '超連結標題',
+	linkUrl: '超連結地址',
+	chooseCoTeacher: '選擇共編教師',
+	chooseShareTeacher: '選擇分享教師',
+	score: '配分',
+	count: '題數',
+	deleteVolume: '删除册別',
+	deleteConfirm: '確認删除該册別?',
+	deleteSuc: '删除成功',
+	deleteFail: '删除失敗',
+	uploadSuc: '上傳成功',
+	removeConfirm: '確定要移除該資源嗎?',
+	doSuc: '操作成功',
+	isExistVolume: '已存在相同册別',
+	tree: {
+		hasResource: '有關聯資源',
+		edit: '編輯',
+		add: '添加',
+		remove: '删除',
+		coEdit: '共編該章節',
+		share: '分享該章節',
+		editTitle: '編輯節點',
+		addTitle: '新增節點',
+		parent: '父節點',
+		nodeName: '節點名稱',
+		place1: '請輸入節點名稱…',
+		confirm: '確認',
+		removeTitle: '删除節點',
+		removeConfirm: '確認删除該節點?',
+		cancel: '取消',
+		removeSucTip: '删除成功',
+		nodeNameTip: '節點名稱不能為空',
+		editSucTip: '編輯成功',
+		addSucTip: '添加成功',
+	}
+}

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

@@ -1,11 +1,13 @@
 export default {
+    preview:'預覽',
+    title:'醍摩豆雲平台',
     loading: '加載中',
     menu: {
         school: '學校',
         private: '個人',
         noSchool1: '學校暫未購買服務',
         noSchool2: '暫未加入學校',
-        copyright: '©2021 Powered by醍摩豆',
+        copyright:'©2021 HABOOK Group',
         schoolMgt: '學校管理',
         schoolRes: '學校資源',
         baseSetting: '基礎設定',

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

@@ -52,6 +52,8 @@ export default {
   delBatchTips2: '請先選擇需要刪除的檔案!',
   specialChart: '不能包含特殊字元',
   noData: '暫無資料',
-  uploadTo:'上傳至:',
+  applyPd:'適用學段:',
+  applySub:'適用學科:',
+  applyGrade:'適用年級:',
   public:'公共資源'
 }

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

@@ -4,7 +4,7 @@
     comfirmUpd:'確認上傳',
     cancelUpd:'取消上傳',
     tips1:'*上傳相同名字的檔案會自動覆蓋',
-    tips2:'*勾選',
+    tips2:'您可以为资源设置适用学段、学科和年级',
     tips3:'支援PPTX檔案轉換成HTEX教材',
     fileType1:'教材',
     fileType2:'圖片',

+ 992 - 0
TEAMModelOS/ClientApp/src/static/countries.js

@@ -0,0 +1,992 @@
+export default [
+    {
+        "en": "Angola",
+        "cn": "安哥拉",
+        "code": "+244"
+    },
+    {
+        "en": "Afghanistan",
+        "cn": "阿富汗",
+        "code": "+93"
+    },
+    {
+        "en": "Alaska(U.S.A)",
+        "cn": "阿拉斯加",
+        "code": "+1907"
+    },
+    {
+        "en": "Albania",
+        "cn": "阿尔巴尼亚",
+        "code": "+335"
+    },
+    {
+        "en": "Algeria",
+        "cn": "阿尔及利亚",
+        "code": "+213"
+    },
+    {
+        "en": "Andorra",
+        "cn": "安道尔共和国",
+        "code": "+376"
+    },
+    {
+        "en": "Anguilla",
+        "cn": "安圭拉岛",
+        "code": "+1254"
+    },
+    {
+        "en": "Antigua and Barbuda",
+        "cn": "安提瓜和巴布达",
+        "code": "+1268"
+    },
+    {
+        "en": "Argentina",
+        "cn": "阿根廷",
+        "code": "+54"
+    },
+    {
+        "en": "Armenia",
+        "cn": "亚美尼亚",
+        "code": "+374"
+    },
+    {
+        "en": "Aruba",
+        "cn": "阿鲁巴岛",
+        "code": "+297"
+    },
+    {
+        "en": "Ascension",
+        "cn": "阿森松",
+        "code": "+247"
+    },
+    {
+        "en": "Australia",
+        "cn": "澳大利亚",
+        "code": "+61"
+    },
+    {
+        "en": "Austria",
+        "cn": "奥地利",
+        "code": "+43"
+    },
+    {
+        "en": "Azerbaijan",
+        "cn": "阿塞拜疆",
+        "code": "+994"
+    },
+    {
+        "en": "Bahamas",
+        "cn": "巴哈马",
+        "code": "+1242"
+    },
+    {
+        "en": "Bahrain",
+        "cn": "巴林",
+        "code": "+973"
+    },
+    {
+        "en": "Bangladesh",
+        "cn": "孟加拉国",
+        "code": "+880"
+    },
+    {
+        "en": "Barbados",
+        "cn": "巴巴多斯",
+        "code": "+1246"
+    },
+    {
+        "en": "Belarus",
+        "cn": "白俄罗斯",
+        "code": "+375"
+    },
+    {
+        "en": "Belgium",
+        "cn": "比利时",
+        "code": "+32"
+    },
+    {
+        "en": "Belize",
+        "cn": "伯利兹",
+        "code": "+501"
+    },
+    {
+        "en": "Benin",
+        "cn": "贝宁",
+        "code": "+229"
+    },
+    {
+        "en": "Bermuda Is",
+        "cn": "百慕大群岛",
+        "code": "+1441"
+    },
+    {
+        "en": "Bhutan",
+        "cn": "不丹",
+        "code": "+975"
+    },
+    {
+        "en": "Bolivia",
+        "cn": "玻利维亚",
+        "code": "+591"
+    },
+    {
+        "en": "Bosnia And Herzegovina",
+        "cn": "波斯尼亚和黑塞哥维那",
+        "code": "+387"
+    },
+    {
+        "en": "Botswana",
+        "cn": "博茨瓦纳",
+        "code": "+267"
+    },
+    {
+        "en": "Brazil",
+        "cn": "巴西",
+        "code": "+55"
+    },
+    {
+        "en": "Brunei",
+        "cn": "文莱",
+        "code": "+673"
+    },
+    {
+        "en": "Bulgaria",
+        "cn": "保加利亚",
+        "code": "+359"
+    },
+    {
+        "en": "Burkina Faso",
+        "cn": "布基纳法索",
+        "code": "+226"
+    },
+    {
+        "en": "Burma",
+        "cn": "缅甸",
+        "code": "+95"
+    },
+    {
+        "en": "Burundi",
+        "cn": "布隆迪",
+        "code": "+257"
+    },
+    {
+        "en": "Cameroon",
+        "cn": "喀麦隆",
+        "code": "+237"
+    },
+    {
+        "en": "Canada",
+        "cn": "加拿大",
+        "code": "+1"
+    },
+    {
+        "en": "Cape Verde",
+        "cn": "佛得角",
+        "code": "+238"
+    },
+    {
+        "en": "Cayman Is",
+        "cn": "开曼群岛",
+        "code": "+1345"
+    },
+    {
+        "en": "Central African Republic",
+        "cn": "中非共和国",
+        "code": "+236"
+    },
+    {
+        "en": "Chad",
+        "cn": "乍得",
+        "code": "+235"
+    },
+    {
+        "en": "Chile",
+        "cn": "智利",
+        "code": "+56"
+    },
+    {
+        "en": "China",
+        "cn": "中国",
+        "code": "+86"
+    },
+    {
+        "en": "Colombia",
+        "cn": "哥伦比亚",
+        "code": "+57"
+    },
+    {
+        "en": "Congo",
+        "cn": "刚果",
+        "code": "+242"
+    },
+    {
+        "en": "Cook Is",
+        "cn": "库克群岛",
+        "code": "+682"
+    },
+    {
+        "en": "Costa Rica",
+        "cn": "哥斯达黎加",
+        "code": "+506"
+    },
+    {
+        "en": "Cuba",
+        "cn": "古巴",
+        "code": "+53"
+    },
+    {
+        "en": "Cyprus",
+        "cn": "塞浦路斯",
+        "code": "+357"
+    },
+    {
+        "en": "Czech Republic",
+        "cn": "捷克",
+        "code": "+420"
+    },
+    {
+        "en": "Republic of Croatia",
+        "cn": "克罗地亚共和国",
+        "code": "+385"
+    },
+    {
+        "en": "Denmark",
+        "cn": "丹麦",
+        "code": "+45"
+    },
+    {
+        "en": "Djibouti",
+        "cn": "吉布提",
+        "code": "+253"
+    },
+    {
+        "en": "Dominica Rep",
+        "cn": "多米尼加共和国",
+        "code": "+1890"
+    },
+    {
+        "en": "Ecuador",
+        "cn": "厄瓜多尔",
+        "code": "+593"
+    },
+    {
+        "en": "Egypt",
+        "cn": "埃及",
+        "code": "+20"
+    },
+    {
+        "en": "EI Salvador",
+        "cn": "萨尔瓦多",
+        "code": "+503"
+    },
+    {
+        "en": "Estonia",
+        "cn": "爱沙尼亚",
+        "code": "+372"
+    },
+    {
+        "en": "Ethiopia",
+        "cn": "埃塞俄比亚",
+        "code": "+251"
+    },
+    {
+        "en": "Fiji",
+        "cn": "斐济",
+        "code": "+679"
+    },
+    {
+        "en": "Finland",
+        "cn": "芬兰",
+        "code": "+358"
+    },
+    {
+        "en": "France",
+        "cn": "法国",
+        "code": "+33"
+    },
+    {
+        "en": "French Guiana",
+        "cn": "法属圭亚那",
+        "code": "+594"
+    },
+    {
+        "en": "French Polynesia",
+        "cn": "法属玻利尼西亚",
+        "code": "+689"
+    },
+    {
+        "en": "Gabon",
+        "cn": "加蓬",
+        "code": "+241"
+    },
+    {
+        "en": "Gambia",
+        "cn": "冈比亚",
+        "code": "+220"
+    },
+    {
+        "en": "Georgia",
+        "cn": "格鲁吉亚",
+        "code": "+995"
+    },
+    {
+        "en": "Germany",
+        "cn": "德国",
+        "code": "+49"
+    },
+    {
+        "en": "Ghana",
+        "cn": "加纳",
+        "code": "+233"
+    },
+    {
+        "en": "Gibraltar",
+        "cn": "直布罗陀",
+        "code": "+350"
+    },
+    {
+        "en": "Greece",
+        "cn": "希腊",
+        "code": "+30"
+    },
+    {
+        "en": "Grenada",
+        "cn": "格林纳达",
+        "code": "+1809"
+    },
+    {
+        "en": "Guam",
+        "cn": "关岛",
+        "code": "+1671"
+    },
+    {
+        "en": "Guatemala",
+        "cn": "危地马拉",
+        "code": "+502"
+    },
+    {
+        "en": "Guinea",
+        "cn": "几内亚",
+        "code": "+224"
+    },
+    {
+        "en": "Guyana",
+        "cn": "圭亚那",
+        "code": "+592"
+    },
+    {
+        "en": "Haiti",
+        "cn": "海地",
+        "code": "+509"
+    },
+    {
+        "en": "Honduras",
+        "cn": "洪都拉斯",
+        "code": "+504"
+    },
+    {
+        "en": "Hongkong",
+        "cn": "香港特别行政区",
+        "code": "+852"
+    },
+    {
+        "en": "Hungary",
+        "cn": "匈牙利",
+        "code": "+36"
+    },
+    {
+        "en": "Iceland",
+        "cn": "冰岛",
+        "code": "+354"
+    },
+    {
+        "en": "India",
+        "cn": "印度",
+        "code": "+91"
+    },
+    {
+        "en": "Indonesia",
+        "cn": "印度尼西亚",
+        "code": "+62"
+    },
+    {
+        "en": "Iran",
+        "cn": "伊朗",
+        "code": "+98"
+    },
+    {
+        "en": "Iraq",
+        "cn": "伊拉克",
+        "code": "+964"
+    },
+    {
+        "en": "Ireland",
+        "cn": "爱尔兰",
+        "code": "+353"
+    },
+    {
+        "en": "Israel",
+        "cn": "以色列",
+        "code": "+972"
+    },
+    {
+        "en": "Italy",
+        "cn": "意大利",
+        "code": "+39"
+    },
+    {
+        "en": "Ivory Coast",
+        "cn": "科特迪瓦",
+        "code": "+225"
+    },
+    {
+        "en": "Jamaica",
+        "cn": "牙买加",
+        "code": "+1876"
+    },
+    {
+        "en": "Japan",
+        "cn": "日本",
+        "code": "+81"
+    },
+    {
+        "en": "Jordan",
+        "cn": "约旦",
+        "code": "+962"
+    },
+    {
+        "en": "Kampuchea (Cambodia )",
+        "cn": "柬埔寨",
+        "code": "+855"
+    },
+    {
+        "en": "Kazakstan",
+        "cn": "哈萨克斯坦",
+        "code": "+327"
+    },
+    {
+        "en": "Kenya",
+        "cn": "肯尼亚",
+        "code": "+254"
+    },
+    {
+        "en": "Korea",
+        "cn": "韩国",
+        "code": "+82"
+    },
+    {
+        "en": "Kuwait",
+        "cn": "科威特",
+        "code": "+965"
+    },
+    {
+        "en": "Kyrgyzstan",
+        "cn": "吉尔吉斯坦",
+        "code": "+331"
+    },
+    {
+        "en": "Laos",
+        "cn": "老挝",
+        "code": "+856"
+    },
+    {
+        "en": "Latvia",
+        "cn": "拉脱维亚",
+        "code": "+371"
+    },
+    {
+        "en": "Lebanon",
+        "cn": "黎巴嫩",
+        "code": "+961"
+    },
+    {
+        "en": "Lesotho",
+        "cn": "莱索托",
+        "code": "+266"
+    },
+    {
+        "en": "Liberia",
+        "cn": "利比里亚",
+        "code": "+231"
+    },
+    {
+        "en": "Libya",
+        "cn": "利比亚",
+        "code": "+218"
+    },
+    {
+        "en": "Liechtenstein",
+        "cn": "列支敦士登",
+        "code": "+423"
+    },
+    {
+        "en": "Lithuania",
+        "cn": "立陶宛",
+        "code": "+370"
+    },
+    {
+        "en": "Luxembourg",
+        "cn": "卢森堡",
+        "code": "+352"
+    },
+    {
+        "en": "Macao",
+        "cn": "澳门特别行政区",
+        "code": "+853"
+    },
+    {
+        "en": "Madagascar",
+        "cn": "马达加斯加",
+        "code": "+261"
+    },
+    {
+        "en": "Malawi",
+        "cn": "马拉维",
+        "code": "+265"
+    },
+    {
+        "en": "Malaysia",
+        "cn": "马来西亚",
+        "code": "+60"
+    },
+    {
+        "en": "Maldives",
+        "cn": "马尔代夫",
+        "code": "+960"
+    },
+    {
+        "en": "Mali",
+        "cn": "马里",
+        "code": "+223"
+    },
+    {
+        "en": "Malta",
+        "cn": "马耳他",
+        "code": "+356"
+    },
+    {
+        "en": "Mariana Is",
+        "cn": "马里亚那群岛",
+        "code": "+1670"
+    },
+    {
+        "en": "Martinique",
+        "cn": "马提尼克",
+        "code": "+596"
+    },
+    {
+        "en": "Mauritius",
+        "cn": "毛里求斯",
+        "code": "+230"
+    },
+    {
+        "en": "Mexico",
+        "cn": "墨西哥",
+        "code": "+52"
+    },
+    {
+        "en": "Moldova",
+        "cn": "摩尔多瓦",
+        "code": "+373"
+    },
+    {
+        "en": "Monaco",
+        "cn": "摩纳哥",
+        "code": "+377"
+    },
+    {
+        "en": "Mongolia",
+        "cn": "蒙古",
+        "code": "+976"
+    },
+    {
+        "en": "Montserrat Is",
+        "cn": "蒙特塞拉特岛",
+        "code": "+1664"
+    },
+    {
+        "en": "Morocco",
+        "cn": "摩洛哥",
+        "code": "+212"
+    },
+    {
+        "en": "Mozambique",
+        "cn": "莫桑比克",
+        "code": "+258"
+    },
+    {
+        "en": "Namibia",
+        "cn": "纳米比亚",
+        "code": "+264"
+    },
+    {
+        "en": "Nauru",
+        "cn": "瑙鲁",
+        "code": "+674"
+    },
+    {
+        "en": "Nepal",
+        "cn": "尼泊尔",
+        "code": "+977"
+    },
+    {
+        "en": "Netheriands Antilles",
+        "cn": "荷属安的列斯",
+        "code": "+599"
+    },
+    {
+        "en": "Netherlands",
+        "cn": "荷兰",
+        "code": "+31"
+    },
+    {
+        "en": "New Zealand",
+        "cn": "新西兰",
+        "code": "+64"
+    },
+    {
+        "en": "Nicaragua",
+        "cn": "尼加拉瓜",
+        "code": "+505"
+    },
+    {
+        "en": "Niger",
+        "cn": "尼日尔",
+        "code": "+227"
+    },
+    {
+        "en": "Nigeria",
+        "cn": "尼日利亚",
+        "code": "+234"
+    },
+    {
+        "en": "North Korea",
+        "cn": "朝鲜",
+        "code": "+850"
+    },
+    {
+        "en": "Norway",
+        "cn": "挪威",
+        "code": "+47"
+    },
+    {
+        "en": "Oman",
+        "cn": "阿曼",
+        "code": "+968"
+    },
+    {
+        "en": "Pakistan",
+        "cn": "巴基斯坦",
+        "code": "+92"
+    },
+    {
+        "en": "Panama",
+        "cn": "巴拿马",
+        "code": "+507"
+    },
+    {
+        "en": "Papua New Cuinea",
+        "cn": "巴布亚新几内亚",
+        "code": "+675"
+    },
+    {
+        "en": "Paraguay",
+        "cn": "巴拉圭",
+        "code": "+595"
+    },
+    {
+        "en": "Peru",
+        "cn": "秘鲁",
+        "code": "+51"
+    },
+    {
+        "en": "Philippines",
+        "cn": "菲律宾",
+        "code": "+63"
+    },
+    {
+        "en": "Poland",
+        "cn": "波兰",
+        "code": "+48"
+    },
+    {
+        "en": "Portugal",
+        "cn": "葡萄牙",
+        "code": "+351"
+    },
+    {
+        "en": "Puerto Rico",
+        "cn": "波多黎各",
+        "code": "+1787"
+    },
+    {
+        "en": "Qatar",
+        "cn": "卡塔尔",
+        "code": "+974"
+    },
+    {
+        "en": "Reunion",
+        "cn": "留尼旺",
+        "code": "+262"
+    },
+    {
+        "en": "Romania",
+        "cn": "罗马尼亚",
+        "code": "+40"
+    },
+    {
+        "en": "Russia",
+        "cn": "俄罗斯",
+        "code": "+7"
+    },
+    {
+        "en": "Saint Lueia",
+        "cn": "圣卢西亚",
+        "code": "+1758"
+    },
+    {
+        "en": "Saint Vincent",
+        "cn": "圣文森特岛",
+        "code": "+1784"
+    },
+    {
+        "en": "Samoa Eastern",
+        "cn": "东萨摩亚(美)",
+        "code": "+684"
+    },
+    {
+        "en": "Samoa Western",
+        "cn": "西萨摩亚",
+        "code": "+685"
+    },
+    {
+        "en": "San Marino",
+        "cn": "圣马力诺",
+        "code": "+378"
+    },
+    {
+        "en": "Sao Tome and Principe",
+        "cn": "圣多美和普林西比",
+        "code": "+239"
+    },
+    {
+        "en": "Saudi Arabia",
+        "cn": "沙特阿拉伯",
+        "code": "+966"
+    },
+    {
+        "en": "Senegal",
+        "cn": "塞内加尔",
+        "code": "+221"
+    },
+    {
+        "en": "Seychelles",
+        "cn": "塞舌尔",
+        "code": "+248"
+    },
+    {
+        "en": "Sierra Leone",
+        "cn": "塞拉利昂",
+        "code": "+232"
+    },
+    {
+        "en": "Singapore",
+        "cn": "新加坡",
+        "code": "+65"
+    },
+    {
+        "en": "Slovakia",
+        "cn": "斯洛伐克",
+        "code": "+421"
+    },
+    {
+        "en": "Slovenia",
+        "cn": "斯洛文尼亚",
+        "code": "+386"
+    },
+    {
+        "en": "Solomon Is",
+        "cn": "所罗门群岛",
+        "code": "+677"
+    },
+    {
+        "en": "Somali",
+        "cn": "索马里",
+        "code": "+252"
+    },
+    {
+        "en": "South Africa",
+        "cn": "南非",
+        "code": "+27"
+    },
+    {
+        "en": "Spain",
+        "cn": "西班牙",
+        "code": "+34"
+    },
+    {
+        "en": "SriLanka",
+        "cn": "斯里兰卡",
+        "code": "+94"
+    },
+    {
+        "en": "St.Lucia",
+        "cn": "圣卢西亚",
+        "code": "+1758"
+    },
+    {
+        "en": "St.Vincent",
+        "cn": "圣文森特",
+        "code": "+1784"
+    },
+    {
+        "en": "Sudan",
+        "cn": "苏丹",
+        "code": "+249"
+    },
+    {
+        "en": "Suriname",
+        "cn": "苏里南",
+        "code": "+597"
+    },
+    {
+        "en": "Swaziland",
+        "cn": "斯威士兰",
+        "code": "+268"
+    },
+    {
+        "en": "Sweden",
+        "cn": "瑞典",
+        "code": "+46"
+    },
+    {
+        "en": "Switzerland",
+        "cn": "瑞士",
+        "code": "+41"
+    },
+    {
+        "en": "Syria",
+        "cn": "叙利亚",
+        "code": "+963"
+    },
+    {
+        "en": "Taiwan",
+        "cn": "台湾",
+        "code": "+886"
+    },
+    {
+        "en": "Tajikstan",
+        "cn": "塔吉克斯坦",
+        "code": "+992"
+    },
+    {
+        "en": "Tanzania",
+        "cn": "坦桑尼亚",
+        "code": "+255"
+    },
+    {
+        "en": "Thailand",
+        "cn": "泰国",
+        "code": "+66"
+    },
+    {
+        "en": "Togo",
+        "cn": "多哥",
+        "code": "+228"
+    },
+    {
+        "en": "Tonga",
+        "cn": "汤加",
+        "code": "+676"
+    },
+    {
+        "en": "Trinidad and Tobago",
+        "cn": "特立尼达和多巴哥",
+        "code": "+1809"
+    },
+    {
+        "en": "Tunisia",
+        "cn": "突尼斯",
+        "code": "+216"
+    },
+    {
+        "en": "Turkey",
+        "cn": "土耳其",
+        "code": "+90"
+    },
+    {
+        "en": "Turkmenistan",
+        "cn": "土库曼斯坦",
+        "code": "+993"
+    },
+    {
+        "en": "Uganda",
+        "cn": "乌干达",
+        "code": "+256"
+    },
+    {
+        "en": "Ukraine",
+        "cn": "乌克兰",
+        "code": "+380"
+    },
+    {
+        "en": "United Arab Emirates",
+        "cn": "阿拉伯联合酋长国",
+        "code": "+971"
+    },
+    {
+        "en": "United Kiongdom",
+        "cn": "英国",
+        "code": "+44"
+    },
+    {
+        "en": "United States of America",
+        "cn": "美国",
+        "code": "+1"
+    },
+    {
+        "en": "Uruguay",
+        "cn": "乌拉圭",
+        "code": "+598"
+    },
+    {
+        "en": "Uzbekistan",
+        "cn": "乌兹别克斯坦",
+        "code": "+233"
+    },
+    {
+        "en": "Venezuela",
+        "cn": "委内瑞拉",
+        "code": "+58"
+    },
+    {
+        "en": "Vietnam",
+        "cn": "越南",
+        "code": "+84"
+    },
+    {
+        "en": "Yemen",
+        "cn": "也门",
+        "code": "+967"
+    },
+    {
+        "en": "Yugoslavia",
+        "cn": "南斯拉夫",
+        "code": "+381"
+    },
+    {
+        "en": "Zimbabwe",
+        "cn": "津巴布韦",
+        "code": "+263"
+    },
+    {
+        "en": "Zaire",
+        "cn": "扎伊尔",
+        "code": "+243"
+    },
+    {
+        "en": "Zambia",
+        "cn": "赞比亚",
+        "code": "+260"
+    }
+]

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

@@ -17,7 +17,7 @@ export default {
     spaceStatus: undefined,
     serviceIntroIsOpen: [],
     hiteachListItemIsOpen: [], //存放每個開關
-    currentTab:0,//0 服務清單, 1 hiteach 清單
+    currentTab:1,//0 服務清單, 1 hiteach 清單
 
     //接實際api使用,一開始序號為空
 

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

@@ -17,7 +17,7 @@ export default {
     //定義狀態
     state: {
         lang: "zh-TW", //存放
-        sideBarIsOpen: true, //存放側邊欄是否開合
+        sideBarIsOpen: true, //存放側邊欄
         userInfo: {
             name: '',
             studentId: '',

+ 0 - 47
TEAMModelOS/ClientApp/src/utils/html2pdf.js

@@ -4,14 +4,8 @@ import store from '@/store'
 import domtoimage from './dom_to_image';
 export default {
     install(Vue, options) {
-        Vue.prototype.getPdfByImg = () => {
-
-        }
-
         Vue.prototype.getPdf = () => {
 			return new Promise((r,j) => {
-				
-			
             var title = store.state.answerSheet.paperItem.name
             setTimeout(() => {
                 domtoimage.toJpeg(document.querySelector('#pdfDom'), { bgcolor: '#fff', scale: 4 })
@@ -55,52 +49,11 @@ export default {
                             PDF.save(title + '.pdf')
 							r(200)
                         }
-
                     })
                     .catch(function (error) {
                         console.error('oops, something went wrong!', error);
 						j(error)
                     });
-
-                // html2canvas( document.querySelector('#pdfDom'), {
-                //     allowTaint: true,  //允许 canvas 污染, allowTaint参数要去掉,否则是无法通过toDataURL导出canvas数据的
-                //     useCORS:true  //允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
-                // } ).then( (canvas)=>{
-                //     var contentWidth = canvas.width;
-                //     var contentHeight = canvas.height;
-                //     console.log(contentWidth)
-                //     console.log(contentHeight)
-                //     //一页pdf显示html页面生成的canvas高度;
-                //     var pageHeight = contentWidth / 592.28 * 841.89;
-                //     //未生成pdf的html页面高度
-                //     var leftHeight = contentHeight;
-                //     //页面偏移
-                //     var position = 0;
-                //     //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
-                //     var imgWidth = 595.28;
-                //     var imgHeight = 595.28/contentWidth * contentHeight;
-                //     var pageData = canvas.toDataURL('image/jpeg', 1.0);
-                //     var pdf = new JsPDF('', 'pt', 'a4');
-                //     //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
-                //     //当内容未超过pdf一页显示的范围,无需分页
-                //     if (leftHeight < pageHeight) {
-                //         //在pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置在pdf中显示;
-                //         pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
-                //         // pdf.addImage(pageData, 'JPEG', 20, 40, imgWidth, imgHeight);
-                //     } else {    // 分页
-                //         while(leftHeight > 0) {
-                //             pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
-                //             leftHeight -= pageHeight;
-                //             position -= 841.89;
-                //             //避免添加空白页
-                //             if(leftHeight > 0) {
-                //                 pdf.addPage();
-                //             }
-                //         }
-                //     }
-                //     //可动态生成
-                //     pdf.save(title + '.pdf')
-                // })
             }, 1000)
 			})
 		}

+ 10 - 21
TEAMModelOS/ClientApp/src/view/Home.vue

@@ -5,7 +5,7 @@
             <!-- 头部右侧个人中心部分 -->
             <div class="header-right-box fl-around" slot="header-content">
                 <Icon custom="iconfont icon-home" :color="routerName == 'homePage' ? '#1CC0F3':'#d0d0d0'" @click="toHome" />
-                <BaseNotification></BaseNotification>
+                <BaseNotification :msgs="msgs"></BaseNotification>
                 <Icon type="ios-settings" :color="routerName == 'settings' ? '#1CC0F3':'#d0d0d0'" @click="toSettings" />
                 <!-- 问题答疑页面暂未开发 暂时注释 -->
                 <!-- <Icon type="md-help-circle" :color="routerName == 'feedback' ? '#1CC0F3':'#d0d0d0'" @click="toFeedback"/> -->
@@ -26,11 +26,9 @@ export default {
     name: 'headers',
     props: ['parentToChild', 'identityselect'],
     components: {},
-    computed: {
-
-    },
     data() {
         return {
+			msgs:[],
             isShowMock: false,
             isOpenDrawer: false,
             routerName: '',
@@ -38,17 +36,6 @@ export default {
         }
     },
     created() {
-        //刷新重置vuex
-        console.log('进入大云...')
-        console.log(this.$store)
-
-        //  window.addEventListener('beforeunload',() => {
-        //     if(this.$store.state.user.school_profile.school_base){
-        //         schoolStr = encodeURIComponent(JSON.stringify(this.$store.state.user.school_profile.school_base), "utf-8")
-        //         localStorage.setItem('school_profile', schoolStr)
-        //     }
-        // })
-
         let user = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"))
         let user_profile = JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"))
         if (user_profile.schools) {
@@ -71,7 +58,14 @@ export default {
                 schoolCode: this.$GLOBAL.DEFAULT_SCHOOL_CODE
             })
         }
-
+		
+		this.$api.service.getNotification({
+			"from":"ies5:" + user_profile.defaultschool || user_profile.schools[0].schoolId,
+			"receiver": user.id
+		}).then(res => {
+			console.log('端外通知',res)
+			this.msgs = res.msgs
+		})
 
 
     },
@@ -90,11 +84,6 @@ export default {
         },
         basicMenu(name) {
             if (name == 'quit') {
-                //     localStorage.removeItem('access_token')
-                //     localStorage.removeItem('expires_in')
-                //     localStorage.removeItem('userInfo')
-                //     localStorage.removeItem('userAccess')
-                //     localStorage.removeItem('user_details')
                 this.$store.commit('user/resetSchoolProfile')
                 this.$User.logout()
                 this.$router.push({

+ 51 - 32
TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue

@@ -1,15 +1,16 @@
 <template>
 	<div class="base-editor-wrap">
 		<div :id="ids + 'btn'" class="base-editor-tools" v-show="isShowTools">
-<!-- 		<div :id="ids + 'btn'" class="base-editor-tools" v-show="isShowTools" @mouseenter="isShowTools = true" @mouseleave="isShowTools = false"> -->
 			<span class="select-model" @click="onSelectModal" v-if="type !== '0'">编辑</span>
 			<span class="select-model btn-delete" @click="onDeleteBlock" v-if="!isAutoCreate">删除</span>
 		</div>
 		<p class="margin-block"></p>
-		<!-- <div @mouseenter="isShowTools = true" @mouseleave="isShowTools = false"> -->
 		<div >
 			<div :id="ids" class="sheet-Editor" ></div>
-			<div v-for="(item,index) in fixArr" :id="ids + 'fix' + index" class="sheet-Editor"></div>
+			<div  v-for="(item,index) in fixArr" :key="index" class="sheet-fix-Editor">
+				<div :id="ids + 'fix' + index" class="sheet-Editor"></div>
+				<span :id="ids + 'fix' + index + 'btn'" class="btn-delete-fix" @click="onDeleteFixBlock(ids + 'fix' + index)">删除</span>
+			</div>
 		</div>
 
 		<Modal v-model="isShowSelectModel" title="设置内容格式" width="600px" @on-ok="doSelectModel">
@@ -113,6 +114,13 @@
 				this.$EventBus.$emit('doRefresh')
 				this.$EventBus.$emit('deleteItem',this.type)
 			},
+			
+			/* 删除附加答题区域富文本块 */
+			onDeleteFixBlock(curId){
+				document.getElementById(curId).remove()
+				document.getElementById(curId + 'btn').remove()
+				this.$EventBus.$emit('doRefresh')
+			},
 
 			/* 切换富文本显示模式(简答题、语文作文、英语作文)*/
 			doSelectModel() {
@@ -221,6 +229,7 @@
 						let lastBottomGap = 20;
 						let curEditorY = Y > paperH ? +((Y % paperH).toFixed(4)) : Y;
 						let curEditorH = editorDom.clientHeight;
+						
 						let leftHeight = paperH - curEditorY - lastBottomGap - SVG_BORDER_MB;
 						let fixHeight = curEditorH - leftHeight + 20
 						if ( curEditorY + curEditorH + lastBottomGap + SVG_BORDER_MB > PAPER_H) {
@@ -296,14 +305,14 @@
 					
 					// 如果vuex有保存 之前的文本内容 则渲染 否则按照默认只显示题号
 					let curSetting = this.hasEditorSetting(this.ids)
-					if (curSetting && curSetting.content) {
+					let hasVuexContent = curSetting && curSetting.content
+					if (hasVuexContent) {
 						this.myEditor.txt.append(curSetting.content);
 					}else{
 						this.myEditor.txt.append(addStr + brHtml);
 					}
 					
 					// 如果自定义插入的是作文题 则进行对应题型渲染
-					console.log('插入的主观题',subjectiveItem)
 					if(subjectiveItem.maxWords > 0){
 						this.myEditor.txt.clear()
 						addStr = '<p>' +  itemOrder + "、 作文(" + (subjectiveItem.score + "分)") + '</p>'; 
@@ -339,18 +348,22 @@
 						let isNewPage = this.$store.state.answerSheet.isNewPage;
 						let lastBottomGap = 20;
 						let rectTop = editorDom.getBoundingClientRect().top
-						let Y = rectTop + scrollDis - 90;
+						let Y = scrollDis > 90 ? scrollDis - Math.abs(rectTop)  - 90 : rectTop + scrollDis - 90;
 						let paperH = PAPER_H;
 						let curEditorY = Y > paperH ? +((Y % paperH).toFixed(4)) : Y;
 						let curEditorH = editorDom.clientHeight; // 默认200px
-						console.log(itemOrder, 'rectTop', rectTop);
-						console.log(itemOrder, 'scrollDis', scrollDis);
-						console.log(itemOrder, '当前Y', Y);
 						let leftHeight = paperH - curEditorY - lastBottomGap - SVG_BORDER_MB;
-						console.log(itemOrder, '高度', curEditorH)
-						console.log(itemOrder, 'LEFT高度', leftHeight)
 						let fixHeight = curEditorH - leftHeight + 20
-						console.log(itemOrder, '需要fix的高度', fixHeight)
+						if(itemOrder === 6){
+							console.log(itemOrder, 'rectTop', rectTop);
+							console.log(itemOrder, 'scrollDis', scrollDis);
+							console.log(itemOrder, '距离第一页顶点的Y', Y);
+							console.log(itemOrder, '距离当前页面顶点的Y', curEditorY);
+							console.log(itemOrder, '高度', curEditorH)
+							console.log(itemOrder, 'LEFT高度', leftHeight)
+							console.log(itemOrder, '需要fix的高度', fixHeight)
+						}
+						
 						// 如果 渲染当前富文本的时候 需要渲染的高度超过当前页的剩余高度 则需要进行加页处理
 						if (curEditorY + curEditorH + lastBottomGap + SVG_BORDER_MB > PAPER_H) {
 							// console.log(itemOrder, Y , curEditorY , curEditorH , '超出了')
@@ -363,8 +376,8 @@
 								heightArr.push(leftHeight)
 								// 如果渲染的客观题高度在这个区间 才需要在下一页添加补充作答区域 其余全部按照正常 跨页处理不需要补充作答区域
 								let fixCount = Math.ceil(fixHeight / SVG_BORDER_PROP.height)
-								console.log(itemOrder + "需要处理跨页,数量为" + fixCount);
-								console.log(itemOrder + "剩余渲染高度" + fixHeight);
+								// console.log(itemOrder + "需要处理跨页,数量为" + fixCount);
+								// console.log(itemOrder + "剩余渲染高度" + fixHeight);
 								for(let i = 0;i < fixCount;i++){
 									this.fixArr.push(0)
 										let curFixHeight = fixHeight > SVG_BORDER_PROP.height  ? SVG_BORDER_PROP.height - 30 : fixHeight
@@ -378,8 +391,8 @@
 								this.$nextTick(() => {
 									let splitHtmlArr = this.getSplitHtml(this.pArr,heightArr)
 									splitHtmlArr.forEach((curEditorContent,editorIndex) => {
-										console.log('富文本的分割高度',heightArr)
-										console.log('富文本的分割',splitHtmlArr)
+										// console.log('富文本的分割高度',heightArr)
+										// console.log('富文本的分割',splitHtmlArr)
 										
 										let editorHeight = curEditorContent.html === '' ? heightArr[editorIndex] : heightArr[editorIndex]
 										// let curEditorContent = this.getSplitHtml(this.pArr,curEditorHeight)
@@ -696,6 +709,7 @@
 					document
 						.getElementById(curId)
 						.getElementsByClassName("w-e-toolbar")[0].style.display = "flex";
+					document.getElementById(curId + 'btn').style.display = "inline-flex";
 				};
 				editor.config.onblur = (html) => {
 					let scrollHeight = editor.$textElem.elems[0].scrollHeight
@@ -706,7 +720,8 @@
 						// this.$EventBus.$emit('doRefresh')
 					}
 					document.getElementById(curId) && (document.getElementById(curId).getElementsByClassName(
-						"w-e-toolbar")[0].style.display = "none");
+						"w-e-toolbar")[0].style.display = "none") && (document.getElementById(curId + 'btn').style.display = "none")
+							
 					this.$store.commit('setEditorHeight', {
 						id: curId,
 						height: editor.config.height,
@@ -758,21 +773,6 @@
 						);
 						this.curPropItem = this.type === "0" ? this.completeItems : n;
 						this.doRenderEditor(this.curPropItem);
-						if(this.type !== "0"){
-							// setTimeout(() => {
-							// 	if(n[0].maxWords > 0){
-							// 		console.log('语文作文',n.maxWords)
-							// 		this.wordCount = n[0].maxWords
-							// 		this.curModel = '3'
-							// 		this.doSelectModel()
-							// 	}else if(n[0].maxLines > 0){
-							// 		console.log('英语作文',n.maxLines)
-							// 		this.lineCount = n[0].maxLines
-							// 		this.curModel = '2'
-							// 		this.doSelectModel()
-							// 	}
-							// },3000)
-						}
 					}
 				},
 				immediate: true,
@@ -893,4 +893,23 @@
 		margin: 0 4px;
 		display: inline-block;
 	}
+
+	.sheet-fix-Editor{
+		position: relative;
+	}
+	.sheet-fix-Editor .btn-delete-fix{
+		position: absolute;
+		padding: 3px 10px;
+		border-radius: 4px;
+		right: 100px;
+		top: 10px;
+		font-size: 12px;
+		background-color: orangered;
+		display: none;
+		justify-content: center;
+		align-items: center;
+		color: #fff;
+		z-index: 99;
+		cursor: pointer;
+	}
 </style>

+ 8 - 4
TEAMModelOS/ClientApp/src/view/answersheet/SheetBaseInfo.vue

@@ -73,6 +73,7 @@ export default {
       let snap = this.snap;
       this.infoLeftBox = snap.paper.g();
       let gap = INFO_H / (this.showInfoList.length + 1);
+	  let lineWidth = INFO_W - this.idLength * 30
       this.showInfoList.forEach((item, index) => {
         // 考号、座号、姓名等
         let leftInfo1 = snap.text(
@@ -85,7 +86,7 @@ export default {
           .line(
             CONTENT_START_X + 80,
             CONTENT_START_Y + INFO_ITEM_MARGIN + gap * index,
-            CONTENT_START_X + 250,
+            CONTENT_START_X + lineWidth - 40,
             CONTENT_START_Y + INFO_ITEM_MARGIN + gap * index
           )
           .attr({ fill: "none", stroke: "#000", strokeWidth: 1 });
@@ -100,13 +101,16 @@ export default {
       let snap = this.snap;
       this.idNumberBox.remove();
       this.idNumberBox = snap.paper.g();
+	  
+	  const CELL_WIDTH = 30
 
-      const INFO_LEFT_W = 275; // 左侧的宽度
+      const INFO_LEFT_W = INFO_W - CELL_WIDTH * idLength; // 左侧的宽度
       const INFO_LEFT_X =
         INFO_LEFT_W + CONTENT_ML + ANCHORPROP.width + ANCHORPROP.gapX; // 左侧的x坐标
 
       var numbers = new Array(idLength).fill("0");
-      var cellWidth = (INFO_W - INFO_LEFT_W) / idLength; // 计算每个号码的宽度
+      // var cellWidth = (INFO_W - INFO_LEFT_W) / idLength; // 计算每个号码的宽度
+      var cellWidth = CELL_WIDTH; // 计算每个号码的宽度
       const NUMBER_ITEM_MLR =
         ((INFO_W - INFO_LEFT_W) / idLength - NUMBER_ITEM_W) / 2; // 计算号码左右间距
 
@@ -136,7 +140,7 @@ export default {
       // 准考证号
       this.idNumberBox.add(
         snap.text(
-          INFO_LEFT_X + (INFO_LEFT_W - 20) / 2,
+          INFO_LEFT_X + (idLength * CELL_WIDTH - 69) / 2,
           CONTENT_MT + 75,
           "准 考 证 号"
         )

+ 2 - 1
TEAMModelOS/ClientApp/src/view/evaluation/bank/ExerciseList.vue

@@ -556,8 +556,9 @@
 					this.exerciseList = await this.$evTools.getFullItem(simpleList);
 					this.currentPage = page;
 					this.pageScrollTo(0);
+					this.onHandleToggle(true)
 				} catch (e) {
-					console.log(e);
+					this.$Message.error('Blob Error : ' + e)
 				}
 			},
 

+ 3 - 3
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseFilter.vue

@@ -11,21 +11,21 @@
 		<div class="filter-item" v-show="(isShowSchoolBank || (filterOrigin === schoolCode)) &&  hasSchool">
 					<span class="filter-title">{{$t('evaluation.filter.period')}}:</span>
 					<RadioGroup v-model="filterPeriod" type="button" @on-change="filterPeriodChange">
-						<Radio v-for="(item, index) in periodList" :key="index" :label="index">{{ item.name }}<span class="filter-count"></span></Radio>
+						<Radio v-for="(item, index) in periodList" :key="index" :label="index">{{ item.name }}<span class="filter-count">({{ filterCounts.periodCountArr.length ? filterCounts.periodCountArr[index] : 0 }})</span></Radio>
 					</RadioGroup>
 				</div>
 				<div class="filter-item" v-show="(isShowSchoolBank || (filterOrigin === schoolCode)) &&  hasSchool">
 					<span class="filter-title">{{$t('evaluation.filter.grade')}}:</span>
 					<CheckboxGroup v-model="filterGrade" border @on-change="filterGradeChange">
 						<Checkbox lable="all">{{$t('evaluation.filter.all')}}</Checkbox>
-						<Checkbox v-for="(item, index) in gradeList" :key="index" :label="index">{{ item }}<span class="filter-count"></span></Checkbox>
+						<Checkbox v-for="(item, index) in gradeList" :key="index" :label="index">{{ item }}<span class="filter-count">({{ filterCounts.gradeCountArr.length ? filterCounts.gradeCountArr[index] : 0 }})</span></Checkbox>
 					</CheckboxGroup>
 				</div>
 				<div class="filter-item" v-show="(isShowSchoolBank || (filterOrigin === schoolCode)) &&  hasSchool">
 					<span class="filter-title">{{$t('evaluation.filter.subject')}}:</span>
 					<CheckboxGroup v-model="filterSubject" border @on-change="filterSubjectChange">
 						<Checkbox lable="all">{{$t('evaluation.filter.all')}}</Checkbox>
-						<Checkbox v-for="(item, index) in subjectList" :key="index" :label="item.id">{{ item.name }}<span class="filter-count"></span></Checkbox>
+						<Checkbox v-for="(item, index) in subjectList" :key="index" :label="item.id">{{ item.name }}<span class="filter-count">({{ filterCounts.subjectCountArr.length ? filterCounts.subjectCountArr[index] : 0 }})</span></Checkbox>
 					</CheckboxGroup>
 				</div>
 		<div class="filter-item">

+ 5 - 1
TEAMModelOS/ClientApp/src/view/evaluation/index/index.vue

@@ -2,7 +2,7 @@
     <div class="evaluation">
         
         <Loading :top="100" v-show="dataLoading" type="3"></Loading>
-        <vuescroll ref="evScroll" id="evScroll">
+        <vuescroll ref="evScroll" id="evScroll" @handle-scroll="handleScroll">
             <div class="ev-body">
                 <div class="ev-content">
                     <router-view />
@@ -42,6 +42,10 @@
               name: name
             })
       },
+	  // 判断容器滚动距离
+	  handleScroll(vertical, horizontal, nativeEvent) {
+	  	console.log(vertical.scrollTop)
+	  },
 
       
     },

+ 0 - 182
TEAMModelOS/ClientApp/src/view/homepage/CoursePlan.vue

@@ -1,182 +0,0 @@
-<template>
-    <!-- 首页mini课表,暂时不用 -->
-    <div class="home-cus-plan dark-iview-table">
-        <Table :columns="columns1" :data="data1" border>
-            <!--星期一-->
-            <template slot-scope="{ row, index }" slot="MON">
-                <div v-if="row.MON == 1" class="active-cell">
-                    <span class="course-dot"></span>
-                </div>
-            </template>
-            <!--星期二-->
-            <template slot-scope="{ row, index }" slot="TUE">
-                <div v-if="row.TUE == 1" class="active-cell">
-                    <span class="course-dot"></span>
-                </div>
-            </template>
-            <!--星期三-->
-            <template slot-scope="{ row, index }" slot="WED">
-                <div v-if="row.WED == 1" class="active-cell">
-                    <span class="course-dot"></span>
-                </div>
-            </template>
-            <!--星期四-->
-            <template slot-scope="{ row, index }" slot="THU">
-                <div v-if="row.THU == 1" class="active-cell">
-                    <span class="course-dot"></span>
-                </div>
-            </template>
-            <!--星期五-->
-            <template slot-scope="{ row, index }" slot="FRI">
-                <div v-if="row.FRI == 1" class="active-cell">
-                    <span class="course-dot"></span>
-                </div>
-            </template>
-            <!--星期六-->
-            <template slot-scope="{ row, index }" slot="SAT">
-                <div v-if="row.SAT == 1" class="active-cell">
-                    <span class="course-dot"></span>
-                </div>
-            </template>
-            <!--星期日-->
-            <template slot-scope="{ row, index }" slot="SUN">
-                <div v-if="row.SUN == 1" class="active-cell">
-                    <span class="course-dot"></span>
-                </div>
-            </template>
-        </Table>
-    </div>
-</template>
-<script>
-    export default {
-        data() {
-            return {
-                columns1: [
-                    {
-                        title: ' ',
-                        type: 'index',
-                        align: 'center'
-                    },
-                    {
-                        title: '一',
-                        slot: 'MON',
-                        align: 'center'
-                    },
-                    {
-                        title: '二',
-                        slot: 'TUE',
-                        align: 'center'
-                    },
-                    {
-                        title: '三',
-                        slot: 'WED',
-                        align: 'center'
-                    },
-                    {
-                        title: '四',
-                        slot: 'THU',
-                        align: 'center'
-                    },
-                    {
-                        title: '五',
-                        slot: 'FRI',
-                        align: 'center'
-                    },
-                    {
-                        title: '六',
-                        slot: 'SAT',
-                        align: 'center'
-                    },
-                    {
-                        title: '日',
-                        slot: 'SUN',
-                        align: 'center'
-                    }
-                ],
-                data1: [
-                    {
-                        MON: '',
-                        THU: '',
-                        WED: '',
-                        THU: '1',
-                        FRI: '',
-                        SAT: '1',
-                        SUN:''
-                    },
-                    {
-                        MON: '',
-                        THU: '',
-                        WED: '',
-                        THU: '1',
-                        FRI: '',
-                        SAT: '',
-                        SUN:''
-                    },
-                    {
-                        MON: '',
-                        THU: '1',
-                        WED: '',
-                        THU: '',
-                        FRI: '1',
-                        SAT: '1',
-                        SUN:''
-                    },
-                    {
-                        MON: '1',
-                        THU: '',
-                        WED: '',
-                        THU: '1',
-                        FRI: '',
-                        SAT: '',
-                        SUN:''
-                    },
-                    {
-                        MON: '',
-                        THU: '',
-                        WED: '',
-                        THU: '1',
-                        FRI: '',
-                        SAT: '',
-                        SUN:''
-                    },
-                    {
-                        MON: '1',
-                        THU: '',
-                        WED: '',
-                        THU: '1',
-                        FRI: '',
-                        SAT: '',
-                        SUN:''
-                    },
-                    {
-                        MON: '',
-                        THU: '',
-                        WED: '1',
-                        THU: '1',
-                        FRI: '',
-                        SAT: '',
-                        SUN:''
-                    }
-                ]
-            }
-        }
-    }
-</script>
-<style scoped lang="less">
-    .course-dot {
-        display:inline-block;
-        width:8px;
-        height:8px;
-        background:aqua;
-        border-radius:4px;
-    }
-    .active-cell {
-        width:100%;
-        height:48px;
-        line-height:48px;
-        background:#505050;
-    }
-</style>
-<style>
-
-</style>

+ 65 - 8
TEAMModelOS/ClientApp/src/view/homepage/HomePage.less

@@ -43,16 +43,19 @@
     margin-top: 15px;
     height: ~"calc(100% - 40px)";
 }
+.cus-table-area{
+    width: ~"calc(25% - 30px)";
+    margin-right: 30px;
+    margin-left: 20px;
+    margin-top: 15px;
+    height: ~"calc(100% - 40px)";
+}
 .class-data-area {
     width: ~"calc(22% - 20px)";
-    margin-right: 20px;
+    margin-right: 30px;
     height: ~"calc(100% - 40px)";
     margin-top: 15px;
 
-    .calss-chart-box {
-        /*padding-bottom: 20px;*/
-    }
-
     .upload-record-box {
         margin-top: 15px;
         height:~"calc(100% - 587px)";
@@ -60,7 +63,7 @@
 }
 .activity-area {
     width: ~"calc(27% - 20px)";
-    margin-right: 20px;
+    margin-right: 30px;
     height: ~"calc(100% - 40px)";
     margin-top: 15px;
     .ac-count-box {
@@ -79,7 +82,8 @@
     margin-top: 15px;
 
     .school-notice-box {
-        height: 33%;
+        // height: 33%;
+        height: 395px;
     }
 
     .common-notice-box {
@@ -89,7 +93,8 @@
 
     .system-notice-box {
         margin-top: 15px;
-        height: ~"calc(33% - 15px)";
+        // height: ~"calc(33% - 15px)";
+        height: ~"calc(100% - 410px)";
     }
 }
 
@@ -360,4 +365,56 @@
     color: white;
     text-align: center;
     font-size: 16px;
+}
+.today-text-label{
+    color: #FFFFFF;
+    margin-top: 30px;
+    border-bottom: 1px solid #606060;
+    padding-bottom: 8px;
+}
+.today-cus-item{
+    padding: 10px 10px;
+    border-bottom: 1px solid #505050;
+    display: flex;
+    align-items: center;
+    &:hover{
+        background: #404040;
+    }
+    
+    .label-icon{
+        color:#1cc0f3;
+        margin-right: 5px;
+        font-size: 22px;
+        display: block;
+        width: 40px;
+        margin-right: 10px;
+        text-align: center;
+    }
+    .cus-time{
+        font-size: 22px;
+        font-weight: 400;
+        color: white;
+        display: inline-block;
+    }
+    .cus-time-label{
+        font-size: 18px;
+        font-weight: 400;
+        margin-left: 5px;
+        // color: #1cc0f3;
+    }
+    .cus-name{
+        color: #a5a5a5;
+        font-size: 14px;
+        text-overflow:ellipsis; 
+        overflow:hidden; 
+        white-space:nowrap; 
+        margin-right: 20px;
+    }
+    .cus-class{
+        color: #a5a5a5;
+        font-size: 14px;
+        text-overflow:ellipsis; 
+        overflow:hidden; 
+        white-space:nowrap; 
+    }
 }

+ 63 - 37
TEAMModelOS/ClientApp/src/view/homepage/HomePage.vue

@@ -38,9 +38,9 @@
         </div>
 
     </div>
-
     <div v-else class="home-page-container dark-iview-split dark-iview-card">
-        <div class="prepare-area box-item">
+        <!-- 课前预习 对应模块暂未排上里程 暂时隐藏 -->
+        <!-- <div class="prepare-area box-item">
             <p class="list-title">
                 {{$t('home.previewStudy')}}
             </p>
@@ -66,11 +66,53 @@
                     </div>
                 </vuescroll>
             </div>
+        </div> -->
+        <div class="cus-table-area box-item">
+            <p class="list-title">
+                {{$t('home.myCourse')}}
+            </p>
+            <div class="card-content-box" style="padding:10px">
+                <vuescroll>
+                    <MinTable @tmwCus="getTmwCus"></MinTable>
+                    <p class="today-text-label">
+                        {{$t('home.tmwCus')}}
+                    </p>
+                    <div class="today-cus-item" v-for="(item,index) in tmwCus" :key="index">
+                        <Icon type="md-time" class="label-icon" />
+                        <div>
+                            <p class="cus-time">
+                                <span>{{item.time}}</span>
+                                <span class="cus-time-label">
+                                    {{item.timeLabel}}
+                                </span>
+                            </p>
+                            <p>
+                                <span class="cus-name">
+                                    {{$t('home.course')}}
+                                    <span style="color:white">
+                                        {{item.course}}
+                                    </span>
+                                </span>
+                                <span class="cus-class">
+                                    {{$t('home.className')}}
+                                    <span style="color:white">
+                                        {{item.class}}
+                                    </span>
+                                </span>
+                            </p>
+                        </div>
+                    </div>
+                    <EmptyData v-show="!tmwCus.length" :textContent="$t('home.tmwNoCus')"></EmptyData>
+                </vuescroll>
+            </div>
         </div>
         <div class="class-data-area" style="display:flex;flex-direction:column;">
             <div class="calss-chart-box box-item">
                 <p class="chart-title">
                     {{$t('home.classData')}}
+                    <span style="color: aqua;margin-left: 6px;font-size: 12px;">
+                        ({{$t('system.preview')}})
+                    </span>
                 </p>
                 <TechScore></TechScore>
                 <TeachScore></TeachScore>
@@ -78,6 +120,9 @@
             <div class="upload-record-box box-item" style="flex:1;">
                 <p class="list-title">
                     {{$t('home.recentRecord')}}
+                    <span style="color: aqua;margin-left: 6px;font-size: 12px;">
+                        ({{$t('system.preview')}})
+                    </span>
                 </p>
                 <div class="card-content-box">
                     <vuescroll>
@@ -197,6 +242,9 @@
             <div class="school-notice-box box-item">
                 <p class="list-title">
                     <span>{{$t('home.scNotice')}}</span>
+                    <span style="color: aqua;margin-left: 6px;font-size: 12px;">
+                        ({{$t('system.preview')}})
+                    </span>
                     <span class="notice-count-tag">2</span>
                 </p>
                 <div class="card-content-box">
@@ -216,7 +264,8 @@
                     </vuescroll>
                 </div>
             </div>
-            <div class="common-notice-box box-item">
+            <!-- 消息通知 暂时去掉移到头部, -->
+            <!-- <div class="common-notice-box box-item">
                 <p class="list-title">
                     <span>{{$t('home.msg')}}</span>
                     <span class="notice-count-tag">1</span>
@@ -234,40 +283,16 @@
                                 </div>
                                 <p class="notice-text">上课的时候有个问题没听懂,想和老师做进一步讨论。</p>
                             </li>
-                            <li>
-                                <div style="display:flex;justify-content:space-between;">
-                                    <p>
-                                        <span class="notice-title">李志轩</span>
-                                    </p>
-                                    <span class="notice-time">2020-09-09 18:02</span>
-                                </div>
-                                <p class="notice-text">上课的时候有个问题没听懂,想和老师做进一步讨论。</p>
-                            </li>
-                            <li>
-                                <div style="display:flex;justify-content:space-between;">
-                                    <p>
-                                        <span class="notice-title">叶曜灵</span>
-                                    </p>
-                                    <span class="notice-time">2020-09-09 18:02</span>
-                                </div>
-                                <p class="notice-text">上课的时候有个问题没听懂,想和老师做进一步讨论。</p>
-                            </li>
-                            <li>
-                                <div style="display:flex;justify-content:space-between;">
-                                    <p>
-                                        <span class="notice-title">王子睿</span>
-                                    </p>
-                                    <span class="notice-time">2020-09-09 18:02</span>
-                                </div>
-                                <p class="notice-text">上课的时候有个问题没听懂,想和老师做进一步讨论。</p>
-                            </li>
                         </ul>
                     </vuescroll>
                 </div>
-            </div>
+            </div> -->
             <div class="system-notice-box box-item">
                 <p class="list-title">
                     <span>{{$t('home.sysMsg')}}</span>
+                    <span style="color: aqua;margin-left: 6px;font-size: 12px;">
+                        ({{$t('system.preview')}})
+                    </span>
                     <span class="notice-count-tag">{{$store.state.userInfo.hasSchool ? 1 : 2}}</span>
                 </p>
                 <div class="card-content-box">
@@ -297,19 +322,24 @@
 import AcCountPie from "./AcCountPie.vue"
 import TechScore from "./TechScore.vue"
 import TeachScore from "./TeachScore.vue"
+import MinTable from "./MinTable.vue"
 export default {
     components: {
-        AcCountPie, TechScore, TeachScore
+        AcCountPie, TechScore, TeachScore, MinTable
     },
     data() {
         return {
             split1: 0.5,
             split2: 0.5,
             split3: 0.5,
-            itemCount: 10
+            itemCount: 10,
+            tmwCus: []
         }
     },
     methods: {
+        getTmwCus(data) {
+            this.tmwCus = data
+        },
         toAc(type) {
             switch (type) {
                 case 'vote':
@@ -366,8 +396,4 @@ export default {
     height: calc(100% - 52px);
     padding: 0px;
 }
-
-.home-page-container .__panel {
-    /* padding-right: 17px; */
-}
 </style>

+ 370 - 0
TEAMModelOS/ClientApp/src/view/homepage/MinTable.vue

@@ -0,0 +1,370 @@
+<template>
+    <!-- 首页mini课表,暂时不用 -->
+    <div class="home-cus-plan dark-iview-table">
+        <Table :columns="columns" :data="cusData" border>
+            <!--星期一-->
+            <template slot-scope="{ row, index }" slot="MON">
+                <div v-if="row.MON == 1" class="active-cell" @click="toDetail">
+                    <!-- <span class="course-dot"></span> -->
+                    <Icon type="md-checkmark" class="has-cus-icon"/>
+                </div>
+            </template>
+            <!--星期二-->
+            <template slot-scope="{ row, index }" slot="TUE">
+                <div v-if="row.TUE == 1" class="active-cell" @click="toDetail">
+                    <!-- <span class="course-dot"></span> -->
+                    <Icon type="md-checkmark" class="has-cus-icon"/>
+                </div>
+            </template>
+            <!--星期三-->
+            <template slot-scope="{ row, index }" slot="WED">
+                <div v-if="row.WED == 1" class="active-cell" @click="toDetail">
+                    <!-- <span class="course-dot"></span> -->
+                    <Icon type="md-checkmark" class="has-cus-icon"/>
+                </div>
+            </template>
+            <!--星期四-->
+            <template slot-scope="{ row, index }" slot="THU">
+                <div v-if="row.THU == 1" class="active-cell" @click="toDetail">
+                    <!-- <span class="course-dot"></span> -->
+                    <Icon type="md-checkmark" class="has-cus-icon"/>
+                </div>
+            </template>
+            <!--星期五-->
+            <template slot-scope="{ row, index }" slot="FRI">
+                <div v-if="row.FRI == 1" class="active-cell" @click="toDetail">
+                    <!-- <span class="course-dot"></span> -->
+                    <Icon type="md-checkmark" class="has-cus-icon"/>
+                </div>
+            </template>
+            <!--星期六-->
+            <template slot-scope="{ row, index }" slot="SAT">
+                <div v-if="row.SAT == 1" class="active-cell" @click="toDetail">
+                    <!-- <span class="course-dot"></span> -->
+                    <Icon type="md-checkmark" class="has-cus-icon"/>
+                </div>
+            </template>
+            <!--星期日-->
+            <template slot-scope="{ row, index }" slot="SUN">
+                <div v-if="row.SUN == 1" class="active-cell" @click="toDetail">
+                    <!-- <span class="course-dot"></span> -->
+                    <Icon type="md-checkmark" class="has-cus-icon"/>
+                </div>
+            </template>
+        </Table>
+    </div>
+</template>
+<script>
+export default {
+    data() {
+        return {
+            classList: [],
+            schoolBase: {
+                period: []
+            },
+            courseList: [],
+            courseListShow: [],
+            fullCus: [],
+            columns: [
+                {
+                    title: ' ',
+                    type: 'index',
+                    align: 'center'
+                },
+                {
+                    title: '一',
+                    slot: 'MON',
+                    align: 'center'
+                },
+                {
+                    title: '二',
+                    slot: 'TUE',
+                    align: 'center'
+                },
+                {
+                    title: '三',
+                    slot: 'WED',
+                    align: 'center'
+                },
+                {
+                    title: '四',
+                    slot: 'THU',
+                    align: 'center'
+                },
+                {
+                    title: '五',
+                    slot: 'FRI',
+                    align: 'center'
+                },
+                {
+                    title: '六',
+                    slot: 'SAT',
+                    align: 'center'
+                },
+                {
+                    title: '日',
+                    slot: 'SUN',
+                    align: 'center'
+                }
+            ],
+            cusData: [],
+            tmwCus:[]
+        }
+    },
+    methods: {
+        toDetail(){
+            this.$router.push({
+                name:'myCourse'
+            })
+        },
+        //获取个人和校本课程列表,API调整后没有进行分开处理
+        getCourseList() {
+            this.listLoading = true
+            let requestData = {
+                'code': this.$store.state.userInfo.TEAMModelId,
+                'schoolId': this.$store.state.userInfo.schoolCode,
+                'scope': 'private'
+            }
+            this.$api.courseMgmt.findCourse(requestData).then(
+                (res) => {
+                    if (!res.error) {
+                        this.courseList = res.courses
+                        //过滤校本课程 
+                        this.courseListShow = this.courseList.filter(item => {
+                            return item.scope == 'school'
+                        })
+                        let promises = []
+                        this.courseListShow.forEach(item => {
+                            let requestData = {
+                                'code': this.$store.state.userInfo.schoolCode,
+                                'scope': 'school',
+                                'id': item.id
+                            }
+                            promises.push(this.$api.courseMgmt.findCusInfo(requestData))
+                        })
+                        Promise.all(promises).then(
+                            async resAll => {
+                                for (const res of resAll) {
+                                    if (res.courses && res.courses.length > 0) {
+                                        res.courses[0].schedule = res.courses[0].schedule ? res.courses[0].schedule : []
+                                        //过滤当前教师的schedule
+                                        res.courses[0].schedule = res.courses[0].schedule.filter(item => {
+                                            return item.teacherId == this.$store.state.userInfo.TEAMModelId
+                                        })
+                                        // 获取自定义名单信息
+                                        let ids = res.courses[0].schedule.map(item => {
+                                            return item.stulist
+                                        })
+                                        for (let i = 0; i < ids.length; i++) {
+                                            if (!ids[i]) {
+                                                ids.splice(i, 1)
+                                                i--
+                                            }
+                                        }
+                                        let stuList = []
+                                        if (ids.length) {
+                                            try {
+                                                let listRes = await this.getListInfo([...ids])
+                                                if (listRes) stuList.push(...listRes.stuList)
+                                            } catch (e) {
+                                                this.$Message.error('API ERROR!')
+                                            }
+                                        }
+
+                                        res.courses[0].schedule.forEach(item => {
+                                            //补充教室信息
+                                            if (item.classId) {
+                                                let classInfo = this.classList.find(classItem => {
+                                                    return classItem.id == item.classId
+                                                })
+                                                item.classInfo = {
+                                                    id: item.classId,
+                                                    name: classInfo ? classInfo.name : '--'
+                                                }
+                                            }
+                                            //补充名单信息
+                                            if (ids.length && item.stulist) {
+                                                let listInfo = stuList.find(listItem => {
+                                                    return listItem.id == item.stulist
+                                                })
+                                                item.listName = listInfo ? listInfo.name : '--'
+                                                item.students = listInfo ? listInfo.students : []
+                                                item.fullStu = false
+                                            }
+                                        })
+                                    }
+                                    this.fullCus.push(res.courses[0])
+                                }
+                                this.dataToTable()
+                            },
+                            err => {
+                                this.$Message.error('API ERROR')
+                            }
+                        ).finally(() => {
+                            this.listLoading = false
+                        })
+
+                    } else {
+                        this.$Message.error('API ERROR!')
+                    }
+                },
+                (err) => {
+                    this.$Message.error('API ERROR!')
+                }
+            ).finally(() => {
+                this.listLoading = false
+            })
+        },
+        //根据id获取stulist信息
+        getListInfo(ids) {
+            let requestData = {
+                'code': this.$store.state.userInfo.schoolCode,
+                'scope': 'school',
+                'ids': ids
+            }
+            return this.$api.courseMgmt.findListSummary(requestData)
+        },
+        //根据schedule处理数据进行渲染
+        dataToTable() {
+            //目前默认显示第一个学段的课程
+            let period = ''
+            if (this.schoolBase.period && this.schoolBase.period.length) {
+                period = this.schoolBase.period[0].id
+            }
+            let pdData = this.schoolBase.period.find(item => {
+                return item.id == period
+            })
+            if (pdData) {
+                let times = pdData.timetable
+                if (times && times.length) {
+                    this.cusData = Array.apply(null, { length: times.length }).map(() => ({
+                        MON: '',
+                        TUE: '',
+                        WED: '',
+                        THU: '',
+                        FRI: '',
+                        SAT: '',
+                        SUN: ''
+                    }))
+                    let tmw = this.getNextDay()
+                    // let tmw = 'WED'
+                    this.fullCus.forEach((cusItem) => {
+                        cusItem.schedule.forEach(schedItem => {
+                            schedItem.time.forEach(timeItem => {
+                                //处理mini课表数据
+                                let index = times.findIndex(i => {
+                                    return i.id == timeItem.id
+                                })
+                                if (index > -1) {
+                                    this.cusData[index][timeItem.week] = '1'
+                                }
+
+                                // 获取明日课程
+                                if(timeItem.week == tmw){
+                                    let t = times.find(i=>{
+                                        return i.id == timeItem.id
+                                    })
+                                    if(t){
+                                        this.tmwCus.push(
+                                            {
+                                                time: t.time,
+                                                timeLabel: t.label,
+                                                course: cusItem.name,
+                                                class: schedItem.classId ? schedItem.classInfo.name : schedItem.listName
+                                            }
+                                        )
+                                    }
+                                }
+                            })
+                        })
+                    })
+                    this.$emit('tmwCus',this.tmwCus)
+                }
+            }
+        },
+        getNextDay() {
+            let today = new Date().getDay()
+            let tomorrow
+            if (today < 7) {
+                tomorrow = today++
+            } else {
+                tomorrow = 1
+            }
+            let name
+            switch (tomorrow) {
+                case 1:
+                    name = 'MON'
+                    break
+                case 2:
+                    name = 'TUE'
+                    break
+                case 3:
+                    name = 'WED'
+                    break
+                case 4:
+                    name = 'THU'
+                    break
+                case 5:
+                    name = 'FRI'
+                    break
+                case 6:
+                    name = 'SAT'
+                    break
+                case 7:
+                    name = 'SUN'
+                    break
+                default:
+                    break
+            }
+            return name
+        }
+    },
+    created() {
+        //直接读取登录成功拿到得学校基础信息
+        this.$store.dispatch('user/getSchoolProfile').then(res => {
+            this.classList = res.school_classes
+            this.schoolBase = res.school_base
+            this.getCourseList()
+        })
+    }
+}
+</script>
+<style scoped lang="less">
+.course-dot {
+    display: inline-block;
+    width: 8px;
+    height: 8px;
+    background: #1cc0f3;
+    border-radius: 4px;
+}
+.active-cell {
+    width: 100%;
+    height: 30px;
+    line-height: 30px;
+    // background: #383838;
+    background-color: #1cc0f3;
+    cursor: pointer;
+}
+.has-cus-icon{
+    color: white;
+    font-size: 16px;
+}
+</style>
+<style>
+.home-cus-plan .ivu-table-cell {
+    padding: 0px;
+}
+.home-cus-plan .ivu-table-row-hover {
+    background: none;
+}
+.home-cus-plan .ivu-table td,
+.ivu-table th {
+    height: 30px;
+}
+.home-cus-plan .ivu-table td, .home-cus-plan .ivu-table-header thead tr th, .home-cus-plan .ivu-table-wrapper{
+    border-color: #383838;
+}
+.home-cus-plan .ivu-table::after{
+    background-color: #383838;
+}
+</style>

+ 8 - 10
TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue

@@ -101,20 +101,24 @@
             <div slot="right" class="evaluation-detail-wrap">
                 <!--顶部菜单-->
                 <div class="evaluation-detail-bar">
+                    <!-- 评测数据 -->
                     <span :class="curBarIndex == 0 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(0)">
                         {{$t('learnActivity.mgtScEv.tab1')}}
                     </span>
+                    <!-- 评测试卷 -->
                     <span :class="curBarIndex == 1 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(1)">
                         {{$t('learnActivity.mgtScEv.tab2')}}
                     </span>
-
-                    <!-- 阅卷功能0531之前完成不了,暂时隐藏 -->
+                    <!-- 阅卷设置 -->
                     <span :class="curBarIndex == 2 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(2)">
                         {{$t('learnActivity.mgtScEv.markSetting')}}
+                        <span style="color:#1cc0f3">(预览)</span>
                     </span>
-                    <!-- <span :class="curBarIndex == 3 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(3)">
+                    <!-- 阅卷数据 -->
+                    <span v-show="isSetting" :class="curBarIndex == 3 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(3)">
                         {{$t('learnActivity.mgtScEv.markData')}}
-                    </span> -->
+                        <span style="color:#1cc0f3">(预览)</span>
+                    </span>
 
                     <!--取消一键作答和一键评分功能-->
                     <!--<div style="float:right;" v-if="$access.ability('admin','mock-eva').validateAll" v-show="evaListShow[curEvaIndex] && evaListShow[curEvaIndex].progress == 'going'">
@@ -161,12 +165,6 @@
                 </div>
                 <!-- 阅卷基础设置 -->
                 <div :class="curBarIndex == 2 ? 'animated fadeIn evaluation-base-info':'evaluation-base-info animated fadeOutRight'" v-show="curBarIndex == 2">
-                    <!-- <div class="evaluation-test-paper-header" v-if="evaListShow[curEvaIndex]">
-                        <span>{{$t('learnActivity.mgtScEv.evSubject')}}</span>
-                        <span v-for="(item,index) in evaListShow[curEvaIndex].subjects" :key="index" :class="index == curSubIndex ? 'subject-item subject-item-active':'subject-item'" @click="selectSubject(index)">
-                            {{item.name}}
-                        </span>
-                    </div> -->
                     <MarkSetting ref="markSetting" v-if="evaListShow[curEvaIndex]" :evInfo="evaListShow[curEvaIndex]" v-model="isSetting"></MarkSetting>
                 </div>
                 <!-- 阅卷数据 -->

+ 0 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkData.vue


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