Selaa lähdekoodia

Merge branch 'develop' of http://106.12.23.251:10080/TEAMMODEL/TEAMModelOS into develop

zhouj1203@hotmail.com 5 vuotta sitten
vanhempi
commit
54666c8b6e
100 muutettua tiedostoa jossa 8378 lisäystä ja 2925 poistoa
  1. 2 1
      TEAMModelOS.Model/BaseInfo/Models/ClassRoom.cs
  2. 4 4
      TEAMModelOS.SDK/Context/Attributes/AllowCors/AllowCorsAttribute.cs
  3. 2 2
      TEAMModelOS.SDK/Context/Constant/Constants.cs
  4. 161 0
      TEAMModelOS.SDK/Context/Constant/ContentTypeDict.cs
  5. 1 1
      TEAMModelOS.SDK/Extension/JwtAuth/Filters/JwtAuthorizationFilter.cs
  6. 1 1
      TEAMModelOS.SDK/Extension/JwtAuth/JwtHelper/JwtHelper.cs
  7. 396 0
      TEAMModelOS.SDK/Helper/Common/ColorHelper/ColorConverter.cs
  8. 3 42
      TEAMModelOS.SDK/Helper/Common/ColorHelper/ColorHSL.cs
  9. 81 140
      TEAMModelOS.SDK/Helper/Common/ColorHelper/ColorHelper.cs
  10. 22 0
      TEAMModelOS.SDK/Helper/Common/StringHelper/StringHelper.cs
  11. 18 1
      TEAMModelOS.SDK/Helper/Network/HttpHelper/HttpContextHelper.cs
  12. 18 0
      TEAMModelOS.SDK/Module/AzureBlob/Container/AzureBlobModel.cs
  13. 82 0
      TEAMModelOS.SDK/Module/AzureBlob/Implements/AzureBlobDBRepository.cs
  14. 3 0
      TEAMModelOS.SDK/Module/AzureBlob/Interfaces/IAzureBlobDBRepository.cs
  15. 0 6
      TEAMModelOS.SDK/Module/PowerPointX/Model/PPTXSlide.cs
  16. 0 1
      TEAMModelOS.SDK/Module/PowerPointX/Model/PPTXText.cs
  17. 3 5
      TEAMModelOS.SDK/Module/PowerPointX/PresentationConvert.cs
  18. 2 1
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  19. 1 1
      TEAMModelOS.Test.PPTX/PresentationConvert.cs
  20. 9 0
      TEAMModelOS.Test.PPTX/Program.cs
  21. 8 1
      TEAMModelOS.sln
  22. 3 0
      TEAMModelOS/ClientApp/api/schoolSetting.js
  23. 54 4
      TEAMModelOS/ClientApp/app.js
  24. 1 0
      TEAMModelOS/ClientApp/assets/image/pin.svg
  25. BIN
      TEAMModelOS/ClientApp/assets/image/school_plan.jpg
  26. 5 56
      TEAMModelOS/ClientApp/common/BaseExamList.vue
  27. 7 5
      TEAMModelOS/ClientApp/common/loading.vue
  28. 93 26
      TEAMModelOS/ClientApp/components/public/main/index.less
  29. 159 177
      TEAMModelOS/ClientApp/components/public/main/index.vue
  30. 372 273
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseBar.vue
  31. 42 25
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseEntryBar.vue
  32. 2 2
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseKnowledgeBar.vue
  33. 182 150
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseKnowledgeDetail.vue
  34. 61 71
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseLine.vue
  35. 14 22
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseLineBar.vue
  36. 265 112
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseMyTable.vue
  37. 56 59
      TEAMModelOS/ClientApp/components/student-analysis/total/BasePie.vue
  38. 26 12
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseRadar.vue
  39. 289 0
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseRateLine.vue
  40. 47 14
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseScatter.vue
  41. 46 11
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseTestScatter.vue
  42. 32 5
      TEAMModelOS/ClientApp/css/site.css
  43. 4 4
      TEAMModelOS/ClientApp/filters/http.js
  44. 21 5
      TEAMModelOS/ClientApp/mock/index.js
  45. 1 0
      TEAMModelOS/ClientApp/router/_import_file.js
  46. 14 17
      TEAMModelOS/ClientApp/router/routes.js
  47. 102 0
      TEAMModelOS/ClientApp/static/chinesePoint.json
  48. 34 53
      TEAMModelOS/ClientApp/static/classList.json
  49. 41 23
      TEAMModelOS/ClientApp/static/examList.json
  50. 36 17
      TEAMModelOS/ClientApp/static/exerciseList.json
  51. 176 0
      TEAMModelOS/ClientApp/static/filter.json
  52. 38 0
      TEAMModelOS/ClientApp/static/percent.json
  53. 737 540
      TEAMModelOS/ClientApp/static/questionList.json
  54. 181 61
      TEAMModelOS/ClientApp/static/scatter.json
  55. 7 28
      TEAMModelOS/ClientApp/static/tableList.json
  56. 252 72
      TEAMModelOS/ClientApp/static/testScatter.json
  57. 9 0
      TEAMModelOS/ClientApp/store/index.js
  58. 13 0
      TEAMModelOS/ClientApp/store/module/authorization.js
  59. 123 5
      TEAMModelOS/ClientApp/store/module/totalAnalysis.js
  60. 71 0
      TEAMModelOS/ClientApp/view/authorization/Index.less
  61. 315 0
      TEAMModelOS/ClientApp/view/authorization/Index.vue
  62. 1 1
      TEAMModelOS/ClientApp/view/index.vue
  63. 73 12
      TEAMModelOS/ClientApp/view/school-mgmt/ClassroomSetting/ClassroomSetting.less
  64. 583 104
      TEAMModelOS/ClientApp/view/school-mgmt/ClassroomSetting/ClassroomSetting.vue
  65. 3 1
      TEAMModelOS/ClientApp/view/school-mgmt/Index.vue
  66. 172 62
      TEAMModelOS/ClientApp/view/school-mgmt/SystemSetting/SystemSetting.vue
  67. 19 6
      TEAMModelOS/ClientApp/view/smartclassdashboard/Index.vue
  68. 18 2
      TEAMModelOS/ClientApp/view/smartschooldashboard/Index.vue
  69. 45 20
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/AchievementAnalysis.css
  70. 86 74
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/AchievementAnalysis.vue
  71. 258 62
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/EarlyWarning.vue
  72. 128 125
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/EntryTables.vue
  73. 123 36
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/EvaluationList/EvaluationList.css
  74. 318 70
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/EvaluationList/EvaluationList.vue
  75. 1 1
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/KnowledgeAnalysis.css
  76. 63 19
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/KnowledgeAnalysis.vue
  77. 125 42
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/ScoreDetails.vue
  78. 2 2
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/ScatterAnalysis/ScatterAnalysis.css
  79. 47 13
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/ScatterAnalysis/ScatterAnalysis.vue
  80. 37 21
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/QuestionList.css
  81. 291 80
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/QuestionList.vue
  82. 11 2
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/TestAnalysis.css
  83. 124 36
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/TestAnalysis.vue
  84. 36 9
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/index.css
  85. 79 41
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/index.vue
  86. 39 0
      TEAMModelOS/ClientApp/view/teachermgmt/Index.less
  87. 66 0
      TEAMModelOS/ClientApp/view/teachermgmt/Index.vue
  88. 69 0
      TEAMModelOS/ClientApp/view/teachermgmt/menu/accountmgmt/Index.less
  89. 188 0
      TEAMModelOS/ClientApp/view/teachermgmt/menu/accountmgmt/Index.vue
  90. 111 0
      TEAMModelOS/ClientApp/view/teachermgmt/menu/authorization/Index.less
  91. 456 0
      TEAMModelOS/ClientApp/view/teachermgmt/menu/authorization/Index.vue
  92. 10 1
      TEAMModelOS/Controllers/Core/FileController.cs
  93. 2 2
      TEAMModelOS/Controllers/Core/GradeController.cs
  94. 3 3
      TEAMModelOS/Controllers/Core/PeriodController.cs
  95. 10 4
      TEAMModelOS/Controllers/Core/RoleController.cs
  96. 3 3
      TEAMModelOS/Controllers/Core/SubjectController.cs
  97. 2 2
      TEAMModelOS/Controllers/Core/TermController.cs
  98. 20 11
      TEAMModelOS/Controllers/Syllabus/KnowledgeController.cs
  99. 8 2
      TEAMModelOS/Controllers/Syllabus/SyllabusController.cs
  100. 0 0
      TEAMModelOS/Controllers/Syllabus/VolumeController.cs

+ 2 - 1
TEAMModelOS.Model/BaseInfo/Models/ClassRoom.cs

@@ -16,6 +16,7 @@ namespace TEAMModelOS.Model.BaseInfo.Models
         public string Grade { get; set; }
         [PartitionKey]
         public string HiTeach { get; set; }
-
+        public int StuNum { get; set; }
+        public string ClassroomType { get; set; }
     }
 }

+ 4 - 4
TEAMModelOS.SDK/Context/Attributes/AllowCors/AllowCorsAttribute.cs

@@ -10,11 +10,11 @@ namespace TEAMModelOS.SDK.Context.Attributes.AllowCors
         public override void OnActionExecuting(ActionExecutingContext filterContext)
         {
             var context = filterContext.HttpContext;
-            //context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
-            context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT");
+            context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
+            context.Response.Headers.Add("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
             context.Response.Headers.Add("Access-Control-Allow-Headers", "Access-Control-Allow-Headers," +
-                                         " Origin,Accept, X-Requested-With, Content-Type, " +
-                                         "Access-Control-Request-Method, Access-Control-Request-Headers," +
+                                         "Origin,Accept,X-Requested-With,Content-Type," +
+                                         "Access-Control-Request-Method,Access-Control-Request-Headers," +
                                          "Content-Type,Accept,access_token,token,Authorization");
             base.OnActionExecuting(filterContext);
         }

+ 2 - 2
TEAMModelOS.SDK/Context/Constant/Constants.cs

@@ -22,10 +22,10 @@ namespace TEAMModelOS.SDK.Context.Constant.Common
         /// <summary>
         /// 苏格拉底作品类型--团队组
         /// </summary>
-		public static readonly string SIGNUPTYPEGRP = "2018TMCNTSGRP";
+		//public static readonly string SIGNUPTYPEGRP = "2018TMCNTSGRP";
         /// <summary>
         /// 苏格拉底作品类型--个人组
         /// </summary>
-		public static readonly string SIGNUPTYPEINT = "2018TMCNTSIND";
+		//public static readonly string SIGNUPTYPEINT = "2018TMCNTSIND";
     }
 }

+ 161 - 0
TEAMModelOS.SDK/Context/Constant/ContentTypeDict.cs

@@ -6,6 +6,167 @@ namespace TEAMModelOS.SDK.Context.Constant
 {
     public static class ContentTypeDict
     {
+        public static readonly Dictionary<string, string> extdict = new Dictionary<string, string> {
+            {"video/3gpp",".3g2"},
+{"audio/mp4",".aac"},
+{"audio/ac3",".ac3"},
+{"text/x-adasrc",".adb"},
+{"image/x-applix-graphics",".ag"},
+{"audio/amr",".amr"},
+{"audio/x-ape",".ape"},
+{"image/x-sony-arw",".arw"},
+{"text/plain",".asc"},
+{"video/x-ms-asf",".asf"},
+{"text/x-ssa",".ass"},
+{"video/x-msvideo",".avi"},
+{"text/x-bibtex",".bib"},
+{"image/bmp",".bmp"},
+{"text/x-csrc",".c"},
+{"text/x-c++src",".c++"},
+{"image/cgm",".cgm"},
+{"text/x-tex",".cls"},
+{"text/x-cmake",".cmake"},
+{"image/x-canon-cr2",".cr2"},
+{"image/x-canon-crw",".crw"},
+{"text/x-csharp",".cs"},
+{"text/css",".css"},
+{"text/csv",".csv"},
+{"image/x-win-bitmap",".cur"},
+{"text/x-dsrc",".d"},
+{"text/x-dcl",".dcl"},
+{"image/x-kodak-dcr",".dcr"},
+{"image/x-dds",".dds"},
+{"text/x-patch",".diff"},
+{"image/vnd.djvu",".djv"},
+{"image/x-adobe-dng",".dng"},
+{"text/vnd.graphviz",".dot"},
+{"text/x-dsl",".dsl"},
+{"image/vnd.dwg",".dwg"},
+{"image/vnd.dxf",".dxf"},
+{"text/x-eiffel",".e"},
+{"text/x-emacs-lisp",".el"},
+{"image/x-emf",".emf"},
+{"image/x-eps",".eps"},
+{"image/x-bzeps",".eps.bz2"},
+{"image/x-gzeps",".eps.gz"},
+{"text/x-erlang",".erl"},
+{"text/x-setext",".etx"},
+{"image/x-exr",".exr"},
+{"text/x-fortran",".f"},
+{"image/x-xfig",".fig"},
+{"image/fits",".fits"},
+{"video/x-flv",".flv"},
+{"text/x-xslfo",".fo"},
+{"image/fax-g3",".g3"},
+{"text/directory",".gcrd"},
+{"image/gif",".gif"},
+{"text/x-google-video-pointer",".gvp"},
+{"text/x-chdr",".h"},
+{"text/x-c++hdr",".h++"},
+{"text/x-haskell",".hs"},
+{"text/html",".htm"},
+{"image/x-tga",".icb"},
+{"image/x-icns",".icns"},
+{"image/x-icon",".ico"},
+{"text/calendar",".ics"},
+{"text/x-idl",".idl"},
+{"image/ief",".ief"},
+{"image/x-iff",".iff"},
+{"image/x-ilbm",".ilbm"},
+{"text/x-imelody",".ime"},
+{"text/x-iptables",".iptables"},
+{"image/jp2",".j2k"},
+{"text/vnd.sun.j2me.app-descriptor",".jad"},
+{"text/x-java",".java"},
+{"image/x-jng",".jng"},
+{"image/jpeg",".jpe"},
+{"application/javascript",".js"},
+{"application/json",".json"},
+{"application/jsonp",".jsonp"},
+{"image/x-kodak-k25",".k25"},
+{"image/x-kodak-kdc",".kdc"},
+{"text/x-ldif",".ldif"},
+{"text/x-literate-haskell",".lhs"},
+{"text/x-log",".log"},
+{"text/x-lua",".lua"},
+{"image/x-lwo",".lwo"},
+{"image/x-lws",".lws"},
+{"text/x-lilypond",".ly"},
+{"text/x-matlab",".m"},
+{"video/mpeg",".m2t"},
+{"audio/x-mpegurl",".m3u"},
+{"application/vnd.apple.mpegurl",".m3u8"},
+{"text/x-troff-me",".me"},
+{"video/x-matroska",".mkv"},
+{"text/x-ocaml",".ml"},
+{"text/x-troff-mm",".mm"},
+{"text/mathml",".mml"},
+{"text/x-moc",".moc"},
+{"text/x-mof",".mof"},
+{"audio/mpeg",".mp3"},
+{"video/mp4",".mp4"},
+{"text/x-mrml",".mrl"},
+{"image/x-minolta-mrw",".mrw"},
+{"text/x-troff-ms",".ms"},
+{"image/x-msod",".msod"},
+{"text/x-mup",".mup"},
+{"image/x-nikon-nef",".nef"},
+{"text/x-nfo",".nfo"},
+{"text/x-ocl",".ocl"},
+{"text/x-opml+xml",".opml"},
+{"image/openraster",".ora"},
+{"image/x-olympus-orf",".orf"},
+{"text/x-pascal",".p"},
+{"image/x-portable-bitmap",".pbm"},
+{"image/x-photo-cd",".pcd"},
+{"image/x-pcx",".pcx"},
+{"application/pdf",".pdf"},
+{"image/x-pentax-pef",".pef"},
+{"image/x-portable-graymap",".pgm"},
+{"image/x-pict",".pict"},
+{"image/png",".png"},
+{"image/x-portable-anymap",".pnm"},
+{"image/x-macpaint",".pntg"},
+{"text/x-gettext-translation",".po"},
+{"text/x-gettext-translation-template",".pot"},
+{"text/x-python",".py"},
+{"image/x-quicktime",".qif"},
+{"image/x-fuji-raf",".raf"},
+{"image/x-cmu-raster",".ras"},
+{"image/x-panasonic-raw",".raw"},
+{"text/x-ms-regedit",".reg"},
+{"image/x-rgb",".rgb"},
+{"image/rle",".rle"},
+{"text/troff",".roff"},
+{"image/vnd.rn-realpix",".rp"},
+{"text/vnd.rn-realtext",".rt"},
+{"text/richtext",".rtx"},
+{"text/x-scheme",".scm"},
+{"image/x-sgi",".sgi"},
+{"text/sgml",".sgm"},
+{"image/x-skencil",".sk"},
+{"text/spreadsheet",".slk"},
+{"text/x-rpm-spec",".spec"},
+{"text/x-sql",".sql"},
+{"image/x-sony-sr2",".sr2"},
+{"image/x-sony-srf",".srf"},
+{"text/x-subviewer",".sub"},
+{"image/x-sun-raster",".sun"},
+{"image/svg+xml",".svg"},
+{"image/svg+xml-compressed",".svgz"},
+{"text/x-txt2tags",".t2t"},
+{"text/x-tcl",".tcl"},
+{"text/x-texinfo",".texi"},
+{"image/tiff",".tif"},
+{"audio/x-voc",".voc"},
+{"image/x-wmf",".wmf"},
+{"text/vnd.wap.wml",".wml"},
+{"text/vnd.wap.wmlscript",".wmls"},
+{"video/x-ms-wmv",".wmv"},
+{"application/xhtml+xml",".xhtml"},
+{"application/xml",".xml"}
+        };
+
         public static readonly  Dictionary<string, string> dict = new Dictionary<string, string> {
             {".3g2", "video/3gpp"},
             {".3ga", "video/3gpp"},

+ 1 - 1
TEAMModelOS.SDK/Extension/JwtAuth/Filters/JwtAuthorizationFilter.cs

@@ -37,7 +37,7 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.Filters
             if (httpContext.Request.Query.ContainsKey(HttpConstant.access_token))
             {
                 tokenHeader = httpContext.Request.Query[HttpConstant.access_token];
-                tokenHeader = tokenHeader.Trim();
+                //tokenHeader = tokenHeader.Trim();
             }
             ClaimModel claimModel = JwtHelper.JwtHelper.SerializeJWT(tokenHeader);
 

+ 1 - 1
TEAMModelOS.SDK/Extension/JwtAuth/JwtHelper/JwtHelper.cs

@@ -43,7 +43,7 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
             claims.Add(new Claim(JwtClaimTypes.Issuer, setting.Issuer));
             claims.Add(new Claim(JwtClaimTypes.Scope, claimModel.Scope));
             claims.Add(new Claim(JwtClaimTypes.JwtId, Guid.NewGuid().ToString()));
-           //claims.AddRange(claimModel.Roles.Select(s=>new Claim(JwtClaimTypes.Role, s)));
+            //claims.AddRange(claimModel.Roles.Select(s=>new Claim(JwtClaimTypes.Role, s)));
             //claims.AddRange(claimModel.Claims.Select(s => new Claim(ClaimTypes.Role, s)));
             string path = BaseConfigModel.ContentRootPath;
             RSACryptoServiceProvider provider = RsaHelper.LoadCertificateFile(path + "/JwtRsaFile/private.pem");

+ 396 - 0
TEAMModelOS.SDK/Helper/Common/ColorHelper/ColorConverter.cs

@@ -0,0 +1,396 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+
+namespace TEAMModelOS.SDK.Helper.Common.ColorHelper
+{
+    public class ColorConverter
+    {
+        public string SetLuminanceMod(string s, double luminance)
+        {
+
+            Color c = ColorTranslator.FromHtml("#" + s);
+
+            return SetLuminanceMod(c, luminance);
+        }
+        public string SetLuminanceOff(string s, double luminance)
+        {
+            Color c = ColorTranslator.FromHtml("#" + s);
+
+            return SetLuminanceOff(c, luminance);
+        }
+        public string SetTint(string s, double tint)
+        {
+            Color c = ColorTranslator.FromHtml("#" + s);
+
+            return SetTint(c, tint);
+        }
+        public string SetShade(string s, double shade)
+        {
+            Color c = ColorTranslator.FromHtml("#" + s);
+
+            return SetShade(c, shade);
+        }
+        public string SetSaturationMod(string s, double saturation)
+        {
+            Color c = ColorTranslator.FromHtml("#" + s);
+
+            return SetSaturationMod(c, saturation);
+        }
+        public string SetSaturationOff(string s, double saturation)
+        {
+            Color c = ColorTranslator.FromHtml("#" + s);
+
+            return SetSaturationOff(c, saturation);
+        }
+        public string SetBrightness(string s, double luminance)
+        {
+            Color c = ColorTranslator.FromHtml("#" + s);
+
+            return SetBrightness(c, luminance);
+        }
+        public string SetHueMod(string s, double hueMod)
+        {
+            Color c = ColorTranslator.FromHtml("#" + s);
+
+            return SetHueMod(c, hueMod);
+        }
+        public string SetHueOff(string s, double hueOff)
+        {
+            Color c = ColorTranslator.FromHtml("#" + s);
+
+            return SetHueOff(c, hueOff);
+        }
+        private double RGB_to_linearRGB(double val)
+        {
+
+            if (val < 0.0)
+                return 0.0;
+            if (val <= 0.04045)
+                return val / 12.92;
+            if (val <= 1.0)
+                return (double)Math.Pow(((val + 0.055) / 1.055), 2.4);
+
+            return 1.0;
+        }
+        private double linearRGB_to_RGB(double val)
+        {
+
+            if (val < 0.0)
+                return 0.0;
+            if (val <= 0.0031308)
+                return val * 12.92;
+            if (val < 1.0)
+                return (1.055 * Math.Pow(val, (1.0 / 2.4))) - 0.055;
+
+            return 1.0;
+            /*
+            Public Function linearRGB_to_sRGB(ByVal value As Double) As Double
+                If value < 0.0# Then Return 0.0#
+                If value <= 0.0031308# Then Return value * 12.92
+                If value < 1.0# Then Return 1.055 * (value ^ (1.0# / 2.4)) - 0.055
+                Return 1.0#
+            End Function
+            */
+
+        }
+        public string SetShade(Color c, double shade)
+        {
+            //Console.WriteLine("Shade: " + shade);
+
+            double convShade = (shade / 1000) * 0.01;
+
+            double r = (double)c.R / 255;
+            double g = (double)c.G / 255;
+            double b = (double)c.B / 255;
+
+            double rLin = RGB_to_linearRGB(r);
+            double gLin = RGB_to_linearRGB(g);
+            double bLin = RGB_to_linearRGB(b);
+
+            //Console.WriteLine("Linear R: " + rLin + "\nLinear G: " + gLin + "\nLinear B: " + bLin);
+
+            //SHADE 
+            if ((rLin * convShade) < 0)
+                rLin = 0;
+            if ((rLin * convShade) > 1)
+                rLin = 0;
+            else
+                rLin *= convShade;
+
+            if ((gLin * convShade) < 0)
+                gLin = 0;
+            if ((gLin * convShade) > 1)
+                gLin = 0;
+            else
+                gLin *= convShade;
+
+            if ((bLin * convShade) < 0)
+                bLin = 0;
+            if ((bLin * convShade) > 1)
+                bLin = 0;
+            else
+                bLin *= convShade;
+
+            //SHADEEND
+
+            r = linearRGB_to_RGB(rLin);
+            g = linearRGB_to_RGB(gLin);
+            b = linearRGB_to_RGB(bLin);
+
+            Color outColor = Color.FromArgb((int)Math.Round(r * 255), (int)Math.Round(g * 255), (int)Math.Round(b * 255));
+
+            return outColor.R.ToString("X2") + outColor.G.ToString("X2") + outColor.B.ToString("X2");
+
+        }
+        public string SetTint(Color c, double tint)
+        {
+
+            double tintConv = (tint / 1000) * 0.01;
+
+            double r = (double)c.R / 255;
+            double g = (double)c.G / 255;
+            double b = (double)c.B / 255;
+
+            double rLin = RGB_to_linearRGB(r);
+            double gLin = RGB_to_linearRGB(g);
+            double bLin = RGB_to_linearRGB(b);
+
+            /**TINT**/
+
+            if (tintConv > 0)
+                rLin = (rLin * tintConv) + (1 - tintConv);
+            else
+                rLin = rLin * (1 + tintConv);
+
+            if (tintConv > 0)
+                gLin = (gLin * tintConv) + (1 - tintConv);
+            else
+                gLin = gLin * (1 + tintConv);
+
+            if (tintConv > 0)
+                bLin = (bLin * tintConv) + (1 - tintConv);
+            else
+                bLin = bLin * (1 + tintConv);
+
+            r = linearRGB_to_RGB(rLin);
+            g = linearRGB_to_RGB(gLin);
+            b = linearRGB_to_RGB(bLin);
+
+            Color outColor = Color.FromArgb((int)Math.Round(r * 255), (int)Math.Round(g * 255), (int)Math.Round(b * 255));
+
+            return outColor.R.ToString("X2") + outColor.G.ToString("X2") + outColor.B.ToString("X2");
+        }
+        public string SetSaturationMod(Color c, double saturation)
+        {
+            double satMod = (saturation / 1000) * 0.01;
+
+            ColorHSL hsl = RGB_to_HSL(c);
+            hsl.S *= satMod;
+            c = HSL_to_RGB(hsl);
+
+            return c.R.ToString("X2") + c.G.ToString("X2") + c.B.ToString("X2");
+        }
+        public string SetSaturationOff(Color c, double saturation)
+        {
+            double satOff = (saturation / 1000) * 0.01;
+
+            ColorHSL hsl = RGB_to_HSL(c);
+            hsl.S += satOff;
+            c = HSL_to_RGB(hsl);
+
+            return c.R.ToString("X2") + c.G.ToString("X2") + c.B.ToString("X2");
+        }
+        public string SetBrightness(Color c, double brightness)
+        {
+
+            double convBrightness = brightness / 100000;
+
+            ColorHSL hsl = RGB_to_HSL(c);
+
+            hsl.L *= convBrightness;
+            c = HSL_to_RGB(hsl);
+
+            return c.R.ToString("X2") + c.G.ToString("X2") + c.B.ToString("X2");
+        }
+        public string SetLuminanceMod(Color c, double luminance)
+        {
+            double lumMod = (luminance / 1000) * 0.01;
+
+            ColorHSL hsl = RGB_to_HSL(c);
+            hsl.L *= lumMod;
+            Color outColor = HSL_to_RGB(hsl);
+
+            return outColor.R.ToString("X2") + outColor.G.ToString("X2") + outColor.B.ToString("X2");
+        }
+        public string SetLuminanceOff(Color c, double luminance)
+        {
+            double lumModOff = (luminance / 1000) * 0.01;
+
+            ColorHSL hsl = RGB_to_HSL(c);
+            hsl.L += lumModOff;
+            Color outColor = HSL_to_RGB(hsl);
+
+            return outColor.R.ToString("X2") + outColor.G.ToString("X2") + outColor.B.ToString("X2");
+        }
+        public string SetHueMod(Color c, double hue)
+        {
+
+            double hueMod = (hue / 1000) * 0.01;
+
+            ColorHSL hsl = RGB_to_HSL(c);
+            hsl.H *= hueMod;
+            Color outColor = HSL_to_RGB(hsl);
+
+            return outColor.R.ToString("X2") + outColor.G.ToString("X2") + outColor.B.ToString("X2");
+
+        }
+        public string SetHueOff(Color c, double hue)
+        {
+
+            double hueMod = (hue / 1000) * 0.01;
+
+            ColorHSL hsl = RGB_to_HSL(c);
+            hsl.H += hueMod;
+            Color outColor = HSL_to_RGB(hsl);
+            return outColor.R.ToString("X2") + outColor.G.ToString("X2") + outColor.B.ToString("X2");
+
+        }
+
+        private ColorHSL RGB_to_HSL(Color c)
+        {
+            ColorHSL hsl = new ColorHSL();
+
+            hsl.H = c.GetHue() / 360.0;
+            hsl.L = c.GetBrightness();
+            hsl.S = c.GetSaturation();
+
+            return hsl;
+        }
+        private ColorHSL CreateHSL(int r, int g, int b)
+        {
+            ColorHSL hsl = new ColorHSL();
+ 
+            double R = (double)r / 255;
+            double G = (double)g / 255;
+            double B = (double)b / 255;
+            double max = 0, min = 0;
+            double H = 0, S = 0, L = 0;
+            bool rBool = false, gBool = false, bBool = false;
+
+            //find max
+            if ((R > G) && (R > B))
+            {
+                max = R;
+                rBool = true;
+            }
+            else if ((G > R) && (G > B))
+            {
+                max = G;
+                gBool = true;
+            }
+            else if ((B > G) && (B > R))
+            {
+                max = B;
+                bBool = true;
+            }
+
+            if ((R < G) && (R < B))
+                min = R;
+            else if ((G < R) && (G < B))
+                min = G;
+            else if ((B < G) && (B < R))
+                min = B;
+
+            //set Luminance
+            hsl.L = (min + max) / 2;
+
+            if (min == max)
+            {
+                hsl.S = 0;
+                hsl.H = 0;
+            }
+
+            //set saturation
+            if (hsl.L < 0.5)
+                hsl.S = (max - min) / (max + min);
+            else if (hsl.L > 0.5)
+                hsl.S = (max - min) / (2.0 - max - min);
+
+            if (rBool)
+            {
+                H = ((G - B) / (max - min)) * 60.0;
+                Console.WriteLine("red");
+            }
+            if (gBool)
+            {
+                H = ((2.0 + ((B - R) / (max - min))) * 60.0);
+                Console.WriteLine("green");
+            }
+            if (bBool)
+            {
+                H = (4.0 + (R - G) / (max - min)) * 60.0;
+                Console.WriteLine("blue");
+            }
+
+            if (H < 0)
+                H += 360;
+
+            H = Math.Round(H);
+            H = H / 360;
+
+            hsl.H = H;
+
+            return hsl;
+        }
+        private Color HSL_to_RGB(ColorHSL hslColor)
+        {
+
+            double r = 0, g = 0, b = 0;
+            double temp1, temp2;
+
+
+            if (hslColor.L == 0)
+                r = g = b = 0;
+            else
+            {
+                if (hslColor.S == 0)
+                {
+                    r = g = b = hslColor.L;
+                }
+                else
+                {
+                    temp2 = ((hslColor.L <= 0.5) ? hslColor.L * (1.0 + hslColor.S) : hslColor.L + hslColor.S - (hslColor.L * hslColor.S));
+                    temp1 = 2.0 * hslColor.L - temp2;
+
+                    double[] t3 = new double[] { hslColor.H + 1.0 / 3.0, hslColor.H, hslColor.H - 1.0 / 3.0 };
+                    double[] clr = new double[] { 0, 0, 0 };
+                    for (int i = 0; i < 3; i++)
+                    {
+                        if (t3[i] < 0)
+                            t3[i] += 1.0;
+                        if (t3[i] > 1)
+                            t3[i] -= 1.0;
+
+                        if (6.0 * t3[i] < 1.0)
+                            clr[i] = temp1 + (temp2 - temp1) * t3[i] * 6.0;
+                        else if (2.0 * t3[i] < 1.0)
+                            clr[i] = temp2;
+                        else if (3.0 * t3[i] < 2.0)
+                            clr[i] = (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - t3[i]) * 6.0);
+                        else
+                            clr[i] = temp1;
+                    }
+                    r = clr[0];
+                    g = clr[1];
+                    b = clr[2];
+                }
+            }
+
+            return Color.FromArgb((int)(255 * r), (int)(255 * g), (int)(255 * b));
+
+        }
+
+    }
+}

+ 3 - 42
TEAMModelOS.SDK/Helper/Common/ColorHelper/ColorHSL.cs

@@ -10,57 +10,18 @@ namespace TEAMModelOS.SDK.Helper.Common.ColorHelper
     /// </summary>
     public class ColorHSL
     {
-        public ColorHSL(int h, int s, int l)
-        {
-            this._h = h;
-            this._s = s;
-            this._l = l;
-        }
-
-        private int _h;
-        private int _s;
-        private int _l;
-
         /// <summary>
         /// 色相
         /// </summary>
-        public int H
-        {
-            get { return this._h; }
-            set
-            {
-                this._h = value;
-                this._h = this._h > 360 ? 360 : this._h;
-                this._h = this._h < 0 ? 0 : this._h;
-            }
-        }
-
+        public double H { get; set; }
         /// <summary>
         /// 饱和度(纯度)
         /// </summary>
-        public int S
-        {
-            get { return this._s; }
-            set
-            {
-                this._s = value;
-                this._s = this._s > 255 ? 255 : this._s;
-                this._s = this._s < 0 ? 0 : this._s;
-            }
-        }
+        public double S { get; set; }
 
         /// <summary>
         /// 饱和度
         /// </summary>
-        public int L
-        {
-            get { return this._l; }
-            set
-            {
-                this._l = value;
-                this._l = this._l > 255 ? 255 : this._l;
-                this._l = this._l < 0 ? 0 : this._l;
-            }
-        }
+        public double L { get; set; }
     }
 }

+ 81 - 140
TEAMModelOS.SDK/Helper/Common/ColorHelper/ColorHelper.cs

@@ -18,8 +18,8 @@ namespace TEAMModelOS.SDK.Helper.Common.ColorHelper
         /// <returns></returns>
         public static ColorHSV RgbToHsv(ColorRGB rgb)
         {
-            float min, max, tmp, H, S, V;
-            float R = rgb.R * 1.0f / 255, G = rgb.G * 1.0f / 255, B = rgb.B * 1.0f / 255;
+            double min, max, tmp, H, S, V;
+            double R = rgb.R * 1.0f / 255, G = rgb.G * 1.0f / 255, B = rgb.B * 1.0f / 255;
             tmp = Math.Min(R, G);
             min = Math.Min(tmp, B);
             tmp = Math.Max(R, G);
@@ -68,17 +68,17 @@ namespace TEAMModelOS.SDK.Helper.Common.ColorHelper
         public static ColorRGB HsvToRgb(ColorHSV hsv)
         {
             if (hsv.H == 360) hsv.H = 359; // 360为全黑,原因不明
-            float R = 0f, G = 0f, B = 0f;
+            double R = 0f, G = 0f, B = 0f;
             if (hsv.S == 0)
             {
                 return new ColorRGB(hsv.V, hsv.V, hsv.V);
             }
-            float S = hsv.S * 1.0f / 255, V = hsv.V * 1.0f / 255;
+            double S = hsv.S * 1.0f / 255, V = hsv.V * 1.0f / 255;
             int H1 = (int)(hsv.H * 1.0f / 60), H = hsv.H;
-            float F = H * 1.0f / 60 - H1;
-            float P = V * (1.0f - S);
-            float Q = V * (1.0f - F * S);
-            float T = V * (1.0f - (1.0f - F) * S);
+            double F = H * 1.0f / 60 - H1;
+            double P = V * (1.0f - S);
+            double Q = V * (1.0f - F * S);
+            double T = V * (1.0f - (1.0f - F) * S);
             switch (H1)
             {
                 case 0: R = V; G = T; B = P; break;
@@ -107,51 +107,51 @@ namespace TEAMModelOS.SDK.Helper.Common.ColorHelper
         /// <returns></returns>
         public static ColorHSL RgbToHsl(ColorRGB rgb)
         {
-            float min, max, tmp, H, S, L;
-            float R = rgb.R * 1.0f / 255, G = rgb.G * 1.0f / 255, B = rgb.B * 1.0f / 255;
+            double min, max, tmp, H = 0, S = 0, L = 0;
+            double R = rgb.R * 1.0f / 255, G = rgb.G * 1.0f / 255, B = rgb.B * 1.0f / 255;
             tmp = Math.Min(R, G);
             min = Math.Min(tmp, B);
             tmp = Math.Max(R, G);
             max = Math.Max(tmp, B);
-            // H
-            H = 0;
-            if (max == min)
+            L = (max + min) / 2.0d;
+            if (min == max)
             {
-                H = 0;  // 此时H应为未定义,通常写为0
+                H = S = 0;
             }
-            else if (max == R && G > B)
-            {
-                H = 60 * (G - B) * 1.0f / (max - min) + 0;
-            }
-            else if (max == R && G < B)
-            {
-                H = 60 * (G - B) * 1.0f / (max - min) + 360;
-            }
-            else if (max == G)
-            {
-                H = H = 60 * (B - R) * 1.0f / (max - min) + 120;
-            }
-            else if (max == B)
-            {
-                H = H = 60 * (R - G) * 1.0f / (max - min) + 240;
-            }
-            // L 
-            L = 0.5f * (max + min);
-            // S
-            S = 0;
-            if (L == 0 || max == min)
-            {
-                S = 0;
-            }
-            else if (0 < L && L < 0.5)
-            {
-                S = (max - min) / (L * 2);
-            }
-            else if (L > 0.5)
+            else
             {
-                S = (max - min) / (2 - 2 * L);
+                double d = max - min;
+                S = L > 0.5 ? d / (2 - max - min) : d / (max + min);
+                if (max == R)
+                {
+                    H = (G - B) / d + (G < B ? 6 : 0);
+                }
+                else if (max == G)
+                {
+                    H = (G - R) / d + 2;
+                }
+                else if (max == B)
+                {
+                    H = (R - G) / d + 4;
+                }
             }
-            return new ColorHSL((int)H, (int)(S * 255), (int)(L * 255));
+            H = H / 6.0F;
+            return new ColorHSL() { H = H, S = S, L = L };
+        }
+
+        public static double hue2rgb(double p, double q, double t)
+        {
+            if (t < 0) t += 1;
+
+            if (t > 1) t -= 1;
+
+            if (t < 1.0 / 6.0d) return p + (q - p) * 6 * t;
+
+            if (t < 1.0 / 2.0d) return q;
+
+            if (t < 2.0 / 3.0d) return p + (q - p) * (2.0d / 3.0d - t) * 6.0d;
+
+            return p;
         }
 
         /// <summary>
@@ -161,49 +161,26 @@ namespace TEAMModelOS.SDK.Helper.Common.ColorHelper
         /// <returns></returns>
         public static ColorRGB HslToRgb(ColorHSL hsl)
         {
-            float R = 0f, G = 0f, B = 0f;
-            float S = hsl.S * 1.0f / 255, L = hsl.L * 1.0f / 255;
-            float temp1, temp2, temp3;
-            if (S == 0f) // 灰色
+            var l = hsl.L;
+            var s = hsl.S;
+            var h = hsl.H;
+            double R = 0, G = 0, B = 0;
+            if (hsl.S == 0)
             {
-                R = L;
-                G = L;
-                B = L;
+                R = G = B = hsl.L;
             }
             else
             {
-                if (L < 0.5f)
-                {
-                    temp2 = L * (1.0f + S);
-                }
-                else
-                {
-                    temp2 = L + S - L * S;
-                }
-                temp1 = 2.0f * L - temp2;
-                float H = hsl.H * 1.0f / 360;
-                // R
-                temp3 = H + 1.0f / 3.0f;
-                if (temp3 < 0) temp3 += 1.0f;
-                if (temp3 > 1) temp3 -= 1.0f;
-                R = temp3;
-                // G
-                temp3 = H;
-                if (temp3 < 0) temp3 += 1.0f;
-                if (temp3 > 1) temp3 -= 1.0f;
-                G = temp3;
-                // B
-                temp3 = H - 1.0f / 3.0f;
-                if (temp3 < 0) temp3 += 1.0f;
-                if (temp3 > 1) temp3 -= 1.0f;
-                B = temp3;
+                var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+                var p = 2 * l - q;
+                R = hue2rgb(p, q, h + 1.0d / 3.0d);
+                G = hue2rgb(p, q, h);
+                B = hue2rgb(p, q, h - 1.0d / 3.0d);
             }
-            R = R * 255;
-            G = G * 255;
-            B = B * 255;
-            return new ColorRGB((int)R, (int)G, (int)B);
+            R = R * 255; G = G * 255; B = B * 255;
+            return new ColorRGB(int.Parse(Math.Round(R, 0) + ""), int.Parse(Math.Round(G, 0) + ""), int.Parse(Math.Round(B, 0) + ""));
         }
-        private static float HueToRGB(float p, float q, float h)
+        private static double HueToRGB(double p, double q, double h)
         {
             if (h < 0) h += 1;
             if (h > 1) h -= 1;
@@ -221,54 +198,21 @@ namespace TEAMModelOS.SDK.Helper.Common.ColorHelper
             }
             return p;
         }
-
-        public static Color GetColorLumModAndLumOff(Color color, int lumMod = 0, int lumOff = 0) {
-            ColorHSL colorHSL=  RgbToHsl(new ColorRGB(color.R,color.G,color.B));
-            colorHSL.L = (colorHSL.L / 100) * (lumMod / 100_000) + (lumOff / 100_000);
-            return color; 
-        }
-
-
-        public static Color GetColorLumModAndOff(Color color, int lumMod=0, int lumOff=0)
+        /// <summary>
+        /// 处理图像饱和度
+        /// </summary>
+        /// <param name="color"></param>
+        /// <param name="lumMod"></param>
+        /// <param name="lumOff"></param>
+        /// <returns></returns>
+        public static string GetColorLumModAndLumOff(Color color, int lumMod = 0, int lumOff = 0)
         {
-            float[] rgb = { color.R, color.G, color.B };
-            float r = rgb[0];
-            float g = rgb[1];
-            float b = rgb[2];
-            float min = Math.Min(r, Math.Min(g, b));
-            float max = Math.Max(r, Math.Max(g, b));
-
-            float h = 0;
-            if (max == min) h = 0;
-            else if (max == r) h = ((60 * (g - b) / (max - min)) + 360) % 360;
-            else if (max == g) h = (60 * (b - r) / (max - min)) + 120;
-            else if (max == b) h = (60 * (r - g) / (max - min)) + 240;
-
-            float l = (max + min) / 2;
-            l = l * (float)lumMod / 100000f + (float)lumOff / 100000f;
-
-            float s = 0;
-            if (max == min) s = 0;
-            else if (l <= .5f) s = (max - min) / (max + min);
-            else s = (max - min) / (2 - max - min);
-
-            h = h % 360.0f;
-            h /= 360f;
-
-            float q = 0;
-            if (l < 0.5) q = l * (1 + s);
-            else q = (l + s) - (s * l);
-            float p = 2 * l - q;
-            r = Math.Max(0, HueToRGB(p, q, h + (1.0f / 3.0f)));
-            g = Math.Max(0, HueToRGB(p, q, h));
-            b = Math.Max(0, HueToRGB(p, q, h - (1.0f / 3.0f)));
-
-            //r = Math.Min(r, 1.0f);
-            //g = Math.Min(g, 1.0f);
-            //b = Math.Min(b, 1.0f);
-
-            return Color.FromArgb((int)r, (int)g, (int)b);
+            ColorHSL colorHSL = RgbToHsl(new ColorRGB(color.R, color.G, color.B));
+            colorHSL.L = colorHSL.L * lumMod / 100_000.0 + lumOff / 100_000.0;
+            ColorRGB colorRGB = HslToRgb(colorHSL);
+            return ColorTranslator.ToHtml(Color.FromArgb(colorRGB.R, colorRGB.G, colorRGB.B)).Replace("#","");
         }
+
         /// <summary>
         /// 
         /// </summary>
@@ -276,21 +220,18 @@ namespace TEAMModelOS.SDK.Helper.Common.ColorHelper
         /// <param name="pa">混合原色占百分比/100% </param>
         /// <param name="Type">Shade 与黑色混合  Tint与白色混合</param>
         /// <returns></returns>
-        public static Color GetShadeOrTintColor(Color color ,double pa,string Type) {
-            double rw = 0, gw = 0, bw = 0;
-            int ra = color.R, ga = color.G, ba = color.B;
-            if (Type.Equals("Shade")) {
-                rw = 0; gw = 0; bw = 0;
+        public static string  GetShadeOrTintColor(Color color, double val, string Type)
+        {
+            ColorConverter converter = new ColorConverter();
+            if (Type.Equals("Shade"))
+            {
+                return converter.SetShade(color, val);
             }
-            if (Type.Equals("Tint"))
+            else if (Type.Equals("Tint"))
             {
-                rw = 255; gw = 255; bw = 255;
+                return converter.SetTint(color, val);
             }
-            double pw = 1 - pa;
-            double rn = rw * pw + ra * pa;
-            double gn = gw * pw + ga * pa;
-            double bn = bw * pw + ba * pa;
-            return Color.FromArgb((int)rn, (int)gn, (int)bn); 
+            else { return ColorTranslator.ToHtml(color).Replace("#",""); }
         }
 
     }

+ 22 - 0
TEAMModelOS.SDK/Helper/Common/StringHelper/StringHelper.cs

@@ -95,5 +95,27 @@ namespace TEAMModelOS.SDK.Helper.Common.StringHelper
             }
             return list;
         }
+
+        /// <summary>
+        /// 截取两个字符串中间的字符串
+        /// </summary>
+        /// <param name="sourse"></param>
+        /// <param name="startstr"></param>
+        /// <param name="endstr"></param>
+        /// <returns></returns>
+        public static string SubMidString(string sourse, string startstr, string endstr)
+        {
+            string result = string.Empty;
+            int startindex, endindex;
+            startindex = sourse.IndexOf(startstr);
+            if (startindex == -1)
+                return result;
+            string tmpstr = sourse.Substring(startindex + startstr.Length);
+            endindex = tmpstr.IndexOf(endstr);
+            if (endindex == -1)
+                return result;
+            result = tmpstr.Remove(endindex);
+            return result;
+        }
     }
 }

+ 18 - 1
TEAMModelOS.SDK/Helper/Network/HttpHelper/HttpContextHelper.cs

@@ -109,7 +109,7 @@ namespace TEAMModelOS.SDK.Helper.Network.HttpHelper
             if (request.Query.ContainsKey(Constants.ACCESS_TOKEN))
             {
                 tokenHeader = request.Query[Constants.ACCESS_TOKEN];
-                tokenHeader = tokenHeader.Trim();
+                //tokenHeader = tokenHeader;
             }
             if (string.IsNullOrEmpty(tokenHeader))
             {
@@ -127,5 +127,22 @@ namespace TEAMModelOS.SDK.Helper.Network.HttpHelper
             }
             return claimValues;
         }
+        public static string GetAuthorizationCode(IHttpContextAccessor httpContextAccessor)
+        {
+            var tokenHeader = "";
+            HttpRequest request = httpContextAccessor.HttpContext.Request;
+            if (request.Headers.ContainsKey(Constants.AUTHORIZATION))
+            {
+                tokenHeader = request.Headers[Constants.AUTHORIZATION];
+                //tokenHeader = tokenHeader.ToString().Substring("Bearer ".Length).Trim();
+                tokenHeader = tokenHeader.Replace("Bearer ", "");
+            }
+            if (request.Query.ContainsKey(Constants.ACCESS_TOKEN))
+            {
+                tokenHeader = request.Query[Constants.ACCESS_TOKEN];
+                tokenHeader = tokenHeader.Trim();
+            }
+            return tokenHeader;
+        }
     }
 }

+ 18 - 0
TEAMModelOS.SDK/Module/AzureBlob/Container/AzureBlobModel.cs

@@ -72,6 +72,24 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
             Extension = fileName.Substring(fileName.LastIndexOf(".") + 1, (fileName.Length - fileName.LastIndexOf(".") - 1)); //扩展名
             Timestamp = DateTimeHelper.ConvertToDateTime(time);
         }
+        public AzureBlobModel(string fileName, string Container, string groupName, string newName,string sha1Code, string contentType, long length)
+        {
+            long time = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
+            ContentType = contentType;
+            ContentDisposition = "form-data; name=\"file\"; filename=\"" + fileName + "\"";
+            FileName = fileName;
+            // Headers = f.Headers.Values;
+            Sha1Code = sha1Code;
+            RealName = groupName + "/" + newName;
+            Folder = groupName;
+            Length = length;
+            Name = "file";
+            UploadTime = time;
+            PartitionKey = Container;
+            RowKey = Guid.NewGuid().ToString();
+            Extension = fileName.Substring(fileName.LastIndexOf(".") + 1, (fileName.Length - fileName.LastIndexOf(".") - 1)); //扩展名
+            Timestamp = DateTimeHelper.ConvertToDateTime(time);
+        }
         [Required(ErrorMessage = "{0} 必须填写")]
         public string Folder { get; set; }
         [Required(ErrorMessage = "{0} 必须填写")]

+ 82 - 0
TEAMModelOS.SDK/Module/AzureBlob/Implements/AzureBlobDBRepository.cs

@@ -341,5 +341,87 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Implements
             };
             return model;
         }
+        public async Task<AzureBlobModel> UploadFileByFolder(Stream fileSteam, string folder, string fileName, string fileSpace = "pptx", bool contentTypeDefault = true)
+        {
+            
+            string groupName = fileSpace + "/" + folder;
+          //  string newFileName = sha1Code;
+            // await InitializeBlob(DateTime.Now.ToString("yyyyMMdd"));
+            blobContainer = blobClient.GetContainerReference(groupName);
+            StorageUri url = blobContainer.StorageUri;
+            string[] names = fileName.Split(".");
+          //  string name ;
+            //for (int i = 0; i < names.Length - 1; i++)
+            //{
+            //    name = name + names[i];
+            //}
+            //if (names.Length <= 1)
+            //{
+            //    name =  newFileName;
+            //}
+            //else
+            //{
+            //    name = newFileName + "." + names[names.Length - 1];
+            //}
+            //var parsedContentDisposition = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
+            //var filename = Path.Combine(parsedContentDisposition.FileName.Trim('"'));
+            var blockBlob = blobContainer.GetBlockBlobReference(fileName);
+            string fileext = fileName.Substring(fileName.LastIndexOf(".") > 0 ? fileName.LastIndexOf(".") : 0);
+            if (!contentTypeDefault)
+            {
+                ContentTypeDict.dict.TryGetValue(fileext, out string content_type);
+                if (!string.IsNullOrEmpty(content_type))
+                {
+                    blockBlob.Properties.ContentType = content_type;
+                }
+                else {
+                    blockBlob.Properties.ContentType = "application/octet-stream";
+                }
+            }
+            await blockBlob.UploadFromStreamAsync(fileSteam);
+            AzureBlobModel model = new AzureBlobModel(fileName, _options.Container, groupName, fileName, folder, blockBlob.Properties.ContentType , fileSteam.Length)
+            {
+                BlobUrl = url.PrimaryUri.ToString().Split("?")[0] + "/" + fileName
+            };
+            return model;
+        }
+
+
+        public async Task<AzureBlobModel> UploadTextByFolder(string text, string folder, string fileName, string fileSpace = "pptx", bool contentTypeDefault = true)
+        {
+            string groupName = fileSpace + "/" + folder;
+            blobContainer = blobClient.GetContainerReference(groupName);
+            StorageUri url = blobContainer.StorageUri;
+        
+            var blockBlob = blobContainer.GetBlockBlobReference(fileName);
+            string fileext = fileName.Substring(fileName.LastIndexOf(".") > 0 ? fileName.LastIndexOf(".") : 0);
+            string content_type = "application/octet-stream";
+            if (!contentTypeDefault)
+            {
+                ContentTypeDict.dict.TryGetValue(fileext, out string contenttype);
+                if (!string.IsNullOrEmpty(contenttype))
+                {
+                    blockBlob.Properties.ContentType = contenttype;
+                    content_type = contenttype;
+                }
+                else
+                {
+                    blockBlob.Properties.ContentType = content_type;
+                }
+            }
+            else
+            {
+                blockBlob.Properties.ContentType = content_type;
+            }
+
+            long length = System.Text.Encoding.Default.GetBytes(text).Length;
+            await blockBlob.UploadTextAsync(text);
+            AzureBlobModel model = new AzureBlobModel(fileName, _options.Container, groupName, fileName, folder, blockBlob.Properties.ContentType, length)
+            {
+                BlobUrl = url.PrimaryUri.ToString().Split("?")[0] + "/" + fileName
+            };
+            return model;
+        }
+
     }
 }

+ 3 - 0
TEAMModelOS.SDK/Module/AzureBlob/Interfaces/IAzureBlobDBRepository.cs

@@ -2,6 +2,7 @@
 using Microsoft.AspNetCore.Http;
 using System.Collections.Generic;
 using System.Threading.Tasks;
+using System.IO;
 
 namespace TEAMModelOS.SDK.Module.AzureBlob.Interfaces
 {
@@ -12,6 +13,8 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Interfaces
         Task<AzureBlobModel> UploadPath(string path, string fileSpace = "common", bool contentTypeDefault = false);
         Task<AzureBlobModel> UploadObject(string fileName, object obj, string fileSpace = "common", bool contentTypeDefault = true);
         Task<AzureBlobModel> UploadText(string fileName, string text, string fileSpace = "common", bool contentTypeDefault = true);
+        Task<AzureBlobModel> UploadFileByFolder(Stream fileSteam, string folder, string fileName, string fileSpace = "pptx", bool contentTypeDefault = true);
+        Task<AzureBlobModel> UploadTextByFolder(string text, string folder, string fileName, string fileSpace = "pptx", bool contentTypeDefault = true);
 
 
     }

+ 0 - 6
TEAMModelOS.SDK/Module/PowerPointX/Model/PPTXSlide.cs

@@ -13,12 +13,6 @@ namespace TEAMModelOS.SDK.Module.PowerPointX.Model
         }
         //public int Width { get; set; }
         //public int Height { get; set; }
-        [XmlElement(typeof(PPTXChart))]
-        [XmlElement(typeof(PPTXConnector))]
-        [XmlElement(typeof(PPTXContainer))]
-        [XmlElement(typeof(PPTXPicture))]
-        [XmlElement(typeof(PPTXPosition))]
-        [XmlElement(typeof(PPTXTable))]
         public List<PPTXElement> Elements { get; set; }
 
 

+ 0 - 1
TEAMModelOS.SDK/Module/PowerPointX/Model/PPTXText.cs

@@ -62,6 +62,5 @@ namespace TEAMModelOS.SDK.Module.PowerPointX.Model
             Words	1	
             文本下划线枚举 (字)。 当项目作为 xml 序列出时,其值为"单词"。
          */
-
     }
 }

+ 3 - 5
TEAMModelOS.SDK/Module/PowerPointX/PresentationConvert.cs

@@ -922,17 +922,15 @@ namespace TEAMModelOS.SDK.Module.PowerPointX
             if (lumModVal > 0 || lumOffVal > 0)
             {
                 Color color = ColorTranslator.FromHtml("#" + schemeColor);
-                color = ColorHelper.GetColorLumModAndOff(color, lumModVal, lumOffVal);
-                schemeColor = ColorTranslator.ToHtml(color).Replace("#", "");
+                schemeColor = ColorHelper.GetColorLumModAndLumOff(color, lumModVal, lumOffVal);
             }
             if (tintVal > 0)
             {
-                schemeColor = ColorTranslator.ToHtml(ColorHelper.GetShadeOrTintColor(ColorTranslator.FromHtml("#" + schemeColor), tintVal / 100000.0000, "Tint")).Replace("#", "");
+                schemeColor = ColorHelper.GetShadeOrTintColor(ColorTranslator.FromHtml("#" + schemeColor), tintVal, "Tint");
             }
             if (shadeVal > 0)
             {
-
-                schemeColor = ColorTranslator.ToHtml(ColorHelper.GetShadeOrTintColor(ColorTranslator.FromHtml("#" + schemeColor), shadeVal / 100000.0000, "Shade")).Replace("#", "");
+                schemeColor = ColorHelper.GetShadeOrTintColor(ColorTranslator.FromHtml("#" + schemeColor), shadeVal, "Shade");
             }
 
             return schemeColor;

+ 2 - 1
TEAMModelOS.SDK/TEAMModelOS.SDK.csproj

@@ -4,7 +4,8 @@
     <TargetFramework>netcoreapp2.2</TargetFramework>
     <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
     <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
-    <Version>1.0.5</Version>
+    <Version>1.0.14</Version>
+    <PackageReleaseNotes>增加两个字符串截取及文件类型获得扩展名</PackageReleaseNotes>
   </PropertyGroup>
 
   <ItemGroup>

+ 1 - 1
TEAMModelOS.Test.PPTX/PresentationConvert.cs

@@ -841,7 +841,7 @@ namespace TEAMModelOS.Test.PPTX
             if (lumModVal > 0 || lumOffVal > 0)
             {
                 Color color = ColorTranslator.FromHtml("#" + schemeColor);
-                color = ColorHelper.GetColorLumModAndOff(color, lumModVal, lumOffVal);
+                color = ColorHelper.GetColorLumModAndLumOff(color, lumModVal, lumOffVal);
                 schemeColor = ColorTranslator.ToHtml(color).Replace("#", "");
             }
             if (tintVal > 0)

+ 9 - 0
TEAMModelOS.Test.PPTX/Program.cs

@@ -19,6 +19,15 @@ namespace TEAMModelOS.Test.PPTX
         static void
             Main(string[] args)
         {
+
+
+            Color color1 = Color.FromArgb(255, 192, 0);
+            ColorHSL colorHSL1 = ColorHelper.RgbToHsl(new ColorRGB(255, 192, 0));
+            ColorRGB colorRGB = ColorHelper.HslToRgb(new ColorHSL { H=colorHSL1.H, S = colorHSL1.S , L = colorHSL1.L });
+            Color  color2=  ColorHelper.GetColorLumModAndLumOff(color1, 20000, 80000);
+            Color color4 = Color.FromArgb(0, 0, 0);
+            Color color5 = ColorHelper.GetShadeOrTintColor(color4, 75000.0d / 100_000.0d, "Tint");
+
             string json =JsonSerialization.ToJson(new Dem { aaa="aaa",bbb="bbb",ccc="cccc",ddd="ddd",eee="eeee"});
             string jwt = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NjQ0NzE1MjUsImhvc3RuYW1lIjoiaHR0cHM6Ly9vcGVuY2VudGVyLml5dW54aWFvLm5ldCIsInNpZ25JbiI6ImFwcEp1bXBMb2dpbi1jZDVmNWMzMC1iMjk5LTExZTktYmFhZC05M2Q0YmYxNmJjNDciLCJpYXQiOjE1NjQ0NzA5MjUsImp0aSI6IjVkM2YwMzRmMDAwMDA4ZmMxZjM2ZTgwNiJ9.OnvKd7eaSzMU-4hgYdTfNGxoaAU8YgZcIZXvrv9g3mNw_59txzibEgvQahkCjxXeKiVnltmP7WGhNqbN8Hp30A";
             var urls = "https://opencenter.iyunxiao.net/passport/v2/user/info";

+ 8 - 1
TEAMModelOS.sln

@@ -29,7 +29,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TEAMModelOS.Test.OfficeDoc"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamModelOS.OfficeDoc.Test", "TeamModelOS.OfficeDoc.Test\TeamModelOS.OfficeDoc.Test.csproj", "{E5E2E853-AAE9-45D8-A59B-BC054434F9AD}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TEAMModelOS.Test.PPTX", "TEAMModelOS.Test.PPTX\TEAMModelOS.Test.PPTX.csproj", "{7A537ADF-61AC-42D6-AF49-A0AAF57E3B5C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TEAMModelOS.Test.PPTX", "TEAMModelOS.Test.PPTX\TEAMModelOS.Test.PPTX.csproj", "{7A537ADF-61AC-42D6-AF49-A0AAF57E3B5C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPTXMLParser", "PPTXMLParser\PPTXMLParser.csproj", "{E66B53C5-B0AA-462C-8D2B-8A5D00B4CE90}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -73,6 +75,10 @@ Global
 		{7A537ADF-61AC-42D6-AF49-A0AAF57E3B5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{7A537ADF-61AC-42D6-AF49-A0AAF57E3B5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{7A537ADF-61AC-42D6-AF49-A0AAF57E3B5C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{E66B53C5-B0AA-462C-8D2B-8A5D00B4CE90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{E66B53C5-B0AA-462C-8D2B-8A5D00B4CE90}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E66B53C5-B0AA-462C-8D2B-8A5D00B4CE90}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{E66B53C5-B0AA-462C-8D2B-8A5D00B4CE90}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -87,6 +93,7 @@ Global
 		{98D55090-23B0-4362-872D-A184D95085C6} = {CFBC5D78-72A7-4330-B779-F6826194F48A}
 		{E5E2E853-AAE9-45D8-A59B-BC054434F9AD} = {CFBC5D78-72A7-4330-B779-F6826194F48A}
 		{7A537ADF-61AC-42D6-AF49-A0AAF57E3B5C} = {CFBC5D78-72A7-4330-B779-F6826194F48A}
+		{E66B53C5-B0AA-462C-8D2B-8A5D00B4CE90} = {CFBC5D78-72A7-4330-B779-F6826194F48A}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {5C55F286-63D0-4235-BDE0-D7AD32B0EDEB}

+ 3 - 0
TEAMModelOS/ClientApp/api/schoolSetting.js

@@ -3,4 +3,7 @@ export default {
   schoolSettingSaveOrUpdate: function (data) {
     return post('/api/SchoolSystem/SaveOrUpdateAll',data);
   },
+  classroomSettingSaveOrUpdate: function (data) {
+    return post('/api/Classroom/SaveOrUpdateAll', data);
+  }
 }

+ 54 - 4
TEAMModelOS/ClientApp/app.js

@@ -1,5 +1,5 @@
 import Vue from 'vue'
-//import axios from 'axios'
+import axios from 'axios'
 import i18n from '@/locale';
 import router from './router/index'
 import store from './store'
@@ -50,14 +50,64 @@ Vue.prototype.$echarts = echarts
 Vue.prototype.common = commons;
 
 // Registration of global components
-Vue.component('icon', FontAwesomeIcon);
+Vue.component('icon', FontAwesomeIcon); 
+
+const _import = require('./router/_import_file.js')//获取组件的方法
+var getRouter //用来获取后台拿到的路由
+
+// 動態加路由
+if(!getRouter){
+  if (!getObjArr('router')) {
+    axios.get('/api/testAPI/GetTestAuth').then(res =>{  
+      getRouter = res.data.data;
+      saveObjArr('router', getRouter) //存储路由到localStorage
+      getRouter = filterAsyncRouter(getRouter) //过滤路由
+      // 存入vuex
+      store.state.authorization.antRouter = getRouter;
+      router.addRoutes(getRouter) //动态添加路由
+    });    
+  } else {
+    getRouter = getObjArr('router')//拿到路由
+    getRouter = filterAsyncRouter(getRouter) //过滤路由
+    // 存入vuex
+    store.state.authorization.antRouter = getRouter;
+    router.addRoutes(getRouter) //动态添加路由
+  }
+}
 
-//使用钩子函数对路由进行权限跳转
-router.beforeEach((to, from, next) => {
+router.beforeEach((to, from, next) => {  
   document.body.scrollTop = 0;
   next();
 });
 
+function saveObjArr(name, data) { // 存储数组对象的方法
+  sessionStorage.setItem(name, JSON.stringify(data))
+}
+
+function getObjArr(name) { // 获取数组对象的方法
+  return JSON.parse(window.sessionStorage.getItem(name));
+}
+
+function filterAsyncRouter(routers){
+  let newRouter = [];
+  routers.forEach(function(item){
+    let page = {
+      name: '',
+      path: '',
+      component: '',
+      meta:{
+        access:[]
+      }
+    };
+    page.name = item.component;
+    page.path = item.path;
+    page.meta.access = item.access;
+    page.component = _import(item.component);
+    newRouter.push(page)
+  }); 
+  return newRouter;
+}
+
 router.afterEach((to, from, next) => {
   document.body.scrollTop = 0;
 });

+ 1 - 0
TEAMModelOS/ClientApp/assets/image/pin.svg

@@ -0,0 +1 @@
+<svg id="圖層_1" data-name="圖層 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58.3 60"><defs><style>.cls-1{fill:#ff6b6a;}</style></defs><title>pin</title><polygon class="cls-1" points="55.3 0 29.1 38.6 3 0 55.3 0"/><polygon class="cls-1" points="29.1 48.9 7.5 16.9 0 16.9 29.1 60 58.3 16.9 50.8 16.9 29.1 48.9"/></svg>

BIN
TEAMModelOS/ClientApp/assets/image/school_plan.jpg


+ 5 - 56
TEAMModelOS/ClientApp/common/BaseExamList.vue

@@ -49,17 +49,17 @@
         periodList: ['所有学段','高中','初中'],
         gradeList: [],
         termList: [],
-        examTypeList: ['所有测验类型','模拟测验','校内测验','全国测验'],
+        examTypeList: ['所有测验类型','区域测验','校内测验','全国测验'],
         examList: [],
         examIndex: 0,
         typesTransfer: {
-          'A': '模拟测验',
+          'A': '区域测验',
           'B': '校内测验',
           'C': '全国测验'
         },
         colorTransfer: {
           '模拟测验':'#fbd103',
-          '校内测验':'#baecff',
+          '诊断测验':'#baecff',
           '全国测验':'#00ff8a'
         }
 
@@ -67,68 +67,17 @@
     },
     created() {
       this.examList = examList;
-      //this.examList.forEach(item => {
-      //  item.examType = this.typesTransfer[item.examType];
-      //})
     },
     methods: {
-
-      ////学段选择
-      //periodChange(val) {
-      //  if (val == 0) {
-      //    this.selectGrade = 0;
-      //    this.gradeChange(0);
-      //  } else if (val == 1) {
-      //    this.gradeList = ['所有年级', '高一', '高二', '高三'];
-      //    this.selectGrade = 1;
-      //    this.gradeChange(1);
-      //  } else {
-      //    this.gradeList = ['所有年级', '初一', '初二', '初三'];
-      //    this.selectGrade = 1;
-      //    this.gradeChange(1);
-      //  }
-
-      //},
-      ////年级选择
-      //gradeChange(val) {
-      //  this.termList = ['所有学年期', '上学期', '下学期'];
-      //  this.selectTerm = val == 0 ? 0 : 1;
-      //  this.termChange(this.selectTerm);
-      //},
-      ////学期选择
-      //termChange(val) {
-      //  console.log(this.gradeList[this.selectGrade]);
-      //  let currentGrade = this.gradeList[this.selectGrade];
-      //  let currentTerm = this.termList[val];
-      //  this.handleFilterExam(currentGrade, currentTerm);
-      //},
-      ////测验类型选择
-      //examTypeChange(val) {
-
-      //},
-
-
-      //handleFilterExam(grade, term) {
-      //  if (this.selectPeriod == 0 && grade == "所有年级" && term == "所有学年期") {
-      //    this.examList = examList;
-      //  } else {
-      //    console.log(grade, term);
-      //  this.examList = examList.filter(item => item.grade == grade && item.term == term);
-      //  console.log(this.examList);
-
-      //  }
-      //        },
-
-
       handleExamClick(index, item) {
+        let that = this;
         this.examIndex = index;
-        this.$router.push({ path: '/total', query: { index:index }});
         this.$emit('chooseExam', item);
+        that.$router.push({ path: '/total', query: { index:index }});
       },
 
       //查看更多评测列表
       goEvaluationList() {
-        //this.$emit('showEvaluationList');
         this.$router.push('/totalindex');
       }
     },

+ 7 - 5
TEAMModelOS/ClientApp/common/loading.vue

@@ -1,13 +1,13 @@
 <template>
   <div class="loading-container">
-    <div id="loadingBox" :style="{'margin-top':top+'px','border-width': borderWidth + 'px'}"></div>
+    <div id="loadingBox" :style="{'margin-top':top+'px','border-width': borderWidth + 'px','border-top-width': borderTopWidth + 'px'}"></div>
   </div>
 </template>
 
 <script>
     export default {
     name: "loadingBox",
-    props: ["top","borderColor","color","borderWidth"],
+    props: ["top","borderColor","color","borderWidth","borderTopWidth"],
     data() {
       return {
       }
@@ -29,15 +29,17 @@
     flex-direction:row;
     justify-content:center;
     background: rgba(102, 102, 102, 0.28);
+    z-index:9999;
   }
 
   #loadingBox {
     margin-top:200px;
     border: 3px solid hsla(185, 100%, 62%, 0.2);
-    border-top-color: #4c9cff;
+    border-top-color: #0ce4eb;
+    border-top-width:8px;
     border-radius: 50%;
-    width: 40px;
-    height: 40px;
+    width: 60px;
+    height: 60px;
     animation: spin .7s linear infinite;
   }
 

+ 93 - 26
TEAMModelOS/ClientApp/components/public/main/index.less

@@ -1,34 +1,101 @@
-.left-menu .ivu-collapse>.ivu-collapse-item, .panel-div .ivu-collapse>.ivu-collapse-item{
-  border: 0;
+// .ivu-collapse>.ivu-collapse-item{
+//   border: 0!important;
+// }
+// .ivu-collapse>.ivu-collapse-item>.ivu-collapse-header{
+//     line-height: 55px!important;;
+//     height: 55px!important;;
+// }
+// .ivu-collapse{
+//   border: 0!important;
+// }
+// .ivu-collapse-content{   
+    // background: -webkit-linear-gradient(left,#ffffff,#f2f2f2);
+    // background: -o-linear-gradient(right,#ffffff,#f2f2f2);
+    // background: -moz-linear-gradient(right,#ffffff,#f2f2f2);
+    // background: linear-gradient(to right,#ffffff,#f2f2f2);
+//     border-bottom: 1px solid #dcdee2;
+// }
+// .ivu-drawer-body::-webkit-scrollbar {
+//     width: 5px;
+// }
+// .ivu-drawer-body::-webkit-scrollbar-track {
+//   margin: 6px;
+//   background: transparent;
+// }
+// .ivu-drawer-body::-webkit-scrollbar-thumb {
+//   border-radius: 10px;
+//   background: #94998a;
+// }
+// .ivu-drawer-body::-webkit-scrollbar-thumb:hover {
+//   // background: #555;
+// }
+// .ivu-drawer-body::-webkit-scrollbar-button {
+//   display: none;
+// }
+
+
+// display: -webkit-flex;
+// display:         flex;
+// -webkit-align-items: center;
+//         align-items: center;
+// -webkit-justify-content: center;
+//         justify-content: center;
+
+.layout{
+  border: 1px solid #d7dde4;
+  background: #f5f7f9;
+  position: relative;
+  border-radius: 4px;
+  overflow: hidden;
+  height: 100%;
 }
-.left-menu .ivu-collapse>.ivu-collapse-item>.ivu-collapse-header, .panel-div .ivu-collapse>.ivu-collapse-item>.ivu-collapse-header{
-    line-height: 55px;
-    height: 55px;
+.layout-header-bar{
+  background: #fff!important;
+  box-shadow: 0 1px 1px rgba(0,0,0,.1)!important;
 }
-.left-menu .ivu-collapse, .panel-div .ivu-collapse{
-  border: 0;
+.layout-logo-left{
+  width: 90%;
+  height: 30px;
+  background: #5b6270;
+  border-radius: 3px;
+  margin: 15px auto;
 }
-.left-menu .ivu-collapse-content,.panel-div  .ivu-collapse-content{   
-    background: -webkit-linear-gradient(left,#ffffff,#f2f2f2);
-    background: -o-linear-gradient(right,#ffffff,#f2f2f2);
-    background: -moz-linear-gradient(right,#ffffff,#f2f2f2);
-    background: linear-gradient(to right,#ffffff,#f2f2f2);
-    border-bottom: 1px solid #dcdee2;
+.menu-icon{
+  transition: all .3s;
 }
-.ivu-drawer-body::-webkit-scrollbar {
-    width: 5px;
+.rotate-icon{
+  transform: rotate(-90deg);
 }
-.ivu-drawer-body::-webkit-scrollbar-track {
-  margin: 6px;
-  background: transparent;
+.menu-item{  
+  &.ivu-menu-light{
+    background-color: #f3f3f3;
+  }
+  span{
+    display: inline-block;
+    overflow: hidden;
+    width: 150px;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    vertical-align: bottom;
+    transition: width .2s ease .2s;
+  }
 }
-.ivu-drawer-body::-webkit-scrollbar-thumb {
-  border-radius: 10px;
-  background: #94998a;
+.menu-item i{
+  transform: translateX(0px);
+  transition: font-size .2s ease, transform .2s ease;
+  vertical-align: middle;
+  font-size: 16px;
+  &.ivu-menu-submenu-title-icon{
+    right: 10px;
+  }
 }
-.ivu-drawer-body::-webkit-scrollbar-thumb:hover {
-  // background: #555;
-}
-.ivu-drawer-body::-webkit-scrollbar-button {
-  display: none;
+.collapsed-menu span{
+  width: 0px;
+  transition: width .2s ease;
 }
+.collapsed-menu i{
+  transform: translateX(5px);
+  transition: font-size .2s ease .2s, transform .2s ease .2s;
+  vertical-align: middle;
+  font-size: 22px;
+}

+ 159 - 177
TEAMModelOS/ClientApp/components/public/main/index.vue

@@ -3,181 +3,145 @@
 </style>
 
 <template>
-    <div id="test" style="height: 100%;">
-        <div style="height: 6%;border-bottom: 1px solid #333;">
-            <Row style="padding: 10px 10px;">
-                <Col :span="23">
-                    <a @click="value2 = true" style="display: inline-block;vertical-align: middle;padding: 6px;">
-                        <Icon :size="26" :color="'#5c6b77'" type="md-menu" />
-                        <Drawer placement="left" :closable="false" v-model="value2" :styles="{padding:'15px 0 0 45px'}" :width="313">
-                            <div style="padding: 5px;">
-                                <a style="background-color: #ccc;display: inline-block;vertical-align: middle;padding: 5px;border-radius: 20px;" @click="value2 = false">
-                                    <Icon :size="26" :color="'#5c6b77'" type="md-menu" />
-                                </a>
-                                <h2 class="ellipsis" style="width: 180px;font-size: 1.6em;color:#d0b772;display: inline-block;vertical-align: middle;margin-left: 20px;">醍摩豆智慧雲平台雲平台雲平台</h2>
-                            </div>
-                            <div class="panel-div" style="margin-top:60px;">
-                                <Collapse v-model="collapse1" accordion>
-                                    <Panel class="panel-style" name="1" style="background-color: #ffffff;" hide-arrow>
-                                        <Icon style="font-size: 1.9em;display: inline-block;vertical-align: middle;color:#5c6b77;transform: rotate(0deg);-webkit-transform: rotate(0deg);-ms-transform: rotate(0deg);transform: rotate(0deg);" type="md-school" />
-                                        <h3 style="font-size: 1.25em;display: inline-block;vertical-align: middle;color:#5c6b77;">智慧校園管理</h3>
-                                        <p slot="content" style=" padding: 7px 0 7px 40px;">
-                                            <ul>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">智慧校園管理</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">學生帳號管理</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">教師帳號管理</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">班級管理</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">軟體暨授權項目管理</h3></li>
-                                            </ul>
-                                        </p>
-                                    </Panel>
-                                    <Panel  name="2" style="background-color: #ffffff;" hide-arrow>
-                                        <Icon style="font-size: 1.9em;display: inline-block;vertical-align: middle;color:#5c6b77;-webkit-transform: rotate(0deg);-ms-transform: rotate(0deg);transform: rotate(0deg);" type="ios-book-outline" />
-                                        <h3 style="font-size: 1.25em;display: inline-block;vertical-align: middle;color:#5c6b77;">教材內容管理</h3>
-                                        <p slot="content" style=" padding: 7px 0 7px 40px;">
-                                            <ul>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">校本課綱總攬</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">校本課綱管理</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">知識點管理</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">內容管理</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">題目/庫管理</h3></li>
-                                            </ul>
-                                        </p>
-                                    </Panel>
-                                    <Panel  name="3" style="background-color: #ffffff;" hide-arrow>
-                                        <Icon style="font-size: 1.9em;display: inline-block;vertical-align: middle;color:#5c6b77;-webkit-transform: rotate(0deg);-ms-transform: rotate(0deg);transform: rotate(0deg);" type="md-calendar" />
-                                        <h3 style="font-size: 1.25em;display: inline-block;vertical-align: middle;color:#5c6b77;">學習活動服務</h3>
-                                        <p slot="content" style=" padding: 7px 0 7px 40px;">
-                                            <ul>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">活動行事曆</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">學習活動儀表板</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">測驗與作業總攬</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">自主學習活動總攬</h3></li>
-                                            </ul>
-                                        </p>
-                                    </Panel>
-                                    <Panel  name="4" style="background-color: #ffffff;" hide-arrow>
-                                        <Icon style="font-size: 1.9em;display: inline-block;vertical-align: middle;color:#5c6b77;-webkit-transform: rotate(0deg);-ms-transform: rotate(0deg);transform: rotate(0deg);" type="md-walk" />
-                                        <h3 style="font-size: 1.25em;display: inline-block;vertical-align: middle;color:#5c6b77;">班親智慧服務</h3>
-                                        <p slot="content" style=" padding: 7px 0 7px 40px;">
-                                            <ul>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">區班校活動紀錄檔</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">全校成績總攬</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">操行成績總攬</h3></li>
-                                                <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><h3 style="font-size: 1.2em;display: inline-block;vertical-align: middle;color:#5c6b77;font-weight: 700;">學情分析儀表</h3></li>
-                                            </ul>
-                                        </p>
-                                    </Panel>
-                                </Collapse>
-                            </div>
-                        </Drawer>
-                    </a>
-                    <div style="display: inline-block;vertical-align: middle;margin-left: 15px;">
-                        <h2 style="font-size: 22px;color:#d0b772">醍摩豆智慧雲平台</h2>
-                        
-                    </div>
-                </Col>
-                <Col :span="1">
-                    <div style="text-align: right;">
-                        <Dropdown trigger="click" placement="bottom-end" style="margin-left: 20px">
-                            <a href="javascript:void(0)">
-                                <img style="width: 35px;cursor: pointer;" src="@/assets/image/touxiang.png">
-                            </a>
-                            <DropdownMenu slot="list">
-                                <div style="width: 250px;text-align:left;padding: 10px;">                                        
-                                    <img style="width: 35px;display:inline-block;margin-right: 16px;border-radius: 50%;" src="@/assets/image/touxiang.png">
-                                    <div style="display:inline-block;text-align:left;">
-                                        <h3>Osbert#1234</h3>
-                                        <h3>Osbert@habook.com.tw</h3>
-                                    </div>
-                                </div>
-                                <DropdownItem disabled divided style="color: #515a6e;cursor: pointer;text-align: left;">
-                                    <Icon size="15" :type="switch1 ? 'ios-moon-outline' : 'ios-sunny'" style="margin-right: 15px;" />深色主題
-                                    <i-switch v-model="switch1" @on-change="themeChange" style="margin-left: 10px;float:right;"></i-switch>
-                                </DropdownItem>
-                                <DropdownItem divided style="text-align: left;"><Icon size="15" type="md-settings" style="margin-right: 15px;" />選項</DropdownItem>
-                                <DropdownItem divided style="text-align: left;"><Icon size="15" type="md-log-out" style="margin-right: 15px;" />登出</DropdownItem>
-                            </DropdownMenu>
-                        </Dropdown>
-                    </div>
-                </Col>
-            </Row>
-        </div>
-        <div style="height: 94%;width: 100%;">
-            <div style="height: 100%;">
-                <div class="left-menu" style="height: 100%;width:3%;float: left;border-right: 1px solid #333;">
-                    <a style="text-align:center;display: block;vertical-align: middle;line-height: 55px!important;height: 55px!important;">
-                        <Icon style="font-size: 1.9em;color:#5c6b77;" type="md-home" />
-                    </a>
-                    <Collapse v-model="collapse1" accordion>
-                        <Panel class="panel-style" name="1" style="background-color: #ffffff;" hide-arrow>
-                            <Icon style="font-size: 1.9em;color:#5c6b77;transform: rotate(0deg);-webkit-transform: rotate(0deg);-ms-transform: rotate(0deg);transform: rotate(0deg);" type="md-school" />
-                            <p slot="content" style="text-align: center;">
-                                <ul>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-school" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-school" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-school" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-school" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-school" /></li>
-                                </ul>
-                            </p>
-                        </Panel>
-                        <Panel class="panel-style" name="2" style="background-color: #ffffff;" hide-arrow>
-                            <Icon style="font-size: 1.9em;color:#5c6b77;transform: rotate(0deg);-webkit-transform: rotate(0deg);-ms-transform: rotate(0deg);transform: rotate(0deg);" type="ios-book-outline" />
-                            <p slot="content" style="text-align: center;">
-                                <ul>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="ios-book-outline" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="ios-book-outline" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="ios-book-outline" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="ios-book-outline" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="ios-book-outline" /></li>
-                                </ul>
-                            </p>
-                        </Panel>
-                        <Panel class="panel-style" name="3" style="background-color: #ffffff;" hide-arrow>
-                            <Icon style="font-size: 1.9em;color:#5c6b77;transform: rotate(0deg);-webkit-transform: rotate(0deg);-ms-transform: rotate(0deg);transform: rotate(0deg);" type="md-calendar" />
-                            <p slot="content" style="text-align: center;">
-                                <ul>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-calendar" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-calendar" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-calendar" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-calendar" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-calendar" /></li>                                    
-                                </ul>
-                            </p>
-                        </Panel>
-                        <Panel class="panel-style" name="4" style="background-color: #ffffff;" hide-arrow>
-                            <Icon style="font-size: 1.9em;color:#5c6b77;transform: rotate(0deg);-webkit-transform: rotate(0deg);-ms-transform: rotate(0deg);transform: rotate(0deg);" type="md-walk" />
-                            <p slot="content" style="text-align: center;">
-                                <ul>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-walk" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-walk" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-walk" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-walk" /></li>
-                                    <li style="list-style-type: none;margin-bottom: 15px;cursor: pointer;"><Icon style="font-size: 1.3em;" type="md-walk" /></li>                                    
-                                </ul>
-                            </p>
-                        </Panel>                        
-                    </Collapse>    
-                    <!-- <a style="text-align:center;display: block;vertical-align: middle;padding: 30px 15px;">
-                        <Icon :size="26" :color="'#5c6b77'" font type="md-home" />
-                    </a>
-                    <a style="text-align:center;display: block;vertical-align: middle;padding: 30px 15px;">
-                        <Icon :size="26" :color="'#5c6b77'" font type="md-school" />
-                    </a>
-                    <a style="text-align:center;display: block;vertical-align: middle;padding: 30px 15px;">
-                        <Icon :size="26" :color="'#5c6b77'" font type="ios-book-outline" />
-                    </a>
-                    <a style="text-align:center;display: block;vertical-align: middle;padding: 30px 15px;">
-                        <Icon :size="26" :color="'#5c6b77'" font type="md-calendar" />
-                    </a>
-                    <a style="text-align:center;display: block;vertical-align: middle;padding: 30px 15px;">
-                        <Icon :size="26" :color="'#5c6b77'" font type="md-walk" />
-                    </a> -->
+    <div class="layout">
+        <Layout style="height: 100%;">
+            <Sider ref="side1" :width="256" hide-trigger collapsible :collapsed-width="100" v-model="isCollapsed" style="background-color: #f3f3f3;">
+                <div style="height: 64px;padding: 10px;">
+                    sdfsdf
                 </div>
-                <div  style="height: 100%;width:97%;float: left;"><router-view/></div>
-            </div>
-        </div>
+                <Menu active-name="0"  width="auto" :class="menuitemClasses">
+                    <MenuItem name="0">
+                        <Icon type="md-home"></Icon>
+                        <span>首頁</span>
+                    </MenuItem>
+                    <Submenu name="1">
+                        <template slot="title">
+                            <Icon type="md-school" />
+                            <span>智慧校園管理</span>
+                        </template>
+                        <MenuItem name="1-1">
+                            <Icon type="ios-paper" />
+                            <span>智慧校園管理</span>
+                        </MenuItem>
+                        <MenuItem name="1-2">
+                            <Icon type="ios-paper" />
+                            <span>學生帳號管理</span>
+                        </MenuItem>
+                        <MenuItem name="1-3">
+                            <Icon type="ios-paper" />
+                            <span>教師帳號管理</span>
+                        </MenuItem>
+                        <MenuItem name="1-4">
+                            <Icon type="ios-paper" />
+                            <span>班級管理</span>
+                        </MenuItem>
+                        <MenuItem name="1-5">
+                            <Icon type="ios-paper" />
+                            <span>軟體暨授權項目管理</span>
+                        </MenuItem>
+                    </Submenu>
+                    <Submenu name="2">
+                        <template slot="title">
+                            <Icon type="ios-book-outline" />
+                            <span>教材內容管理</span>
+                        </template>
+                        <MenuItem name="2-1">
+                            <Icon type="ios-paper" />
+                            <span>校本課綱總攬</span>
+                        </MenuItem>
+                        <MenuItem name="2-2">
+                            <Icon type="ios-paper" />
+                            <span>校本課綱管理</span>
+                        </MenuItem>
+                        <MenuItem name="2-3">
+                            <Icon type="ios-paper" />
+                            <span>知識點管理</span>
+                        </MenuItem>
+                        <MenuItem name="2-4">
+                            <Icon type="ios-paper" />
+                            <span>內容管理</span>
+                        </MenuItem>
+                        <MenuItem name="2-5">
+                            <Icon type="ios-paper" />
+                            <span>題目/庫管理</span>
+                        </MenuItem>
+                    </Submenu>
+                    <Submenu name="3">
+                        <template slot="title">
+                            <Icon type="md-calendar" />
+                            <span>學習活動服務</span>
+                        </template>
+                        <MenuItem name="3-1">
+                            <Icon type="ios-paper" />
+                            <span>活動行事曆</span>
+                        </MenuItem>
+                        <MenuItem name="3-2">
+                            <Icon type="ios-paper" />
+                            <span>學習活動儀錶板</span>
+                        </MenuItem>
+                        <MenuItem name="3-3">
+                            <Icon type="ios-paper" />
+                            <span>測驗與作業總攬</span>
+                        </MenuItem>
+                        <MenuItem name="3-4">
+                            <Icon type="ios-paper" />
+                            <span>自主學習活動總攬</span>
+                        </MenuItem>
+                    </Submenu>
+                    <Submenu name="4">
+                        <template slot="title">
+                            <Icon type="ios-book-outline" />
+                            <span>班級智慧服務</span>
+                        </template>
+                        <MenuItem name="4-1">
+                            <Icon type="ios-paper" />
+                            <span>區班校活動紀錄簿</span>
+                        </MenuItem>
+                        <MenuItem name="4-2">
+                            <Icon type="ios-paper" />
+                            <span>全校成績總攬</span>
+                        </MenuItem>
+                        <MenuItem name="4-3">
+                            <Icon type="ios-paper" />
+                            <span>操行成績總攬</span>
+                        </MenuItem>
+                        <MenuItem name="4-4">
+                            <Icon type="ios-paper" />
+                            <span>學積分析儀表</span>
+                        </MenuItem>
+                    </Submenu>
+                </Menu>
+            </Sider>
+            <Layout>
+                <Header :style="{padding: 0}" class="layout-header-bar">
+                    <Icon @click.native="collapsedSider" :class="rotateIcon" :style="{margin: '0 20px'}" type="md-menu" size="24"></Icon>
+                    <h2 style="font-size: 1.6em;color:#d0b772;display: inline-block;vertical-align: middle;">醍摩豆智慧雲平台雲平台雲平台</h2>
+                    <Dropdown trigger="click" placement="bottom-end" style="    float: right;padding: 0 10px;vertical-align: middle;">
+                        <a style="display: inline-block;vertical-align: middle;height: 35px;" href="javascript:void(0)">
+                            <img style="width: 35px;cursor: pointer;" src="@/assets/image/touxiang.png">
+                        </a>
+                        <DropdownMenu slot="list">
+                            <DropdownItem disabled style="color: #515a6e;cursor: pointer;text-align: left;">
+                                <img style="width: 35px;display:inline-block;margin-right: 16px;border-radius: 50%;" src="@/assets/image/touxiang.png">
+                                <div style="display:inline-block;text-align:left;">
+                                    <h3>Osbert#1234</h3>
+                                    <h3>Osbert@habook.com.tw</h3>
+                                </div>
+                            </DropdownItem>
+                            <DropdownItem disabled divided style="color: #515a6e;cursor: pointer;text-align: left;">
+                                <Icon size="15" :type="switch1 ? 'ios-moon-outline' : 'ios-sunny'" style="margin-right: 15px;" />深色主題
+                                <i-switch v-model="switch1" @on-change="themeChange" style="margin-left: 10px;float:right;"></i-switch>
+                            </DropdownItem>
+                            <DropdownItem divided style="text-align: left;"><Icon size="15" type="md-settings" style="margin-right: 15px;" />選項</DropdownItem>
+                            <DropdownItem divided style="text-align: left;"><Icon size="15" type="md-log-out" style="margin-right: 15px;" />登出</DropdownItem>
+                        </DropdownMenu>
+                    </Dropdown>
+                </Header>              
+                <Content :style="{background: '#fff', minHeight: '260px'}">
+                    <router-view/>
+                </Content>
+            </Layout>      
+        </Layout> 
     </div>
 </template>
 
@@ -185,9 +149,24 @@
 export default {
     data () {
         return {
+            isCollapsed: false,
             value2: false,
             switch1: false,
-            collapse1: 0,
+            collapse1: '0',
+        }
+    },
+    computed: {
+        rotateIcon () {
+            return [
+                'menu-icon',
+                this.isCollapsed ? 'rotate-icon' : ''
+            ];
+        },
+        menuitemClasses () {
+            return [
+                'menu-item',
+                this.isCollapsed ? 'collapsed-menu' : ''
+            ]
         }
     },
     created(){
@@ -197,11 +176,14 @@ export default {
         themeChange (status) {
             if(status){
                 let x = document.getElementsByTagName("html")[0]; // 抓取html TAG
-                x.setAttribute("dark", true); // 設定新屬性 並給值
+                x.setAttribute("white", true); // 設定新屬性 並給值
             } else {
                 let x = document.getElementsByTagName("html")[0]; // 抓取html TAG
-                x.removeAttribute("dark"); // 刪除屬性
+                x.removeAttribute("white"); // 刪除屬性
             }
+        },
+        collapsedSider () {
+            this.$refs.side1.toggleCollapse();
         }
     },
     mounted(){

+ 372 - 273
TEAMModelOS/ClientApp/components/student-analysis/total/BaseBar.vue

@@ -1,304 +1,403 @@
 <template>
-    <div id="myBar"></div>
+  <div id="myBar"></div>
 </template>
 
 <script>
-export default {
-  name: "hello",
-  data() {
-    return {
-      msg: "Welcome to Your Vue.js App"
-    };
-  },
-  mounted() {
-    this.drawLine();
-
-  },
-  methods: {
-    drawLine() {
-      // 基于准备好的dom,初始化echarts实例
-      let myBar = this.$echarts.init(document.getElementById("myBar"));
+  export default {
+    name: "hello",
+    props: ['echartsData'],
+    data() {
+      return {
+        subjectList: [],
+        lineData: 440,
+        areaData: 490.5
+      };
+    },
+    created() {
+      this.subjectList = this.echartsData;
+      this.subjectList.forEach(item => {
+        item.className = '初一' + item.id + '班'
+      })
+    },
+    mounted() {
+      this.drawLine(this.subjectList);
+    },
+    methods: {
+      drawLine(data) {
+        // 基于准备好的dom,初始化echarts实例
+        let myBar = this.$echarts.init(document.getElementById("myBar"));
 
-      // 指定图表的配置项和数据
-      var option = {
-        dataset: {
-        // 提供一份数据。
-          source: [
-              ['class', '语文', '数学', '英语', '生物', '化学','区级平均分'],
-              ['初一1班', 43.3, 85.8 , 40, 43.3, 85.8 , 200],
-              ['初一2班', 83.1, 73.4 , 50, 43.3, 85.8 , 200],
-              ['初一3班', 86.4, 35.2 , 60, 43.3, 85.8 , 200],
-              ['初一4班', 86.4, 25.2 , 30, 43.3, 85.8 , 200],
-              ['初一5班', 86.4, 62.2 , 60, 43.3, 85.8 , 200],
-              ['初一6班', 86.4, 65.2 , 70, 43.3, 85.8 , 200],
-              ['初一7班', 86.4, 45.2 , 40, 43.3, 85.8 , 200],
-              ['初一8班', 86.4, 25.2 , 70, 43.3, 85.8 , 200],
-              ['初一9班', 86.4, 65.2 , 35, 43.3, 85.8 , 200],
-              ['初一10班', 86.4, 35.2 , 30, 43.3, 85.8 , 200],
-              ['初一11班', 86.4, 45.2 , 60, 43.3, 85.8 , 200],
-              ['初一12班', 86.4, 65.2 , 70, 43.3, 85.8 , 200],
-              ['初一13班', 86.4, 75.2 , 30, 43.3, 85.8 , 200]
-            ] 
-        },
-        // ---- legend ----
-        legend: {
-          //  data:['班级进线人数','班级总人数']
-          textStyle: {
-            color:"#e4eadb"
-          }
-        },
-        // ---  提示框 ----
-        tooltip: {
-          show: true, // 是否显示提示框,默认为true
-          trigger: "axis", // 数据项图形触发
-          axisPointer: {
-            type: "shadow",
-            axis: "auto",
-            shadowStyle: {
-              color: "rgba(128,128,128,0.1)"
+        // 指定图表的配置项和数据
+        var option = {
+          legend: {
+            data: ['语文', '数学', '英语', '生物', '化学', '物理', '校级平均分', '区级平均分'],
+            textStyle: {
+              color: "#e4eadb"
             }
           },
-          padding: 5,
-          textStyle: {
-            color: "#fff"
-          },
-            formatter: function (value) {
-                let arr = '';
-                for (var i = 0; i < value.length; i++) {
-                  //console.log(value[i].seriesName,666666)
-                  var datalist = value[i].seriesName + ' : ' + value[i].data[i+1]+'<br>';
-                  arr += datalist;
-                };
-                return arr;
-             }
-          
-        },
-        grid: {
-          show: false,
-          containLabel: true,
-          height: 480,
-          width: "90%",
-          x2: "5%",
+          // ---  提示框 ----
           tooltip: {
-            show: true,
-            trigger: "axis", // 触发类型
+            show: true, // 是否显示提示框,默认为true
+            trigger: "axis", // 数据项图形触发
+            axisPointer: {
+              type: "shadow",
+              axis: "auto",
+              shadowStyle: {
+                color: "rgba(128,128,128,0.1)"
+              }
+            },
+            padding: 5,
             textStyle: {
-              color: "#666"
+              color: "#fff"
             },
-          }
-        },
-        dataZoom: {
-          show: true,
-          realtime: true,
-          handleSize: 20,
-          textStyle: {
-            color:'#f1f1f1'
-          },
-          height: 15,
-          start: 0,
-          end: 100,
-        },
-        xAxis: {
-          show: true, // 是否显示
-          position: "bottom", // x轴的位置
-          offset: 0, // x轴相对于默认位置的偏移
-          type: "category", // 轴类型, 默认为 'category'
-          name: "月份", // 轴名称
-          nameLocation: "end", // 轴名称相对位置
-          nameTextStyle: {
-            color: "transparent",
-            padding: [5, 0, 10, -5]
-          },
-          nameGap: 35, // 坐标轴名称与轴线之间的距离
-          nameRotate: 0, // 坐标轴名字旋转
-          axisLine: {
-            show: false, // 是否显示
-            symbol: ["none", "arrow"], // 是否显示轴线箭头
-            symbolSize: [8, 8], // 箭头大小
-            symbolOffset: [0, 7], // 箭头位置
-            lineStyle: {
-              color: "#6aabef",
-              width: 1,
-              type: "solid"
+            formatter: function (value) {
+              let arr = value[0].name + '<br>';
+              let sum = 0;
+              for (var i = 0; i < value.length; i++) {
+                var datalist = value[i].marker + value[i].seriesName + ' : ' + value[i].data + '<br>';
+                if (i == value.length - 1 || i == value.length - 2) {
+                  sum += 0;
+                } else {
+                  sum += value[i].data;
+                }
+                arr += datalist;
+              };
+              return arr + value[value.length - 1].marker + '班级平均分 :' + sum;
             }
+
           },
-          axisTick: {
-            // 坐标轴 刻度
-            show: false, // 是否显示
-            inside: true, // 是否朝内
-            length: 3, // 长度
-            lineStyle: {
-              // 默认取轴线的样式
-              color: "#989898",
-              width: 2,
-              type: "solid"
+          grid: {
+            show: false,
+            containLabel: true,
+            height: 480,
+            width: "90%",
+            x2: "5%",
+            tooltip: {
+              show: true,
+              trigger: "axis", // 触发类型
+              textStyle: {
+                color: "#666"
+              },
             }
           },
-          axisLabel: {
-            // 坐标轴标签
+          dataZoom: [{
+            "show": true,
+            "height": 18,
+            "xAxisIndex": [
+              0
+            ],
+            bottom: 30,
+            "start": 0,
+            "end": 100,
+            handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
+            handleSize: '110%',
+            handleStyle: {
+              color: "#d3dee5",
+
+            },
+            textStyle: {
+              color: "#fff"
+            },
+            borderColor: "#90979c"
+          }, {
+            "type": "inside",
+            "show": true,
+            "height": 15,
+            "start": 0,
+            "end": 100
+          }],
+          xAxis: {
             show: true, // 是否显示
-            inside: false, // 是否朝内
-            rotate: 45, // 旋转角度
-            margin: 15, // 刻度标签与轴线之间的距离
-            color: "#989898", // 默认取轴线的颜色,
-            fontSize: 14,
-            fontFamily: "Microsoft YaHei"
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-               color: '#4c504a',
-            }
-          },
-          splitArea: {
-            show: false // 是否显示,默认为false
-          },
-        },
-        //   ------   y轴  ----------
-        yAxis: {
-          show: true, // 是否显示
-          position: "left", // y轴位置
-          offset: 0, // y轴相对于默认位置的偏移
-          type: "value", // 轴类型,默认为 ‘category’
-          nameLocation: "end", // 轴名称相对位置value
-          nameTextStyle: {
-            color: "#fff",
-            padding: [5, 0, 0, 5] // 坐标轴名称相对位置
+            position: "bottom", // x轴的位置
+            offset: 0, // x轴相对于默认位置的偏移
+            type: "category", // 轴类型, 默认为 'category'
+            name: "月份", // 轴名称
+            nameLocation: "end", // 轴名称相对位置
+            nameTextStyle: {
+              color: "transparent",
+              padding: [5, 0, 10, -5]
+            },
+            nameGap: 35, // 坐标轴名称与轴线之间的距离
+            nameRotate: 0, // 坐标轴名字旋转
+            axisLine: {
+              show: false, // 是否显示
+              symbol: ["none", "arrow"], // 是否显示轴线箭头
+              symbolSize: [8, 8], // 箭头大小
+              symbolOffset: [0, 7], // 箭头位置
+              lineStyle: {
+                color: "#6aabef",
+                width: 1,
+                type: "solid"
+              }
+            },
+            axisTick: {
+              // 坐标轴 刻度
+              show: false, // 是否显示
+              inside: true, // 是否朝内
+              length: 3, // 长度
+              lineStyle: {
+                // 默认取轴线的样式
+                color: "#989898",
+                width: 2,
+                type: "solid"
+              }
+            },
+            axisLabel: {
+              // 坐标轴标签
+              show: true, // 是否显示
+              inside: false, // 是否朝内
+              rotate: 45, // 旋转角度
+              margin: 15, // 刻度标签与轴线之间的距离
+              color: "#989898", // 默认取轴线的颜色,
+              fontSize: 14,
+              fontFamily: "Microsoft YaHei"
+            },
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: '#4c504a',
+              }
+            },
+            splitArea: {
+              show: false // 是否显示,默认为false
+            },
+            data: data.map(item => item.className)
           },
-          nameGap: 15, // 坐标轴名称与轴线之间的距离
-          nameRotate: 270, // 坐标轴名字旋转
+          //   ------   y轴  ----------
+          yAxis: {
+            show: true, // 是否显示
+            position: "left", // y轴位置
+            offset: 0, // y轴相对于默认位置的偏移
+            type: "value", // 轴类型,默认为 ‘category’
+            nameLocation: "end", // 轴名称相对位置value
+            nameTextStyle: {
+              color: "#fff",
+              padding: [5, 0, 0, 5] // 坐标轴名称相对位置
+            },
+            nameGap: 15, // 坐标轴名称与轴线之间的距离
+            nameRotate: 270, // 坐标轴名字旋转
 
-          axisLine: {
-            show: false, // 是否显示
-            symbol: ["none", "arrow"], // 是否显示轴线箭头
-            symbolSize: [8, 8], // 箭头大小
-            symbolOffset: [0, 7], // 箭头位置
-            lineStyle: {
-              color: "#6aabef",
-              width: 1,
-              type: "solid"
-            }
-          },
-          axisTick: {
-            show: false, // 是否显示
-            inside: true, // 是否朝内
-            length: 3, // 长度
-            lineStyle: {
-              color: "#989898", // 默认取轴线的颜色
-              width: 2,
-              type: "solid"
+            axisLine: {
+              show: false, // 是否显示
+              symbol: ["none", "arrow"], // 是否显示轴线箭头
+              symbolSize: [8, 8], // 箭头大小
+              symbolOffset: [0, 7], // 箭头位置
+              lineStyle: {
+                color: "#6aabef",
+                width: 1,
+                type: "solid"
+              }
+            },
+            axisTick: {
+              show: false, // 是否显示
+              inside: true, // 是否朝内
+              length: 3, // 长度
+              lineStyle: {
+                color: "#989898", // 默认取轴线的颜色
+                width: 2,
+                type: "solid"
+              }
+            },
+            axisLabel: {
+              show: true, // 是否显示
+              inside: false, // 是否朝内
+              rotate: 0, // 旋转角度
+              margin: 8, // 刻度标签与轴线之间的距离
+              color: "#989898", // 默认轴线的颜色
+              fontSize: 12,
+              fontFamily: "Microsoft YaHei"
+            },
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: "#4c504a",
+                width: 0.5,
+                type: "solid"
+              }
             }
           },
-          axisLabel: {
-            show: true, // 是否显示
-            inside: false, // 是否朝内
-            rotate: 0, // 旋转角度
-            margin: 8, // 刻度标签与轴线之间的距离
-            color: "#989898", // 默认轴线的颜色
-            fontSize: 12,
-            fontFamily: "Microsoft YaHei"
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: "#4c504a",
-              width: 0.5,
-              type: "solid"
-            }
-          }
-        },
-        series: [
-          {
-            name:"语文",
-            type: "bar", 
-            stack: '英语',
-            legendHoverLink: true, 
-            itemStyle: {
-              color: "#db615e",
-              width: 20,
+          series: [
+            {
+              name: "语文",
+              type: "bar",
+              stack: '英语',
+              legendHoverLink: true,
+              itemStyle: {
+                color: "#db615e",
+                width: 20,
+              },
+              barWidth: 40,
+              data: data.map(item => item.chinese)
             },
-          },
-          {
-            name:"数学",
-            type: "bar", 
-            stack: '英语',
-            legendHoverLink: true,
-            itemStyle: {
-              color: "#db8dd2",
-              width: 20,
+            {
+              name: "数学",
+              type: "bar",
+              stack: '英语',
+              legendHoverLink: true,
+              itemStyle: {
+                color: "#db8dd2",
+                width: 20,
+              },
+              barWidth: 40,
+              data: data.map(item => item.math)
             },
-          },
-          {
-            name:"英语",
-            type: "bar", 
-            stack: '英语',
-            legendHoverLink: true,
-            itemStyle: {
-              color: "#42beda",
-              width: 20,
+            {
+              name: "英语",
+              type: "bar",
+              stack: '英语',
+              legendHoverLink: true,
+              itemStyle: {
+                color: "#42beda",
+                width: 20,
+              },
+              barWidth: 40,
+              data: data.map(item => item.english)
             },
-            barWidth:40
-          },
-          {
-            name:"生物",
-            type: "bar", 
-            stack: '英语',
-            legendHoverLink: true,
-            itemStyle: {
-              color: "#1eb58d",
-              width: 20,
+            {
+              name: "生物",
+              type: "bar",
+              stack: '英语',
+              legendHoverLink: true,
+              itemStyle: {
+                color: "#1eb58d",
+                width: 20,
+              },
+              barWidth: 40,
+              data: data.map(item => item.biology)
             },
-          },
-          {
-            name:"化学",
-            type: "bar", 
-            stack: '英语',
-            legendHoverLink: true,
-            itemStyle: {
-              color: "#dbaf4f",
-              width: 10,
+            {
+              name: "化学",
+              type: "bar",
+              stack: '英语',
+              legendHoverLink: true,
+              itemStyle: {
+                color: "#99ccff",
+                width: 10,
+              },
+              data: data.map(item => item.chemistry)
             },
-          },
-          {
-          type: "line",
-          itemStyle: {
-            color: "#66ff99",
-            width: 2,
-          },
-          symbol: 'none',
-          lineStyle: {
-            type: "dashed",
-            width:0,
-          },
-          markLine: {
-            data: [
-              { type: 'average' }
-            ],
-            lineStyle: {
-              color: '#66ff99',
-              type: "dashed",
-              width:2
-            }
+            {
+              name: "物理",
+              type: "bar",
+              stack: '英语',
+              legendHoverLink: true,
+              itemStyle: {
+                color: "#dbaf4f",
+                width: 10,
+              },
+              barWidth: 40,
+              data: data.map(item => item.physics)
             },
-        },
-        ]
-      };
+            {
+              name: "校级平均分",
+              type: "line",
+              itemStyle: {
+                color: "#66ff99",
+                width: 2,
+              },
+              symbol: 'none',
+              lineStyle: {
+                type: "dashed",
+                width: 0,
+              },
+              markLine: {
+                data: [
+                  { type: 'average' }
+                ],
+                lineStyle: {
+                  color: '#66ff99',
+                  type: "dashed",
+                  width: 2
+                }
+              },
+              data: data.map(item => this.lineData)
+            },
+            {
+              name: "区级平均分",
+              type: "line",
+              itemStyle: {
+                color: "#11C2EE",
+                width: 2,
+              },
+              symbol: 'none',
+              lineStyle: {
+                type: "dashed",
+                width: 0,
+              },
+              markLine: {
+                data: [
+                  { type: 'average' }
+                ],
+                lineStyle: {
+                  color: '#11C2EE',
+                  type: "dashed",
+                  width: 2
+                }
+              },
+              data: data.map(item => this.areaData)
+            },
+          ]
+        };
+
+        // 绘制图表
+        myBar.setOption(option);
+        window.addEventListener("resize", function () {
+          myBar.resize();
+        });
 
-      // 绘制图表
-      myBar.setOption(option);
-      window.addEventListener("resize", function() {
-        myBar.resize();
-      });
+        myBar.on('legendselectchanged', function (obj) {
+          var selected = obj.selected;
+          var legend = obj.name;
+          let arr = [];
+          for (let i in selected) {
+            let o = {};
+            o[i] = selected[i];
+            arr.push(o)
+          }
+          arr.length = 6;
+          let keyArr = [];
+          arr.forEach(item => {
+            for (let key in item) {
+              if (item[key]) {
+                keyArr.push(key);
+              }
+            }
+          })
+          if (keyArr.length) {
+            this.lineData = 440 - (100 - Math.random().toFixed(2) * 20) * (6 - keyArr.length);
+            this.areaData = 495 - (100 - Math.random().toFixed(2) * 20) * (6 - keyArr.length);
+          } else {
+            this.lineData = 0;
+            this.areaData = 0;
+          }
+          option.series[option.series.length - 2].data = [...Array(10).keys()].map(item => this.lineData);
+          option.series[option.series.length - 1].data = [...Array(10).keys()].map(item => this.areaData);
+          myBar.setOption(option);
+
+        });
+      }
+    },
+    computed: {
+      //获取最新柱状图数据
+      getBaseBarData() {
+        let list = this.$store.state.totalAnalysis.baseBarData;
+        return list;
+      }
+    },
+    watch: {
+      getBaseBarData(val) {
+        this.drawLine(val);
+      }
     }
-  }
-};
+  };
 </script>
 
 <style scoped>
-#myBar {
-  width: 100%;
-  height: 600px;
-  margin: 0 auto;
-  display: block;
-}
+
+  #myBar {
+    width: 100%;
+    height: 600px;
+    margin: 0 auto;
+    display: block;
+  }
 </style>

+ 42 - 25
TEAMModelOS/ClientApp/components/student-analysis/total/BaseEntryBar.vue

@@ -4,11 +4,9 @@
 
 <script>
 export default {
-    name: "hello",
     props: ['echartData'],
   data() {
     return {
-      msg: "Welcome to Your Vue.js App"
     };
   },
   mounted() {
@@ -43,6 +41,11 @@ export default {
           textStyle: {
             // 提示框内容的样式
             color: "#fff"
+          },
+          formatter: function (params) {
+            return params[0].name + '<br>' + params[0].marker + params[0].seriesName + ':' + params[0].data + '<br>'
+              + params[1].marker + params[1].seriesName + ':' + params[1].data + '<br>'
+             + params[2].marker + params[2].seriesName + ':' + params[2].data + '%'
           }
         },
         // ---- gird区域 ---
@@ -60,18 +63,32 @@ export default {
             },
           }
         },
-        dataZoom: {
-          show: true,
-          realtime: true,
-          type: "inside",
-        },
-        toolbox: {
-          show: true,
-          feature: {
-            magicType: { show: true, type: ['line', 'bar'] },
-            saveAsImage: { show: true }
-          }
-        },
+        dataZoom: [{
+            "show": true,
+            "height": 18,
+            "xAxisIndex": [
+              0
+            ],
+            bottom: 0,
+            "start": 0,
+            "end": 100,
+            handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
+            handleSize: '110%',
+            handleStyle: {
+              color: "#d3dee5",
+
+            },
+            textStyle: {
+              color: "#fff"
+            },
+            borderColor: "#90979c"
+          }, {
+            "type": "inside",
+            "show": true,
+            "height": 15,
+            "start": 0,
+            "end": 100
+          }],
         xAxis: {
           show: true, // 是否显示
           position: "bottom", // x轴的位置
@@ -294,9 +311,9 @@ export default {
           {
             name: '进线率',
             type: 'line',
-            color: "#42beda",
+            color: "#66cc00",
             itemStyle: {
-              color: '#42beda',
+              color: '#66cc00',
               borderColor: "#efefef",
               borderWidth:3
             },
@@ -322,15 +339,15 @@ export default {
       });
 
       let that = this;
-      myBar.on('click', function (params) {
-        let className = params.name;
-        if (className == "高二5班") {
-          //that.$router.push('')
-          that.$router.push({path: '/total/achievement/entryTables', replace: true})
-        } else {
-          that.$Message.warning("暂不支持查看其它班级数据!")
-        }
-      })
+      //myBar.on('click', function (params) {
+      //  let className = params.name;
+      //  if (className == "高二5班") {
+      //    //that.$router.push('')
+      //    that.$router.push({path: '/total/achievement/entryTables', replace: true})
+      //  } else {
+      //    that.$Message.warning("暂不支持查看其它班级数据!")
+      //  }
+      //})
     }
   }
 };

+ 2 - 2
TEAMModelOS/ClientApp/components/student-analysis/total/BaseKnowledgeBar.vue

@@ -7,8 +7,8 @@ export default {
     props: ['echartData'],
   data() {
     return {
-      x: ['方程与不等式', '图形的性质', '统计与概率', '函数', '图形的相似', '锐角三角函数', '几何图形初步', '投影与视图'],
-      y:[28,10,23,25,11,10,12,10]
+      x: ['方程与不等式', '图形的性质', '统计与概率', '函数', '图形的变化'],
+      y:[28,10,23,25,12]
     };
   },
   mounted() {

+ 182 - 150
TEAMModelOS/ClientApp/components/student-analysis/total/BaseKnowledgeDetail.vue

@@ -1,174 +1,206 @@
 <template>
-    <div id="knowledgeBar"></div>
+  <div id="knowledgeBar"></div>
 </template>
 
 <script>
-export default {
+  export default {
     name: "hello",
     props: ['echartData'],
-  data() {
-    return {
-      x: ['方程与不等式', '图形的性质', '统计与概率', '函数', '图形的相似', '锐角三角函数', '几何图形初步', '投影与视图'],
-      y: [28, 10, 23, 25, 11, 10, 12, 10],
-      activeItemIndex:""
-    };
-  },
-  mounted() {
-    this.drawLine();
+    data() {
+      return {
+        knowledgeData:[],
+        x: [],
+        y: [],
+        activeItemIndex: 0
+      };
+    },
 
-  },
-  methods: {
-    drawLine() {
-      // 基于准备好的dom,初始化echarts实例
-      let myBar = this.$echarts.init(document.getElementById("knowledgeBar"));
+    created() {
+      this.knowledgeData = this.echartData;
+      this.x = this.echartData.map(item => item.knowledgePoint);
+      let arr = this.echartData.map(item => item.gradeScoreRate);
+      arr.forEach(items => items = items.replace("\"", "").replace("\"", ""));
+      this.y = arr;
+      
+    },
 
-      // 指定图表的配置项和数据
-      var option = {
-        tooltip: {
-          show: true, // 是否显示提示框,默认为true
-          trigger: "axis", // 数据项图形触发
-          axisPointer: {
-            // 指示样式
-            type: "shadow",
-            axis: "auto",
-            shadowStyle: {
-              color: "rgba(128,128,128,0.1)"
-            }
-          },
-          padding: 5,
-          textStyle: {
-            // 提示框内容的样式
-            color: "#fff"
-          }
-        },
-        // ---- gird区域 ---
-        grid: {
-          show: false, // 是否显示直角坐标系网格
-          top: 30, // 相对位置 top\bottom\left\right
-          height:430,
-          containLabel: true, // gird 区域是否包含坐标轴的刻度标签
-        },
-        dataZoom: {
-          show: true,
-          realtime: true,
-          type: "inside",
-        },
-        xAxis: {
-          show: true, // 是否显示
-          position: "bottom", // x轴的位置
-          offset: 0, // x轴相对于默认位置的偏移
-          type: "category", // 轴类型, 默认为 'category'
-          name: "月份", // 轴名称
-          nameLocation: "end", // 轴名称相对位置
-          nameTextStyle: {
-            color: "transparent",
-            padding: [5, 0, 10, -5]
-          },
-          nameGap: 35, // 坐标轴名称与轴线之间的距离
-          nameRotate: 0, // 坐标轴名字旋转
-          axisLabel: {
-            // 坐标轴标签
-            show: true, // 是否显示
-            inside: false, // 是否朝内
-            margin: 15,
-            rotate:60,
-            color: "#989898", // 默认取轴线的颜色,
-          },
-          splitLine: {
-            show: false,
-            lineStyle: {
-               color: '#4c504a',
-            }
+    methods: {
+      drawLine() {
+        let _this = this;
+        // 基于准备好的dom,初始化echarts实例
+        let myBar = this.$echarts.init(document.getElementById("knowledgeBar"));
+        // 指定图表的配置项和数据
+        var option = {
+          tooltip: {
+            show: true, // 是否显示提示框,默认为true
+            trigger: "axis", // 数据项图形触发
+            axisPointer: {
+              // 指示样式
+              type: "shadow",
+              axis: "auto",
+              shadowStyle: {
+                color: "rgba(128,128,128,0.1)"
+              }
+            },
+            padding: 5,
+            textStyle: {
+              // 提示框内容的样式
+              color: "#fff"
+            },
+            formatter: function (value) {
+              //console.log(value);
+              return value[0].name + ' : ' + value[0].data + '%';
+             }
           },
-          splitArea: {
-            show: false // 是否显示,默认为false
+          // ---- gird区域 ---
+          grid: {
+            show: false, // 是否显示直角坐标系网格
+            top: 50, // 相对位置 top\bottom\left\right
+            height: 550,
+            containLabel: true, // gird 区域是否包含坐标轴的刻度标签
           },
-          data:this.x
-        },
-        yAxis: {
-          show: true, // 是否显示
-          position: "left", // y轴位置
-          offset: 0, // y轴相对于默认位置的偏移
-          type: "value", // 轴类型,默认为 ‘category’
-          nameLocation: "end", // 轴名称相对位置value
-          nameTextStyle: {
-            color: "#fff",
-            padding: [5, 0, 0, 5] // 坐标轴名称相对位置
+          dataZoom: {
+            show: true,
+            realtime: true,
+            type: "inside",
           },
-          nameGap: 15, // 坐标轴名称与轴线之间的距离
-          nameRotate: 270, // 坐标轴名字旋转
-          axisLine: {
-            show: false, // 是否显示
-            lineStyle: {
-              color: "#595959",
-              width: 1,
-              type: "solid"
-            }
+          xAxis: {
+            show: true, // 是否显示
+            position: "bottom", // x轴的位置
+            offset: 0, // x轴相对于默认位置的偏移
+            type: "category", // 轴类型, 默认为 'category'
+            name: "月份", // 轴名称
+            nameLocation: "end", // 轴名称相对位置
+            nameTextStyle: {
+              color: "transparent",
+              padding: [5, 0, 10, -5]
+            },
+            nameGap: 35, // 坐标轴名称与轴线之间的距离
+            nameRotate: 0, // 坐标轴名字旋转
+            axisLabel: {
+              // 坐标轴标签
+              show: true, // 是否显示
+              inside: false, // 是否朝内
+              margin: 15,
+              rotate: 60,
+              color: "#989898", // 默认取轴线的颜色,
+            },
+            splitLine: {
+              show: false,
+              lineStyle: {
+                color: '#4c504a',
+              }
+            },
+            splitArea: {
+              show: false // 是否显示,默认为false
+            },
+            data: this.x
           },
-          axisLabel: {
+          yAxis: {
             show: true, // 是否显示
-            inside: false, // 是否朝内
-            rotate: 0, // 旋转角度
-            margin: 8, // 刻度标签与轴线之间的距离
-            color: "#989898", // 默认轴线的颜色
-            fontSize: 12,
-            formatter: '{value} %' ,
+            position: "left", // y轴位置
+            offset: 0, // y轴相对于默认位置的偏移
+            type: "value", // 轴类型,默认为 ‘category’
+            nameLocation: "end", // 轴名称相对位置value
+            nameTextStyle: {
+              color: "#fff",
+              padding: [5, 0, 0, 5] // 坐标轴名称相对位置
+            },
+            nameGap: 15, // 坐标轴名称与轴线之间的距离
+            nameRotate: 270, // 坐标轴名字旋转
+            axisLine: {
+              show: false, // 是否显示
+              lineStyle: {
+                color: "#595959",
+                width: 1,
+                type: "solid"
+              }
+            },
+            axisLabel: {
+              show: true, // 是否显示
+              inside: false, // 是否朝内
+              rotate: 0, // 旋转角度
+              margin: 8, // 刻度标签与轴线之间的距离
+              color: "#989898", // 默认轴线的颜色
+              fontSize: 12,
+              formatter: '{value} %',
 
-          },
-          splitLine: {
-            show: true,
-            lineStyle: {
-              color: "#4c504a",
-              width: 0.5,
-              type: "solid"
-            }
-          }
-        },
-        series: [
-          {
-            type: "bar", 
-            itemStyle: {
-              color: "#4ad8f1",
-              //color: function (params) {//柱子颜色
-              //  console.log(params);
-              //  var key = params.dataIndex.replace(/<\/?.+?>/g, "").replace(/[\r\n]/g, "");
-              //  if (key == this.activeItemIndex) {
-              //        return "#FE8463";
-              //    }else{
-              //        return "#4ad8f1";
-              //    }
-              //},
-              width: 20,
             },
-            barWidth:30,
-            data:this.y
-          }]
-      };
+            splitLine: {
+              show: true,
+              lineStyle: {
+                color: "#4c504a",
+                width: 0.5,
+                type: "solid"
+              }
+            }
+          },
+          series: [
+            {
+              type: "bar",
+              animation: false,
+              itemStyle: {
+                color: function(params) {
+                    var key = params.dataIndex;
+                    if (key == _this.activeItemIndex) {
+                        return '#ff9999';
+                    } else {
+                        return '#1b9dff' 
+                    }
+                },
+                width: 20,
+              },
+              emphasis: {
+                itemStyle: {
+                  color: "#ff9999",
+                }
+              },
+              barWidth: 30,
+              data: this.y
+            }]
+        };
+
+        // 绘制图表
+        myBar.setOption(option);
+        window.addEventListener("resize", function () {
+          myBar.resize();
+        });
+
+        let that = this;
+        myBar.on('click', function (params) {
+          that.activeItemIndex = params.dataIndex;
+          that.$emit('handleItemClick', params);
+          myBar.setOption(option);
+        })
+      }
+    },
 
-      // 绘制图表
-      myBar.setOption(option);
-      window.addEventListener("resize", function() {
-        myBar.resize();
-      });
+    mounted() {
+      this.drawLine();
 
-      let that = this;
-      myBar.on('click', function (params) {
-        console.log(params);
-        that.activeItemIndex = params.dataIndex;
-        that.$emit('handleItemClick', params);
+    },
 
-      })
+    watch: {
+      echartData(val) {
+        this.x = this.echartData.map(item => item.knowledgePoint);
+        let arr = this.echartData.map(item => item.gradeScoreRate);
+        //arr.forEach(item => {
+        //  item = parseInt(item)
+        //});
+        this.y = arr.map(item => parseInt(item));
+        this.drawLine();
+      }
     }
-  }
-};
+  };
 </script>
 
 <!-- Add "scoped" attribute to limit CSS to this component only -->
 <style scoped>
-#knowledgeBar {
-  width: 100%;
-  height: 460px;
-  margin: 0 auto;
-  display: block;
-}
+
+  #knowledgeBar {
+    width: 100%;
+    height: 600px;
+    margin: 0 auto;
+    display: block;
+  }
 </style>

+ 61 - 71
TEAMModelOS/ClientApp/components/student-analysis/total/BaseLine.vue

@@ -1,43 +1,54 @@
 <template>
-  <div id="myLine"></div>
+  <div :id="ids" class="myLine"></div>
 </template>
 
 <script>
   export default {
     name: "hello",
+    props:['ids','echartsData'],
     data() {
       return {
+        y:[]
       };
     },
+    created() {
+      let echartsData = this.echartsData;
+      let arr = [];
+        arr.push(parseInt(echartsData.R1));
+        arr.push(parseInt(echartsData.R2));
+        arr.push(parseInt(echartsData.R3));
+        arr.push(parseInt(echartsData.R4));
+        arr.push(parseInt(echartsData.R5));
+        arr.push(parseInt(echartsData.R6));
+      this.y = arr;
+    },
     mounted() {
       this.drawLine();
-
+      let myLine = this.$echarts.init(document.getElementById(this.ids), 'chalk');
+      this.initWidth = document.getElementById(this.ids).offsetWidth;
+        let resize = {
+            width: 500,
+            height: 400
+        };
+         myLine.resize(resize);
     },
     methods: {
       drawLine() {
         // 基于准备好的dom,初始化echarts实例
-        let myLine = this.$echarts.init(document.getElementById("myLine"),'chalk');
+        let myLine = this.$echarts.init(document.getElementById(this.ids), 'chalk');
 
         // 指定图表的配置项和数据
         var option = {
-          dataset: {
-          // 提供一份数据。
-            source: [
-                ['product', '语文', '数学', '英语', '生物', '化学','总量'],
-                ['高三1班', 43.3, 85.8 , 50, 43.3, 45.8,280],
-                ['高三2班', 43.1, 73.4 , 50, 43.3, 45.8,280],
-                ['高三3班', 56.4, 65.2 , 30, 43.3, 55.8,280],
-                ['高三4班', 66.4, 45.2 , 50, 43.3, 65.8,280],
-                ['高三5班', 36.4, 55.2 , 40, 43.3, 45.8,280],
-                ['高三6班', 56.4, 65.2 , 50, 43.3, 43.8,280],
-                ['高三7班', 66.4, 65.2 , 30, 43.3, 55.8,280],
-                ['高三8班', 46.4, 63.2 , 40, 43.3, 42.8,280],
-                ['高三9班', 76.4, 63.2 , 30, 43.3, 45.8,280],
-                ['高三10班', 56.4, 62.2 , 40, 43.3, 53.8,280],
-                ['高三11班', 36.4, 65.2 , 30, 43.3, 65.8,280],
-                ['高三12班', 72.4, 53.9 , 50, 43.3, 44.8,280]
-              ] 
-          },
+           title: {
+	              text: 'R1-R6作答曲线',
+	              textStyle: {
+	        	       align: 'center',
+	                  color: '#333',
+	                  fontSize: 14,
+	              },
+	              top: '3%',
+	              left: '10%',
+	          },
           tooltip: {
             trigger: 'axis',
             axisPointer: {
@@ -45,6 +56,9 @@
               label: {
                 backgroundColor: '#6a7985'
               }
+            },
+            formatter: function (v) {
+              return v[0].name + ':' + v[0].data + '%'
             }
           },
           legend: {
@@ -52,13 +66,7 @@
               color:"#e4eadb"
             }
           },
-          toolbox: {
-            feature: {
-              magicType: { show: true, type: ['line', 'bar'] },
-              saveAsImage: {}
-            }
-          },
-          grid: {
+          gird: {
             left: '3%',
             right: '4%',
             bottom: '3%',
@@ -69,7 +77,7 @@
               type: 'category',
               boundaryGap: false,
               splitLine: {
-                show: true,
+                show: false,
                 lineStyle: {
                    color: '#4c504a',
                 }
@@ -82,6 +90,7 @@
                 color: "#989898", // 默认取轴线的颜色,
                 fontSize: 14
               },
+              data:['R1','R2','R3','R4','R5','R6']
             }
           ],
           yAxis: [
@@ -90,7 +99,7 @@
               splitLine: {
                 show: true,
                 lineStyle: {
-                   color: '#4c504a',
+                   color: '#ccc',
                 }
               },
             }
@@ -98,48 +107,29 @@
           series: [
             {
               type: 'line',
-              areaStyle: {
-                color:"#1f866b"
-              },
               lineStyle: {
-                color:"#1f866b"
-              }
-            },
-            {
-              type: 'line',
-              areaStyle: {
-                color:"#49b093"
+                color:"#66cc99"
               },
-              lineStyle: {
-                color:"#49b093"
-              }
-            },
-            {
-              type: 'line',
-              areaStyle: {
-                color:"#59a48c"
-              },
-              lineStyle: {
-                color:"#59a48c"
-              }
-            },
-            {
-              type: 'line',
-              areaStyle: {
-                color:"#59a48c"
+              itemStyle: {
+                color: '#66cc99',
+                borderColor: "#efefef",
+                borderWidth:3
               },
-              lineStyle: {
-                color:"#59a48c"
-              }
-            },
-            {
-              type: 'line',
-              areaStyle: {
-                color:"#59a48c"
-              },
-              lineStyle: {
-                color:"#59a48c"
-              }
+              //areaStyle: {
+              //  normal: {
+              //      color: this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+              //          offset: 0,
+              //          color: 'rgba(37, 129, 27, 0.3)'
+              //      }, {
+              //          offset: 0.8,
+              //          color: 'rgba(137, 119, 27, 0)'
+              //      }], false),
+              //      shadowColor: 'rgba(255, 255, 255, 0.2)',
+              //      shadowBlur: 10
+              //  }
+              //},
+              symbolSize: 10,
+              data: this.y
             }
           ]
         };
@@ -158,10 +148,10 @@
 <!-- Add "scoped" attribute to limit CSS to this component only -->
 <style scoped>
 
-  #myLine {
+  .myLine {
     width: 100%;
     height: 400px;
-    margin: 0 auto;
+    margin: 20px auto;
     display: block;
   }
 </style>

+ 14 - 22
TEAMModelOS/ClientApp/components/student-analysis/total/BaseLineBar.vue

@@ -8,7 +8,9 @@ export default {
     props: ['echartData'],
   data() {
       return {
-        echartDatas:[]
+        echartDatas: [],
+        gradeRate: 62.4,
+        areaRate:76.2
       };
     },
     created() {
@@ -59,19 +61,16 @@ export default {
             padding: 5,
             textStyle: {
               color: "#fff"
+            },
+            formatter: function (params) {
+              return params[0].name + '<br>'
+                + params[0].marker + params[0].seriesName + ':' + params[0].data + '%<br>'
+                + params[1].marker + params[1].seriesName + ':'+ params[1].data + '%<br>'
+                + params[2].marker + params[2].seriesName + ':'+ params[2].data + '%<br>'
             }
           },
-          gird: {
-            show: true, // 是否显示直角坐标系网格
+          grid: {
             top: 80, // 相对位置 top\bottom\left\right
-            containLabel: true, // gird 区域是否包含坐标轴的刻度标签
-            tooltip: {
-              show: true,
-              trigger: "axis", // 触发类型
-              textStyle: {
-                color: "#666"
-              }
-            }
           },
           dataZoom: {
             show: true,
@@ -137,14 +136,7 @@ export default {
                     {type : 'min', name: '最小值'}
                 ],
               },
-              //markLine: {
-              //  data: [
-              //      {type : 'average', name: '平均值'},
-              //  ],
-              //  textStyle: {
-              //    color:"#ebebeb"
-              //  }
-              //},
+              barWidth:50,
               data: echartData.map(item => item.entryRate)
             },
             {
@@ -168,7 +160,7 @@ export default {
                   type: "dashed"
                 }
               },
-              data: echartData.map(item => 60)
+              data: echartData.map(item => this.gradeRate)
             },
             {
               name:'区级得分率',
@@ -191,7 +183,7 @@ export default {
                   type: "dashed"
                 }
               },
-              data: echartData.map(item => 88)
+              data: echartData.map(item => this.areaRate)
             },
           ]
         };
@@ -210,7 +202,7 @@ export default {
 <style scoped>
 #stuAverageBar {
   width: 100%;
-  height: 560px;
+  height: 600px;
   margin: 0 auto;
   display: block;
 }

+ 265 - 112
TEAMModelOS/ClientApp/components/student-analysis/total/BaseMyTable.vue

@@ -1,40 +1,87 @@
 <template>
   <div class="myTable">
-      <Table :border="isShowBorder" :data="tableData" :columns="tableColumns"></Table>
-      <div style="margin: 10px;overflow: hidden">
-        <div style="float: right;">
-          <Page show-total
-                :current="1"
-                :total="tableDatas.length"
-                :page-size="pageSize"
-                @on-change="pageChange"
-                @on-page-size-change="pageSizeChange"
-                show-sizer />
-        </div>
+    <div class="table-subject-select"  v-if="tips || showSelect">
+      <Select v-model="subjectSelectVal" style="width:100px" v-if="showSelect" @on-change="onSelectChange">
+        <Option v-for="(item,index) in subjectList" :value="index" :key="index">{{ item.name }}</Option>
+      </Select>
+      <span class="table-tips" v-if="tips">{{tips}}</span>
+      <span class="table-tips" v-if="!tips">* 模拟数据,仅供参考</span>
+    </div>
+    <Table :border="isShowBorder" :data="tableData" :columns="tableColumns"></Table>
+    <div style="margin: 10px;overflow: hidden">
+      <div style="float: right;">
+        <Page show-total
+              :current="1"
+              :total="tableDatas.length"
+              :page-size="pageSize"
+              :page-size-opts="pageSizeOpts"
+              @on-change="pageChange"
+              @on-page-size-change="pageSizeChange"
+              show-sizer />
       </div>
+    </div>
   </div>
 </template>
 <script>
   export default {
-    props: ['columns','isScroll','tableDatas'],
+    props: {
+      columns: {
+        type: Array,
+        default:[]
+      },
+      isScroll: {
+        type: Boolean,
+        default:false
+      },
+      tableDatas: {
+        type: Array,
+        default:[]
+      },
+      showSelect: {
+        type: Boolean,
+        default:false
+      },
+      tips: {
+        type: String,
+        default:null
+      },
+      pageSize: {
+        type: Number,
+        default:10
+      }
+    },
     data() {
       return {
         isShowBorder: true,
-        tableData:[],
+        subjectSelectVal:1,
+        tableData: [],
         tableColumns: [],
+        pageSizeOpts:[5,10,20,30,40],
         poperData: [],
-        pageSize:10
+        subjectList: [
+          {
+            name:"语文"
+          },
+          {
+            name:"数学"
+          },
+          {
+            name:"英语"
+          },
+          {
+            name:"生物"
+          },
+          {
+            name:"化学"
+          },
+        ],
       }
     },
     created() {
       this.tableColumns = this.columns;
       this.tableData = this.tableDatas;
       this.columns.forEach(item => {
-        item.render = this[item.renderType] || '';
-      })
-
-      this.tableData.forEach(item => {
-        item.poperData = [Math.floor(Math.random() * 50 + 1),Math.floor(Math.random() * 100 + 1),Math.floor(Math.random() * 70 + 1)]
+        item.render = typeof item.renderType == 'function' ? item.renderType : this[item.renderType];
       })
 
       this.pageChange(1);
@@ -55,6 +102,10 @@
         this.pageChange(1);
       },
 
+      onSelectChange(val) {
+        this.$emit('onSelectChange', val);
+      },
+
       renderSimple() {
 
       },
@@ -64,17 +115,34 @@
         return h('span', {
           on: {
             click: function () {
-              that.$router.push('/total/achievement/earlyWarning')
+              that.$router.push({ name: 'earlyWarning', params: { name : params.row.name } })
             }
           },
           style: {
             cursor: 'pointer',
             color: "#00ffd2",
-            fontWeight:"bold"
+            fontWeight: "bold"
           }
         }, params.row.name)
       },
 
+      renderEventIndex(h, params) {
+        let that = this;
+        return h('span', {
+          on: {
+            click: function () {
+                that.$parent.$parent.$parent.isShowQuestions = true;
+                that.$router.push({ path: '/total/questionList', query: { QIndex: params.row.id } })
+            }
+          },
+          style: {
+            cursor: 'pointer',
+            color: "#00ffd2",
+            fontWeight: "bold"
+          }
+        }, params.row.id)
+      },
+
       //总分排名Render
       renderRank(h, params) {
         const row = params.row;
@@ -108,7 +176,7 @@
           props: {
             trigger: 'hover',
             placement: 'right',
-            transfer:true
+            transfer: true
           },
           on: {
             //鼠标触发气泡事件
@@ -118,7 +186,7 @@
             },
           }
         }, [
-          h('Icon', {
+            h('Icon', {
               props: {
                 type: row.classRank == 1 ? 'md-trending-up' : row.classRank == 2 ? 'md-trending-down' : 'md-git-commit',
                 color: row.classRank == 1 ? '#13ff13' : row.classRank == 2 ? '#fd4e4e' : 'yellow',
@@ -128,17 +196,17 @@
                 cursor: 'pointer'
               }
             }),
-          h('div', {
-            slot: 'content'
-          }, [ h('BaseChangeLine', {
-                props: {
-                  poperData: row.poperData,
-                  isLoad:true,
-                  lineColor:row.classRank == 1 ? 'green' : row.classRank == 2 ? '#fd4e4e' : '#ffcc33'
-                }
-              })
-            ])
-        ]);
+            h('div', {
+              slot: 'content'
+            }, [h('BaseChangeLine', {
+              props: {
+                poperData: row.poperData,
+                isLoad: true,
+                lineColor: row.classRank == 1 ? 'green' : row.classRank == 2 ? '#fd4e4e' : '#ffcc33'
+              }
+            })
+              ])
+          ]);
       },
       //排名变化
       renderRankChange(h, params) {
@@ -146,8 +214,8 @@
         return h('span', [
           h('Icon', {
             props: {
-              type: row.classRank == 1 ? 'md-arrow-up' : row.classRank == 2 ? 'md-arrow-down' : 'md-git-commit',
-              color: row.classRank == 1 ? '#13ff13' : row.classRank == 2 ? '#fd4e4e' : 'yellow',
+              type: (row.changesStatus == 1 && row.changesVal != 0) ? 'md-arrow-up' : (row.changesStatus == -1 && row.changesVal != 0) ? 'md-arrow-down' : 'md-git-commit',
+              color: (row.changesStatus == 1 && row.changesVal != 0) ? '#13ff13' : (row.changesStatus == -1 && row.changesVal != 0) ? '#fd4e4e' : 'yellow',
               size: '22'
             },
             style: {
@@ -158,9 +226,33 @@
             domProps: {
               className: "table-rank-value"
             },
-          }, row.classRank)
+          }, row.changesStatus == 0 ? '' : row.changesVal)
         ]);
       },
+
+      //是否进线
+      renderEntry(h, params) {
+        const row = params.row;
+        return h('span', [
+          h('span', {
+            domProps: {
+              className: "table-entry-status"
+            },
+            style: {
+              cursor: 'pointer',
+              background: row.score > 580 ? '#209a31' : row.score > 550 ? '#00767d' : 'transparent'
+            }
+          }, row.score > 580 ? '进' : row.score > 550 ? '踩' : ''),
+          h('span', {
+            domProps: {
+              className: "table-rank-value"
+            },
+          }, row.score)
+        ]);
+      },
+
+
+
       //变化状态
       renderStauts(h, params) {
         const row = params.row;
@@ -181,19 +273,19 @@
       renderHard(h, params) {
         let that = this;
         const row = params.row;
-        return h('span', row.hardList.map(function (item,index) {
-          return h('span',{
+        return h('span', row.hardList.map(function (item, index) {
+          return h('span', {
             style: {
               fontSize: '16px',
               fontWeight: "600",
               color: '#03efdb',
               cursor: 'pointer',
-              textDecoration:"underline"
+              textDecoration: "underline"
             },
             on: {
               'click': function () {
                 that.$parent.$parent.$parent.isShowQuestions = true;
-                that.$router.push({ path: '/total/questionList', query: { index : item }})
+                that.$router.push({ path: '/total/questionList', query: { QIndex: item } })
               }
             }
           }, item + (index == row.hardList.length - 1 ? '' : ' , '))
@@ -203,35 +295,40 @@
       renderCareful(h, params) {
         let that = this;
         const row = params.row;
-        return h('span', row.carefulList.map(function (item,index) {
-        return h('span',{
-          style: {
-            fontSize: '16px',
-            fontWeight: "600",
-            color: '#03efdb',
-            cursor: 'pointer',
-            textDecoration:"underline"
-          },
-          on: {
-            'click': function () {
-              that.$parent.$parent.$parent.isShowQuestions = true;
-              that.$router.push({ path: '/total/questionList', query: { index : item }})
+        return h('span', row.carefulList.map(function (item, index) {
+          return h('span', {
+            style: {
+              fontSize: '16px',
+              fontWeight: "600",
+              color: '#03efdb',
+              cursor: 'pointer',
+              textDecoration: "underline"
+            },
+            on: {
+              'click': function () {
+                that.$parent.$parent.$parent.isShowQuestions = true;
+                that.$router.push({ path: '/total/questionList', query: { QIndex: item } })
+              }
             }
-          }
-        }, item + (index == row.carefulList.length - 1 ? '' : ' , '))
-      }))
+          }, item + (index == row.carefulList.length - 1 ? '' : ' , '))
+        }))
+      },
+
+
+      renderPercent(h , params){
+        return h('span', params.row.scoreRate + '%');
       }
       },
 
-    mounted() {
+  mounted() {
 
-    },
+  },
 
-    watch: {
-      tableDatas: function (data) {
-        this.tableData = data;
-      }
+  watch: {
+    tableDatas: function (data) {
+      this.tableData = data;
     }
+  }
 
 
 
@@ -243,10 +340,10 @@
   .myTable {
     width: 100%;
     /*height: 400px;*/
-    padding:20px 0;
+    /*padding: 20px 0;*/
     margin: 0 auto;
     display: block;
-    user-select:none !important;
+    user-select: none !important;
   }
 
     .myTable .ivu-table td, .myTable .ivu-table th {
@@ -258,7 +355,7 @@
     .myTable .ivu-table-wrapper {
       /*border:none;*/
       border-color: #595959;
-      border-right:1px solid #595959;
+      border-right: 1px solid #595959;
     }
 
     .myTable .ivu-table::before, .myTable .ivu-table::after {
@@ -267,21 +364,21 @@
     }
 
     .myTable .ivu-table {
-      box-sizing:border-box;
+      box-sizing: border-box;
       /*border:1px solid #595959;*/
     }
 
-    .myTable .ivu-table, .myTable .ivu-table td {
-      background: #282828;
-      text-align: center;
-      position: relative;
-    }
+      .myTable .ivu-table, .myTable .ivu-table td {
+        background: #282828;
+        text-align: center;
+        position: relative;
+      }
 
-    .myTable .ivu-table th {
-      background: rgba(107, 107, 107, 0.19);
-      text-align: center;
-      position: relative;
-    }
+        .myTable .ivu-table th {
+          background: rgba(107, 107, 107, 0.19);
+          text-align: center;
+          position: relative;
+        }
 
     .myTable .ivu-table-sort {
       margin-left: -6px;
@@ -303,20 +400,20 @@
 
     .myTable .table-rank-value {
       margin-left: 10px;
-      vertical-align:middle;
-      font-size:14px;
+      vertical-align: middle;
+      font-size: 14px;
     }
 
     .myTable .table-rank-badge {
       position: absolute;
       right: 10px;
       top: 12px;
-      font-size:14px;
+      font-size: 14px;
       padding: 2px 14px;
       color: #e4eadb;
     }
 
-    .myTable .badge-wrap .ivu-icon , .myTable .badge-wrap img {
+    .myTable .badge-wrap .ivu-icon, .myTable .badge-wrap img {
       position: absolute;
       left: 7px;
       top: 12px;
@@ -324,67 +421,123 @@
 
 
     .myTable .ivu-page-item {
-      background:rgba(40,40,40,.5);
+      background: rgba(40,40,40,.5);
     }
 
-    .myTable .ivu-page-item:hover {
-      border-color:#e4eadb;
-    }
+      .myTable .ivu-page-item:hover {
+        border-color: #e4eadb;
+      }
 
     .myTable .ivu-page-item-active {
-      background:#fff;
+      background: #fff;
     }
 
 
-      .myTable .ivu-page-item a {
-        color:#f1f1f1;
-      }
+    .myTable .ivu-page-item a {
+      color: #f1f1f1;
+    }
 
     .myTable .ivu-page-next, .myTable .ivu-page-prev {
-      background:rgba(0,0,0,0);
+      background: rgba(0,0,0,0);
     }
 
-    .myTable .ivu-page-next a, .myTable .ivu-page-prev a{
-      color:#e4eadb;
-    }
+      .myTable .ivu-page-next a, .myTable .ivu-page-prev a {
+        color: #e4eadb;
+      }
 
       .myTable .ivu-page-next:hover, .myTable .ivu-page-prev:hover {
-        border-color:#e4eadb;
+        border-color: #e4eadb;
       }
 
 
     .myTable .ivu-page-item-active, .myTable .ivu-page-item:hover a {
-      border-color:#e4eadb;
+      border-color: #e4eadb;
     }
 
-    .myTable .ivu-page-item-active a {
-      color:#595959;
-    }
+      .myTable .ivu-page-item-active a {
+        color: #595959;
+      }
 
     .myTable .ivu-table-fixed {
       /*padding-top:3px;*/
-      background:#282828;
+      background: #282828;
     }
 
     .myTable .ivu-select-arrow {
-      top:72%;
+      top: 72%;
     }
 
     .myTable .ivu-table-fixed-right::before, .ivu-table-fixed::before {
-      height:0;
+      height: 0;
     }
 
-    .ivu-table-overflowX::-webkit-scrollbar {
-        height: 12px !important;
-     }
-    .ivu-table-overflowX::-webkit-scrollbar-track {
-        border-radius: 0px;
-        display:none;
-    }
-    .ivu-table-overflowX::-webkit-scrollbar-thumb {
-        border-radius: 0px;
-        background: #949494;
-    }
+  .table-subject-select {
+    position:relative;
+    display:flex;
+    justify-content:space-between;
+    padding-right:5px;
+    height:40px;
+    margin-bottom:10px;
+  }
+
+         .table-subject-select .table-tips{
+           font-size:14px;
+           color:#4cf8da;
+           font-weight:bold;
+           position:absolute;
+           right:5px;
+           top:0;
+         }
+
+      .table-subject-select .ivu-select {
+      margin: 5px 20px 15px 0;
+      height: 30px;
+  }
+
+      .table-subject-select .ivu-select-single .ivu-select-selection {
+          height: 30px;
+          background: transparent;
+          border: 1px solid #595959;
+          box-shadow: none;
+          color:#cecece; 
+      }
+
+      .table-subject-select .ivu-select-single .ivu-select-arrow {
+          top:76%;
+      }
 
+      .table-subject-select .ivu-select-single .ivu-select-placeholder {
+          height: 30px;
+          line-height: 30px;
+          font-size: 16px;
+      }
+
+
+  .myTable .table-entry-status {
+    position:absolute;
+    right:20px;
+    top:15px;
+    background:#209a31;
+    width:15px;
+    height:15px;
+    display:flex;
+    justify-content:center;
+    align-items:center;
+    padding:10px;
+  }
+
+  .ivu-table-overflowX::-webkit-scrollbar {
+    height: 12px !important;
+  }
+
+  .ivu-table-overflowX::-webkit-scrollbar-track {
+    border-radius: 0px;
+    display: none;
+  }
+
+  .ivu-table-overflowX::-webkit-scrollbar-thumb {
+    border-radius: 0px;
+    background: #949494;
+  }
 </style>
 

+ 56 - 59
TEAMModelOS/ClientApp/components/student-analysis/total/BasePie.vue

@@ -3,80 +3,77 @@
 </template>
 
 <script>
-// import func from '../../vue-temp/vue-editor-bridge';
-export default {
-  name: "BasePie",
-  data() {
-    return {
-    };
-  },
-  mounted() {
-    this.drawLine();
-  },
-  methods: {
-    drawLine() {
-      // 基于准备好的dom,初始化echarts实例
-      let myPie = this.$echarts.init(document.getElementById("myPie"),'chalk');
+  // import func from '../../vue-temp/vue-editor-bridge';
+  export default {
+    name: "BasePie",
+    data() {
+      return {
+        pieData: []
+      };
+    },
+    mounted() {
+      this.pieData = this.$store.state.totalAnalysis.pieData;
+      this.drawLine(this.pieData);
+    },
+    methods: {
+      drawLine(data) {
+        // 基于准备好的dom,初始化echarts实例
+        let myPie = this.$echarts.init(document.getElementById("myPie"), 'chalk');
 
-      // 指定图表的配置项和数据
-      var option = {
-        tooltip: {
-          trigger: "item",
-          formatter: "{a} <br/>{b} : {c} ({d}%)"
-        },
-        legend: {
-          x: "center",
-          y: "bottom",
-          data: [
-            "rose1",
-            "rose2",
-            "rose3",
-            "rose4",
-            "rose5"
-          ]
-        },
-        calculable: true,
-        series: {
+        // 指定图表的配置项和数据
+        var option = {
+          tooltip: {
+            trigger: "item",
+            formatter: "{a} <br/>{b} : {c} ({d}%)"
+          },
+          calculable: true,
+          series: {
             name: "知识点占比",
             type: "pie",
             radius: [70, 150],
             center: ["45%", 190],
             max: 100, // for funnel
             sort: "ascending", // for funnel
-            data: [
-              { value: 28, name: "方程与不等式",itemStyle:{color:'#00cc66'} },
-              { value: 10, name: "图形的性质",itemStyle:{color:'#b6a2df'} },
-              { value: 23, name: "统计与概率",itemStyle:{color:'#59b2ef'} },
-              { value: 25, name: "函数",itemStyle:{color:'#ffba82'} },
-              { value: 11, name: "图形的相似",itemStyle:{color:'#2cc7cb'} },
-              { value: 10, name: "锐角三角函数",itemStyle:{color:'#66cc33'} },
-              { value: 12, name: "几何图形初步",itemStyle:{color:'#db7984'} },
-              { value: 10, name: "投影与视图",itemStyle:{color:'#66ccff'} },
-            ]
+            data: data
           }
-      };
+        };
 
-      // 绘制图表
-      myPie.setOption(option);
-      // window.addEventListener('resize',function(){
-      //     myRadar.resize();
-      // })
+        // 绘制图表
+        myPie.setOption(option);
+        // window.addEventListener('resize',function(){
+        //     myRadar.resize();
+        // })
 
         let that = this;
         myPie.on('click', function (item) {
-           that.$emit('handleItemClick', item);
-      })
+          that.$emit('handleItemClick', item);
+        })
+
+      }
+    },
+    computed: {
+      //获取最新柱状图数据
+      getPieData() {
+        let list = this.$store.state.totalAnalysis.pieData;
+        let a = list.map(item => item.value);
+        return list;
+      }
+    },
+    watch: {
+      getPieData(val) {
+        this.drawLine(val);
+      }
     }
-  }
-};
+  };
 </script>
 
 <!-- Add "scoped" attribute to limit CSS to this component only -->
 <style scoped>
-#myPie {
-  width: 100%;
-  height: 380px;
-  margin: 0 auto;
-  display: block;
-}
+
+  #myPie {
+    width: 100%;
+    height: 380px;
+    margin: 0 auto;
+    display: block;
+  }
 </style>

+ 26 - 12
TEAMModelOS/ClientApp/components/student-analysis/total/BaseRadar.vue

@@ -1,22 +1,24 @@
 <template>
-  <div id="myRadar"></div>
+  <div>
+    <div id="myRadar"></div>
+  </div>
 </template>
 
 <script>
-  // import func from '../../vue-temp/vue-editor-bridge';
   export default {
     name: "helloLine",
     data() {
       return {
-        msg: "Welcome to Your Vue.js App"
+        radarData:[]
       };
     },
     mounted() {
-      this.drawLine();
+      this.radarData = this.getRadarData;
+      this.drawLine(this.radarData);
 
     },
     methods: {
-      drawLine() {
+      drawLine(data) {
         // 基于准备好的dom,初始化echarts实例
         let myRadar = this.$echarts.init(document.getElementById("myRadar"), 'chalk');
 
@@ -100,12 +102,12 @@
               lineStyle: {
                 color: '#9FACE6'
               },
-              data: [
-                {
-                  value: [70, 80, 65, 72, 82, 70],
-                  name: "认知层次"
-                }
-              ]
+              data:  [
+                  {
+                    value: data,
+                    name: "认知层次"
+                  }
+                ]
             }
           ]
         };
@@ -116,8 +118,20 @@
         //     myRadar.resize();
         // })
       }
+    },
+    //利用计算属性
+  computed: {
+    getRadarData() {
+      return this.$store.state.totalAnalysis.radarData;
     }
-  };
+  },
+  //监听执行
+  watch: {
+    getRadarData(val) {
+      this.drawLine(val);
+  }
+  }
+  }
 </script>
 
 <!-- Add "scoped" attribute to limit CSS to this component only -->

+ 289 - 0
TEAMModelOS/ClientApp/components/student-analysis/total/BaseRateLine.vue

@@ -0,0 +1,289 @@
+<template>
+  <div :id="ids" class="myRateLine"></div>
+</template>
+
+<script>
+  export default {
+    name: "hello",
+    props: ['ids','echartsData'],
+    data() {
+      return {
+      };
+    },
+    mounted() {
+      this.drawLine();
+      let myLine = this.$echarts.init(document.getElementById(this.ids), 'chalk');
+      this.initWidth = document.getElementById(this.ids).offsetWidth;
+      let resize = {
+        width: 500,
+        height: 400
+      };
+      myLine.resize(resize);
+    },
+    methods: {
+      drawLine() {
+        // 基于准备好的dom,初始化echarts实例
+        let myLine = this.$echarts.init(document.getElementById(this.ids), 'chalk');
+
+        // 指定图表的配置项和数据
+        var option = {
+          title: {
+            text: '选项选答率分析',
+            textStyle: {
+              align: 'center',
+              color: '#333',
+              fontSize: 14,
+            },
+            top: '3%',
+            left: '10%',
+          },
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              label: {
+                backgroundColor: '#6a7985'
+              }
+            },
+            formatter: function (v) {
+              let str = "选项" + v[0].name +'<br>';
+              v.forEach(item => {
+                str = str + item.seriesName + ':' + item.data + '%' + '<br>'
+              })
+              return str
+            }
+          },
+          legend: {
+            textStyle: {
+              color: "#969696"
+            },
+            top:35
+          },
+          gird: {
+            left: '3%',
+            right: '4%',
+            containLabel: true
+          },
+          xAxis: [
+            {
+              type: 'category',
+              boundaryGap: false,
+              splitLine: {
+                show: false,
+                lineStyle: {
+                  color: '#4c504a',
+                }
+              },
+              axisLine: {
+                lineStyle: {
+                  color: '#969696',
+                }
+              },
+              axisLabel: {
+                show: true, // 是否显示
+                inside: false, // 是否朝内
+                rotate: 0, // 旋转角度
+                margin: 15, // 刻度标签与轴线之间的距离
+                color: "#989898", // 默认取轴线的颜色,
+                fontSize: 14
+              },
+              data: this.echartsData.map(item => item.option)
+            }
+          ],
+          yAxis: [
+            {
+              type: 'value',
+              splitLine: {
+                show: true,
+                lineStyle: {
+                  color: '#ccc',
+                }
+              },
+              axisLine: {
+                lineStyle: {
+                  color: '#969696',
+                }
+              },
+            }
+          ],
+          series: [
+            {
+              name: '选答率',
+              type: 'line',
+              data: this.echartsData.map(item => item.rate),
+              color: "#F58080",
+              lineStyle: {
+                normal: {
+                  width: 2,
+                  color: {
+                    type: 'linear',
+
+                    colorStops: [{
+                      offset: 0,
+                      color: '#FFCAD4' // 0% 处的颜色
+                    }, {
+                      offset: 0.4,
+                      color: '#F58080' // 100% 处的颜色
+                    }, {
+                      offset: 1,
+                      color: '#F58080' // 100% 处的颜色
+                    }],
+                    globalCoord: false // 缺省为 false
+                  },
+                  shadowColor: 'rgba(245,128,128, 0.5)',
+                  shadowBlur: 10,
+                  shadowOffsetY: 7
+                }
+              },
+        //areaStyle: {
+        //    normal: {
+        //        color: this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+        //            offset: 0,
+        //            color: 'rgba(137, 189, 27, 0.3)'
+        //        }, {
+        //            offset: 0.8,
+        //            color: 'rgba(137, 189, 27, 0)'
+        //        }], false),
+        //        shadowColor: 'rgba(0, 0, 0, 0.1)',
+        //        shadowBlur: 10
+        //    }
+        //},
+            itemStyle: {
+                normal: {
+                  color: '#F58080',
+                  borderWidth: 5,
+                  /*shadowColor: 'rgba(72,216,191, 0.3)',
+                   shadowBlur: 100,*/
+                  borderColor: "#F58080"
+                }
+              },
+              smooth: false
+            },
+            {
+              name: '高分组选答率',
+              type: 'line',
+              data: this.echartsData.map(item => item.PH),
+              lineStyle: {
+                normal: {
+                  width: 2,
+                  color: {
+                    type: 'linear',
+
+                    colorStops: [{
+                      offset: 0,
+                      color: '#AAF487' // 0% 处的颜色
+                    },
+                    {
+                      offset: 0.4,
+                      color: '#47D8BE' // 100% 处的颜色
+                    }, {
+                      offset: 1,
+                      color: '#47D8BE' // 100% 处的颜色
+                    }
+                    ],
+                    globalCoord: false // 缺省为 false
+                  },
+                  shadowColor: 'rgba(71,216,190, 0.5)',
+                  shadowBlur: 10,
+                  shadowOffsetY: 7
+                }
+              },
+        //areaStyle: {
+        //    normal: {
+        //        color: this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+        //            offset: 0,
+        //            color: 'rgba(0, 136, 212, 0.3)'
+        //        }, {
+        //            offset: 0.8,
+        //            color: 'rgba(0, 136, 212, 0)'
+        //        }], false),
+        //        shadowColor: 'rgba(0, 0, 0, 0.1)',
+        //        shadowBlur: 10
+        //    }
+        //},
+            itemStyle: {
+                normal: {
+                  color: '#AAF487',
+                  borderWidth: 10,
+                  /*shadowColor: 'rgba(72,216,191, 0.3)',
+                   shadowBlur: 100,*/
+                  borderColor: "#AAF487"
+                }
+              },
+              smooth: false
+            },
+            {
+              name: '低分组选答率',
+              type: 'line',
+              data: this.echartsData.map(item => item.PL),
+              lineStyle: {
+                normal: {
+                  width: 2,
+                  color: {
+                    type: 'linear',
+
+                    colorStops: [{
+                      offset: 0,
+                      color: '#F6D06F' // 0% 处的颜色
+                    },
+                    {
+                      offset: 0.4,
+                      color: '#F9A589' // 100% 处的颜色
+                    }, {
+                      offset: 1,
+                      color: '#F9A589' // 100% 处的颜色
+                    }
+                    ],
+                    globalCoord: false // 缺省为 false
+                  },
+                  shadowColor: 'rgba(249,165,137, 0.5)',
+                  shadowBlur: 10,
+                  shadowOffsetY: 7
+                }
+              },
+              //areaStyle: {
+              //  normal: {
+              //    color: this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+              //      offset: 0,
+              //      color: 'rgba(0, 136, 212, 0.2)'
+              //    }, {
+              //      offset: 1,
+              //      color: 'rgba(0, 136, 212, 0)'
+              //    }], false),
+              //    shadowColor: 'rgba(0, 0, 0, 0.1)',
+              //    shadowBlur: 10
+              //  }
+              //},
+              itemStyle: {
+                normal: {
+                  color: '#F6D06F',
+                  borderWidth: 10,
+                  /*shadowColor: 'rgba(72,216,191, 0.3)',
+                   shadowBlur: 100,*/
+                  borderColor: "#F6D06F"
+                }
+              },
+              smooth: false
+            }]
+        };
+
+
+        // 绘制图表
+        myLine.setOption(option);
+        window.addEventListener("resize", function () {
+          myLine.resize();
+        });
+      }
+    }
+  };
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+
+  .myRateLine {
+    width: 100%;
+    height: 400px;
+    margin: 20px auto;
+    display: block;
+  }
+</style>

+ 47 - 14
TEAMModelOS/ClientApp/components/student-analysis/total/BaseScatter.vue

@@ -9,7 +9,8 @@
     data() {
       return {
         originArr:[],
-        dataArr:[]
+        dataArr: [],
+        activeItemIndex:0
       };
     },
     created() {
@@ -19,6 +20,7 @@
         arr.push(item.x);
         arr.push(item.y);
         arr.push(item.name);
+        arr.push(item.id);
         this.dataArr.push(arr);
       })
 
@@ -32,8 +34,7 @@
 
     },
     mounted() {
-      this.drawLine();
-
+      this.drawLine(this.dataArr);
     },
     methods: {
 
@@ -50,7 +51,6 @@
                   break; 
           } 
       },
-
       areaName(x, y) {
         if (x <= 0.5 && y <= 50) {
           return 'C';
@@ -66,12 +66,10 @@
           return 'A-'
         }
       },
-
       random() {
         var r = Math.floor(Math.random() * 100 );
         return r;
       },
-       
       randomDataArray() {
         var d = [];
         var len = 60;
@@ -81,9 +79,10 @@
         console.log(d);
         return d;
       },
-      drawLine() {
+      drawLine(data) {
         // 基于准备好的dom,初始化echarts实例
-        let myScatter = this.$echarts.init(document.getElementById("myScatter"),'chalk');
+        let myScatter = this.$echarts.init(document.getElementById("myScatter"), 'chalk');
+        let _this = this;
 
         // 指定图表的配置项和数据
         var option = {
@@ -102,8 +101,7 @@
             },
             formatter: function (params) {
               const item = params;
-              return `信息<br/>
-                        姓名:${item.data[2]}
+              return `姓名:${item.data[2]}
                         <br/>通过率:${item.data[1]}%
                         <br/>稳定度:${item.data[0]}
                        `;
@@ -178,11 +176,22 @@
             {
               name: "学生",
               type: "scatter",
-              symbolSize:10,
-              data: this.dataArr,
+              symbolSize:15,
+              data: data,
               itemStyle: {
                 color: "#79c8e8",
               },
+              //itemStyle: {
+              //  color: function(params) {
+              //      var key = params.dataIndex;
+              //      if (key == _this.activeItemIndex) {
+              //          return '#ff99cc';
+              //      } else {
+              //          return '#79c8e8' 
+              //      }
+              //  },
+              //  width: 20,
+              //},
               emphasis: {
                  itemStyle: {
                     color: "#ff99cc"
@@ -339,9 +348,9 @@
         });
 
         let that = this;
-
         myScatter.on('click', function (item) {
-          that.$emit('handleItemClick', item);
+          that.activeItemIndex = item.dataIndex;
+          //that.$emit('handleItemClick', item);
         })
 
         //缩放后显示还原按钮
@@ -362,6 +371,30 @@
       })
 
       }
+    },
+
+    computed: {
+      //获取最新柱状图数据
+      getScatterData() {
+        let list = this.$store.state.totalAnalysis.scatter;
+        let a = list.map(item => item.y);
+        return list;
+      }
+    },
+    watch: {
+      getScatterData(val) {
+        let newArr = [];
+        val.forEach(item => {
+          let arr = [];
+          arr.push(item.x);
+          arr.push(item.y);
+          arr.push(item.name);
+          arr.push(item.id);
+          newArr.push(arr);
+        })
+        this.scatterList = val;
+        this.drawLine(newArr);
+      }
     }
   };
 </script>

+ 46 - 11
TEAMModelOS/ClientApp/components/student-analysis/total/BaseTestScatter.vue

@@ -11,7 +11,8 @@
     data() {
       return {
         originArr:[],
-        dataArr:[]
+        dataArr: [],
+        activeItemIndex:0
       };
     },
     created(){
@@ -37,7 +38,7 @@
 
     },
     mounted() {
-      this.drawLine();
+      this.drawLine(this.dataArr);
 
     },
     methods: {
@@ -84,9 +85,10 @@
         console.log(d);
         return d;
       },
-      drawLine() {
+      drawLine(data) {
         // 基于准备好的dom,初始化echarts实例
-        let myScatter = this.$echarts.init(document.getElementById("testScatter"),'chalk');
+        let myScatter = this.$echarts.init(document.getElementById("testScatter"), 'chalk');
+        let _this = this;
 
         // 指定图表的配置项和数据
         var option = {
@@ -181,15 +183,26 @@
             {
               name: "试题",
               type: "scatter",
-              data: this.dataArr,
+              data: data,
               symbolSize: 20,
               emphasis: {
                  itemStyle: {
                     color: "#ff99cc"
                   },
               },
+              //itemStyle: {
+              //  color: "#79c8e8"
+              //},
               itemStyle: {
-                color: "#79c8e8"
+                color: function(params) {
+                    var key = params.dataIndex;
+                    if (key == _this.activeItemIndex) {
+                        return '#ff99cc';
+                    } else {
+                        return '#79c8e8' 
+                    }
+                },
+                width: 20,
               },
               markLine: {
                 silent: true,
@@ -300,11 +313,9 @@
 
         let that = this;
         myScatter.on('click', function (item) {
-           that.$emit('handleItemClick', item);
-        })
-
-        myScatter.on('hover', function (item) {
-          console.log("asdasdasd");
+          that.activeItemIndex = item.dataIndex;
+          that.$emit('handleItemClick', item);
+          myScatter.setOption(option);
         })
 
         //缩放后显示还原按钮
@@ -324,6 +335,30 @@
           myScatter.setOption(option);
       })
       }
+    },
+
+    computed: {
+      //获取最新柱状图数据
+      getTestScatterData() {
+        let list = this.$store.state.totalAnalysis.testScatter;
+        let a = list.map(item => item.y);
+        return list;
+      }
+    },
+    watch: {
+      getTestScatterData(val) {
+        let newArr = [];
+        val.forEach(item => {
+          let arr = [];
+          arr.push(item.x);
+          arr.push(item.y);
+          arr.push(item.type);
+          arr.push(item.id);
+          newArr.push(arr);
+        })
+        this.scatterList = val;
+        this.drawLine(newArr);
+      }
     }
   };
 </script>

+ 32 - 5
TEAMModelOS/ClientApp/css/site.css

@@ -1,9 +1,9 @@
-html{ /*色主題*/
-    --bg-color: #fff; /*背景顏色*/
+html{ /*色主題*/
+    --bg-color: #252525; /*背景顏色*/
 }
 
-html[dark]{ /*深色主題*/
-    --bg-color: #011b28; /*背景顏色*/
+html[white]{ /*白色主題*/
+    --bg-color: #fff; /*背景顏色*/    
 }
 
 .backdrop{
@@ -27,7 +27,7 @@ html[dark]{ /*深色主題*/
 .backdrop-dark{
     width: 100%;
     height: 100%;
-    background-image: url('../assets/image/bak_dark.jpg');
+    background-image: url('../assets/image/bak_dark.jpg'); 
     background-repeat: no-repeat;
     background-attachment: fixed;
     background-position: center;
@@ -90,3 +90,30 @@ html[dark]{ /*深色主題*/
     white-space: nowrap;
     text-overflow: ellipsis;
 }
+
+/* 拉軸固定黑色*/
+.scrollstyle::-webkit-scrollbar {
+    width: 5px;
+}
+.scrollstyle::-webkit-scrollbar-track {
+  margin: 6px;
+  background: transparent;
+}
+.scrollstyle::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  background: #94998a;
+}
+.scrollstyle::-webkit-scrollbar-thumb:hover {
+  /* background: #555; */
+}
+.scrollstyle::-webkit-scrollbar-button {
+  display: none;
+}
+
+.leftInOut-enter-active, .leftInOut-leave-active {
+    transition: all 0.7s;
+}
+.leftInOut-enter, .leftInOut-leave-to /* .list-leave-active below version 2.1.8 */ {
+    opacity: 0;
+    transform: translateX(-150px);    
+}

+ 4 - 4
TEAMModelOS/ClientApp/filters/http.js

@@ -1,17 +1,17 @@
 import axios from 'axios';
-import Vue from 'vue'
+import { Message } from 'iview';
 import router from '@/router/index'
 axios.defaults.timeout = 10000; //设置超时时长
 axios.defaults.baseURL ='';
 
+//Message.error('数据访问错误!');
+
 //http request 拦截器
 axios.interceptors.request.use(
   config => {
     // const token = getCookie('名称');
     config.data = JSON.stringify(config.data);
 
-    console.log(config);
-
     if (localStorage.getItem('token')) {
       config.headers = {
         'Content-Type': 'application/json',
@@ -77,7 +77,7 @@ export function fetch(url, params) {
       })
       .catch(err => {
         reject(err);
-        this.$Message.error('数据访问错误!');
+        Message.error('数据访问错误!');
       })
   })
 }

+ 21 - 5
TEAMModelOS/ClientApp/mock/index.js

@@ -38,19 +38,19 @@ export default {
       "score|520-630": 630,
       "classRank|1-60": 1,
       "classPR": function () {
-        return 100 - Math.ceil(Math.random() * 20) + '%'
+        return 100 - Math.ceil(Math.random() * 20)
       },
       "gradeRank|1-200": function () {
         return this.classRank + Math.ceil(Math.random() * 100);
       },
       "gradePR": function () {
-        return 100 - Math.ceil(Math.random() * 20) + '%'
+        return 100 - Math.ceil(Math.random() * 20)
       },
       "areaRank|1-400": function () {
         return this.classRank + Math.ceil(Math.random() * 300)
       },
       "areaPR": function () {
-        return 100 - Math.ceil(Math.random() * 20) + '%'
+        return 100 - Math.ceil(Math.random() * 20)
       },
       "chinese|90-150": 150,
       "math|90-150": 150,
@@ -63,8 +63,24 @@ export default {
       "englishRank|1-400":400,
       "chemistryRank|1-400":400,
       "physicsRank|1-400":400,
-      "biologyRank|1-400":400,
-    }]
+      "biologyRank|1-400": 400,
+      "changesStatus|1": [1, -1, 0],
+      "changesStatus2|1": [1, -1, 0],
+      "changesStatus3|1": [1, -1, 0],
+      "changesVal|1-30":1,
+      "changesVal2|1-30":1,
+      "changesVal3|1-30":1,
+    }],
+    'subjectList|10': [{
+      "id|+1": 1,
+      "className|1-10": 1,
+      "chinese|60-120": 60,
+      "math|60-120": 60,
+      "english|60-120": 60,
+      "physics|60-120": 60,
+      "chemistry|60-120": 60,
+      "biology|60-120": 60,
+    }], 
     })
 };
 

+ 1 - 0
TEAMModelOS/ClientApp/router/_import_file.js

@@ -0,0 +1 @@
+module.exports = file => require('@/view/' + file + '/Index.vue').default // vue-loader at least v13.0.0+

+ 14 - 17
TEAMModelOS/ClientApp/router/routes.js

@@ -11,23 +11,19 @@ export const routes = [
   { name: 'selectModule', path: '/selectModule', component: resolve => require(['@/view/index'], resolve) },
   { name: 'login', path: '/login', component: Login },
   { name: 'ServerSideLogin', path: '/serverside/login', component: ServerSideLogin },    
-  { name: 'smartschooldashboard', path: '/smartschooldashboard', component: resolve => require(['@/view/smartschooldashboard'], resolve), },
-  { name: 'classmgmtdashboard', path: '/smartclassdashboard', component: resolve => require(['@/view/smartclassdashboard'], resolve), },
-  //{ name: 'talmgmtdashboard', path: '/smarttaldashboard', component: resolve => require(['@/view/talmgmtdashboard'], resolve), },
-  { name: 'embedschooldashboard', path: '/embedclassdashboard/:schoolshortcode', component: resolve => require(['@/view/smartclassdashboard'], resolve), },
-  // {  共用組件試用
-  //   path: '/smartschooldashboardinMain',
-  //   component: Main,
-  //   children: [
-  //     {
-  //       path: '/',
-  //       component: () => import('@/view/smartschooldashboard')
-  //     }
-  //   ]
-  // },
-
-
-
+  // { name: 'smartschooldashboard', path: '/smartschooldashboard', component: resolve => require(['@/view/smartschooldashboard'], resolve), },
+  { name: 'smartclassdashboard', path: '/smartclassdashboard', component: resolve => require(['@/view/smartclassdashboard'], resolve), },  
+  { name: 'embedschooldashboard', path: '/embedclassdashboard/:schoolshortcode', component: resolve => require(['@/view/smartclassdashboard'], resolve), }, // IES 呼叫專用
+  { // 共用組件試用
+    path: '/teachermgmt',
+    component: Main,
+    children: [
+      {
+        path: '/',
+        component: () => import('@/view/teachermgmt')
+      }
+    ]
+  },
   //学情分析
   {
     name: 'saindex',
@@ -70,6 +66,7 @@ export const routes = [
         component: resolve => require(['@/view/student-analysis/total-analysis/AchievementAnalysis/EntryTables.vue'], resolve),
       },
       {
+        name:'earlyWarning',
         path: '/total/achievement/earlyWarning',
         component: resolve => require(['@/view/student-analysis/total-analysis/AchievementAnalysis/earlyWarning.vue'], resolve),
       },

+ 102 - 0
TEAMModelOS/ClientApp/static/chinesePoint.json

@@ -0,0 +1,102 @@
+[
+  {
+    "id": "1",
+    "name": "",
+    "type": "问答",
+    "knowledgePoint": "文言实词",
+    "blockId": 1,
+    "level": "评鉴",
+    "gradeScoreRate": "90%",
+    "poperData": [ 14, 50, 44 ]
+  },
+  {
+    "id": "2",
+    "name": "",
+    "type": "多选",
+    "blockId": 1,
+    "knowledgePoint": "文言虚词",
+    "level": "理解",
+    "gradeScoreRate": "77%",
+    "poperData": [ 18, 46, 60 ]
+  },
+  {
+    "id": "3",
+    "name": "",
+    "type": "判断",
+    "blockId": 1,
+    "knowledgePoint": "文言句式",
+    "level": "评鉴",
+    "gradeScoreRate": "85%",
+    "poperData": [ 24, 87, 69 ]
+  },
+  {
+    "id": "4",
+    "name": "",
+    "type": "判断",
+    "blockId": 2,
+    "knowledgePoint": "文言文断句",
+    "level": "评鉴",
+    "gradeScoreRate": "70%",
+    "poperData": [ 34, 9, 63 ]
+  },
+  {
+    "id": "5",
+    "name": "",
+    "type": "多选",
+    "blockId": 2,
+    "knowledgePoint": "诗",
+    "level": "应用",
+    "gradeScoreRate": "62%",
+    "poperData": [ 40, 40, 68 ]
+  },
+  {
+    "id": "6",
+    "name": "",
+    "type": "判断",
+    "blockId": 3,
+    "knowledgePoint": "记叙文",
+    "level": "应用",
+    "gradeScoreRate": "71%",
+    "poperData": [ 33, 45, 22 ]
+  },
+  {
+    "id": "7",
+    "name": "",
+    "type": "问答",
+    "blockId": 3,
+    "knowledgePoint": "说明文",
+    "level": "应用",
+    "gradeScoreRate": "83%",
+    "poperData": [ 23, 43, 25 ]
+  },
+  {
+    "id": "8",
+    "name": "",
+    "type": "判断",
+    "blockId": 4,
+    "knowledgePoint": "议论文",
+    "level": "应用",
+    "gradeScoreRate": "77%",
+    "poperData": [ 46, 4, 63 ]
+  },
+  {
+    "id": "9",
+    "name": "",
+    "type": "判断",
+    "blockId": 4,
+    "knowledgePoint": "中国诗歌",
+    "level": "综合",
+    "gradeScoreRate": "81%",
+    "poperData": [ 41, 73, 55 ]
+  },
+  {
+    "id": "10",
+    "name": "",
+    "type": "判断",
+    "blockId": 5,
+    "knowledgePoint": "外国诗歌",
+    "level": "综合",
+    "gradeScoreRate": "81%",
+    "poperData": [ 41, 73, 55 ]
+  }
+]

+ 34 - 53
TEAMModelOS/ClientApp/static/classList.json

@@ -8,9 +8,11 @@
     "rankStatus": 5,
     "name": "初一1班",
     "entryNum": 38,
-    "gradeRank": 5,
+    "gradeRank": 9,
     "entryRate": 69,
-    "overAverageRate": "70%"
+    "overAverageRate": "70%",
+    "changesStatus": -1,
+    "changesVal": 2
   },
   {
     "id": 2,
@@ -23,7 +25,9 @@
     "entryNum": 52,
     "gradeRank": 6,
     "entryRate": 75,
-    "overAverageRate": "73%"
+    "overAverageRate": "73%",
+    "changesStatus": -1,
+    "changesVal": 4
   },
   {
     "id": 3,
@@ -36,7 +40,9 @@
     "entryNum": 51,
     "gradeRank": 3,
     "entryRate": 93,
-    "overAverageRate": "76%"
+    "overAverageRate": "76%",
+    "changesStatus": 1,
+    "changesVal": 2
   },
   {
     "id": 4,
@@ -49,7 +55,9 @@
     "entryNum": 63,
     "gradeRank": 7,
     "entryRate": 95,
-    "overAverageRate": "80%"
+    "overAverageRate": "80%",
+    "changesStatus": -1,
+    "changesVal": 3
   },
   {
     "id": 5,
@@ -62,7 +70,9 @@
     "entryNum": 48,
     "gradeRank": 1,
     "entryRate": 91,
-    "overAverageRate": "82%"
+    "overAverageRate": "82%",
+    "changesStatus": 1,
+    "changesVal": 4
   },
   {
     "id": 6,
@@ -75,7 +85,9 @@
     "entryNum": 47,
     "gradeRank": 2,
     "entryRate": 78,
-    "overAverageRate": "70%"
+    "overAverageRate": "70%",
+    "changesStatus": 0,
+    "changesVal": 0
   },
   {
     "id": 7,
@@ -88,7 +100,9 @@
     "entryNum": 56,
     "gradeRank": 8,
     "entryRate": 95,
-    "overAverageRate": "75%"
+    "overAverageRate": "75%",
+    "changesStatus": -1,
+    "changesVal": 4
   },
   {
     "id": 8,
@@ -101,20 +115,24 @@
     "entryNum": 63,
     "gradeRank": 4,
     "entryRate": 95,
-    "overAverageRate": "78%"
+    "overAverageRate": "78%",
+    "changesStatus": 1,
+    "changesVal": 2
   },
   {
     "id": 9,
     "classId": 140015511008,
     "average": 570,
-    "totalNum":76,
+    "totalNum": 76,
     "standardDeviation": 55,
     "rankStatus": 3,
     "name": "初一9班",
     "entryNum": 67,
-    "gradeRank": 4,
+    "gradeRank": 5,
     "entryRate": 85,
-    "overAverageRate": "78%"
+    "overAverageRate": "78%",
+    "changesStatus": 1,
+    "changesVal": 2
   },
   {
     "id": 10,
@@ -125,47 +143,10 @@
     "rankStatus": 3,
     "name": "初一10班",
     "entryNum": 43,
-    "gradeRank": 4,
+    "gradeRank": 10,
     "entryRate": 55,
-    "overAverageRate": "78%"
-  },
-  {
-    "id": 11,
-    "classId": 140015511008,
-    "average": 570,
-    "totalNum": 66,
-    "standardDeviation": 55,
-    "rankStatus": 3,
-    "name": "初一11班",
-    "entryNum": 63,
-    "gradeRank": 4,
-    "entryRate": 95,
-    "overAverageRate": "78%"
-  },
-  {
-    "id": 12,
-    "classId": 140015511008,
-    "average": 570,
-    "totalNum": 66,
-    "standardDeviation": 55,
-    "rankStatus": 3,
-    "name": "初一12班",
-    "entryNum": 43,
-    "gradeRank": 4,
-    "entryRate": 65,
-    "overAverageRate": "78%"
-  },
-  {
-    "id": 13,
-    "classId": 140015511008,
-    "average": 570,
-    "totalNum": 66,
-    "standardDeviation": 55,
-    "rankStatus": 3,
-    "name": "初一13班",
-    "entryNum": 63,
-    "gradeRank": 4,
-    "entryRate": 95,
-    "overAverageRate": "78%"
+    "overAverageRate": "78%",
+    "changesStatus": -1,
+    "changesVal": 6
   }
 ]

+ 41 - 23
TEAMModelOS/ClientApp/static/examList.json

@@ -1,62 +1,80 @@
 [
   {
     "id": "1",
-    "name": "成都新川外国语学校2019年5月期中考试",
+    "name": "成都新川外国语学校2019年5月诊断测验",
     "joinNum": "1580",
-    "date": "2019-06-11",
-    "examType": "模拟测验",
+    "date": "2019-05-11",
+    "examType": "诊断测验",
+    "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "初中",
-    "grade": "初一",
+    "grade": "一年级",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "上学期"
   },
   {
     "id": "2",
-    "name": "成都新川外国语学校2019年6月期中考试",
+    "name": "成都新川外国语学校2019年6月诊断测验",
     "joinNum": "1380",
-    "date": "2019-06-11",
-    "examType": "模拟测验",
+    "date": "2019-06-12",
+    "examType": "诊断测验",
+    "examArea": "校内测验",
     "period": "高中",
-    "grade": "高一",
+    "grade": "一年级",
+    "feedback": "考试分析",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "下学期"
   },
   {
     "id": "3",
-    "name": "成都新川外国语学校2019年7月期中考试",
+    "name": "成都新川外国语学校2019年7月诊断测验",
     "joinNum": "1280",
-    "date": "2019-06-11",
-    "examType": "校内测验",
+    "date": "2019-07-21",
+    "examType": "诊断测验",
+    "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "初中",
-    "grade": "初一",
+    "grade": "一年级",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "上学期"
   },
   {
     "id": "4",
-    "name": "成都新川外国语学校2019年8月期中考试",
+    "name": "成都新川外国语学校2019年8月诊断测验",
     "joinNum": "2580",
-    "date": "2019-06-11",
+    "date": "2019-08-15",
     "examType": "模拟测验",
+    "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "初中",
-    "grade": "初一",
+    "grade": "一年级",
+    "subject": "语文,数学,英语",
     "term": "上学期"
   },
   {
     "id": "5",
-    "name": "成都新川外国语学校2019年9月期中考试",
+    "name": "成都新川外国语学校2019年9月诊断测验",
     "joinNum": "1580",
-    "date": "2019-06-11",
-    "examType": "全国测验",
+    "date": "2019-09-19",
+    "examType": "诊断测验",
+    "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "高中",
-    "grade": "高一",
+    "grade": "一年级",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "上学期"
   },
   {
     "id": "6",
-    "name": "成都新川外国语学校2019年10月期中考试",
+    "name": "成都新川外国语学校2019年10月诊断测验",
     "joinNum": "1540",
-    "date": "2019-06-11",
-    "examType": "校内测验",
+    "date": "2019-10-10",
+    "examType": "诊断测验",
+    "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "初中",
-    "grade": "初一",
+    "grade": "二年级",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "上学期"
   }
 

+ 36 - 17
TEAMModelOS/ClientApp/static/exerciseList.json

@@ -1,35 +1,39 @@
 [
   {
     "id": "1",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "问答",
-    "knowledgePoint": "函数",
+    "knowledgePoint": "统计与概率",
+    "blockId": 1,
     "level": "评鉴",
     "gradeScoreRate": "90%",
     "poperData": [ 14, 50, 44 ]
   },
   {
     "id": "2",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "多选",
-    "knowledgePoint": "锐角三角函数",
+    "blockId": 1,
+    "knowledgePoint": "几何图形初步",
     "level": "理解",
     "gradeScoreRate": "77%",
     "poperData": [ 18, 46, 60 ]
   },
   {
     "id": "3",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
-    "knowledgePoint": "图形的相似",
+    "blockId": 1,
+    "knowledgePoint": "一元二次方程",
     "level": "评鉴",
     "gradeScoreRate": "85%",
     "poperData": [ 24, 87, 69 ]
   },
   {
     "id": "4",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
+    "blockId": 2,
     "knowledgePoint": "几何图形初步",
     "level": "评鉴",
     "gradeScoreRate": "70%",
@@ -37,45 +41,60 @@
   },
   {
     "id": "5",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "多选",
-    "knowledgePoint": "投影与视图",
+    "blockId": 2,
+    "knowledgePoint": "函数",
     "level": "应用",
     "gradeScoreRate": "62%",
     "poperData": [ 40, 40, 68 ]
   },
   {
     "id": "6",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
-    "knowledgePoint": "函数",
+    "blockId": 3,
+    "knowledgePoint": "数据分析",
     "level": "应用",
     "gradeScoreRate": "71%",
     "poperData": [ 33, 45, 22 ]
   },
   {
     "id": "7",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "问答",
-    "knowledgePoint": "锐角三角函数",
+    "blockId": 3,
+    "knowledgePoint": "数据的收集与整理",
     "level": "应用",
     "gradeScoreRate": "83%",
     "poperData": [ 23, 43, 25 ]
   },
   {
     "id": "8",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
-    "knowledgePoint": "投影与视图",
+    "blockId": 4,
+    "knowledgePoint": "函数的基础知识",
     "level": "应用",
     "gradeScoreRate": "77%",
     "poperData": [ 46, 4, 63 ]
   },
   {
     "id": "9",
-    "name": "求复平面内对应的坐标",
+    "name": "",
+    "type": "判断",
+    "blockId": 4,
+    "knowledgePoint": "一次函数",
+    "level": "综合",
+    "gradeScoreRate": "81%",
+    "poperData": [ 41, 73, 55 ]
+  },
+  {
+    "id": "10",
+    "name": "",
     "type": "判断",
-    "knowledgePoint": "图形的性质",
+    "blockId": 5,
+    "knowledgePoint": "图形的相似",
     "level": "综合",
     "gradeScoreRate": "81%",
     "poperData": [ 41, 73, 55 ]

+ 176 - 0
TEAMModelOS/ClientApp/static/filter.json

@@ -0,0 +1,176 @@
+{
+  "periodList": [
+    {
+      "name": "全部",
+      "key": "all"
+    },
+    {
+      "name": "高中",
+      "key": "highSchool"
+    },
+    {
+      "name": "初中",
+      "key": "middleSchool"
+    },
+    {
+      "name": "小学",
+      "key": "primarySchool"
+    }
+  ],
+  "gradeList": [
+    {
+      "name": "全部",
+      "key": "all"
+    },
+    {
+      "name": "一年级",
+      "key": "first"
+    },
+    {
+      "name": "二年级",
+      "key": "second"
+    },
+    {
+      "name": "三年级",
+      "key": "third"
+    },
+    {
+      "name": "四年级",
+      "key": "fourth"
+    },
+    {
+      "name": "五年级",
+      "key": "fifth"
+    },
+    {
+      "name": "六年级",
+      "key": "sixth"
+    }
+  ],
+  "termList": [
+    {
+      "name": "全部",
+      "key": "all"
+    },
+    {
+      "name": "上学期",
+      "key": "lastTerm"
+    },
+    {
+      "name": "下学期",
+      "key": "nextTerm"
+    }
+  ],
+  "typeList": [
+    {
+      "name": "全部",
+      "key": "all"
+    },
+    {
+      "name": "周考",
+      "key": "week"
+    },
+    {
+      "name": "期初考",
+      "key": "start"
+    },
+    {
+      "name": "期中考",
+      "key": "middle"
+    },
+    {
+      "name": "期末考",
+      "key": "end"
+    },
+    {
+      "name": "诊断测验",
+      "key": "diagnosis"
+    },
+    {
+      "name": "模拟测验",
+      "key": "simulation"
+    }
+  ],
+  "feedbackList": [
+    {
+      "name": "全部",
+      "key": "all"
+    },
+    {
+      "name": "考试分析",
+      "key": "1"
+    },
+    {
+      "name": "课堂反馈",
+      "key": "2"
+    },
+    {
+      "name": "线上作业",
+      "key": "3"
+    },
+    {
+      "name": "自学课堂",
+      "key": "4"
+    }
+  ],
+  "areaList": [
+    {
+      "name": "全部",
+      "key": "all"
+    },
+    {
+      "name": "班级测验",
+      "key": "school"
+    },
+    {
+      "name": "校级测验",
+      "key": "area"
+    },
+    {
+      "name": "区级测验",
+      "key": "country"
+    }
+  ],
+  "subjectList": [
+    {
+      "name": "全部",
+      "key": "all"
+    },
+    {
+      "name": "语文",
+      "key": "chinese"
+    },
+    {
+      "name": "数学",
+      "key": "math"
+    },
+    {
+      "name": "英语",
+      "key": "English"
+    },
+    {
+      "name": "物理",
+      "key": "physics"
+    },
+    {
+      "name": "化学",
+      "key": "chemistry"
+    },
+    {
+      "name": "政治",
+      "key": "politics"
+    },
+    {
+      "name": "历史",
+      "key": "history"
+    },
+    {
+      "name": "地理",
+      "key": "geography"
+    },
+    {
+      "name": "生物",
+      "key": "biology"
+    }
+  ]
+}

+ 38 - 0
TEAMModelOS/ClientApp/static/percent.json

@@ -0,0 +1,38 @@
+[
+  {
+    "name": "语文",
+    "classRate": "85%",
+    "gradeRate": "78%",
+    "areaRate": "86%"
+  },
+  {
+    "name": "数学",
+    "classRate": "72%",
+    "gradeRate": "78%",
+    "areaRate": "83%"
+  },
+  {
+    "name": "英语",
+    "classRate": "75%",
+    "gradeRate": "76%",
+    "areaRate": "74%"
+  },
+  {
+    "name": "物理",
+    "classRate": "82%",
+    "gradeRate": "76%",
+    "areaRate": "81%"
+  },
+  {
+    "name": "化学",
+    "classRate": "75%",
+    "gradeRate": "75%",
+    "areaRate": "81%"
+  },
+  {
+    "name": "生物",
+    "classRate": "65%",
+    "gradeRate": "68%",
+    "areaRate": "72%"
+  }
+]

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 737 - 540
TEAMModelOS/ClientApp/static/questionList.json


+ 181 - 61
TEAMModelOS/ClientApp/static/scatter.json

@@ -35,11 +35,13 @@
       "areaRank": 109,
       "areaPR": "84%",
       "className": "初一5班",
-      "poperData": [ 50, 94, 15 ]
+      "poperData": [ 50, 94, 15 ],
+      "changesStatus": 1,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
-    "changesStatus": -1,
+    "changesStatus": 1,
     "hardList": [ 3, 8, 9, 11, 12 ],
     "carefulList": [ 2, 6, 7, 8, 11, 12 ]
   },
@@ -79,7 +81,9 @@
       "areaRank": 75,
       "areaPR": "89%",
       "className": "初一5班",
-      "poperData": [ 15, 60, 64 ]
+      "poperData": [ 15, 60, 64 ],
+      "changesStatus": 1,
+      "changesVal": 2
     },
     "className": "初一5班",
     "changesVal": 2,
@@ -123,7 +127,9 @@
       "areaRank": 261,
       "areaPR": "89%",
       "className": "初一5班",
-      "poperData": [ 3, 33, 63 ]
+      "poperData": [ 3, 33, 63 ],
+      "changesStatus": 1,
+      "changesVal": 5
     },
     "className": "初一5班",
     "changesVal": 5,
@@ -167,7 +173,9 @@
       "areaRank": 163,
       "areaPR": "91%",
       "className": "初一5班",
-      "poperData": [ 24, 84, 65 ]
+      "poperData": [ 24, 84, 65 ],
+      "changesStatus": 0,
+      "changesVal": 2
     },
     "className": "初一5班",
     "changesVal": 2,
@@ -211,7 +219,9 @@
       "areaRank": 325,
       "areaPR": "98%",
       "className": "初一5班",
-      "poperData": [ 4, 86, 27 ]
+      "poperData": [ 4, 86, 27 ],
+      "changesStatus": -1,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
@@ -255,7 +265,9 @@
       "areaRank": 171,
       "areaPR": "97%",
       "className": "初一5班",
-      "poperData": [ 36, 97, 32 ]
+      "poperData": [ 36, 97, 32 ],
+      "changesStatus": 0,
+      "changesVal": 5
     },
     "className": "初一5班",
     "changesVal": 5,
@@ -299,7 +311,9 @@
       "areaRank": 254,
       "areaPR": "83%",
       "className": "初一5班",
-      "poperData": [ 48, 5, 9 ]
+      "poperData": [ 48, 5, 9 ],
+      "changesStatus": 1,
+      "changesVal": 5
     },
     "className": "初一5班",
     "changesVal": 5,
@@ -343,7 +357,9 @@
       "areaRank": 57,
       "areaPR": "99%",
       "className": "初一5班",
-      "poperData": [ 29, 88, 62 ]
+      "poperData": [ 29, 88, 62 ],
+      "changesStatus": 0,
+      "changesVal": 1
     },
     "className": "初一5班",
     "changesVal": 1,
@@ -387,7 +403,9 @@
       "areaRank": 121,
       "areaPR": "88%",
       "className": "初一5班",
-      "poperData": [ 15, 55, 59 ]
+      "poperData": [ 15, 55, 59 ],
+      "changesStatus": 0,
+      "changesVal": 4
     },
     "className": "初一5班",
     "changesVal": 4,
@@ -431,7 +449,9 @@
       "areaRank": 130,
       "areaPR": "85%",
       "className": "初一5班",
-      "poperData": [ 19, 54, 65 ]
+      "poperData": [ 19, 54, 65 ],
+      "changesStatus": -1,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -475,7 +495,9 @@
       "areaRank": 101,
       "areaPR": "88%",
       "className": "初一5班",
-      "poperData": [ 37, 57, 20 ]
+      "poperData": [ 37, 57, 20 ],
+      "changesStatus": -1,
+      "changesVal": 5
     },
     "className": "初一5班",
     "changesVal": 5,
@@ -519,7 +541,9 @@
       "areaRank": 259,
       "areaPR": "94%",
       "className": "初一5班",
-      "poperData": [ 21, 75, 51 ]
+      "poperData": [ 21, 75, 51 ],
+      "changesStatus": 0,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -563,7 +587,9 @@
       "areaRank": 51,
       "areaPR": "95%",
       "className": "初一5班",
-      "poperData": [ 16, 6, 1 ]
+      "poperData": [ 16, 6, 1 ],
+      "changesStatus": 1,
+      "changesVal": 7
     },
     "className": "初一5班",
     "changesVal": 7,
@@ -607,7 +633,9 @@
       "areaRank": 83,
       "areaPR": "92%",
       "className": "初一5班",
-      "poperData": [ 2, 62, 43 ]
+      "poperData": [ 2, 62, 43 ],
+      "changesStatus": 1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,
@@ -651,7 +679,9 @@
       "areaRank": 354,
       "areaPR": "85%",
       "className": "初一5班",
-      "poperData": [ 5, 5, 30 ]
+      "poperData": [ 5, 5, 30 ],
+      "changesStatus": -1,
+      "changesVal": 1
     },
     "className": "初一5班",
     "changesVal": 1,
@@ -695,7 +725,9 @@
       "areaRank": 206,
       "areaPR": "98%",
       "className": "初一5班",
-      "poperData": [ 3, 43, 48 ]
+      "poperData": [ 3, 43, 48 ],
+      "changesStatus": -1,
+      "changesVal": 1
     },
     "className": "初一5班",
     "changesVal": 1,
@@ -739,7 +771,9 @@
       "areaRank": 93,
       "areaPR": "83%",
       "className": "初一5班",
-      "poperData": [ 14, 88, 11 ]
+      "poperData": [ 14, 88, 11 ],
+      "changesStatus": 1,
+      "changesVal": 7
     },
     "className": "初一5班",
     "changesVal": 7,
@@ -783,7 +817,9 @@
       "areaRank": 301,
       "areaPR": "90%",
       "className": "初一5班",
-      "poperData": [ 19, 29, 66 ]
+      "poperData": [ 19, 29, 66 ],
+      "changesStatus": -1,
+      "changesVal": 5
     },
     "className": "初一5班",
     "changesVal": 5,
@@ -827,7 +863,9 @@
       "areaRank": 114,
       "areaPR": "94%",
       "className": "初一5班",
-      "poperData": [ 41, 92, 62 ]
+      "poperData": [ 41, 92, 62 ],
+      "changesStatus": 0,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
@@ -871,7 +909,9 @@
       "areaRank": 113,
       "areaPR": "90%",
       "className": "初一5班",
-      "poperData": [ 22, 54, 46 ]
+      "poperData": [ 22, 54, 46 ],
+      "changesStatus": -1,
+      "changesVal": 5
     },
     "className": "初一5班",
     "changesVal": 5,
@@ -915,7 +955,9 @@
       "areaRank": 321,
       "areaPR": "89%",
       "className": "初一5班",
-      "poperData": [ 43, 43, 68 ]
+      "poperData": [ 43, 43, 68 ],
+      "changesStatus": 0,
+      "changesVal": 7
     },
     "className": "初一5班",
     "changesVal": 7,
@@ -959,7 +1001,9 @@
       "areaRank": 170,
       "areaPR": "94%",
       "className": "初一5班",
-      "poperData": [ 6, 21, 66 ]
+      "poperData": [ 6, 21, 66 ],
+      "changesStatus": 1,
+      "changesVal": 1
     },
     "className": "初一5班",
     "changesVal": 1,
@@ -1003,7 +1047,9 @@
       "areaRank": 47,
       "areaPR": "97%",
       "className": "初一5班",
-      "poperData": [ 10, 33, 70 ]
+      "poperData": [ 10, 33, 70 ],
+      "changesStatus": -1,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -1047,7 +1093,9 @@
       "areaRank": 344,
       "areaPR": "80%",
       "className": "初一5班",
-      "poperData": [ 8, 32, 8 ]
+      "poperData": [ 8, 32, 8 ],
+      "changesStatus": 1,
+      "changesVal": 7
     },
     "className": "初一5班",
     "changesVal": 7,
@@ -1091,7 +1139,9 @@
       "areaRank": 198,
       "areaPR": "95%",
       "className": "初一5班",
-      "poperData": [ 46, 41, 68 ]
+      "poperData": [ 46, 41, 68 ],
+      "changesStatus": -1,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -1135,7 +1185,9 @@
       "areaRank": 205,
       "areaPR": "82%",
       "className": "初一5班",
-      "poperData": [ 15, 49, 22 ]
+      "poperData": [ 15, 49, 22 ],
+      "changesStatus": 1,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
@@ -1179,7 +1231,9 @@
       "areaRank": 254,
       "areaPR": "85%",
       "className": "初一5班",
-      "poperData": [ 48, 36, 70 ]
+      "poperData": [ 48, 36, 70 ],
+      "changesStatus": 1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,
@@ -1223,7 +1277,9 @@
       "areaRank": 195,
       "areaPR": "85%",
       "className": "初一5班",
-      "poperData": [ 16, 76, 17 ]
+      "poperData": [ 16, 76, 17 ],
+      "changesStatus": 1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,
@@ -1267,7 +1323,9 @@
       "areaRank": 81,
       "areaPR": "86%",
       "className": "初一5班",
-      "poperData": [ 20, 66, 56 ]
+      "poperData": [ 20, 66, 56 ],
+      "changesStatus": -1,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -1311,7 +1369,9 @@
       "areaRank": 136,
       "areaPR": "85%",
       "className": "初一5班",
-      "poperData": [ 11, 51, 8 ]
+      "poperData": [ 11, 51, 8 ],
+      "changesStatus": -1,
+      "changesVal": 1
     },
     "className": "初一5班",
     "changesVal": 1,
@@ -1355,7 +1415,9 @@
       "areaRank": 70,
       "areaPR": "92%",
       "className": "初一5班",
-      "poperData": [ 19, 56, 34 ]
+      "poperData": [ 19, 56, 34 ],
+      "changesStatus": 0,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
@@ -1399,7 +1461,9 @@
       "areaRank": 167,
       "areaPR": "92%",
       "className": "初一5班",
-      "poperData": [ 14, 7, 60 ]
+      "poperData": [ 14, 7, 60 ],
+      "changesStatus": 0,
+      "changesVal": 4
     },
     "className": "初一5班",
     "changesVal": 4,
@@ -1443,7 +1507,9 @@
       "areaRank": 302,
       "areaPR": "87%",
       "className": "初一5班",
-      "poperData": [ 47, 50, 4 ]
+      "poperData": [ 47, 50, 4 ],
+      "changesStatus": 0,
+      "changesVal": 5
     },
     "className": "初一5班",
     "changesVal": 5,
@@ -1487,7 +1553,9 @@
       "areaRank": 70,
       "areaPR": "90%",
       "className": "初一5班",
-      "poperData": [ 32, 61, 47 ]
+      "poperData": [ 32, 61, 47 ],
+      "changesStatus": 1,
+      "changesVal": 2
     },
     "className": "初一5班",
     "changesVal": 2,
@@ -1531,7 +1599,9 @@
       "areaRank": 50,
       "areaPR": "93%",
       "className": "初一5班",
-      "poperData": [ 37, 37, 1 ]
+      "poperData": [ 37, 37, 1 ],
+      "changesStatus": -1,
+      "changesVal": 1
     },
     "className": "初一5班",
     "changesVal": 1,
@@ -1575,7 +1645,9 @@
       "areaRank": 188,
       "areaPR": "82%",
       "className": "初一5班",
-      "poperData": [ 18, 50, 34 ]
+      "poperData": [ 18, 50, 34 ],
+      "changesStatus": 0,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -1619,7 +1691,9 @@
       "areaRank": 326,
       "areaPR": "97%",
       "className": "初一5班",
-      "poperData": [ 36, 99, 31 ]
+      "poperData": [ 36, 99, 31 ],
+      "changesStatus": 0,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
@@ -1663,7 +1737,9 @@
       "areaRank": 117,
       "areaPR": "83%",
       "className": "初一5班",
-      "poperData": [ 32, 13, 39 ]
+      "poperData": [ 32, 13, 39 ],
+      "changesStatus": 0,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -1707,7 +1783,9 @@
       "areaRank": 242,
       "areaPR": "93%",
       "className": "初一5班",
-      "poperData": [ 22, 18, 16 ]
+      "poperData": [ 22, 18, 16 ],
+      "changesStatus": -1,
+      "changesVal": 2
     },
     "className": "初一5班",
     "changesVal": 2,
@@ -1751,7 +1829,9 @@
       "areaRank": 203,
       "areaPR": "99%",
       "className": "初一5班",
-      "poperData": [ 38, 95, 58 ]
+      "poperData": [ 38, 95, 58 ],
+      "changesStatus": 0,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
@@ -1795,7 +1875,9 @@
       "areaRank": 153,
       "areaPR": "92%",
       "className": "初一5班",
-      "poperData": [ 42, 88, 16 ]
+      "poperData": [ 42, 88, 16 ],
+      "changesStatus": -1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,
@@ -1839,7 +1921,9 @@
       "areaRank": 115,
       "areaPR": "95%",
       "className": "初一5班",
-      "poperData": [ 22, 33, 42 ]
+      "poperData": [ 22, 33, 42 ],
+      "changesStatus": -1,
+      "changesVal": 2
     },
     "className": "初一5班",
     "changesVal": 2,
@@ -1883,7 +1967,9 @@
       "areaRank": 68,
       "areaPR": "87%",
       "className": "初一5班",
-      "poperData": [ 37, 25, 58 ]
+      "poperData": [ 37, 25, 58 ],
+      "changesStatus": 0,
+      "changesVal": 4
     },
     "className": "初一5班",
     "changesVal": 4,
@@ -1927,7 +2013,9 @@
       "areaRank": 136,
       "areaPR": "92%",
       "className": "初一5班",
-      "poperData": [ 33, 20, 49 ]
+      "poperData": [ 33, 20, 49 ],
+      "changesStatus": 1,
+      "changesVal": 4
     },
     "className": "初一5班",
     "changesVal": 4,
@@ -1971,7 +2059,9 @@
       "areaRank": 251,
       "areaPR": "99%",
       "className": "初一5班",
-      "poperData": [ 15, 67, 47 ]
+      "poperData": [ 15, 67, 47 ],
+      "changesStatus": 1,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -2015,7 +2105,9 @@
       "areaRank": 284,
       "areaPR": "93%",
       "className": "初一5班",
-      "poperData": [ 19, 80, 46 ]
+      "poperData": [ 19, 80, 46 ],
+      "changesStatus": 1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,
@@ -2059,7 +2151,9 @@
       "areaRank": 53,
       "areaPR": "87%",
       "className": "初一5班",
-      "poperData": [ 4, 68, 49 ]
+      "poperData": [ 4, 68, 49 ],
+      "changesStatus": -1,
+      "changesVal": 5
     },
     "className": "初一5班",
     "changesVal": 5,
@@ -2103,7 +2197,9 @@
       "areaRank": 46,
       "areaPR": "94%",
       "className": "初一5班",
-      "poperData": [ 1, 3, 28 ]
+      "poperData": [ 1, 3, 28 ],
+      "changesStatus": -1,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
@@ -2147,7 +2243,9 @@
       "areaRank": 108,
       "areaPR": "83%",
       "className": "初一5班",
-      "poperData": [ 8, 73, 60 ]
+      "poperData": [ 8, 73, 60 ],
+      "changesStatus": -1,
+      "changesVal": 4
     },
     "className": "初一5班",
     "changesVal": 4,
@@ -2191,7 +2289,9 @@
       "areaRank": 47,
       "areaPR": "83%",
       "className": "初一5班",
-      "poperData": [ 44, 80, 8 ]
+      "poperData": [ 44, 80, 8 ],
+      "changesStatus": -1,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -2235,7 +2335,9 @@
       "areaRank": 169,
       "areaPR": "89%",
       "className": "初一5班",
-      "poperData": [ 14, 46, 17 ]
+      "poperData": [ 14, 46, 17 ],
+      "changesStatus": 0,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
@@ -2279,7 +2381,9 @@
       "areaRank": 107,
       "areaPR": "92%",
       "className": "初一5班",
-      "poperData": [ 9, 83, 34 ]
+      "poperData": [ 9, 83, 34 ],
+      "changesStatus": -1,
+      "changesVal": 0
     },
     "className": "初一5班",
     "changesVal": 0,
@@ -2323,7 +2427,9 @@
       "areaRank": 101,
       "areaPR": "84%",
       "className": "初一5班",
-      "poperData": [ 25, 52, 19 ]
+      "poperData": [ 25, 52, 19 ],
+      "changesStatus": -1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,
@@ -2367,7 +2473,9 @@
       "areaRank": 117,
       "areaPR": "88%",
       "className": "初一5班",
-      "poperData": [ 14, 48, 42 ]
+      "poperData": [ 14, 48, 42 ],
+      "changesStatus": -1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,
@@ -2411,7 +2519,9 @@
       "areaRank": 282,
       "areaPR": "95%",
       "className": "初一5班",
-      "poperData": [ 3, 29, 37 ]
+      "poperData": [ 3, 29, 37 ],
+      "changesStatus": 1,
+      "changesVal": 2
     },
     "className": "初一5班",
     "changesVal": 2,
@@ -2455,7 +2565,9 @@
       "areaRank": 272,
       "areaPR": "86%",
       "className": "初一5班",
-      "poperData": [ 17, 29, 46 ]
+      "poperData": [ 17, 29, 46 ],
+      "changesStatus": -1,
+      "changesVal": 1
     },
     "className": "初一5班",
     "changesVal": 1,
@@ -2499,7 +2611,9 @@
       "areaRank": 44,
       "areaPR": "90%",
       "className": "初一5班",
-      "poperData": [ 42, 16, 14 ]
+      "poperData": [ 42, 16, 14 ],
+      "changesStatus": -1,
+      "changesVal": 7
     },
     "className": "初一5班",
     "changesVal": 7,
@@ -2543,7 +2657,9 @@
       "areaRank": 279,
       "areaPR": "92%",
       "className": "初一5班",
-      "poperData": [ 27, 77, 40 ]
+      "poperData": [ 27, 77, 40 ],
+      "changesStatus": -1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,
@@ -2587,7 +2703,9 @@
       "areaRank": 143,
       "areaPR": "94%",
       "className": "初一5班",
-      "poperData": [ 40, 59, 23 ]
+      "poperData": [ 40, 59, 23 ],
+      "changesStatus": -1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,
@@ -2631,7 +2749,9 @@
       "areaRank": 95,
       "areaPR": "93%",
       "className": "初一5班",
-      "poperData": [ 18, 65, 27 ]
+      "poperData": [ 18, 65, 27 ],
+      "changesStatus": -1,
+      "changesVal": 6
     },
     "className": "初一5班",
     "changesVal": 6,

+ 7 - 28
TEAMModelOS/ClientApp/static/tableList.json

@@ -1,14 +1,7 @@
 [
   {
     "id": "1",
-    "name": "进线生统计",
-    "joinNum": "1580",
-    "date": "2019-06-11",
-    "examType": "A"
-  },
-  {
-    "id": "1",
-    "name": "踩线生统计",
+    "name": "年级成绩统计表",
     "joinNum": "1580",
     "date": "2019-06-11",
     "examType": "A"
@@ -29,42 +22,28 @@
   },
   {
     "id": "1",
-    "name": "百分等级",
-    "joinNum": "1580",
-    "date": "2019-06-11",
-    "examType": "A"
-  },
-  {
-    "id": "1",
-    "name": "排名情况",
-    "joinNum": "1580",
-    "date": "2019-06-11",
-    "examType": "A"
-  },
-  {
-    "id": "1",
-    "name": "班级得分明细表",
+    "name": "排名统计(PR/成绩)",
     "joinNum": "1580",
     "date": "2019-06-11",
     "examType": "A"
   },
   {
     "id": "1",
-    "name": "试题区域落点统计",
+    "name": "学生稳定度统计表",
     "joinNum": "1580",
     "date": "2019-06-11",
     "examType": "A"
   },
   {
     "id": "1",
-    "name": "班级单题得分率",
+    "name": "试题分析总表",
     "joinNum": "1580",
     "date": "2019-06-11",
     "examType": "A"
   },
   {
     "id": "1",
-    "name": "得分率关系表",
+    "name": "试题得分率表",
     "joinNum": "1580",
     "date": "2019-06-11",
     "examType": "A"
@@ -72,14 +51,14 @@
 
   {
     "id": "1",
-    "name": "试题明细表",
+    "name": "得分率关系表",
     "joinNum": "1580",
     "date": "2019-06-11",
     "examType": "A"
   },
   {
     "id": "1",
-    "name": "学习稳定度统计表",
+    "name": "错题率关系表",
     "joinNum": "1580",
     "date": "2019-06-11",
     "examType": "A"

+ 252 - 72
TEAMModelOS/ClientApp/static/testScatter.json

@@ -7,7 +7,7 @@
     "tableData": {
       "id": "1",
       "name": "算法平均值",
-      "type": "问答",
+      "type": "单选",
       "areaName": "A",
       "score": 4,
       "diff": 0.47,
@@ -21,7 +21,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "统计与概率",
-      "poperData": [ 47, 92, 36 ]
+      "poperData": [ 49, 86, 2 ],
+      "R1": "92%",
+      "R2": "88%",
+      "R3": "74%",
+      "R4": "68%",
+      "R5": "59%",
+      "R6": "47%",
+      "PH": "92%",
+      "PL": "54%",
+      "stem": ""
     }
   },
   {
@@ -32,9 +41,9 @@
     "tableData": {
       "id": "2",
       "name": "一元二次方程",
-      "type": "判断",
+      "type": "单选",
       "areaName": "A",
-      "score": 7,
+      "score": 4,
       "diff": 0.08,
       "identify": "0.60",
       "classScoreRate": "66%",
@@ -46,7 +55,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "几何图形初步",
-      "poperData": [ 34, 57, 37 ]
+      "poperData": [ 45, 68, 26 ],
+      "R1": "95%",
+      "R2": "81%",
+      "R3": "75%",
+      "R4": "63%",
+      "R5": "59%",
+      "R6": "41%",
+      "PH": "96%",
+      "PL": "52%",
+      "stem": ""
     }
   },
   {
@@ -57,9 +75,9 @@
     "tableData": {
       "id": "3",
       "name": "全等三角形性质",
-      "type": "选",
+      "type": "选",
       "areaName": "A",
-      "score": 3,
+      "score": 4,
       "diff": 0.05,
       "identify": "0.70",
       "classScoreRate": "73%",
@@ -71,7 +89,16 @@
       "standardDeviation": "55",
       "rankStatus": "0",
       "knowledgePoint": "图形的相似",
-      "poperData": [ 30, 10, 26 ]
+      "poperData": [ 11, 65, 12 ],
+      "R1": "96%",
+      "R2": "85%",
+      "R3": "74%",
+      "R4": "66%",
+      "R5": "59%",
+      "R6": "45%",
+      "PH": "94%",
+      "PL": "56%",
+      "stem": ""
     }
   },
   {
@@ -82,9 +109,9 @@
     "tableData": {
       "id": "4",
       "name": "全等三角形性质",
-      "type": "选",
+      "type": "选",
       "areaName": "A",
-      "score": 12,
+      "score": 4,
       "diff": 0.42,
       "identify": "0.20",
       "classScoreRate": "87%",
@@ -96,7 +123,16 @@
       "standardDeviation": "45",
       "rankStatus": "2",
       "knowledgePoint": "统计与概率",
-      "poperData": [ 22, 19, 28 ]
+      "poperData": [ 5, 73, 18 ],
+      "R1": "95%",
+      "R2": "85%",
+      "R3": "75%",
+      "R4": "61%",
+      "R5": "51%",
+      "R6": "45%",
+      "PH": "93%",
+      "PL": "58%",
+      "stem": ""
     }
   },
   {
@@ -109,7 +145,7 @@
       "name": "二元二次方程",
       "type": "单选",
       "areaName": "A",
-      "score": 5,
+      "score": 4,
       "diff": 0.5,
       "identify": "0.50",
       "classScoreRate": "69%",
@@ -121,7 +157,16 @@
       "standardDeviation": "55",
       "rankStatus": "0",
       "knowledgePoint": "几何图形初步",
-      "poperData": [ 15, 73, 63 ]
+      "poperData": [ 20, 32, 4 ],
+      "R1": "93%",
+      "R2": "82%",
+      "R3": "79%",
+      "R4": "62%",
+      "R5": "52%",
+      "R6": "42%",
+      "PH": "95%",
+      "PL": "60%",
+      "stem": ""
     }
   },
   {
@@ -130,11 +175,11 @@
     "y": 87.139,
     "x": 0.21,
     "tableData": {
-      "id": "1",
+      "id": "6",
       "name": "算法平均值",
       "type": "单选",
       "areaName": "A",
-      "score": 2,
+      "score": 4,
       "diff": 0.21,
       "identify": "0.30",
       "classScoreRate": "73%",
@@ -146,20 +191,29 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "函数",
-      "poperData": [ 21, 8, 27 ]
+      "poperData": [ 28, 13, 56 ],
+      "R1": "92%",
+      "R2": "86%",
+      "R3": "78%",
+      "R4": "70%",
+      "R5": "55%",
+      "R6": "47%",
+      "PH": "100%",
+      "PL": "60%",
+      "stem": ""
     }
   },
   {
-    "id":7,
+    "id": 7,
     "type": "多选",
     "y": 54.914,
     "x": 0.03,
     "tableData": {
-      "id": "1",
+      "id": "7",
       "name": "算法平均值",
-      "type": "选",
+      "type": "选",
       "areaName": "A",
-      "score": 2,
+      "score": 4,
       "diff": 0.03,
       "identify": "0.90",
       "classScoreRate": "53%",
@@ -171,7 +225,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "几何图形初步",
-      "poperData": [ 37, 62, 13 ]
+      "poperData": [ 37, 14, 18 ],
+      "R1": "95%",
+      "R2": "87%",
+      "R3": "73%",
+      "R4": "61%",
+      "R5": "53%",
+      "R6": "46%",
+      "PH": "93%",
+      "PL": "53%",
+      "stem": ""
     }
   },
   {
@@ -180,11 +243,11 @@
     "y": 54.212,
     "x": 0.16,
     "tableData": {
-      "id": "1",
+      "id": "8",
       "name": "算法平均值",
-      "type": "问答",
+      "type": "单选",
       "areaName": "A",
-      "score": 2,
+      "score": 4,
       "diff": 0.16,
       "identify": "0.80",
       "classScoreRate": "65%",
@@ -196,7 +259,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "函数",
-      "poperData": [ 36, 3, 20 ]
+      "poperData": [ 21, 46, 46 ],
+      "R1": "93%",
+      "R2": "85%",
+      "R3": "78%",
+      "R4": "61%",
+      "R5": "60%",
+      "R6": "44%",
+      "PH": "91%",
+      "PL": "59%",
+      "stem": ""
     }
   },
   {
@@ -205,11 +277,11 @@
     "y": 82.468,
     "x": 0.13,
     "tableData": {
-      "id": "1",
+      "id": "9",
       "name": "算法平均值",
-      "type": "填空",
+      "type": "单选",
       "areaName": "A",
-      "score": 8,
+      "score": 4,
       "diff": 0.13,
       "identify": "0.30",
       "classScoreRate": "51%",
@@ -221,7 +293,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "图形的性质",
-      "poperData": [ 11, 98, 36 ]
+      "poperData": [ 27, 22, 4 ],
+      "R1": "93%",
+      "R2": "84%",
+      "R3": "79%",
+      "R4": "62%",
+      "R5": "53%",
+      "R6": "45%",
+      "PH": "100%",
+      "PL": "52%",
+      "stem": ""
     }
   },
   {
@@ -230,11 +311,11 @@
     "y": 80.553,
     "x": 0.44,
     "tableData": {
-      "id": "1",
+      "id": "10",
       "name": "算法平均值",
-      "type": "判断",
+      "type": "单选",
       "areaName": "A",
-      "score": 1,
+      "score": 4,
       "diff": 0.44,
       "identify": "0.90",
       "classScoreRate": "83%",
@@ -246,7 +327,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "图形的相似",
-      "poperData": [ 22, 70, 68 ]
+      "poperData": [ 49, 68, 21 ],
+      "R1": "99%",
+      "R2": "89%",
+      "R3": "78%",
+      "R4": "70%",
+      "R5": "51%",
+      "R6": "46%",
+      "PH": "96%",
+      "PL": "55%",
+      "stem": ""
     }
   },
   {
@@ -255,11 +345,11 @@
     "y": 81.154,
     "x": 0.84,
     "tableData": {
-      "id": "1",
+      "id": "11",
       "name": "算法平均值",
       "type": "多选",
       "areaName": "A -",
-      "score": 3,
+      "score": 6,
       "diff": 0.84,
       "identify": "0.20",
       "classScoreRate": "73%",
@@ -271,7 +361,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "图形的相似",
-      "poperData": [ 23, 59, 6 ]
+      "poperData": [ 39, 1, 2 ],
+      "R1": "100%",
+      "R2": "86%",
+      "R3": "78%",
+      "R4": "64%",
+      "R5": "59%",
+      "R6": "46%",
+      "PH": "91%",
+      "PL": "56%",
+      "stem": ""
     }
   },
   {
@@ -280,11 +379,11 @@
     "y": 82.468,
     "x": 0.73,
     "tableData": {
-      "id": "1",
+      "id": "12",
       "name": "算法平均值",
-      "type": "填空",
+      "type": "多选",
       "areaName": "A -",
-      "score": 10,
+      "score": 6,
       "diff": 0.73,
       "identify": "0.80",
       "classScoreRate": "72%",
@@ -296,7 +395,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "几何图形初步",
-      "poperData": [ 47, 39, 29 ]
+      "poperData": [ 37, 12, 21 ],
+      "R1": "100%",
+      "R2": "87%",
+      "R3": "74%",
+      "R4": "65%",
+      "R5": "53%",
+      "R6": "49%",
+      "PH": "93%",
+      "PL": "51%",
+      "stem": ""
     }
   },
   {
@@ -305,11 +413,11 @@
     "y": 80.553,
     "x": 0.64,
     "tableData": {
-      "id": "1",
+      "id": "13",
       "name": "算法平均值",
-      "type": "判断",
+      "type": "多选",
       "areaName": "A -",
-      "score": 3,
+      "score": 6,
       "diff": 0.64,
       "identify": "0.30",
       "classScoreRate": "57%",
@@ -321,7 +429,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "锐角三角函数",
-      "poperData": [ 34, 60, 40 ]
+      "poperData": [ 35, 88, 8 ],
+      "R1": "100%",
+      "R2": "88%",
+      "R3": "74%",
+      "R4": "63%",
+      "R5": "52%",
+      "R6": "42%",
+      "PH": "93%",
+      "PL": "58%",
+      "stem": ""
     }
   },
   {
@@ -330,11 +447,11 @@
     "y": 31.154,
     "x": 0.54,
     "tableData": {
-      "id": "1",
+      "id": "14",
       "name": "算法平均值",
-      "type": "多选",
+      "type": "判断",
       "areaName": "B -",
-      "score": 2,
+      "score": 4,
       "diff": 0.54,
       "identify": "0.40",
       "classScoreRate": "64%",
@@ -346,7 +463,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "统计与概率",
-      "poperData": [ 44, 44, 30 ]
+      "poperData": [ 14, 23, 64 ],
+      "R1": "99%",
+      "R2": "84%",
+      "R3": "74%",
+      "R4": "69%",
+      "R5": "55%",
+      "R6": "49%",
+      "PH": "96%",
+      "PL": "54%",
+      "stem": ""
     }
   },
   {
@@ -355,11 +481,11 @@
     "y": 42.468,
     "x": 0.13,
     "tableData": {
-      "id": "1",
+      "id": "15",
       "name": "算法平均值",
-      "type": "填空",
+      "type": "判断",
       "areaName": "B",
-      "score": 3,
+      "score": 4,
       "diff": 0.13,
       "identify": "0.40",
       "classScoreRate": "53%",
@@ -371,20 +497,29 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "图形的性质",
-      "poperData": [ 43, 8, 46 ]
+      "poperData": [ 30, 35, 38 ],
+      "R1": "97%",
+      "R2": "88%",
+      "R3": "78%",
+      "R4": "62%",
+      "R5": "60%",
+      "R6": "42%",
+      "PH": "94%",
+      "PL": "53%",
+      "stem": ""
     }
   },
   {
-    "id":16,
+    "id": 16,
     "type": "判断",
     "y": 40.553,
     "x": 0.24,
     "tableData": {
-      "id": "1",
+      "id": "16",
       "name": "算法平均值",
       "type": "判断",
       "areaName": "B",
-      "score": 8,
+      "score": 4,
       "diff": 0.24,
       "identify": "0.60",
       "classScoreRate": "70%",
@@ -396,7 +531,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "图形的性质",
-      "poperData": [ 40, 15, 5 ]
+      "poperData": [ 47, 69, 29 ],
+      "R1": "98%",
+      "R2": "84%",
+      "R3": "74%",
+      "R4": "62%",
+      "R5": "53%",
+      "R6": "49%",
+      "PH": "100%",
+      "PL": "56%",
+      "stem": ""
     }
   },
   {
@@ -405,11 +549,11 @@
     "y": 31.154,
     "x": 0.34,
     "tableData": {
-      "id": "1",
+      "id": "17",
       "name": "算法平均值",
-      "type": "多选",
+      "type": "填空",
       "areaName": "B",
-      "score": 6,
+      "score": 5,
       "diff": 0.34,
       "identify": "1.00",
       "classScoreRate": "80%",
@@ -421,7 +565,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "函数",
-      "poperData": [ 1, 68, 53 ]
+      "poperData": [ 22, 39, 33 ],
+      "R1": "92%",
+      "R2": "84%",
+      "R3": "77%",
+      "R4": "64%",
+      "R5": "59%",
+      "R6": "45%",
+      "PH": "98%",
+      "PL": "55%",
+      "stem": ""
     }
   },
   {
@@ -430,11 +583,11 @@
     "y": 51.154,
     "x": 0.37,
     "tableData": {
-      "id": "1",
+      "id": "18",
       "name": "算法平均值",
-      "type": "多选",
+      "type": "填空",
       "areaName": "A -",
-      "score": 1,
+      "score": 5,
       "diff": 0.74,
       "identify": "1.00",
       "classScoreRate": "90%",
@@ -446,7 +599,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "投影与视图",
-      "poperData": [ 10, 7, 70 ]
+      "poperData": [ 17, 98, 4 ],
+      "R1": "96%",
+      "R2": "88%",
+      "R3": "75%",
+      "R4": "68%",
+      "R5": "55%",
+      "R6": "48%",
+      "PH": "96%",
+      "PL": "60%",
+      "stem": ""
     }
   },
   {
@@ -455,11 +617,11 @@
     "y": 52.154,
     "x": 0.74,
     "tableData": {
-      "id": "1",
+      "id": "19",
       "name": "算法平均值",
-      "type": "多选",
+      "type": "填空",
       "areaName": "A -",
-      "score": 1,
+      "score": 5,
       "diff": 0.74,
       "identify": "1.00",
       "classScoreRate": "90%",
@@ -471,7 +633,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "投影与视图",
-      "poperData": [ 10, 7, 70 ]
+      "poperData": [ 37, 41, 18 ],
+      "R1": "100%",
+      "R2": "82%",
+      "R3": "80%",
+      "R4": "69%",
+      "R5": "54%",
+      "R6": "46%",
+      "PH": "92%",
+      "PL": "56%",
+      "stem": ""
     }
   },
   {
@@ -480,11 +651,11 @@
     "y": 55.154,
     "x": 0.34,
     "tableData": {
-      "id": "1",
+      "id": "20",
       "name": "算法平均值",
-      "type": "多选",
+      "type": "主观",
       "areaName": "A -",
-      "score": 1,
+      "score": 15,
       "diff": 0.74,
       "identify": "1.00",
       "classScoreRate": "90%",
@@ -496,7 +667,16 @@
       "standardDeviation": "55",
       "rankStatus": "1",
       "knowledgePoint": "投影与视图",
-      "poperData": [ 10, 7, 70 ]
+      "poperData": [ 36, 7, 26 ],
+      "R1": "93%",
+      "R2": "86%",
+      "R3": "79%",
+      "R4": "65%",
+      "R5": "57%",
+      "R6": "42%",
+      "PH": "94%",
+      "PL": "59%",
+      "stem": ""
     }
   }
 ]

+ 9 - 0
TEAMModelOS/ClientApp/store/index.js

@@ -1,7 +1,9 @@
 import Vue from 'vue'
 import Vuex from 'vuex'
+import Mock from 'mockjs';//es6语法引入mock模块
 import classMgmt from './module/classMgmt';
 import talMgmt from './module/talMgmt';
+import authorization from './module/authorization';
 import totalAnalysis from './module/totalAnalysis';
 
 Vue.use(Vuex)
@@ -24,9 +26,15 @@ const actions = ({
   }
 })
 
+const getters = {
+  radarData: state => state.totalAnalysis.radarData
+}
+
+
 export default new Vuex.Store({
   mutations,
   actions,
+  getters,
   state: {
     //选择关注年级
     selectgrade: [],
@@ -65,6 +73,7 @@ export default new Vuex.Store({
   modules: {
     classMgmt,
     talMgmt,
+    authorization,
     totalAnalysis
   }
 })

+ 13 - 0
TEAMModelOS/ClientApp/store/module/authorization.js

@@ -0,0 +1,13 @@
+export default {
+    state: {
+        antRouter:''
+    },
+    getters: {
+        
+    },
+    mutations: {
+    },
+    actions: {
+        
+    }
+}

+ 123 - 5
TEAMModelOS/ClientApp/store/module/totalAnalysis.js

@@ -1,30 +1,148 @@
 //全科学情分析数据
+import Mock from 'mockjs';//es6语法引入mock模块
 import mockTools from '@/mock';
 import classList from '@/static/classList.json' //模拟班级数据
-import memberList from '@/static/studentsInfo.json' //模拟学生数据
 import scatter from '@/static/scatter.json' //模拟学生数据
+import testScatter from '@/static/testScatter.json' //模拟试题分析落点数据
 import examList from '@/static/examList.json' //模拟评测数据
 import knowledgeList from '@/static/knowledgeList.json' //模拟知识点数据
 import exerciseList from '@/static/exerciseList.json' //模拟知识点数据
-import questions from '@/view/evaluation/index/list.json' //模拟题目数据
+import chineseList from '@/static/chinesePoint.json' //模拟语文知识点数据
+import questions from '@/static/questionList.json' //模拟题目数据
+import filter from '@/static/filter.json' //模拟题目数据
+import subjectPercent from '@/static/percent.json' //模拟各科平均分数据
 
 
 export default {
   state: {
     classList: classList,
+    subjectPercent: subjectPercent,
     memberList: mockTools.data.studentList,
     examList: examList,
     knowledgeList: knowledgeList,
     questions: questions,
     scatter: scatter,
-    exerciseList: exerciseList
+    testScatter: testScatter,
+    exerciseList: exerciseList,
+    filterData: filter,
+    baseBarData: mockTools.data.subjectList,
+    subjectList: [],
+    pieData: [
+      { value: 3, name: "方程与不等式", id: 1, itemStyle: { color: '#00cc66' } },
+      { value: 2, name: "图形的性质", id: 2, itemStyle: { color: '#b6a2df' } },
+      { value: 2, name: "统计与概率", id: 3, itemStyle: { color: '#59b2ef' } },
+      { value: 2, name: "函数", id: 4, itemStyle: { color: '#ffba82' } },
+      { value: 1, name: "图形的变化", id: 5, itemStyle: { color: '#db7984' } },
+    ],
+    radarData: [70, 80, 65, 72, 82, 70],
+    entryData:0
   },
   getters: {
-
+    getRandomBarData() {
+      let newData = Mock.mock({
+        'subjectList|10': [{
+          "id|+1": 1,
+          "className|1-10": 1,
+          "chinese|60-120": 60,
+          "math|60-120": 60,
+          "english|60-120": 60,
+          "physics|60-120": 60,
+          "chemistry|60-120": 60,
+          "biology|60-120": 60,
+        }]
+      });
+      return newData;
+    }
   },
   mutations: {
+    //修改首页成绩分析的及格率百分比
+    updatePercent(state, val) {
+      val.forEach(item => {
+        item.classRate = (90 - Math.ceil(Math.random() * 20)) + '%';
+        item.gradeRate = (90 - Math.ceil(Math.random() * 20)) + '%';
+        item.areaRate = (90 - Math.ceil(Math.random() * 20)) + '%';
+      })
+      state.subjectPercent = val;
+    },
+
+    //更新均分分析柱状图
+    updateBaseBarData(state, val) {
+      //console.log(newData);
+      let newData = Mock.mock({
+        'subjectList|10': [{
+          "id|+1": 1,
+          "className|1-10": 1,
+          "chinese|60-120": 60,
+          "math|60-120": 60,
+          "english|60-120": 60,
+          "physics|60-120": 60,
+          "chemistry|60-120": 60,
+          "biology|60-120": 60,
+        }]
+      });
+
+      newData.subjectList.forEach(item => {
+        item.className = '初一' + item.id + '班'
+      })
+      state.baseBarData = newData.subjectList;
+    },
+
+    //更新科目选择科目列表数据
+    updateSubjectList(state, list) {
+      state.subjectList = list;
+    },
+
+    //更新试题落点数据
+    updateScatterData(state, val) {
+      val.forEach(item => {
+        item.x = Math.random().toFixed(2);
+        item.y = Math.floor(Math.random() * 100);
+      })
+      state.scatter = val;
+    },
+
+    //更新试题落点数据
+    updateTestScatterData(state, val) {
+      val.forEach(item => {
+        item.x = Math.random().toFixed(2);
+        item.y = Math.floor(Math.random() * 100);
+      })
+      state.testScatter = val;
+    },
+
+    //更新知识点占比数据
+    updatePieData(state, subject) {
+      let list = ['文言文', '古代诗歌', '现代文', '文学常识', '语言表达与应用'];
+      let mathList = ['图形的变化', '方程与不等式', '图形的性质', '统计与概率', '函数'];
+
+        state.pieData.forEach((item, index) => {
+          item.name = subject == 0 ? list[index] : mathList[index];
+          item.value = Math.floor(Math.random() * 3) + 1;
+        })
+
+      state.exerciseList = subject == 0 ? chineseList : exerciseList;
+    },
+
+    //更新认知层次分布数据
+    updateRadarData(state) {
+      let list = JSON.parse(JSON.stringify(state.radarData)); //必须转化深拷贝才能监听到State内部的数据变化
+      for (let i = 0; i < list.length; i++) {
+        list[i] = 90 - Math.floor(Math.random() * 30);
+      }
+      state.radarData = list;
+    },
+
+    updateEntryData(state, data) {
+      state.entryData = data;
+    },
+
+    updateSubjectPercent(state, data) {
+      state.subjectList = data;
+    }
   },
   actions: {
-
+    updateRadarData(context) {
+      context.commit('updateRadarData')
+    }
   }
 }

+ 71 - 0
TEAMModelOS/ClientApp/view/authorization/Index.less

@@ -0,0 +1,71 @@
+#authMgmt{    
+    width: 100%;
+    height: 100%;
+    color: #fff;
+    padding: 1%;
+    overflow-x: auto;
+    overflow-y: hidden;
+    .main{
+        white-space: nowrap;
+        display: -webkit-box;
+        display: -ms-flexbox;
+        display: flex;
+        height:95%;
+        .pane{
+            height: 100%;
+            border: 1px #333 solid;
+            padding:10px;
+            background-color: #13313e;
+            border:1px solid #333;
+            position: relative;
+            z-index:10;
+            box-shadow: 2px 0 2px 0px rgba(81, 90, 110, 0.5);
+            .title{
+                height:5%;
+            }
+            .head{
+                border-bottom: 1px solid rgb(148, 153, 138);
+                padding-bottom: 10px                
+            }
+            .conet{
+                overflow: auto;
+                height: 94%;
+                width: 100%;
+                .user{
+                    &:hover, &.active{
+                        background: -webkit-linear-gradient(right, rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -o-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -moz-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: linear-gradient(to right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                    }
+                    padding: 15px 10px 10px 25px;
+                    background-color: rgba(17, 17, 17, 0.14);
+                    cursor: pointer;
+                    margin-bottom:5px;
+                    .box{
+                        height: 50px;
+                        .name{
+                            h3{
+                                font-size: 1.5em
+                            }
+                            span{
+                                font-size: 1em;color: #dcdee2;
+                            }
+                        }
+                        .nickName{
+                            span{
+                                font-size: 1em
+                            }
+                        }
+                        .play{
+                            text-align: right;
+                        }
+                    }
+                }
+            }
+        }
+        .pane-z-index-1{
+            z-index:1;
+        }
+    }
+}

+ 315 - 0
TEAMModelOS/ClientApp/view/authorization/Index.vue

@@ -0,0 +1,315 @@
+<style lang="less" scoped>
+  @import './Index.less';
+</style>
+
+
+<template>
+  <div id="authMgmt" class="backdrop-dark">
+    <h2 class="title">權限設定</h2>
+    <Row class="main">
+        <Col class="pane" :span="7">
+            <Row class="head">
+                <Col :span="10">
+                    <Input v-model="filterName" suffix="ios-search" placeholder="ID / Name" />
+                </Col>
+                <Col :span="14">
+                    <Button @click="userPaneBtn('addUser')" style="float: right;" icon="md-add"></Button>
+                </Col>
+            </Row>
+            <div class="conet scrollstyle">
+                <div v-for="(user, index) in filterLists" :key="index" class="user" :class="{ 'active': user.id === userSelect }" @click="userPaneBtn('auth', user.id)">
+                    <Row class="box" type="flex" justify="center" align="middle">
+                        <Col class="name" :span="8">
+                            <h3>{{user.id}}</h3>
+                            <span>{{user.name}}</span>
+                        </Col>
+                        <Col class="nickName" :span="8"><span>{{user.nickName}}</span></Col>
+                        <Col class="play" :span="8"><Icon size="20" type="md-play" /></Col>
+                    </Row>
+                </div>
+            </div>
+        </Col>
+        <transition name="leftInOut">
+            <Col class="pane" style=" z-index:9;" v-if="userPane == 'addUser'" :span="4">
+                <Row style="border-bottom: 1px solid #94998a;padding-bottom: 10px;    min-height: 44px;">
+                    <Col :span="12">
+                        <h3>
+                            是否讓以下的老師加入:
+                            <!-- 老師加入後給予預設的權限 -->
+                        </h3>
+                    </Col>
+                    <Col :span="12">
+                        <a style="color:#fff;float: right;"  @click="closeBtn()"><Icon size="17" type="md-close" /></a>
+                    </Col>                    
+                </Row>
+                <Row class="scrollstyle"  style="margin-top: 10px;overflow: auto;height: 88%;">
+                    <Col>
+                        <div style="padding: 15px 10px 10px 15px;background-color: rgba(17, 17, 17, 0.14);cursor: pointer;margin-bottom: 5px;">
+                            <h3>JEFF-<small>JEFF#1234</small></h3>
+                             <RadioGroup>
+                                <Radio true-value="01" label="通過"></Radio>
+                                <Radio true-value="10" label="拒絕"></Radio>
+                            </RadioGroup>
+                        </div>
+                        <div style="padding: 15px 10px 10px 15px;background-color: rgba(17, 17, 17, 0.14);cursor: pointer;margin-bottom: 5px;">
+                            <h3>Mickey-<small>Mikey#1234</small></h3>
+                            <RadioGroup>
+                                <Radio true-value="01" label="通過"></Radio>
+                                <Radio true-value="10" label="拒絕"></Radio>
+                            </RadioGroup>
+                        </div>
+                    </Col>
+                </Row>
+                <Row >
+                    <Col style="text-align: right;">
+                        <Button>確定</Button>
+                    </Col>
+                </Row>
+            </Col>
+            </transition>
+        <transition name="leftInOut">
+            <Col class="pane" style=" z-index:8;" v-if="(userPane == 'addUser' && show)" :span="3">
+                addUser2
+            </Col>
+        </transition>
+        <transition name="leftInOut">
+            <Col class="pane"  style=" z-index:9;" v-if="userPane == 'auth'" :span="3">
+                <Row style="border-bottom: 1px solid #94998a;padding-bottom: 10px;    min-height: 44px;">
+                    <Col :span="12">
+                        <h3>
+                            {{userAuth.name}}
+                            <small>{{userAuth.id}}</small>
+                        </h3>                        
+                    </Col>
+                    <Col :span="12">
+                        <a style="color:#fff;float: right;"  @click="closeBtn()"><Icon size="17" type="md-close" /></a>
+                    </Col>                    
+                </Row>
+                <Row style="margin-top: 10px;">
+                    <Col :span="12" style="text-align: right;">
+                        <Input size="small">
+                            <span slot="prepend">稱謂</span>
+                        </Input>
+                    </Col>                    
+                    <Col :span="12" style="text-align: right;">
+                        <Button size="small" icon="md-copy" @click="copyUserAuthFlag = true"></Button>
+                    </Col>
+                </Row>
+                <Row class="scrollstyle"  style="margin-top: 10px;overflow: auto;height: 84%;">
+                    <Col v-for="(item, authKey) in userAuth.authList" :key="authKey">
+                        <div style="padding: 15px 10px 10px 25px;background-color: rgba(17, 17, 17, 0.14);cursor: pointer;margin-bottom: 5px;">
+                            <Checkbox v-model="item.permissions"> {{item.path}}</Checkbox>
+                        </div>
+                        <transition name="leftInOut">
+                            <div v-if="item.permissions == 1">                 
+                                <ul style="margin-left: 15px;list-style-type: none;">
+                                    <li v-for="(value, name) in item.access">
+                                        <div style="padding: 15px 10px 10px 25px;background-color: rgba(17, 17, 17, 0.14);cursor: pointer;margin-bottom: 5px;">
+                                            {{ name }}
+                                            <Checkbox v-model="item.access[name]"></Checkbox>
+                                        </div>
+                                    </li>
+                                </ul>
+                            </div>    
+                        </transition>
+                    </Col>                    
+                </Row>
+                <Row >
+                    <Col style="text-align: right;">
+                        <Button>確定</Button>
+                    </Col>
+                </Row>
+                <Spin size="large" fix v-if="authSpin">
+                    <Icon type="ios-loading" size=18 class="spin-icon-load"></Icon>
+                    <div>Loading</div>
+                </Spin>
+            </Col>           
+        </transition>
+        <transition name="leftInOut">
+            <Col class="pane" style=" z-index:8;" v-if="copyUserAuthFlag" :span="3">
+                <Row style="border-bottom: 1px solid #94998a;padding-bottom: 10px;    min-height: 44px;">
+                    <Col :span="12">
+                        <h3>權限複製</h3>                        
+                    </Col>
+                    <Col :span="12">
+                        <a style="color:#fff;float: right;"  @click="copyUserAuthFlag = false"><Icon size="17" type="md-close" /></a>
+                    </Col>                    
+                </Row>
+                <Row style="margin-top: 10px;">
+                    <Col>
+                        <Input v-model="filterNameBycopy" suffix="ios-search" placeholder="ID / Name" />                
+                    </Col>
+                </Row>
+                <Row class="scrollstyle"  style="margin-top: 10px;overflow: auto;height: 88%;">
+                    <Col v-for="(item, key) in filterCopyName" :key="key">
+                        <div style="padding: 15px 10px 10px 15px;background-color: rgba(17, 17, 17, 0.14);cursor: pointer;margin-bottom: 5px;text-align:center;">
+                            {{item.name}}
+                        </div>                        
+                    </Col>
+                </Row>
+            </Col>
+        </transition>
+    </Row>
+  </div>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+        copyUserAuthFlag: false,
+        filterName:'',
+        filterNameBycopy: '',
+        userSelect:'', // 被點選的人
+        userPane: '', // 啟動的功能頁紀錄
+        authSpin: false, // 權限頁Spin
+        userList:[ // UserLIST
+            {
+                id: 'Osbert#1234',
+                name: '歐斯柏',
+                nickName: '老師',
+                authList:[
+                    {
+                        path: '/smartschooldashboard',
+                        component: 'smartschooldashboard',
+                        access: {  // 小組件權限
+                            'fun1': true, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/smartclassdashboard',
+                        component: 'smartclassdashboard',
+                        access: {  // 小組件權限
+                            'fun1': true, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/guidelines',
+                        component: 'guidelines',
+                        access: {  // 小組件權限
+                            'fun1': true, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                ]
+            },
+            {
+                id: 'James#1234',
+                name: '詹姆士',
+                nickName: '老師',
+                authList:[
+                    {
+                        path: '/smartschooldashboard', // 頁面
+                        component: 'smartschooldashboard', //組件名
+                        access: {  // 小組件權限
+                            'fun1': false, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/smartclassdashboard',
+                        component: 'smartclassdashboard',
+                        access: {  // 小組件權限
+                            'fun1': true, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/guidelines',
+                        component: 'guidelines',
+                        access: {  // 小組件權限
+                            'fun1': false, 
+                            'fun2': false
+                        },
+                        permissions: false // true: 有權訪問, false: 無權訪問
+                    },
+                ]
+            },
+        ],
+        userAuth:{ // 使用者個人權限顯示
+            id: '',
+            name: '',
+            nickName: '',
+            authList:[]
+        },
+        
+    }
+  },
+  computed:{
+    filterLists: function(){
+    // 通通轉小寫比對。
+    let filterName = this.filterName.toLowerCase();
+
+    return ( filterName.trim() !== '' ) ?
+        this.userList.filter(function(d){ return (d.name.toLowerCase().indexOf(filterName) > -1 || d.id.toLowerCase().indexOf(filterName) > -1); }) :
+        this.userList;
+    },
+    filterCopyName: function(){
+        // 通通轉小寫比對。
+        let filterName = this.filterNameBycopy.toLowerCase();
+
+        return ( filterName.trim() !== '' ) ?
+        this.userList.filter(function(d){ return (d.name.toLowerCase().indexOf(filterName) > -1 || d.id.toLowerCase().indexOf(filterName) > -1); }) :
+        this.userList;
+    }
+  },
+  methods:{
+    async userPaneBtn(pane, id){
+        this.userSelect = id;
+        if(this.userPane !='' && this.userPane != pane){
+           this.userPane = '' 
+           await this.sleep(700);
+           this.userPane = pane;
+        } else {
+            this.userPane = pane;
+        }
+        
+        switch (pane) {
+            case 'auth':
+                this.userAuthSeting(id);
+            break;
+        }
+    },
+    closeBtn(pane){
+        this.userPane = '';
+        this.userSelect = '';
+        this.copyUserAuthFlag = false;
+    },    
+    sleep (time) {
+        return new Promise((resolve) => setTimeout(resolve, time));
+    },
+    async userAuthSeting(id){
+        // if(this.userSelect == id) return false;
+        this.authSpin = true;
+        await this.sleep(2000);
+        let auth = this.userList.find(function(item){
+            return item.id == id
+        });
+        this.userAuth.id = auth.id;
+        this.userAuth.name = auth.name;
+        this.userAuth.nickName = auth.nickName;
+        this.userAuth.authList = auth.authList;        
+        this.authSpin = false;
+    }
+  }
+}
+</script>
+<style scoped>
+.leftInOut-enter-active, .leftInOut-leave-active {
+    transition: all 0.7s;
+}
+.leftInOut-enter, .leftInOut-leave-to /* .list-leave-active below version 2.1.8 */ {
+    opacity: 0;
+    transform: translateX(-150px);    
+}
+.spin-icon-load{
+    animation: ani-demo-spin 1s linear infinite;
+}
+</style>

+ 1 - 1
TEAMModelOS/ClientApp/view/index.vue

@@ -62,7 +62,7 @@
         moduleList: [{
           name: "学情分析",
           icon:"ios-podium",
-          link: "/saindex"
+          link: "/totalIndex"
         },
           {
           name: "课纲管理",

+ 73 - 12
TEAMModelOS/ClientApp/view/school-mgmt/ClassroomSetting/ClassroomSetting.less

@@ -2,7 +2,8 @@
 @borderColor: #424242; //边框颜色
 @primary-textColor: #fff; //文本主颜色
 @second-textColor: #a5a5a5; //文本副级颜色
-@third-textColor: #dddddd; //其他颜色
+@third-textColor: #dddddd;//其他颜色
+@fourth-textColor: #6BDFC3;
 @primary-fontSize: 14px;
 @second-fontSize: 16px;
 @large-fontSize: 20px;
@@ -73,15 +74,15 @@
     margin-right:15px;
 }
 
-.school-plan-wrap{
-    position:absolute;
-    top:50px;
-    bottom:0px;
-    width:100%;
-    display:flex;
-    flex-direction:row;
-    justify-content:center;
-    align-items:center;
+.school-plan-wrap {
+    position: absolute;
+    top: 50px;
+    bottom: 0px;
+    width: 100%;
+    display: flex;
+    flex-flow: row;
+    align-items: center;
+    justify-content: center;
 }
 .school-plan-wrap p{
     position:absolute;
@@ -185,10 +186,18 @@
 .third-text-color{
     color:@third-textColor;
 }
+.fourth-text-color {
+    color: #ED4014 !important;
+    /*text-shadow:1px 1px 1px white;*/
+}
 .class-hiteach-code {
+    margin-top:5px;
 }
 .class-type {
-    margin-top:8px;
+    margin-top:6px;
+    margin-bottom:4px;
+    color:#6BDFC3;
+    margin-left:-4px;
 }
 .primary-text-color{
     color:@primary-textColor;
@@ -228,7 +237,6 @@
     top: 50px;
     bottom: 0px;
     left: 47%;
-
     &-header {
         width: ~"calc(100% - 30px)";
         -moz-width: ~"calc(100% - 30px)";
@@ -261,6 +269,7 @@
             li{
                 &:hover{
                     background:@borderColor;
+                    color:white;
                 }
                 height:40px;
                 line-height:40px;
@@ -276,3 +285,55 @@
         }
     }
 }
+#school-plan {
+    background: none;
+    /*max-width: 100%;*/
+    /*border: 1px solid white;*/
+}
+.school-plan-zoom {
+    position: absolute;
+    right: 150px;
+    top: 10px;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    .ivu-icon {
+        margin-right: 10px;
+        cursor: pointer;
+    }
+
+    span {
+        color: white;
+        font-size: 16px;
+        margin-right: 15px;
+        display: inline-block;
+        letter-spacing: 3px;
+        cursor: pointer;
+    }
+}
+.school-plan-box {
+    /*position: absolute;
+    top: 50px;
+    left: 30px;*/
+    width: -moz-calc(100% - 60px);
+    width: -webkit-calc(100% - 60px);
+    width: calc(100% - 60px);
+    max-height: 90%;
+    overflow: scroll;
+    text-align:center;
+    &::-webkit-scrollbar { /*滚动条整体样式*/
+        width: 5px; /*高宽分别对应横竖滚动条的尺寸*/
+        height: 8px;
+    }
+
+    &::-webkit-scrollbar-thumb { /*滚动条里面小方块*/
+        -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
+        background: rgb(124,124,124);
+    }
+
+    &::-webkit-scrollbar-track { /*滚动条里面轨道*/
+        -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
+        background: rgba(68,68,68,.5);
+    }
+}

+ 583 - 104
TEAMModelOS/ClientApp/view/school-mgmt/ClassroomSetting/ClassroomSetting.vue

@@ -7,62 +7,73 @@
     background: none;
     line-height: 30px;
     border: none;
+    color:white;
+    font-size:15px;
   }
+
   .hiteach-code-wrap-header .ivu-input {
-    width:calc(100% - 30px);
-    -webkit-width:calc(100% - 30px);
-    -moz-width:calc(100% - 30px);
-    background:none;
-    border:none;
-    border-radius:0px;
-    font-size:12px;
-    color:#424242;
+    width: calc(100% - 30px);
+    -webkit-width: calc(100% - 30px);
+    -moz-width: calc(100% - 30px);
+    background: none;
+    border: none;
+    border-radius: 0px;
+    color:white;
+    font-size:15px;
   }
+
   .class-attr-wrap .ivu-input {
-    width:calc(100% - 30px);
-    -webkit-width:calc(100% - 30px);
-    -moz-width:calc(100% - 30px);
-    background:none;
-    border:none;
-    border-radius:0px;
-    font-size:16px;
-    color:white;
+    width: calc(100% - 30px);
+    -webkit-width: calc(100% - 30px);
+    -moz-width: calc(100% - 30px);
+    background: none;
+    border: none;
+    border-radius: 0px;
+    font-size: 16px;
+    color: white;
     border-bottom: 2px solid #424242;
   }
+
   .class-attr-wrap .ivu-select {
-    width:calc(100% - 30px);
-    -webkit-width:calc(100% - 30px);
-    -moz-width:calc(100% - 30px);
-    color:white;
+    width: calc(100% - 30px);
+    -webkit-width: calc(100% - 30px);
+    -moz-width: calc(100% - 30px);
+    color: white;
   }
+
   .class-attr-wrap .ivu-select-selected-value {
-    font-size:16px !important;
+    font-size: 16px !important;
   }
+
   .class-attr-wrap .ivu-select-selection {
-    background:none;
+    background: none;
     border-color: #424242;
   }
+
   .class-attr-wrap .ivu-divider {
-    background-color:#424242;
+    background-color: #424242;
   }
+
   .school-plan-wrap .ivu-upload {
-    position:absolute;
-    top:0px;
-    right:0px;
-    color:white;
-    cursor:pointer;
+    position: absolute;
+    top: 0px;
+    right: 0px;
+    color: white;
+    cursor: pointer;
   }
+
   .school-plan-wrap .ivu-btn {
-    background:none;
-    border:none;
-    color:white;
-    padding:8px 35px 6px 20px;
-    border-bottom:1px solid #424242;
-    border-radius:0px;
-    font-size:14px;
+    background: none;
+    border: none;
+    color: white;
+    padding: 8px 35px 6px 20px;
+    border-bottom: 1px solid #424242;
+    border-radius: 0px;
+    font-size: 14px;
   }
+
   .school-plan-wrap .ivu-upload-list {
-    display:none;
+    display: none;
   }
 </style>
 <template>
@@ -70,13 +81,13 @@
     <div class="container-left">
       <div class="container-left-title">
         <span class="first-title">教室列表</span>
-        <span class="label-style" @click="saveClassroom"><Icon class="label-icon" color="white" type="ios-albums-outline"/>储存变更</span>
-        <span class="label-style" @click="addClassroom()"><Icon class="label-icon" color="white" type="md-add"/>新增教室</span>
+        <span class="label-style" @click="saveClassroom" v-if="updated"><Icon class="label-icon" color="white" type="ios-albums-outline" />储存变更</span>
+        <span class="label-style" @click="addClassroom()"><Icon class="label-icon" color="white" type="md-add" />新增教室</span>
       </div>
       <div class="container-left-wrap">
         <div class="container-left-box">
           <div class="class-search-input">
-            <Input placeholder="请输入关键字或资讯" style="width: 100%;height:30px;">
+            <Input v-model="serchClassName" placeholder="请输入关键字或资讯" style="width: 100%;height:30px;" @on-change="filterClassname">
             <Icon style="margin-top:0px;" type="ios-search" slot="suffix" />
             </Input>
           </div>
@@ -85,24 +96,24 @@
             依创建时间排序
           </p>
           <div class="class-list">
-            <div class="class-list-item" v-for="(item,index) in classroomList" @click="chooseClassroom(index)" :class="currentClassroomIndex == index ? 'active-item-bg':''">
+            <div class="class-list-item" v-for="(item,index) in classroomListShow" @click="chooseClassroom(index)" :class="currentClassroomIndex == index ? 'active-item-bg':''">
               <div class="class-list-item-left">
                 <p class="class-name">{{item.name}}</p>
-                <p class="class-hiteach-code second-text-color">{{item.hiteachCode}}</p>
-                <p class="class-type third-text-color">
+                <p class="class-hiteach-code second-text-color">{{item.hiTeach}}</p>
+                <p class="class-type">
                   <Icon type="md-arrow-dropright" size="18" />{{item.classroomType}}
                 </p>
                 <p class="second-text-color">
-                  <span>学生人数:</span>
-                  <span class="primary-text-color">{{item.stuNum}}</span>
-                  <span>|</span>
+                  <!--<span>学生人数:</span>
+                <span class="primary-text-color">{{item.stuNum}}</span>
+                <span>|</span>-->
                   <span>班主任:</span>
-                  <span class="primary-text-color">{{item.headmaster}}</span>
+                  <span class="primary-text-color">{{item.headMaster}}</span>
                 </p>
               </div>
               <div class="class-list-item-tool">
                 <Icon type="ios-copy" title="不知道" />
-                <Icon type="md-trash" title="删除" @click.stop="delClassroom(index)"/>
+                <Icon type="md-trash" title="删除" @click.stop="delClassroom(index)" />
               </div>
             </div>
           </div>
@@ -113,10 +124,12 @@
             <span class="first-title">教室属性</span>
           </div>
           <div class="class-attr-wrap">
+            <span class="class-attr-wrap-label">教室编码</span>
+            <Input v-model="classroomList[currentClassroomIndex].classroomCode" placeholder="请输入教室编码..." />
             <span class="class-attr-wrap-label">教室名称</span>
             <Input v-model="classroomList[currentClassroomIndex].name" placeholder="请输入教室名称..." />
             <span class="class-attr-wrap-label">班主任设定</span>
-            <Input v-model="classroomList[currentClassroomIndex].headmaster" placeholder="请输入指定教师名称..." />
+            <Input v-model="classroomList[currentClassroomIndex].headMaster" placeholder="请输入指定教师名称..." />
             <span class="class-attr-wrap-label">选择教室学段</span>
             <Select v-model="classroomList[currentClassroomIndex].period">
               <Option v-for="(item,index) in periodList" :value="item.value" :key="index">{{ item.value }}</Option>
@@ -126,25 +139,34 @@
               <Option v-for="(item,index) in gradeList" :value="item.value" :key="index">{{ item.value }}</Option>
             </Select>
             <span class="class-attr-wrap-label">HiTeach软件序号</span>
-            <Input v-model="classroomList[currentClassroomIndex].hiteachCode" placeholder="请输入序号或在右侧列表选择可用序号..." />
+            <Input v-model="classroomList[currentClassroomIndex].hiTeach" disabled placeholder="请在右侧列表选择可用序号..." />
             <Divider style="margin-top:60px;color:#424242;" />
           </div>
           <div class="hiteach-code-wrap">
             <div class="hiteach-code-wrap-header">
-              <p>HiTeach序号列表(星号为大量授权序号)</p>
-              <Input placeholder="请输入关键字或资讯" style="width: 100%;height:30px;">
+              <p> 
+                HiTeach序号列表(星号为大量授权序号)
+                <Icon style="float:right;margin-right:12px;margin-top:2px;" class="label-icon" color="white" type="md-add" @click="addHiTeachCode" />
+              </p>
+              <Input v-model="serchCode" placeholder="请输入关键字或资讯" style="width: 100%;height:30px;" @on-change="filterCode">
               <Icon style="margin-top:0px;" type="ios-search" slot="suffix" />
               </Input>
             </div>
             <div class="hiteach-code-wrap-list">
-              <h1 v-if="!hiteachCodes.length">没有序号登录</h1>
+              <h1 v-if="!hiTeachs.length">没有序号登录</h1>
               <ul v-else>
-                <li v-for="(item,index) in hiteachCodes" :key="index" @click="chooseHiteachCode(index)">{{item.code}} <Icon v-if="item.single == 1" type="ios-star" color="white"/></li>
+                <li v-for="(item,index) in hiTeachsShow" :key="index" @click="chooseHiTeach(index)" :class="item.using > 0 ? 'fourth-text-color':''">
+                  {{item.code}}
+                  <Icon type="ios-star" color="white" v-if="item.single == 1 && item.using <= 0" />
+                  <Badge :count="item.using" v-if="item.single == 1 && item.using > 0">
+
+                  </Badge>
+                </li>
               </ul>
             </div>
           </div>
         </div>
-        
+
       </div>
     </div>
     <div class="container-right">
@@ -152,13 +174,30 @@
         <span class="first-title">校园平面图与教室位置设定</span>
       </div>
       <div class="school-plan-wrap">
-        <Upload action="//jsonplaceholder.typicode.com/posts/" :on-success="uploadSchoolPlan">
-          <Button icon="ios-cloud-upload-outline">传平面图</Button>
+        <Upload action="//jsonplaceholder.typicode.com/posts/" :on-success="uploadSchoolPlan" :before-upload="getFileData">
+          <Button icon="ios-cloud-upload-outline">传平面图</Button>
         </Upload>
-        <!--<p>长传平面图</p>-->
-        <h1>未上传平面图</h1>
+        <div class="school-plan-zoom">
+          <span @click="defaultSize()">1:1</span>
+          <Icon type="ios-add-circle-outline" color="white" size="24" @click="bigger()" />
+          <Icon type="ios-remove-circle-outline" color="white" size="24" @click="smaller()" />
+        </div>
+        <!--<h1>未上传平面图</h1>-->
+        <div class="school-plan-box" id="school-plan-box">
+          <canvas id="school-plan" style="" @mousedown="canvasMouseDown" @mousemove="canvasMouseMove" @mouseup="canvasMouseUp" @mouseout="canvasMouseOut">
+            当前浏览器不支持Canvas,请更换浏览器再试试。
+          </canvas>
+        </div>
       </div>
     </div>
+    <Modal v-model="addCode"
+           title="Common Modal dialog box title"
+           @on-ok="ok"
+           @on-cancel="cancel">
+      <p>Content of dialog</p>
+      <p>Content of dialog</p>
+      <p>Content of dialog</p>
+    </Modal>
   </div>
 </template>
 
@@ -166,72 +205,370 @@
   export default {
     data() {
       return {
-        model1:'',
-        headmaster: '',
+        addCode:false,
+        isInit: true,
+        updated: false,
+        model1: '',
+        headMaster: '',
         className: '',
-        hiteachCodes: [
+        hiTeachsShow:[],
+        hiTeachs: [
           {
             code: "C7A3804A-4DF7-436B-8D29-B5B88A644937",
-            single:0
+            single: 0,
+            using:0
           },
           {
             code: "512ADF7A-91D0-4E70-8BA7-EC4D4441394E",
-            single:0
+            single: 0,
+            using:0
           },
           {
             code: "F9BF4C21-FFD6-41AD-A459-237030F42C28",
-            single:1
+            single: 1,
+            using:0
           },
           {
             code: "F42DBB41-88C6-42FA-8EBD-1467BDCB897F",
-            single:0
+            single: 0,
+            using:0
           },
           {
-            code: "C7A3804A-4DF7-436B-8D29-B5B88A644937",
-            single:0
+            code: "C7A37895-4DF7-436B-8D29-B5B88A644937",
+            single: 0,
+            using:0
           },
           {
-            code: "512ADF7A-91D0-4E70-8BA7-EC4D4441394E",
-            single:0
+            code: "9825322A-91D0-4E70-8BA7-EC4D4441394E",
+            single: 0,
+            using:0
           },
           {
-            code: "F9BF4C21-FFD6-41AD-A459-237030F42C28",
-            single:0
+            code: "54612931-FFD6-41AD-A459-237030F42C28",
+            single: 0
           },
           {
-            code: "F42DBB41-88C6-42FA-8EBD-1467BDCB897F",
-            single:0
+            code: "F42DBB41-8666-42FA-8EBD-1467B564897F",
+            single: 0,
+            using:0
           },
           {
-            code: "C7A3804A-4DF7-436B-8D29-B5B88A644937",
-            single:1
+            code: "C845854A-4DF7-436B-8D29-B5B88A644999",
+            single: 1,
+            using:0
           },
           {
-            code: "512ADF7A-91D0-4E70-8BA7-EC4D4441394E",
-            single:0
+            code: "512ADF7A-91D0-4E70-8BA7-EC4D25813963",
+            single: 0,
+            using:0
           },
           {
-            code: "F42DBB41-88C6-42FA-8EBD-1467BDCB897F",
-            single:0
+            code: "ASDFTF41-88C6-42FA-8EBD-1467BDCB897F",
+            single: 0,
+            using:0
           },
           {
-            code: "C7A3804A-4DF7-436B-8D29-B5B88A644937",
-            single:0
+            code: "CTREYUIA-4DF7-436B-8D29-B5B88A644789",
+            single: 0,
+            using:0
           },
           {
-            code: "512ADF7A-91D0-4E70-8BA7-EC4D4441394E",
-            single:0
+            code: "51200000-91D0-4E70-8BA7-EC4D44413178",
+            single: 0,
+            using:0
           }
         ],
         classroomList: [],
+        classroomListShow: [],
         periodList: [],
         gradeList: [],
-        currentClassroomIndex:0
+        currentClassroomIndex: 0,
+        schoolPlan: '',
+        file: '',
+        imgUrl: '',
+        point: {},
+        clickPoint: {},
+        isMouseDown: false,
+        isFirstDraw: 0,
+        schoolImageData: [],
+        pinImageData: {},
+        whiteImageData: {},
+        greenImageData: {},
+        activeIcon: -1,
+        textStatus: true,
+        serchClassName: '',
+        serchCode:'',
+        serchHiteach: '',
+        scaleDefault: 1,
+        maxScale: 3,
+        minScale: 0.4,
+        scaleStep: 0.1,
+        stopScale:false
       }
     },
     methods: {
+      addHiTeachCode() {
+        this.addCode = true;
+      },
+      bundleScoll() {
+        let schoolPlanBox = document.getElementById('school-plan-box');
+        let _this = this;
+        //this.schoolPlan.addEventListener('mousewheel', this.scrollFunc(e), true) || this.schoolPlan.addEventListener("DOMMouseScroll", this.scrollFunc(e), false);
+        schoolPlanBox.addEventListener('mousewheel', function (e) {
+          if (e.preventDefault) {
+            e.preventDefault();
+          } else {
+            window.event.returnValue == false;
+          }
+          _this.scrollFunc(e);
+        }, false) || schoolPlanBox.addEventListener('DOMMouseScroll', function (e) {
+          if (e.preventDefault) {
+            e.preventDefault();
+          } else {
+            window.event.returnValue == false;
+          }
+          _this.scrollFunc(e);
+        }, false);
+      },
+      scrollFunc(e) {
+        e = e || window.event;
+        if (e.wheelDelta) {  //判断浏览器IE,谷歌滑轮事件
+          if (e.wheelDelta > 0) { //当滑轮向上滚动时
+            this.bigger();
+          }
+          if (e.wheelDelta < 0) { //当滑轮向下滚动时
+            this.smaller();
+          }
+        } else if (e.detail) {  //Firefox滑轮事件
+          if (e.detail > 0) { //当滑轮向上滚动时
+            this.bigger();
+          }
+          if (e.detail < 0) { //当滑轮向下滚动时
+             this.smaller();
+          }
+        }
+      },
+      defaultSize() {
+        this.scaleDefault = 1;
+        this.repaint(this.scaleDefault);
+      },
+      bigger() {
+        if (this.scaleDefault + this.scaleStep > this.maxScale) {
+          if (!this.stopScale) {
+            this.$Message.warning('已放大至最大倍数!');
+            this.stopScale = true;
+          }
+        } else {
+          this.stopScale = false;
+          this.scaleDefault += this.scaleStep;
+          this.repaint(this.scaleDefault);
+        }
+      },
+      smaller() {
+        if (this.scaleDefault - this.scaleStep < this.minScale) {
+          if (!this.stopScale) {
+            this.$Message.warning('已缩小至最小倍数!');
+            this.stopScale = true;
+          }
+        } else {
+          this.stopScale = false;
+          this.scaleDefault -= this.scaleStep;
+          this.repaint(this.scaleDefault);
+        }
+      },
+      repaint(scale) {
+        this.schoolPlan = document.getElementById('school-plan');
+        this.schoolPlan.height =  this.schoolImageData.height * this.scaleDefault;
+        this.schoolPlan.width = this.schoolImageData.width * this.scaleDefault;
+        let ctx = this.schoolPlan.getContext('2d');
+        this.drawSchoolPlan("imgUrl");
+        this.initIcon();
+      },
+      filterCode() {
+        let _this = this;
+        if (this.serchCode == '') {
+          this.hiTeachsShow = [...this.hiTeachs];
+        } else {
+          this.hiTeachsShow = this.hiTeachs.filter(item => item.code.indexOf(_this.serchCode) != -1);
+        }
+        
+      },
+      filterClassname() {
+        let _this = this;
+        if (this.serchClassname == '') {
+          this.classroomListShow = [...this.classroomList];
+        } else {
+          this.classroomListShow = this.classroomList.filter(item => item.name.indexOf(_this.serchClassName) != -1);
+        }
+      },
+      drawText(text, x, y) {
+          this.schoolPlan = document.getElementById('school-plan');
+          let ctx = this.schoolPlan.getContext('2d');
+          ctx.font = "16px Arial";
+          ctx.fillStyle = "yellow";
+          ctx.fillText(text, x, y);
+      },
+      drawIcon(x, y) {
+        this.schoolPlan = document.getElementById('school-plan');
+        let ctx = this.schoolPlan.getContext('2d');
+        ctx.beginPath();
+        ctx.drawImage(this.whiteImageData, x * this.scaleDefault, y * this.scaleDefault, 20 * this.scaleDefault, 20 * this.scaleDefault);
+      },
+      moveIcon(x, y) {
+        this.schoolPlan = document.getElementById('school-plan');
+        let ctx = this.schoolPlan.getContext('2d');
+        let _this = this;
+        for (let i = 0; i < _this.classroomList.length; i++) {
+          if (this.activeIcon == i) {
+            ctx.drawImage(this.greenImageData, x * _this.scaleDefault, y * _this.scaleDefault,  20 * _this.scaleDefault, 20 * _this.scaleDefault);
+          } else {
+            ctx.drawImage(this.whiteImageData, _this.classroomList[i].point.x * _this.scaleDefault, _this.classroomList[i].point.y * _this.scaleDefault, 20 * _this.scaleDefault, 20 * _this.scaleDefault);
+          }
+        }
+      },
+      initIcon() {
+        this.schoolPlan = document.getElementById('school-plan');
+        let ctx = this.schoolPlan.getContext('2d');
+        for (let i = 0; i < this.classroomList.length; i++) {
+          ctx.drawImage(this.whiteImageData,
+            this.classroomList[i].point.x * this.scaleDefault, this.classroomList[i].point.y * this.scaleDefault,
+            20 * this.scaleDefault, 20 * this.scaleDefault);
+        }
+      },
+      checkActivieIcon(point) {
+        for (let item in this.classroomList) {
+          if (point.x > this.classroomList[item].point.x * this.scaleDefault && point.x < (this.classroomList[item].point.x + 15)* this.scaleDefault && point.y > this.classroomList[item].point.y * this.scaleDefault && point.y < (this.classroomList[item].point.y + 15) * this.scaleDefault) {
+            return item;
+          }
+        }
+        return -1;
+      },
+      getCanvasPoint(x, y) {
+        this.schoolPlan = document.getElementById('school-plan');
+        let canvasRect = this.schoolPlan.getBoundingClientRect();
+        let ctx = this.schoolPlan.getContext('2d');
+        return {
+          x: x - canvasRect.left,
+          y: y - canvasRect.top
+        }
+      },
+      canvasMouseDown(e) {
+        this.isMouseDown = true;
+        this.point = this.getCanvasPoint(e.clientX, e.clientY);
+        this.clickPoint = this.getCanvasPoint(e.clientX, e.clientY);
+        this.activeIcon = this.checkActivieIcon(this.point);
+      },
+      moveCanvas(start,current) {
+        let container = document.getElementById("school-plan-box");
+        container.scrollLeft = container.scrollLeft + (start.x - current.x);
+        container.scrollTop = container.scrollTop + (start.y - current.y);
+      },
+      canvasMouseMove(e) {
+        this.point = this.getCanvasPoint(e.clientX, e.clientY);
+        if (this.isMouseDown == true && this.activeIcon != -1) {
+          this.drawSchoolPlan("");
+          this.moveIcon(this.point.x / this.scaleDefault, this.point.y / this.scaleDefault);
+        } else if (this.isMouseDown == true && this.activeIcon == -1) {
+          this.moveCanvas(this.clickPoint, this.point);
+        }else {
+          let index = this.checkActivieIcon(this.point);
+          if (index != -1) {
+            if (this.textStatus == true) {
+              this.drawText(this.classroomList[index].name, (this.classroomList[index].point.x + 25)* this.scaleDefault, (this.classroomList[index].point.y + 20) * this.scaleDefault);
+              this.textStatus = false;
+            }
+          } else {
+            this.drawSchoolPlan("");
+            this.moveIcon(this.point.x, this.point.y);
+            this.textStatus = true;
+          }
+        }
+      },
+      canvasMouseUp(e) {
+        this.isMouseDown = false;
+        if (this.activeIcon != -1) {
+          this.classroomList[this.activeIcon].point.x = this.point.x / this.scaleDefault;
+          this.classroomList[this.activeIcon].point.y = this.point.y / this.scaleDefault;
+        }
+        this.activeIcon = -1;
+      },
+      canvasMouseOut(e) {
+        this.isMouseDown = false;
+        if (this.activeIcon != -1) {
+          this.classroomList[this.activeIcon].point = this.point;
+        }
+        this.activeIcon = -1;
+      },
+      drawSchoolPlan(imgUrl) {
+        this.schoolPlan = document.getElementById('school-plan');
+        let context = this.schoolPlan.getContext('2d');
+        context.clearRect(0, 0, this.schoolPlan.width, this.schoolPlan.height);
+        let _this = this;
+        if (_this.isFirstDraw <= 0) {
+          let image = new Image();
+          //image.src = require('../../../assets/image/school_plan.jpg');
+          image.src = 'https://teammodelstorage.blob.core.chinacloudapi.cn/teammodelos/test/school_plan.jpg';
+          //image.src = imgUrl;
+          image.crossOrigin = 'anonymous';
+          image.onload = function () {
+            _this.schoolPlan.width = image.width;
+            _this.schoolPlan.height = image.height;
+            context.drawImage(image, 0, 0);
+            let imgData = context.getImageData(0, 0, _this.schoolPlan.width, _this.schoolPlan.height);
+            for (let i = 0; i < imgData.data.length; i += 4) {
+              let r = imgData.data[i];
+              let g = imgData.data[i + 1];
+              let b = imgData.data[i + 2];
+              let a = imgData.data[i + 3];
+              if (r > 200 && g > 200 && b > 200) {
+                imgData.data[i + 3] = 0;
+              } else {
+                imgData.data[i] = 255;
+                imgData.data[i + 1] = 255;
+                imgData.data[i + 2] = 255;
+                imgData.data[i + 3] = 255;
+              }
+              //if (r == 255 && g == 255 && b == 255) {
+              //  imgData.data[i + 3] = 0;
+              //  imgData.data[i + 1] = 0;
+              //  imgData.data[i + 2] = 0;
+              //} else {
+              //  imgData.data[i] = 255 - r;
+              //  imgData.data[i + 1] = 255 - g;
+              //  imgData.data[i + 2] = 255 - b;
+              //  imgData.data[i + 3] = 255;
+              //}
+            }
+            context.putImageData(imgData, 0, 0);
+            let PNGImg = new Image();
+            PNGImg.src = _this.schoolPlan.toDataURL("image/png");
+            PNGImg.onload = function () {
+              _this.schoolImageData = PNGImg;
+            }
+            _this.isFirstDraw++;
+          }
+        } else {
+          context.drawImage(this.schoolImageData, 0, 0, this.schoolImageData.width, this.schoolImageData.height, 0, 0, this.schoolImageData.width * this.scaleDefault, this.schoolImageData.height * this.scaleDefault);
+        }
+      },
+      getFileData(file) {
+        let _this = this;
+        const reader = new FileReader()
+        reader.readAsDataURL(file)
+        reader.onload = () => {
+          const _base64 = reader.result
+          this.imgUrl = _base64 //将_base64赋值给图片的src,实现图片预览
+          _this.drawSchoolPlan(this.imgUrl);
+        }
+        return false;
+      },
       saveClassroom() {
-        console.log(this.classroomList);
+        this.$api.schoolSetting.classroomSettingSaveOrUpdate(this.classroomList[this.currentClassroomIndex]).then(res => {
+          if (res.error == null) {
+            this.$Message.success('保存成功!');
+            this.updated = false;
+          }
+        });
       },
       delClassroom(index) {
         if (this.currentClassroomIndex >= index && index > 0) {
@@ -239,31 +576,118 @@
         }
         if (this.classroomList.length > 1) {
           this.classroomList.splice(index, 1);
+          this.classroomListShow.splice(index, 1);
         } else {
           this.$Message.warning('至少需要保留一项!');
         }
-        
+
       },
       uploadSchoolPlan(res, file) {
-        console.log(res);
-        console.log(file);
         this.$Message.success('上传成功!');
       },
       chooseClassroom(index) {
         this.currentClassroomIndex = index;
       },
-      chooseHiteachCode(index) {
-        this.classroomList[this.currentClassroomIndex].hiteachCode = this.hiteachCodes[index].code;
+      isEmpty(obj){
+          if(typeof obj == "undefined" || obj == null || obj == ""){
+              return true;
+          }else{
+              return false;
+          }
+      },
+      chooseHiTeach(index) {
+        
+        
+        let i = this.hiTeachs.indexOf(this.hiTeachsShow[index]);
+        //if (this.hiTeachsShow[index].single == 0) {
+        //  this.hiTeachsShow[index].using = 1;
+        //} else {
+        //  this.hiTeachsShow[index].using++;
+        //}
+        //console.log(this.hiTeachsShow[index]);
+        //console.log(this.hiTeachs[i]);
+        if (this.hiTeachs[i].single == 0) {
+          if (this.hiTeachs[i].using > 0) {
+            this.$Message.warning('此序号已绑定到教室!');
+          } else {
+            if (!this.isEmpty(this.classroomList[this.currentClassroomIndex].hiTeach)) {
+              let showIndex = -1;
+              let allIndex = -1;
+              this.hiTeachsShow.forEach((v, i) => {
+                if (v.code == this.classroomList[this.currentClassroomIndex].hiTeach) {
+                  showIndex = i;
+                }
+              });
+              this.hiTeachs.forEach((v, i) => {
+                if (v.code == this.classroomList[this.currentClassroomIndex].hiTeach) {
+                  allIndex = i;
+                }
+              });
+              if (showIndex != -1 && allIndex != -1) {
+                //this.hiTeachsShow[showIndex].using--; 
+                this.hiTeachs[allIndex].using--;
+              }
+            }
+            this.hiTeachs[i].using = 1;
+            this.classroomList[this.currentClassroomIndex].hiTeach = this.hiTeachsShow[index].code;
+          }
+        } else {
+          if (!this.isEmpty(this.classroomList[this.currentClassroomIndex].hiTeach)) {
+            let showIndex = -1;
+            let allIndex = -1;
+            this.hiTeachsShow.forEach((v, i) => {
+              if (v.code == this.classroomList[this.currentClassroomIndex].hiTeach) {
+                showIndex = i;
+              }
+            });
+            this.hiTeachs.forEach((v, i) => {
+              if (v.code == this.classroomList[this.currentClassroomIndex].hiTeach) {
+                allIndex = i;
+              }
+            });
+            if (showIndex != -1 && allIndex != -1) {
+              //this.hiTeachsShow[showIndex].using--; 
+              this.hiTeachs[allIndex].using--;
+            }
+          }
+          this.hiTeachs[i].using++;
+          this.classroomList[this.currentClassroomIndex].hiTeach = this.hiTeachsShow[index].code;
+        }
+        this.filterCode();
       },
       initData() {
+        let white = new Image();
+        let pink = new Image();
+        let green = new Image();
+        white.crossOrigin = 'anonymous';
+        pink.crossOrigin = 'anonymous';
+        green.crossOrigin = 'anonymous';
+        white.src = require('../../../assets/pin.svg');
+        pink.src = require('../../../assets/redpin.svg');
+        green.src = require('../../../assets/greenpin.svg');
+        let _this = this;
+        white.onload = function () {
+          _this.whiteImageData = white;
+        }
+        pink.onload = function () {
+          _this.pinImageData = pink;
+        }
+        green.onload = function () {
+          _this.greenImageData = green;
+        }
         this.classroomList.push({
-          name: '预设教室',
-          hiteachCode: '未输入HiTeach软件序号',
-          headmaster: '未指定班主任',
+          name: '预设教室' + (this.classroomList.length + 1),
+          hiTeach: '',
+          headMaster: '未指定班主任',
           period: '',
           grade: '',
           stuNum: 0,
-          classroomType:'一般教室'
+          classroomType: 'TEAM MODEL智慧教室',
+          classroomCode: '教室编码',
+          point: {
+            x: 5,
+            y: 5
+          }
         });
         this.periodList = [
           {
@@ -284,38 +708,93 @@
         ];
         this.gradeList = [
           {
-            value:'一年级'
+            value: '一年级'
           },
           {
-            value:'二年级'
+            value: '二年级'
           },
           {
-            value:'三年级'
+            value: '三年级'
           },
           {
-            value:'四年级'
+            value: '四年级'
           },
           {
-            value:'五年级'
+            value: '五年级'
           },
           {
-            value:'六年级'
+            value: '六年级'
           }
         ]
       },
       addClassroom() {
+        this.serchClassName = '';
         this.classroomList.push({
-          name: '预设教室',
-          hiteachCode: '未输入HiTeach软件序号',
-          headmaster: '未指定班主任',
+          name: '预设教室' + (this.classroomList.length + 1),
+          hiTeach: '',
+          headMaster: '未指定班主任',
           period: '小学',
           grade: '一年级',
           stuNum: 0,
-          classroomType:'一般教室'
+          classroomType: '一般教室',
+          classroomCode: '教室编码',
+          point: {
+            x: 5,
+            y: 5
+          }
         });
+        this.classroomListShow = [...this.classroomList];
+        this.drawIcon(5, 6);
       }
     },
     mounted() {
+      this.drawSchoolPlan();
+      let _this = this;
+      setTimeout(function () {
+        _this.initIcon();
+      }, 1000);
+      this.filterClassname();
+      this.filterCode();
+      this.bundleScoll();
+    },
+    beforeRouteLeave(to, from, next) {
+      if (this.updated) {
+        let config = {
+          render: (h) => {
+            return h("h3", {
+              style: {
+                  textAlign:"center"
+              },
+              domProps: {
+                innerText: "您修改信息后还未保存,如果离开数据将会丢失!"
+               }
+            } );
+          },
+          onOk: () => {
+            next();
+          },
+          onCancel: () => {
+            next(false)
+          }
+        }
+        this.$Modal.confirm(config);
+      } else {
+         next();
+      }
+    },
+    watch: {
+      classroomList: {
+        handler(newValue, oldValue) {
+          if (this.isInit) {
+            this.isInit = false;
+          } else {
+            this.updated = true;
+          }
+        },
+        deep: true
+      }
+    },
+    created() {
       this.initData();
     }
   }

+ 3 - 1
TEAMModelOS/ClientApp/view/school-mgmt/Index.vue

@@ -11,7 +11,9 @@
 
     <div class="data-container">
       <transition name="fade">
-        <router-view />
+        <keep-alive>
+          <router-view />
+        </keep-alive>        
       </transition>
     </div>
 

+ 172 - 62
TEAMModelOS/ClientApp/view/school-mgmt/SystemSetting/SystemSetting.vue

@@ -24,46 +24,46 @@
       <div>
         <span class="setting-title">学校名称设定:</span>
         <!--<span class="school-name">{{schoolSetting.name}}</span>-->
-      <div class="editable">
-        <EditableLabel ref="schoolName" class="school-name" :content="schoolSetting.name" @editComplete="handleEditSchoolName($event,-1)">
-        </EditableLabel>
-        <Icon type="md-create" class="edit-btn" title="编辑" @click="changeSchoolNameStatus()" />
-      </div>        
+        <div class="editable">
+          <EditableLabel ref="schoolName" class="school-name" :content="schoolSetting.name" @editComplete="handleEditSchoolName($event,-1)">
+          </EditableLabel>
+          <Icon type="md-create" class="edit-btn" title="编辑" @click="changeSchoolNameStatus()" />
+        </div>
       </div>
-      <span class="school-tools" @click="saveData()"><Icon type="ios-albums-outline" />存储变更</span>
+      <span class="school-tools" @click="saveData()" v-if="updated"><Icon type="ios-albums-outline" />存储变更</span>
     </div>
 
     <div class="sm-system-body">
       <div class="sm-system-left">
         <div class="col-title">
           <span>学制建立与设定</span>
-          <Icon type="md-add" @click="addPeriod()"/>
+          <Icon type="md-add" @click="addPeriod()" />
         </div>
         <div class="col-order">
           <Icon type="md-cube" />
           <span>依建立时间排序</span>
         </div>
-          <div class="period-list">
-            <div class="period-item" v-for="(item,index) in schoolSetting.systems" :key="index" @click="choosePeriod(index)" :class="index == currentSchoolSysIndex ? 'item-active-div':''">
-              <p class="period-item-name">
-                <EditableLabel ref="periodName" class="term-item-name" :content="item.name" @editComplete="handleEditPeriod($event,index)">
-                </EditableLabel>
-                <Icon type="md-create" class="period-btn-edit" title="编辑" @click="changePeriodEditStatus(index)" />
-              </p>
-              <p class="period-item-num"><span></span>学期(季)数:{{item.semester.length}}</p>
-              <p class="period-item-num"><span></span>学级(年级)数:{{item.grade.length}}</p>
-              <p class="period-item-num"><span></span>学科(科目)数:{{item.subject.length}}</p>
-              <div class="period-item-tool">
-                <Icon type="ios-copy" title="不知道" />
-                <Icon type="md-trash" title="删除" @click.stop="delPeriod(index)"/>
-              </div>
+        <div class="period-list">
+          <div class="period-item" v-for="(item,index) in schoolSetting.systems" :key="index" @click="choosePeriod(index)" :class="index == currentSchoolSysIndex ? 'item-active-div':''">
+            <p class="period-item-name">
+              <EditableLabel ref="periodName" class="term-item-name" :content="item.name" @editComplete="handleEditPeriod($event,index)">
+              </EditableLabel>
+              <Icon type="md-create" class="period-btn-edit" title="编辑" @click="changePeriodEditStatus(index)" />
+            </p>
+            <p class="period-item-num"><span></span>学期(季)数:{{item.semester.length}}</p>
+            <p class="period-item-num"><span></span>学级(年级)数:{{item.grade.length}}</p>
+            <p class="period-item-num"><span></span>学科(科目)数:{{item.subject.length}}</p>
+            <div class="period-item-tool">
+              <Icon type="ios-copy" title="不知道" />
+              <Icon type="md-trash" title="删除" @click.stop="delPeriod(index)" />
             </div>
           </div>
+        </div>
       </div>
       <div class="sm-system-center">
         <div class="col-title">
           <span>学期(季)设定</span>
-          <Icon type="md-add" @click="handleAddTerm"/>
+          <Icon type="md-add" @click="handleAddTerm" />
         </div>
         <div class="col-body">
           <div class="no-data-text" v-if="!schoolSetting.systems[currentSchoolSysIndex].semester.length">没有设置学期</div>
@@ -73,7 +73,7 @@
               <EditableLabel ref="semesterName" class="term-item-name" :content="item.name" @editComplete="handleEditSemester($event,index)">
               </EditableLabel>
               <Icon type="md-create" class="edit-btn" title="编辑" @click="changeSemesterStatus(index)" />
-              <p class="term-item-students-num">涉及学生数:0人</p>
+              <!--<p class="term-item-students-num">涉及学生数:0人</p>-->
               <div class="term-item-start">
                 <span>开始于</span>
                 <Select v-model="item.month" placeholder="月">
@@ -94,13 +94,20 @@
             <ul>
               <li v-for="(item,index) in monthEnList" :key="index">
                 <span class="time-label">{{item}}.</span>
-                <span class="time-dot"> 
-                  <span class="time-inner-dot" :class="index + 1 >= schoolSetting.systems[currentSchoolSysIndex].semester[currentSemesterIndex].month && index < 12 ? 'bg-color-check':'bg-color-uncheck'"></span>
+                <span class="time-dot">
+                  <span v-if="auto" class="time-inner-dot" :class="index + 1 >= schoolSetting.systems[currentSchoolSysIndex].semester[currentSemesterIndex].month && index < endMonth ? 'bg-color-check':'bg-color-uncheck'"></span>
+                  <span v-else class="time-inner-dot" :class="index + 1 >= schoolSetting.systems[currentSchoolSysIndex].semester[currentSemesterIndex].month || index < endMonth ? 'bg-color-check':'bg-color-uncheck'"></span>
                   <span class="time-line-tail"></span>
                 </span>
                 <div>
-                  <Icon class="first-arrow" size="22" type="ios-arrow-back" v-if="index + 1 == schoolSetting.systems[currentSchoolSysIndex].semester[currentSemesterIndex].month || index == 12" />
-                  <Icon class="second-arrow" size="22" :class="index + 1 < 11 ? 'color-check':'color-uncheck'" type="ios-arrow-back" v-if="index + 1 == schoolSetting.systems[currentSchoolSysIndex].semester[currentSemesterIndex].month || index == 12" />
+                  <Icon class="first-arrow" size="22" type="ios-arrow-back" v-if="index + 1 == schoolSetting.systems[currentSchoolSysIndex].semester[currentSemesterIndex].month || index + 1 == endMonth" />
+                  <!--<Icon class="second-arrow" size="22" :class="index  < endMonth ? 'color-check':'color-uncheck'" type="ios-arrow-back" v-if="index + 1 == schoolSetting.systems[currentSchoolSysIndex].semester[currentSemesterIndex].month || index + 1 == endMonth" />-->
+                  <span v-if="auto">
+                    <Icon class="second-arrow" size="22" :class="index  < endMonth ? 'color-check':'color-uncheck'" type="ios-arrow-back" v-if="index + 1 == schoolSetting.systems[currentSchoolSysIndex].semester[currentSemesterIndex].month || index + 1 == endMonth" />
+                  </span>
+                  <span v-else>
+                    <Icon class="second-arrow" size="22" :class="index + 1 >= endMonth ? 'color-check':'color-uncheck'" type="ios-arrow-back" v-if="index + 1 == schoolSetting.systems[currentSchoolSysIndex].semester[currentSemesterIndex].month || index + 1 == endMonth" />
+                  </span>
                 </div>
               </li>
             </ul>
@@ -111,37 +118,40 @@
         <div class="col-title">
           <span>学级(年级)项目建置</span>
           <div>
-            <Icon type="md-add" @click="addGrade"/>
+            <Icon type="md-add" @click="addGrade" />
             <Icon type="md-trash" v-show="gradeSelectList.length" />
           </div>
         </div>
         <div class="grade-body">
-          <div class="grade-item item-active" v-for="(item,index) in schoolSetting.systems[currentSchoolSysIndex].grade" :key="index" >
+          <div class="grade-item item-active" v-for="(item,index) in schoolSetting.systems[currentSchoolSysIndex].grade" :key="index">
             <span class="grade-item-icon"></span>
             <EditableLabel ref="gradeName" class="grade-item-name" :content="item.name" @editComplete="handleEditGrade($event,index)">
             </EditableLabel>
             <Icon type="md-create" class="period-btn-edit" title="编辑" @click="changeGradeEditStatus(index)" />
-            <Icon type="md-close" @click="delGrade(index)"/>
+            <Icon type="md-close" @click="delGrade(index)" />
           </div>
         </div>
         <div class="col-title">
           <span>学科(科目)项目建置</span>
           <div>
-            <Icon type="md-add" @click="addSubject()"/>
+            <Icon type="md-add" @click="addSubject()" />
             <Icon type="md-trash" v-show="subjectSelectList.length" />
           </div>
         </div>
         <div class="grade-body">
-          <div class="grade-item item-active" v-for="(item,index) in schoolSetting.systems[currentSchoolSysIndex].subject" :key="index" >
+          <div class="grade-item item-active" v-for="(item,index) in schoolSetting.systems[currentSchoolSysIndex].subject" :key="index">
             <span class="grade-item-icon"></span>
             <EditableLabel ref="subjectName" class="grade-item-name" :content="item.name" @editComplete="handleEditSubject($event,index)">
             </EditableLabel>
             <Icon type="md-create" class="period-btn-edit" title="编辑" @click="changeSubjectEditStatus(index)" />
-            <Icon type="md-close" @click="delSubject(index)"/>
+            <Icon type="md-close" @click="delSubject(index)" />
           </div>
         </div>
       </div>
     </div>
+    <!--<Modal v-model="updated">
+      <p>您修改信息后还未保存,如果离开数据将会丢失!</p>
+    </Modal>-->
   </div>
 
 </template>
@@ -162,21 +172,24 @@
     },
     data() {
       return {
+        auto: true,
+        updated:false,
         currentSchoolSysIndex:0,
-        currentSemesterIndex:0,
+        currentSemesterIndex: 0,
+        isInit: true,
         schoolSetting: {
           //id:"",
           code: "学校编码",
           name: "学校名称",
           systems: [
             {
-              name: "预设学段",
+              name: "预设学段1",
               gradeCount: 0,
               semesterCount: 0,
               subjectCount: 0,
               semester: [
                 {
-                  name: "预设学期",
+                  name: "预设学期1",
                   studentCount: "学生人数",
                   month: 1,
                   day:26
@@ -221,6 +234,8 @@
           this.currentSchoolSysIndex = 0;
         }
         if (this.schoolSetting.systems.length > 1) {
+          this.currentSchoolSysIndex = 0;
+          this.currentSemesterIndex = 0;
           this.schoolSetting.systems.splice(index, 1);
         } else {
           this.$Message.warning('至少需要保留一项!');
@@ -228,6 +243,8 @@
       },
       delSemester(index) {
         if (this.schoolSetting.systems[this.currentSchoolSysIndex].semester.length > 1) {
+          this.currentSchoolSysIndex = 0;
+          this.currentSemesterIndex = 0;
           this.schoolSetting.systems[this.currentSchoolSysIndex].semester.splice(index, 1);
         } else {
           this.$Message.warning('至少需要保留一项!');
@@ -277,7 +294,8 @@
         this.handleData();
         this.$api.schoolSetting.schoolSettingSaveOrUpdate(this.schoolSetting).then(res => {
           if (res.error == null) {
-            alert("成功");
+            this.$Message.success("保存/修改 信息成功!");
+            this.updated = false;
           }
         }
         );
@@ -289,20 +307,61 @@
           this.schoolSetting.systems[i].subjectCount = this.schoolSetting.systems[i].subject.length;
         }
       },
-      handleEditGrade(val,index) {
-        this.schoolSetting.systems[this.currentSchoolSysIndex].grade[index].name = val;
+      handleEditGrade(val, index) {
+        let flag = false;
+        this.schoolSetting.systems[this.currentSchoolSysIndex].grade.forEach((v, i) => {
+          if (v.name == val) {
+            flag = true;
+          }
+        });
+        if (flag) {
+          this.$Message.warning('已有相同的名字,请重新设置名字!');
+        } else {
+          this.schoolSetting.systems[this.currentSchoolSysIndex].grade[index].name = val;
+        }
+        
       },
       handleEditSubject(val, index) {
-        this.schoolSetting.systems[this.currentSchoolSysIndex].subject[index].name = val;
+        let flag = false;
+        this.schoolSetting.systems[this.currentSchoolSysIndex].subject.forEach((v, i) => {
+          if (v.name == val) {
+            flag = true;
+          }
+        });
+        if (flag) {
+          this.$Message.warning('已有相同的名字,请重新设置名字!');
+        } else {
+          this.schoolSetting.systems[this.currentSchoolSysIndex].subject[index].name = val;
+        }
       },
       handleEditSchoolName(val) {
         this.schoolSetting.name = val;
       },
-      handleEditPeriod(val,index) {
-        this.schoolSetting.systems[index].name = val;
+      handleEditPeriod(val, index) {
+        let flag = false;
+        this.schoolSetting.systems.forEach((v, i) => {
+          if (v.name == val) {
+            flag = true;
+          }
+        });
+        if (flag) {
+          this.$Message.warning('已有相同的名字,请重新设置名字!');
+        } else {
+          this.schoolSetting.systems[index].name = val;
+        }
       },
-      handleEditSemester(val,index) {
-        this.schoolSetting.systems[this.currentSchoolSysIndex].semester[index].name = val;
+      handleEditSemester(val, index) {
+        let flag = false;
+        this.schoolSetting.systems[this.currentSchoolSysIndex].semester.forEach((v, i) => {
+          if (v.name == val) {
+            flag = true;
+          }
+        });
+        if (flag) {
+          this.$Message.warning('已有相同的名字,请重新设置名字!');
+        } else {
+          this.schoolSetting.systems[this.currentSchoolSysIndex].semester[index].name = val;
+        }
       },
       changePeriodEditStatus(index) {
         this.$refs.periodName[index].handleEdit();
@@ -317,7 +376,7 @@
         if (this.termList.length < this.TERM_MAX_LENGTH) {
           let newTerm = Object.assign({}, defaultTerm);
           this.schoolSetting.systems[this.currentSchoolSysIndex].subject.push({
-            name: "预设学科",
+            name: "预设学科"+(this.schoolSetting.systems[this.currentSchoolSysIndex].subject.length+1),
             code:this.guid()
           });
         } else {
@@ -334,7 +393,7 @@
         if (this.termList.length < this.TERM_MAX_LENGTH) {
           let newTerm = Object.assign({}, defaultTerm);
           this.schoolSetting.systems[this.currentSchoolSysIndex].grade.push({
-            name: "预设年级",
+            name: "预设年级"+(this.schoolSetting.systems[this.currentSchoolSysIndex].grade.length),
             code:this.guid()
           });
         } else {
@@ -343,28 +402,28 @@
       },
       addPeriod() {
         this.schoolSetting.systems.push({
-              name: "预设学段",
+              name: "预设学段"+(this.schoolSetting.systems.length+1),
               gradeCount: 0,
               semesterCount: 0,
               subjectCount: 0,
               semester: [
                 {
-                  name: "预设学期",
+                  name: "预设学期1",
                   studentCount: "学生人数",
-                  month: 2,
+                  month: this.schoolSetting.systems[this.currentSchoolSysIndex].semester[this.currentSemesterIndex].month + 1,
                   day:26
                 }
               ],
               grade: [
                 {
                   code: "年级编码",
-                  name: "预设年级"
+                  name: "预设年级1"
                 }
               ],
               subject: [
                 {
                   code: "科目编码",
-                  name: "预设科目"
+                  name: "预设科目1"
                 }
               ]
             });
@@ -373,24 +432,20 @@
       getRandomColor() {
         return '#' + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, '0');
       },
-
       //添加学期
       handleAddTerm() {
         if (this.termList.length < this.TERM_MAX_LENGTH) {
           let newTerm = Object.assign({}, defaultTerm);
           this.schoolSetting.systems[this.currentSchoolSysIndex].semester.push({
-            name: "预设学期",
+            name: "预设学期"+(this.schoolSetting.systems[this.currentSchoolSysIndex].semester.length+1),
             studentCount: "学生人数",
-            month: 2,
+            month: this.schoolSetting.systems[this.currentSchoolSysIndex].semester[this.currentSemesterIndex].month + 1,
             day: 26
           });
         } else {
           this.$Message.info("学期数已达上限!");
         }
       },
-
-      
-
       //年级选择事件
       handleGradeClick(item, e) {
         e.preventDefault();
@@ -420,16 +475,71 @@
       },
 
     },
-    mounted() {
+    watch: {
+      schoolSetting: {
+        handler(newValue, oldValue) {
+          if (this.isInit) {
+            this.isInit = false;
+          } else {
+            this.updated = true;
+          }
+    },
+    deep: true
+      }
+    },
+    created() {
       this.initData();
-      this.monthList = [...Array(11).keys()];
+    },
+    beforeRouteLeave(to, from, next) {
+      if (this.updated) {
+        let config = {
+          render: (h) => {
+            return h("h3", {
+              style: {
+                  textAlign: "center",
+              },
+              domProps: {
+                innerText: "您修改信息后还未保存,如果离开数据将会丢失!"
+               }
+            } );
+          },
+          onOk: () => {
+            next();
+          },
+          onCancel: () => {
+            next(false)
+          }
+        }
+        this.$Modal.confirm(config);
+      } else {
+         next();
+      }
+    },
+    mounted() {
+      this.monthList = [...Array(12).keys()];
       this.gradeList = ['一年级','二年级','三年级','四年级','五年级'];
       this.subjectList = ['语文','数学','外语','化学','物理','语文','数学','外语','化学','物理'];
       this.dayList = [...Array(30).keys()];
-      this.monthEnList = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC', 'JAN'];
+      this.monthEnList = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
       this.colorList = ['#F16C6A', '#68CDF1', '#00796B', '#7C4DFF', '#0288D1', '#D32F2F', '#00796B', '#7C4DFF','#0288D1', '#D32F2F', '#00796B', '#7C4DFF'];
-
+    },
+    computed: {
+      endMonth() {
+        let end = 1;
+        if(this.schoolSetting.systems[this.currentSchoolSysIndex].semester.length == 1){
+          end = 12;
+          this.auto = true;
+        } else if (this.currentSemesterIndex + 1 < this.schoolSetting.systems[this.currentSchoolSysIndex].semester.length) {
+          end = this.schoolSetting.systems[this.currentSchoolSysIndex].semester[this.currentSemesterIndex + 1].month;
+          this.auto = true;
+        } else if (this.currentSemesterIndex + 1 == this.schoolSetting.systems[this.currentSchoolSysIndex].semester.length){
+          end = this.schoolSetting.systems[this.currentSchoolSysIndex].semester[0].month;
+          this.auto = false;
+        }
+        return end;
+      }
     }
+
   }
 </script>
 
@@ -452,6 +562,6 @@
   }
 
   .term-item-start .ivu-select-arrow {
-   top:72%;
+   /*top:72%;*/
   }
 </style>

+ 19 - 6
TEAMModelOS/ClientApp/view/smartclassdashboard/Index.vue

@@ -118,11 +118,19 @@
                             <img v-else-if="h == 'ezStation'" class="teachIcon" width="15" height="15" src="@/assets/icon/product_ezstation.svg">
                             <img v-else-if="h == 'sokrates'" class="teachIcon" width="15" height="15" src="@/assets/icon/product_sokrates.svg"> 
                           </Col> -->
-                          <Col :span="12">
-                            <img class="teachIcon" width="15" height="15" src="@/assets/icon/product_board.svg">
-                            <img class="teachIcon" width="15" height="15" src="@/assets/icon/product_irs.svg">
-                            <img class="teachIcon" width="15" height="15" src="@/assets/icon/product_ezstation.svg">
-                            <img class="teachIcon" width="15" height="15" src="@/assets/icon/product_sokrates.svg"> 
+                          <Col :span="12">                         
+                            <Tooltip v-if="item.hardware.board" :transfer="true" placement="top-start">
+                                <img class="teachIcon" width="15" height="15" src="@/assets/icon/product_board.svg">
+                                <div slot="content">
+                                   <p>教室名稱: {{item.hardware.board.classNo}}</p>
+                                   <p>裝置名稱: {{item.hardware.board.deviceName}}</p>
+                                   <p>IP位置: {{item.hardware.board.IP}}</p>
+                                   <p>使用序號: {{item.hardware.board.serialNo}}</p>
+                                </div>
+                            </Tooltip>
+                            <img v-if="item.hardware.irs" class="teachIcon" width="15" height="15" src="@/assets/icon/product_irs.svg">
+                            <img v-if="item.hardware.ezstation" class="teachIcon" width="15" height="15" src="@/assets/icon/product_ezstation.svg">
+                            <img v-if="item.hardware.sokrates" class="teachIcon" width="15" height="15" src="@/assets/icon/product_sokrates.svg">                            
                           </Col> 
                           <Col :span="12">
                             <Icon v-if="item.teacher.name" size="15" type="md-person" class="teachIcon" /><span class="ellipsis teacherName">{{item.teacher.name}}</span>
@@ -458,7 +466,12 @@
                     </Col>
                     <Col class="conect" :span="18">
                       <!-- <span class="conect-title">{{$t('classMgmt.block4SubTitle3')}}</span> -->
-                      <h5 class="conect-name ellipsis">{{item.name}}</h5>
+                      <Tooltip :transfer="true" placement="top-start">
+                          <h5 class="conect-name ellipsis">{{item.name}}</h5>
+                          <div slot="content">
+                              <p>{{item.id}}</p>
+                          </div>
+                      </Tooltip>                      
                       <!-- <Icon class="conect-icon" :size="15" type="ios-information-circle" /> -->
                       <span class="conect-val">{{$t('classMgmt.block4SubTitle6')}}: <span class="number">{{item.today}}</span> {{$t('unit.text1')}}</span>
                       <span class="conect-val">{{$t('classMgmt.block4SubTitle7')}}: <span class="number">{{item.cumClass}}</span> {{$t('unit.text1')}}</span>

+ 18 - 2
TEAMModelOS/ClientApp/view/smartschooldashboard/Index.vue

@@ -54,7 +54,7 @@
                 <div class="image-border image-border-lright-bottom" ></div>
                 <!-- 边角设计 end-->
                 <Row class="total" type="flex" align="middle" justify="space-around">
-                  <Col :span="10">
+                  <Col :span="10" v-if="viewAccess('fun1')">
                     <div class="total-box">
                       <div class="total-box-border total-box-left-top" ></div>
                       <div class="total-box-border total-box-right-top" ></div>
@@ -562,7 +562,7 @@ export default {
   computed:{
     ...mapState({
         test: state => state.classroomManagement.test
-    })
+    }),
   },
   components:{
     AccountLine,
@@ -575,6 +575,22 @@ export default {
     ClassResourceBar
   },
   methods:{   
+    viewAccess:function (comp) {
+      return this.hasOneOf(comp);
+    },
+    hasOneOf: function(comp){
+      let router = this.$store.state.authorization.antRouter;
+      let nowPath = this.$route.path; // 現在的頁面
+      let res = false; // 預設False
+      router.forEach(element => {
+        if(element.path == nowPath){
+          if(element.meta.access[comp]){
+            res = element.meta.access[comp];
+          }
+        }
+      });
+      return res;
+    }
   },
   created(){
     console.log(this.test)

+ 45 - 20
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/AchievementAnalysis.css

@@ -12,6 +12,33 @@
         margin:30px 0 30px 60px;
         display:block;
     }
+    .achievement-container .class-info {
+        position:relative;
+        font-size: 14px;
+        font-weight: bold;
+        color: #f1f1f1;
+        margin: 30px 0 10px 60px;
+        display: block;
+    }
+
+        .achievement-container .class-info .ivu-icon {
+            font-size: 26px;
+            color: #0bdfc4;
+            margin-right: 10px;
+        }
+
+        .achievement-container .class-info-back {
+            position:absolute;
+            right:40px;
+            top:0px;
+            color: #0bdfc4;
+            cursor:pointer;
+        }
+
+    .achievement-container .ivu-btn {
+        background: #447a94;
+        border:none;
+    }
 
     .achievement-container .ivu-divider-horizontal {
         background:#595959;
@@ -22,20 +49,25 @@
     .achievement-container .component-percents {
         display: flex;
         flex-direction: row;
-        justify-content: space-around;
+        /*justify-content: space-around;*/
+        flex-wrap:wrap;
     }
 
     .achievement-container .percent-item {
-        width:20%;
+        width:16%;
+        margin:20px 0;
+        min-width:250px;
     }
 
         .achievement-container .percent-item .percent-name {
-            font-size:16px;
+            font-size: 16px;
+            text-align: left;
         }
         .achievement-container .percent-item .percent-value {
             font-size:48px;
             font-weight:200;
             padding-left:20px;
+            text-align:left;
         }
         .achievement-container .percent-item .percent-line {
             width:3px;
@@ -45,25 +77,18 @@
             margin-right:30px;
         }
 
-    .achievement-container .award-class {
-        width: 85%;
-        height: 100%;
-        border: 1px solid rgba(212, 212, 212, 0.2);
-        background:rgba(239, 239, 239, 0.1);
-        padding: 50px 0;
-        margin-left:50px;
+    .achievement-container .award-wrap {
+        margin-left:30px;
+        font-size:14px;
+        margin-bottom:10px;
     }
 
-    .achievement-container .award-item {
-        display:flex;
-        flex-direction:row;
-        justify-content:space-around;
-        padding:10px 0;
-    }
 
-    .achievement-container .award-item .ivu-icon {
-         font-size:60px;
-    }
+        .achievement-container .award-wrap .ivu-icon {
+            margin-left:40px;
+            margin-right:10px;
+            font-size:26px;
+        }
 
         .achievement-container .award-class .ivu-divider-horizontal {
             width: 90%;
@@ -73,7 +98,7 @@
         }
 
         .achievement-container .award-item .award-class-list {
-            font-size: 20px;
+            font-size: 28px;
             font-weight:bold;
         }
 

+ 86 - 74
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/AchievementAnalysis.vue

@@ -4,43 +4,27 @@
       <span class="component-title" style="margin-top:40px">及格率统计</span>
     </Row>
     <Row class-name="component-percents">
-      <div class="percent-item fl-col-center">
-        <span class="percent-name">语文课平均</span>
-        <span class="percent-value"><span class="percent-line" style="background:#ff6b68"></span>85%</span>
-        <span class="percent-grade-value">年级平均:81%</span>
-        <span class="percent-area-value">区级平均:86%</span>
+      <div class="percent-item fl-col-center" v-for="(item,index) in subjectPercent" :key="index" v-if="subjectList.length > 3 && item.name" >
+        <span class="percent-name">{{item.name}}及格率</span>
+        <span class="percent-value"><span class="percent-line" :style="{background:colorList[index]}"></span>{{item.classRate}}</span>
+        <span class="percent-grade-value">年级:{{item.gradeRate}}</span>
+        <span class="percent-area-value">区级:{{item.areaRate}}</span>
       </div>
-      <div class="percent-item fl-col-center">
-        <span class="percent-name">数学课平均</span>
-        <span class="percent-value"><span class="percent-line" style="background:#ffa1f4"></span>72%</span>
-        <span class="percent-grade-value">年级平均:76%</span>
-        <span class="percent-area-value">区级平均:78%</span>
-      </div>
-      <div class="percent-item fl-col-center">
-        <span class="percent-name">英语课平均</span>
-        <span class="percent-value"><span class="percent-line" style="background:#41b0c7"></span>80%</span>
-        <span class="percent-grade-value">年级平均:75%</span>
-        <span class="percent-area-value">区级平均:75%</span>
-      </div>
-      <div class="percent-item fl-col-center">
-        <span class="percent-name">生物课平均</span>
-        <span class="percent-value"><span class="percent-line" style="background:#1cd1a1"></span>95%</span>
-        <span class="percent-grade-value">年级平均:96%</span>
-        <span class="percent-area-value">区级平均:79%</span>
-      </div>
-      <div class="percent-item fl-col-center">
-        <span class="percent-name">化学课平均</span>
-        <span class="percent-value"><span class="percent-line"></span>65%</span>
-        <span class="percent-grade-value">年级平均:82%</span>
-        <span class="percent-area-value">区级平均:79%</span>
+
+      <div  class="percent-item fl-col-center" v-for="(item,index) in subjectPercent" :key="index" v-if="subjectList.length <= 3 && item.name">
+        <span class="percent-name">{{item.name}}及格率</span>
+        <span class="percent-value"><span class="percent-line" :style="{background:colorList[index]}"></span>{{item.classRate}}</span>
+        <span class="percent-grade-value">年级:{{item.gradeRate}}</span>
+        <span class="percent-area-value">区级:{{item.areaRate}}</span>
       </div>
+
     </Row>
     <Divider />
     <Row>
       <span class="component-title">均分分析</span>
     </Row>
     <Row>
-      <BaseBar></BaseBar>
+      <BaseBar :echartsData="getBaseBarData" ref="baseBar"></BaseBar>
     </Row>
     <Divider />
     <Row>
@@ -50,53 +34,29 @@
       </div>
       <!--<Col span="12">
     <span class="component-title">进线率统计</span>
-    <BaseEntryLine :echartData="classDatas"></BaseEntryLine>  
+    <BaseEntryLine :echartData="classDatas"></BaseEntryLine>
     </Col>-->
     </Row>
     <Divider />
-    <EntryTables></EntryTables>
+    <EntryTables ref="entryTable"></EntryTables>
     <Divider />
     <Row>
       <span class="component-title">预警统计</span>
     </Row>
-    <Row type="flex" justify="space-around">
-      <Col span="6">
-      <div class="award-class">
-        <div class="award-item">
-          <div class="fl-col-center">
-            <span class="award-class-list">1班,2班,3班</span>
-            <span class="award-class-type">进步较大班级</span>
-          </div>
-          <Icon type="ios-trophy" color="#ffee00" />
-        </div>
-        <Divider />
-        <div class="award-item">
-          <div class="fl-col-center">
-            <span class="award-class-list">3班</span>
-            <span class="award-class-type">持续进步班级</span>
-          </div>
-          <Icon type="ios-trophy" color="#ffee00" />
-        </div>
-        <Divider />
-        <div class="award-item">
-          <div class="fl-col-center">
-            <span class="award-class-list">5班,7班</span>
-            <span class="award-class-type">退步较大班级</span>
-          </div>
-          <Icon type="ios-trophy" color="#d0d0d0" />
-        </div>
-        <Divider />
-        <div class="award-item">
-          <div class="fl-col-center">
-            <span class="award-class-list">7班</span>
-            <span class="award-class-type">持续退步班级</span>
-          </div>
-          <Icon type="ios-trophy" color="#d0d0d0" />
-        </div>
-
+    <Row>
+      <div class="award-wrap">
+        <Icon type="ios-trophy" color="#ffee00" />
+        <span>进步较大班级:初一5班,初一8班,初一9班</span>
+        <Icon type="ios-trophy" color="#ffee00" />
+        <span>持续进步班级:初一5班,初一3班</span>
+        <Icon type="ios-trophy" color="#eee" />
+        <span>退步较大班级 :初一7班,初一10班</span>
+        <Icon type="ios-trophy" color="#eee" />
+        <span>持续退步班级 :初一4班</span>
       </div>
-      </Col>
-      <Col span="16" class-name="achievement-table">
+    </Row>
+    <Row type="flex" justify="space-around">
+      <Col span="22" class-name="achievement-table">
       <BaseTable :columns="tableColumns" :tableDatas="tableData" ref="achievementTable"></BaseTable>
       </Col>
     </Row>
@@ -118,7 +78,11 @@
     },
     data() {
       return {
+        subjectPercent: [],
+        subjectList:[],
+        colorList:['#ff6b68','#ffa1f4','#41b0c7','#1cd1a1','#83dc07'],
         tableData: [],
+        baseBarData:[],
         classDatas:[],
         tableColumns: [
           {
@@ -150,11 +114,30 @@
             title: '年级排名',
             key: 'gradeRank',
             sortable: true,
-          },
-          {
-            title: '排名变化',
-            key: 'rankStatus',
-            renderType: 'renderRankChange'
+            renderType:function(h, params) {
+              const row = params.row;
+              return h('span', {
+                domProps: {
+                  className: "badge-wrap"
+                },
+              }, [
+                  h('span', {
+                    domProps: {
+                      className: 'table-rank-badge'
+                    },
+                    style: {
+                      color: row.changesStatus == 1 ? '#0ccb0c' : '#ff5d5d'
+                    },
+                  }, (row.changesStatus == 1 && row.changesVal != 0) ? '+' + row.changesVal : (row.changesStatus == -1 && row.changesVal != 0) ? '-' + row.changesVal : ''),
+                  h('span', {
+                    domProps: {
+                      className: "table-rank-value"
+                    },
+                  }, row.gradeRank),
+
+                ]
+              );
+            }
           },
         ]
       }
@@ -163,14 +146,43 @@
     created() {
       this.tableData = this.$store.state.totalAnalysis.classList;
       this.classDatas = this.$store.state.totalAnalysis.classList;
+      this.baseBarData = this.$store.state.totalAnalysis.baseBarData;
+      this.subjectPercent = this.$store.state.totalAnalysis.subjectPercent;
+      console.log(this.subjectPercent);
+
     },
     methods: {
 
 
     },
+    computed: {
+      //获取最新柱状图数据
+      getBaseBarData() {
+        let list = this.$store.state.totalAnalysis.baseBarData;
+        return list;
+      },
+      getSubjectList() {
+        let list = this.$store.state.totalAnalysis.subjectList;
+        return list;
+      }
+    },
+
     mounted() {
-      this.$refs.achievementTable.$el.childNodes[0].style.borderRight = "0";
+      this.$parent.dataSelectIndex = 0;
+      this.$refs.achievementTable.$el.childNodes[2].style.borderRight = "0";
+      this.subjectList = this.$store.state.totalAnalysis.subjectList;
     },
+
+    watch: {
+      getSubjectList(val) {
+        this.subjectList = val;
+        this.subjectPercent.forEach((item,index) => {
+          item.name = val[index] || null
+        })
+        console.log(val);
+      }
+    }
+
   }
 </script>
 

+ 258 - 62
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/EarlyWarning.vue

@@ -1,17 +1,26 @@
 <template>
   <div class="achievement-container">
     <Row>
-      <span class="component-title">预警统计</span>
+      <span class="class-info">
+        <Icon type="ios-ribbon" />当前选择班级: <span style="color:#0bdfc4;font-size:16px;margin-right:20px"> {{className}} </span> 总人数  <span style="color:#0bdfc4;font-size:20px"> 60 </span>人
+        <span class="class-info-back">
+          <Button type="primary" @click="goBack">
+            返回
+          </Button>
+        </span>
+      </span>
     </Row>
     <Row>
-      <div class="early-warning-tab">
+      <span class="component-title">排名统计(PR/成绩)</span>
+    </Row>
+    <Row>
+      <!--<div class="early-warning-tab">
         <span :class="warningIndex == 0 ? 'early-warning-active': '' " @click="warningTabClick('0')">百分等级(PR)</span>
-        <span :class="warningIndex == 1 ? 'early-warning-active': '' " @click="warningTabClick('1')">成绩排名</span>
-      </div>
+      </div>-->
     </Row>
     <Row class-name="base-table-row">
-      <BaseTable :columns="earlyPercentColumns" :tableDatas="tableData"  ref="percentTable" v-show="warningIndex == 0"></BaseTable>
-      <BaseTable :columns="earlyScoreColumns" :tableDatas="tableData" ref="scoreTable" v-show="warningIndex == 1"></BaseTable>
+      <BaseTable :columns="earlyPercentColumns" :tableDatas="tableData" ref="percentTable" v-show="warningIndex == 0" showSelect @onSelectChange="onSelectChange"></BaseTable>
+      <!--<BaseTable :columns="earlyScoreColumns" :tableDatas="tableData" ref="scoreTable" v-show="warningIndex == 1"></BaseTable>-->
     </Row>
     <Row class-name="averageBarRow">
       <span class="component-title">均分分析</span>
@@ -37,55 +46,208 @@
     data() {
       return {
         echartData: [],
-        tableData:[],
-        warningIndex: 1,
-        sortValue:0,
-        sortArr:["默认排序","分数从高到低","分数从低到高"],
+        tableData: [],
+        warningIndex: 0,
+        sortValue: 0,
+        className:"",
+        sortArr: ["默认排序", "分数从高到低", "分数从低到高"],
         earlyPercentColumns: [
           {
             title: '姓名',
             key: 'name',
-            fixed: "left"
+            fixed: "left",
+            minWidth:100
           },
           {
-            title: '学号',
-            key: 'memberId'
+            title: '座号',
+            key: 'id',
+            minWidth:100
           },
           {
             title: '得分',
             sortable: true,
-            key: 'score'
+            key: 'chinese',
+            minWidth:100
           },
           {
             title: '班级PR值排名',
             key: 'classPR',
             sortable: true,
+            minWidth:150,
+            renderType: function (h, params) {
+              const row = params.row;
+              return h('span', {
+                domProps: {
+                  className: "badge-wrap"
+                },
+              }, [
+                  h('span', {
+                    domProps: {
+                      className: 'table-rank-badge'
+                    },
+                    style: {
+                      color: row.changesStatus == 1 ? '#0ccb0c' : '#ff5d5d'
+                    },
+                  }, (row.changesStatus == 1 && row.changesVal != 0) ? '+' + row.changesVal : (row.changesStatus == -1 && row.changesVal != 0) ? '-' + row.changesVal : ''),
+                  h('span', {
+                    domProps: {
+                      className: "table-rank-value"
+                    },
+                  }, row.classPR),
+
+                ]
+              );
+            }
           },
           {
-            title: '班级PR值变化',
+            title: '班级排名',
             key: 'classPR',
-            renderType: 'renderStauts'
+            minWidth:150,
+            sortable: true,
+            renderType: function (h, params) {
+              const row = params.row;
+              return h('span', {
+                domProps: {
+                  className: "badge-wrap"
+                },
+              }, [
+                  h('span', {
+                    domProps: {
+                      className: 'table-rank-badge'
+                    },
+                    style: {
+                      color: row.changesStatus == 1 ? '#0ccb0c' : '#ff5d5d'
+                    },
+                  }, (row.changesStatus == 1 && row.changesVal != 0) ? '+' + row.changesVal : (row.changesStatus == -1 && row.changesVal != 0) ? '-' + row.changesVal : ''),
+                  h('span', {
+                    domProps: {
+                      className: "table-rank-value"
+                    },
+                  }, row.classRank),
+
+                ]
+              );
+            }
           },
           {
             title: '年级PR值排名',
             key: 'gradePR',
+            minWidth:150,
             sortable: true,
+            renderType: function (h, params) {
+              const row = params.row;
+              return h('span', {
+                domProps: {
+                  className: "badge-wrap"
+                },
+              }, [
+                  h('span', {
+                    domProps: {
+                      className: 'table-rank-badge'
+                    },
+                    style: {
+                      color: row.changesStatus2 == 1 ? '#0ccb0c' : '#ff5d5d'
+                    },
+                  }, (row.changesStatus2 == 1 && row.changesVal2 != 0) ? '+' + row.changesVal2 : (row.changesStatus2 == -1 && row.changesVal2 != 0) ? '-' + row.changesVal2 : ''),
+                  h('span', {
+                    domProps: {
+                      className: "table-rank-value"
+                    },
+                  }, row.gradePR),
+
+                ]
+              );
+            }
           },
           {
-            title: '年级PR值变化',
+            title: '年级排名',
             key: 'gradePR',
-            width: 150,
-            renderType: 'renderStauts'
+            minWidth:150,
+            sortable: true,
+            renderType: function (h, params) {
+              const row = params.row;
+              return h('span', {
+                domProps: {
+                  className: "badge-wrap"
+                },
+              }, [
+                  h('span', {
+                    domProps: {
+                      className: 'table-rank-badge'
+                    },
+                    style: {
+                      color: row.changesStatus2 == 1 ? '#0ccb0c' : '#ff5d5d'
+                    },
+                  }, (row.changesStatus2 == 1 && row.changesVal2 != 0) ? '+' + row.changesVal2 : (row.changesStatus2 == -1 && row.changesVal2 != 0) ? '-' + row.changesVal2 : ''),
+                  h('span', {
+                    domProps: {
+                      className: "table-rank-value"
+                    },
+                  }, row.gradeRank),
+
+                ]
+              );
+            }
           },
           {
             title: '区级PR值排名',
             key: 'areaPR',
+            minWidth:150,
             sortable: true,
+            renderType: function (h, params) {
+              const row = params.row;
+              return h('span', {
+                domProps: {
+                  className: "badge-wrap"
+                },
+              }, [
+                  h('span', {
+                    domProps: {
+                      className: 'table-rank-badge'
+                    },
+                    style: {
+                      color: row.changesStatus3 == 1 ? '#0ccb0c' : '#ff5d5d'
+                    },
+                  }, (row.changesStatus3 == 1 && row.changesVal3 != 0) ? '+' + row.changesVal : (row.changesStatus3 == -1 && row.changesVal3 != 0) ? '-' + row.changesVal3 : ''),
+                  h('span', {
+                    domProps: {
+                      className: "table-rank-value"
+                    },
+                  }, row.areaPR),
+
+                ]
+              );
+            }
           },
           {
-            title: '区级PR值变化',
+            title: '区级排名',
             key: 'areaPR',
-            renderType: 'renderStauts'
+            sortable: true,
+            minWidth:150,
+            renderType: function (h, params) {
+              const row = params.row;
+              return h('span', {
+                domProps: {
+                  className: "badge-wrap"
+                },
+              }, [
+                  h('span', {
+                    domProps: {
+                      className: 'table-rank-badge'
+                    },
+                    style: {
+                      color: row.changesStatus3 == 1 ? '#0ccb0c' : '#ff5d5d'
+                    },
+                  }, (row.changesStatus3 == 1 && row.changesVal3 != 0) ? '+' + row.changesVal3 : (row.changesStatus3 == -1 && row.changesVal3 != 0) ? '-' + row.changesVal3 : ''),
+                  h('span', {
+                    domProps: {
+                      className: "table-rank-value"
+                    },
+                  }, row.areaRank),
+
+                ]
+              );
+            }
           },
         ],
         earlyScoreColumns: [
@@ -95,8 +257,12 @@
             fixed: "left"
           },
           {
-            title: '学号',
-            key: 'memberId'
+            title: '班级',
+            key: 'className'
+          },
+          {
+            title: '座号',
+            key: 'id'
           },
           {
             title: '得分',
@@ -107,11 +273,12 @@
             title: '班级排名',
             key: 'classRank',
             sortable: true,
+            renderType: 'renderRank'
           },
           {
             title: '班级排名变化',
             key: 'classRank',
-            renderType: 'renderRankChange'
+            renderType: 'renderRank'
           },
           {
             title: '年级排名',
@@ -122,30 +289,28 @@
             title: '年级排名变化',
             key: 'gradeRank',
             width: 150,
-            renderType: 'renderRankChange'
+            renderType: 'renderRank'
           },
           {
             title: '区级排名',
             key: 'areaRank',
             sortable: true,
+            renderType: 'renderRank'
           },
           {
             title: '区级排名变化',
             key: 'areaRank',
-            renderType: 'renderRankChange'
-          },
-          {
-            title: '成绩变化趋势',
-            key: 'areaRank',
-            renderType: 'renderLineChange'
+            renderType: 'renderRank'
           },
         ],
       }
     },
 
     created() {
+      console.log(this.$route);
+      this.className = this.$route.params.name;
       let memberList = this.$store.state.totalAnalysis.memberList;
-      this.tableData = memberList;
+      this.tableData = this.$store.state.totalAnalysis.memberList;
       this.echartData = memberList;
     },
 
@@ -155,16 +320,37 @@
       },
 
       handleSort(index) {
+        let memberList = [...this.$store.state.totalAnalysis.memberList];
         if (index == 0) {
-          this.echartData = this.echartData.sort(function (a, b) { return  Number(b.id) - Number(a.id) });
+          this.echartData = memberList.sort(function (a, b) { return Number(b.id) - Number(a.id) });
         } else if (index == 1) {
-          this.echartData = this.echartData.sort(function (a, b) { return  Number(b.score) - Number(a.score) });
+          this.echartData = memberList.sort(function (a, b) { return Number(b.score) - Number(a.score) });
         } else {
-          this.echartData = this.echartData.sort(function (a, b) { return  Number(b.score) - Number(a.score) }).reverse();
+          this.echartData = memberList.sort(function (a, b) { return Number(b.score) - Number(a.score) }).reverse();
         }
         this.drawLine(this.echartData);
       },
 
+      onSelectChange(val) {
+        let memberList = this.$store.state.totalAnalysis.memberList;
+        let list = ['A', 'A-', 'B', 'B-', 'C', 'C-'];
+        memberList.forEach(item => {
+          item.chinese = Math.abs(90 - Math.ceil(Math.random() * 30));
+          item.classPR = Math.abs(item.classPR - 9 + Math.ceil(Math.random() * 10));
+          item.classRank = Math.abs(item.classRank - 9 + Math.ceil(Math.random() * 10));
+          item.gradePR = Math.abs(item.gradePR - 9 + Math.ceil(Math.random() * 10));
+          item.gradeRank = Math.abs(item.gradeRank - 9 + Math.ceil(Math.random() * 10));
+          item.areaPR = Math.abs(item.areaPR - 9 + Math.ceil(Math.random() * 10));
+          item.areaRank = Math.abs(item.areaRank - 9 + Math.ceil(Math.random() * 10));
+        })
+        this.tableData = memberList;
+      },
+
+      goBack() {
+        this.$router.back(-1);
+        this.$parent.isShowQuestions = false;
+      },
+
       drawLine(echartData) {
         let myBar = this.$echarts.init(document.getElementById("stuAverageBar"));
         var option = {
@@ -213,6 +399,12 @@
             padding: 5,
             textStyle: {
               color: "#fff"
+            },
+            formatter: function (params) {
+              let name = echartData[params[0].dataIndex].name;
+              return name + '<br>' +  params[0].marker  + '总分:' + params[0].data + '<br>' +  params[1].marker  +'班级平均分:'
+                + params[1].data + '<br>' + params[2].marker  + '年级平均分:' + params[2].data + '<br>'
+                +  params[3].marker  + '区级平均分:' + params[3].data;
             }
           },
           gird: {
@@ -243,13 +435,17 @@
             show: true,
             offset: 0,
             type: "category",
+            nameTextStyle: {
+              color: "#a2a2a2"
+            },
+            name: "座号",
             axisLabel: {
               show: true,
               inside: false,
               margin: 15,
               color: "#989898",
             },
-            data: echartData.map(item => item.name)
+            data: echartData.map(item => item.id)
           },
           yAxis: {
             show: true,
@@ -274,24 +470,24 @@
           },
           series: [
             {
-              name:"学生得分",
+              name: "学生得分",
               type: "bar",
               itemStyle: {
                 normal: {  //渐变色
-                      color: '#66cccc'
-                    },
+                  color: '#c38e9e'
+                },
                 width: 20,
               },
-              markPoint : {
-                data : [
-                    {type : 'max', name: '最大值'},
-                    {type : 'min', name: '最小值'}
+              markPoint: {
+                data: [
+                  { type: 'max', name: '最大值' },
+                  { type: 'min', name: '最小值' }
                 ],
               },
               data: echartData.map(item => item.score)
             },
             {
-              name:"班级平均分",
+              name: "班级平均分",
               type: "line",
               itemStyle: {
                 color: "yellow",
@@ -311,10 +507,10 @@
                   type: "dashed"
                 }
               },
-              data: echartData.map(item => item.score - 100)
+              data: echartData.map(item => 561.87)
             },
             {
-              name:"年级平均分",
+              name: "年级平均分",
               type: "line",
               itemStyle: {
                 color: "#ff33cc",
@@ -334,10 +530,10 @@
                   type: "dashed"
                 }
               },
-              data: echartData.map(item => item.score - 120)
+              data: echartData.map(item => 526.35)
             },
             {
-              name:"区级平均分",
+              name: "区级平均分",
               type: "line",
               itemStyle: {
                 color: "#66ff99",
@@ -357,7 +553,7 @@
                   type: "dashed"
                 }
               },
-              data: echartData.map(item => item.score - 160)
+              data: echartData.map(item => 485)
             },
           ]
         };
@@ -372,11 +568,10 @@
     },
 
     mounted() {
-
+      this.$parent.isShowQuestions = true;
       this.drawLine(this.echartData);
-
-      this.$refs.percentTable.$el.childNodes[0].style.borderRight = "0";
-      this.$refs.scoreTable.$el.childNodes[0].style.borderRight = "0";
+      this.$refs.percentTable.$el.childNodes[2].style.borderRight = "0";
+      //this.$refs.scoreTable.$el.childNodes[2].style.borderRight = "0";
     },
   }
 </script>
@@ -407,22 +602,21 @@
   }
 
   .averageBarRow {
-    position:relative;
+    position: relative;
   }
+
   .sort-box {
-    position:absolute;
-    right:150px;
-    top:20px;
+    position: absolute;
+    right: 150px;
+    top: 20px;
   }
-
-  
 </style>
 
 <style>
 
   .sort-box .ivu-input::-webkit-input-placeholder {
-      color: #a9a9a9;
-   }
+    color: #a9a9a9;
+  }
 
   .sort-box .ivu-select {
     margin: 5px 0;
@@ -445,12 +639,14 @@
     line-height: 26px;
     font-size: 16px;
   }
+
   .sort-box .ivu-select-single .ivu-select-selected-value {
     color: #a9a9a9;
   }
+
   .sort-box .ivu-select-single .ivu-select-arrow {
     color: #a9a9a9;
-    top:80%;
+    top: 80%;
   }
 </style>
 

+ 128 - 125
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/EntryTables.vue

@@ -1,16 +1,10 @@
 <template>
   <div class="achievement-container">
     <Row>
-      <span class="component-title">进线统计</span>
+      <span class="component-title">进线情况统计</span>
     </Row>
     <Row class-name="base-table-row">
-      <BaseTable :columns="entryNumberColumns" :tableDatas="echartData"></BaseTable>
-    </Row>
-    <Row>
-      <span class="component-title">踩线生统计</span>
-    </Row>
-    <Row class-name="base-table-row">
-      <BaseTable :columns="footfaultColumns" :tableDatas="echartData"></BaseTable>
+      <BaseTable :columns="entryNumberColumns" :tableDatas="echartData" :pageSize="20" :tips="'* 绿色代表进线,蓝色代表踩线'"></BaseTable>
     </Row>
     <Row>
       <span class="component-title">进线率统计</span>
@@ -22,7 +16,6 @@
 </template>
 
 <script>
-  import scatter from '@/static/scatter.json'
   import BaseTable from '@/components/student-analysis/total/BaseMyTable.vue'
   export default {
     components: {
@@ -31,7 +24,11 @@
     data() {
       return {
         echartData: [],
-        classList:[],
+        entryData: [],
+        footfaultData: [],
+        tipContent:"asdasdasd",
+        classList: [],
+        joinNum:0,
         entryNumberColumns: [
           {
             title: '姓名',
@@ -42,86 +39,96 @@
           {
             title: '班级',
             width:150,
-            key: 'className'
-          },
-          {
-            title: '座号',
-            width:150,
-            key: 'id'
+            key: 'className',
+            renderType: function (h, params) {
+              return h('span', '初一' + Math.ceil(Math.random() * 10) + '班')
+            }
           },
+          //{
+          //  title: '座号',
+          //  width:150,
+          //  key: 'id'
+          //},
           {
-            title: '年级排名变化',
-            key: 'classRank',
-            width:150,
-            renderType: 'renderRankChange'
-          },
-          {
-            title: '总分/年级排名',
-            sortable: true,
-            width:150,
-            renderType: 'renderRank'
-          },
-          {
-            title: '语文/年级排名',
-            sortable: true,
-            width: 150,
-            key:"chinese",
-            renderType: 'renderRank'
-          },
-          {
-            title: '数学/年级排名',
-            sortable: true,
+            title: '年级排名',
             width:150,
             renderType: 'renderRank'
           },
           {
-            title: '英语/年级排名',
+            title: '总分',
             sortable: true,
             width:150,
-            renderType: 'renderRank'
-          },
-          {
-            title: '化学/年级排名',
+            renderType: 'renderEntry',
+            filters: [
+                {
+                    label: '进线',
+                    value: 1
+                },
+                {
+                    label: '踩线',
+                    value: 2
+                }
+            ],
+            filterMultiple: false,
+            filterMethod (value, row) {
+              if (value === 1) {
+                return row.score > 550;
+                } else if (value === 2) {
+                    return row.score > 550  && row.score < 580;
+                }
+            }
+          },
+          {
+            title: '语文',
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.chinese);
+            }
           },
           {
-            title: '物理/年级排名',
+            title: '数学',
             sortable: true,
             width:150,
-            renderType: 'renderRank'
-          },
-          {
-            title: '生物/年级排名',
-            sortable: true,
-            width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.math);
+            }
           },
           {
-            title: '英语/年级排名',
+            title: '英语',
+            
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.english);
+            }
           },
           {
-            title: '化学/年级排名',
+            title: '化学',
+            
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.chemistry);
+            }
           },
           {
-            title: '物理/年级排名',
+            title: '物理',
+            
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.physics);
+            }
           },
           {
-            title: '生物/年级排名',
+            title: '生物',
             
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.biology);
+            }
           }
         ],
         footfaultColumns: [
@@ -142,87 +149,69 @@
             key: 'id'
           },
           {
-            title: '年级排名变化',
-            key: 'time',
-            width:150,
-            renderType: 'renderRankChange'
-          },
-          {
-            title: '总分/年级排名',
-            
-            sortable: true,
-            width:150,
-            renderType: 'renderRank'
-          },
-          {
-            title: '语文/年级排名',
-            
-            sortable: true,
-            width:150,
-            renderType: 'renderRank'
-          },
-          {
-            title: '数学/年级排名',
-            
-            sortable: true,
-            width:150,
-            renderType: 'renderRank'
-          },
-          {
-            title: '英语/年级排名',
-            
-            sortable: true,
+            title: '年级排名',
             width:150,
             renderType: 'renderRank'
           },
           {
-            title: '化学/年级排名',
-            
+            title: '总分',
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.score);
+            }
           },
           {
-            title: '物理/年级排名',
-            
+            title: '语文',
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.chinese);
+            }
           },
           {
-            title: '生物/年级排名',
-            
+            title: '数学',
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.math);
+            }
           },
           {
-            title: '英语/年级排名',
+            title: '英语',
             
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.english);
+            }
           },
           {
-            title: '化学/年级排名',
+            title: '化学',
             
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.chemistry);
+            }
           },
           {
-            title: '物理/年级排名',
+            title: '物理',
             
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.physics);
+            }
           },
           {
-            title: '生物/年级排名',
+            title: '生物',
             
             sortable: true,
             width:150,
-            renderType: 'renderRank'
+            renderType: function (h, params) {
+              return h('span', params.row.biology);
+            }
           }
         ],
         entryRateColumns: [
@@ -247,37 +236,39 @@
           },
           {
             title: '进线率',
-            key: 'entryRate',
             sortable: true,
-          },
-          {
-            title: '进线率变化',
-            key: 'people',
-            renderType: 'renderRankChange'
-          },
+            renderType: function (h, params) {
+              return h('span', params.row.entryRate + '%');
+            }
+          },
+          //{
+          //  title: '进线率变化',
+          //  key: 'people',
+          //  renderType: 'renderRank'
+          //},
         ]
       }
     },
 
     created() {
-      let memberList = this.$store.state.totalAnalysis.memberList;
+      let scatter = this.$store.state.totalAnalysis.scatter;
       this.classList = this.$store.state.totalAnalysis.classList;
-
+      
       let tableList = scatter.map(item => item.achievement);
 
-      this.echartData = tableList;
+      for (let i = 0; i < 4; i++) {
+        tableList.push.apply(tableList, tableList); //复制班级数据 创建模拟年级数据
+      }
 
+      //tableList.length = parseInt(JSON.parse(sessionStorage.getItem('c_exam')).joinNum);
+      //tableList.length = this.joinNum;
+
+      this.echartData = tableList;
       //console.log(tableList);
 
       //scatter.forEach((item, index) => {
-      //  let arr = [];
-      //  let arr2 = [];
-      //  for (let i = 0; i < 6; i++) {
-      //    arr.push(Math.floor(Math.random() * 19) + 1)
-      //    arr2.push( Math.floor(Math.random()*18) + 1)
-      //  }
-      //  item.hardList = Array.from(new Set(arr.sort(function (a, b) { return a-b })));
-      //  item.carefulList = Array.from(new Set(arr2.sort(function (a, b) { return a-b })));
+      //  tableList[index].changesStatus = item.changesStatus;
+      //  tableList[index].changesVal = item.changesVal;
 
       //})
 
@@ -289,8 +280,20 @@
 
     },
 
+    computed: {
+      getEntryData() {
+        //console.log(this.$store.state.totalAnalysis.entryData)
+        return this.$store.state.totalAnalysis.entryData;
+      }
+    },
+    watch: {
+      getEntryData(val) {
+
+      }
+    },
+
     mounted() {
-      this.$refs.rateTable.$el.childNodes[0].style.borderRight = "0";
+      this.$refs.rateTable.$el.childNodes[2].style.borderRight = "0";
     },
   }
 </script>

+ 123 - 36
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/EvaluationList/EvaluationList.css

@@ -3,14 +3,16 @@
     width: 100%;
     color: #e4eadb;
     padding: 20px 50px;
+    user-select:none;
 }
     .evaluation-list-container .el-title-wrap {
         width: 100%;
         padding: 30px 20px;
         background: #404040;
-        display:flex;
-        flex-direction:row;
-        justify-content:space-between;
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        border-radius: 5px;
     }
 
     .evaluation-list-container .el-title-wrap .el-title{
@@ -20,23 +22,59 @@
 
     }
 
-    .evaluation-list-container .el-filter-wrap {
+    .evaluation-list-container .datas-wrap {
+        width: 100%;
+        height:200px;
+        margin:20px 0;
+        display: flex;
+        flex-direction: row;
+        justify-content:space-between;
+     }
+
+        .evaluation-list-container .datas-wrap .datas-item {
+            width: 15.6%;
+            height: 100%;
+            background: #404040;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+            font-size: 16px;
+            border-radius: 5px;
+        }
+
+        .evaluation-list-container .datas-wrap .datas-val{
+            font-size: 50px;
+            font-weight: bold;
+        }
+
+    .evaluation-list-container .el-search-wrap {
         width: 100%;
         padding: 30px 20px;
+        /*margin-top: 20px;*/
+        background: #404040;
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        border-radius: 5px;
+    }
+
+    .evaluation-list-container .el-filter-wrap {
+        width: 100%;
+        padding: 10px 20px 20px 0px;
         background: #404040;
-        margin-top: 20px;
     }
 
     .evaluation-list-container .el-list-wrap {
         width: 100%;
         padding: 30px 0;
         display:flex;
-        flex-direction:row;
+        flex-direction:column;
         flex-wrap:wrap;
-        justify-content:space-around;
     }
 
     .evaluation-list-container .el-bread {
+        position:relative;
         width: 100%;
         height:30px;
         padding-left:10px;
@@ -44,33 +82,67 @@
         font-size:14px;
         text-align:left;
      }
+        .evaluation-list-container .el-bread .list-length {
+           position:absolute;
+           right:30px;
+        }
+
+    .evaluation-list-container .filter-item {
+        background: #0087af;
+        color: #fff;
+        padding: 5px 10px;
+        margin-left: 15px;
+        border-radius: 5px;
+        font-size: 12px;
+    }
+
+        .evaluation-list-container .filter-item .ivu-icon {
+            font-size: 16px;
+            margin-bottom: 3px;
+            cursor:pointer;
+        }
 
-    .evaluation-list-container .el-bread .ivu-icon{
+    /*.evaluation-list-container .el-bread .ivu-icon{
         font-size: 18px;
         margin-right:10px;
         margin-bottom:5px;
-    }
+    }*/
 
-    .evaluation-list-container .el-item{
-        width: 49%;
-        padding: 30px 20px;
-        border: 1px solid #808080;
+    .evaluation-list-container .el-item {
+        width: 100%;
+        padding: 10px 20px;
+        border: 1px solid #646363;
         margin-top: 10px;
-        cursor:pointer;
+        cursor: pointer;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        background: #404040;
+        border-radius: 5px;
     }
 
     .evaluation-list-container .el-item:hover {
-        background:#404040;
+        background:#515151;
     }
 
-    .evaluation-list-container .el-item .el-item-name {
-        font-size:20px;
-        font-weight:bold;
-    }
-    .evaluation-list-container .el-item .el-item-info {
-        font-size:14px;
-        margin:20px 0;
-    }
+        .evaluation-list-container .el-item .el-item-name {
+            font-size: 22px;
+            /*font-weight: bold;*/
+            display: inline-block;
+            max-width:60%;
+        }
+
+            .evaluation-list-container .el-item .el-item-name .ivu-icon {
+                font-size: 22px;
+                display: inline-block;
+                margin-bottom: 5px;
+            }
+
+        .evaluation-list-container .el-item .el-item-info {
+            font-size: 14px;
+            margin: 20px 0;
+            display: inline-block;
+        }
 
         .evaluation-list-container .el-item .el-item-info span:first-child {
             margin-left: 0;
@@ -90,24 +162,38 @@
 
         .evaluation-list-container .el-item .el-item-type {
             font-size: 14px;
-            margin: 20px 0;
+            margin-right: 10px;
             border:1px solid #ffd800;
             color:#ffd800;
-            padding:3px 10px;
+            padding:1px 10px;
             border-radius:5px;
-            margin-right:10px;
+        }
+        .evaluation-list-container .el-item .el-item-area {
+            font-size: 14px;
+            /*border: 1px solid #31f253;*/
+            color: #fff;
+            margin-left: 10px;
+            padding: 4px 10px;
+            border-radius: 5px;
+            background: #009f90;
+        }
+        .evaluation-list-container .el-item .el-item-subject {
+            font-size: 14px;
+            /*border: 1px solid #31f253;*/
+            color: #fff;
+            margin-left: 10px;
+            padding: 4px 10px;
+            border-radius: 5px;
+            background: #0087af;
         }
 
+    .evaluation-list-container .ivu-spin-fix {
+        background-color: rgba(222, 222, 222, 0.13);
+    }
 
-
-
-
-
-
-
-.el-filter-wrap .el-filter-item:first-child {
-    margin-top: 0px;
-}
+    .el-filter-wrap .el-filter-item:first-child {
+        margin-top: 0px;
+    }
 
 .el-filter-wrap .el-filter-item {
     margin-top: 10px;
@@ -120,6 +206,7 @@
     width: 70px;
     text-align: end;
     display: inline-block;
+    color: #e4eadb;
 }
 
 .el-filter-wrap .ivu-radio-group {
@@ -152,7 +239,7 @@
 }
 
 .el-filter-wrap .ivu-radio-wrapper-checked {
-    background: #447a94 !important;
+    background: #0087af !important;
     box-shadow: none !important;
     color: white;
 }

+ 318 - 70
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/EvaluationList/EvaluationList.vue

@@ -1,63 +1,103 @@
 <template>
   <div class="evaluation-list-container fl-col-center">
+    <Spin fix v-show="contentLoading"></Spin>
     <div class="el-title-wrap">
       <div>
-        <span style="width:4px;height:20px;display:inline-block;background:#447a94"></span>
+        <span style="width:6px;height:28px;display:inline-block;background:#009dec;margin-bottom:-5px;"></span>
         <span class="el-title">成都新川外国语学校历次考试汇总</span>
       </div>
     </div>
 
-    <div class="el-filter-wrap">
-      <div class="el-filter-item">
-        <span class="el-filter-title">关注年级:</span>
-        <RadioGroup v-model="filterGrade" type="button" @on-change="filterGradeChange">
-          <Radio label="all">全部</Radio>
-          <Radio label="self">高中一年级</Radio>
-          <Radio label="school">高中二年级</Radio>
-          <Radio label="system">高中三年级</Radio>
-        </RadioGroup>
-      </div>
-      <div class="el-filter-item">
-        <span class="el-filter-title">学年期:</span>
-        <RadioGroup v-model="filterTerm" type="button" @on-change="filterTermChange">
-          <Radio label="all">全部</Radio>
-          <Radio label="pre">上学期</Radio>
-          <Radio label="next">下学期</Radio>
-        </RadioGroup>
-      </div>
-      <div class="el-filter-item">
-        <span class="el-filter-title">考试类型:</span>
-        <RadioGroup v-model="filterType" type="button" @on-change="filterTypeChange">
-          <Radio label="all">全部</Radio>
-          <Radio label="school">校内测验</Radio>
-          <Radio label="area">区域测验</Radio>
-          <Radio label="global">全国测验</Radio>
-        </RadioGroup>
-      </div>
-      <div class="el-filter-item">
-        <span class="el-filter-title">考试学科:</span>
-        <RadioGroup v-model="filterSubject" type="button" @on-change="filterSubjectChange">
-          <Radio label="all">全部</Radio>
-          <Radio label="chinese">语文</Radio>
-          <Radio label="math">数学</Radio>
-          <Radio label="english">英语</Radio>
-          <Radio label="physic">物理</Radio>
-          <Radio label="chemistry">化学</Radio>
-        </RadioGroup>
+    <div class="datas-wrap">
+      <div class="datas-item" v-for="item in dataList">
+        <p>{{item.name}}次数</p>
+        <div class="datas-val">
+          <countTo :startVal='10' :endVal='40' :duration='3000'></countTo>
+        </div>
       </div>
     </div>
 
-    <div class="el-bread"><Icon type="ios-arrow-forward" />当前筛选条件:无</div>
+    <div class="el-search-wrap">
+      <Input v-model="searchValue"
+             placeholder="输入考试名称..."
+             @on-click="handleSearch"
+             @on-change="handleChange"
+             @on-enter="handleSearch"
+             icon="ios-search"
+             style="width:500px">
+      </Input>
+    </div>
+
+    <Collapse>
+      <Panel name="1" hide-arrow>
+        <Icon type="ios-funnel" /> 更多筛选
+        <div class="el-filter-wrap" slot="content">
+          <div class="el-filter-item">
+            <span class="el-filter-title">关注学段:</span>
+            <RadioGroup v-model="filterPeriod" type="button" @on-change="filterPeriodChange">
+              <Radio v-for="(item,index) in filterData.periodList" :label="item.name" :key="index">{{item.name}}</Radio>
+            </RadioGroup>
+          </div>
+          <div class="el-filter-item">
+            <span class="el-filter-title">关注年级:</span>
+            <RadioGroup v-model="filterGrade" type="button" @on-change="filterGradeChange">
+              <Radio v-for="(item,index) in filterData.gradeList" :label="item.name" :key="index">{{item.name}}</Radio>
+            </RadioGroup>
+          </div>
+          <div class="el-filter-item">
+            <span class="el-filter-title">学年期:</span>
+            <RadioGroup v-model="filterTerm" type="button" @on-change="filterTermChange">
+              <Radio v-for="(item,index) in filterData.termList" :label="item.name" :key="index">{{item.name}}</Radio>
+            </RadioGroup>
+          </div>
+          <div class="el-filter-item">
+            <span class="el-filter-title">考试类型:</span>
+            <RadioGroup v-model="filterType" type="button" @on-change="filterTypeChange">
+              <Radio v-for="(item,index) in filterData.typeList" :label="item.name" :key="index">{{item.name}}</Radio>
+            </RadioGroup>
+          </div>
+          <div class="el-filter-item">
+            <span class="el-filter-title">考试范围:</span>
+            <RadioGroup v-model="filterArea" type="button" @on-change="filterAreaChange">
+              <Radio v-for="(item,index) in filterData.areaList" :label="item.name" :key="index">{{item.name}}</Radio>
+            </RadioGroup>
+          </div>
+          <div class="el-filter-item">
+            <span class="el-filter-title">反馈类型:</span>
+            <RadioGroup v-model="filterFeedback" type="button" @on-change="filterFeedbackChange">
+              <Radio v-for="(item,index) in filterData.feedbackList" :label="item.name" :key="index">{{item.name}}</Radio>
+            </RadioGroup>
+          </div>
+          <div class="el-filter-item">
+            <span class="el-filter-title">考试学科:</span>
+            <RadioGroup v-model="filterSubject" type="button" @on-change="filterSubjectChange">
+              <Radio v-for="(item,index) in filterData.subjectList" :label="item.name" :key="index">{{item.name}}</Radio>
+            </RadioGroup>
+          </div>
+        </div>
+      </Panel>
+    </Collapse>
+
+
+
+    <div class="el-bread">
+      <!--<Icon type="ios-arrow-forward" />-->
+      <span>当前筛选条件:</span>
+      <span v-if="!hasCondition">无</span>
+      <span v-for="(item,index) in filterList" :key="index" class="filter-item" v-if="item.val">{{item.val}} <Icon type="ios-close" @click="handleRemove(index,item.keyName)" /></span>
+      <span class="list-length">当前共 {{examList.length}} 条</span>
+    </div>
 
     <div class="el-list-wrap">
-      <div class="el-item" v-for="(item,index) in examList" @click="handleChooseExam(item,index)">
+      <div class="no-data-text" v-if="!examList.length">暂无数据</div>
+      <div class="el-item" v-else v-for="(item,index) in examList" @click="handleChooseExam(item,index)">
         <div class="el-item-name">
-          <span class="el-item-type">{{item.examType}}</span>
-
+          <!--<span class="el-item-type">{{item.examType}}</span>-->
           {{item.name}}
+          <span class="el-item-area">{{item.examArea}}</span>
+          <span class="el-item-subject" v-for="subject in item.subject.split(',')">{{subject}}</span>
         </div>
         <div class="el-item-info">
-          <span><Icon type="md-school" />参与年级:2019级文科班</span>
           <span><Icon type="md-people" />参与人数:{{item.joinNum}} 人</span>
           <span><Icon type="md-time" />考试日期:{{item.date}} </span>
         </div>
@@ -70,54 +110,185 @@
 </template>
 
 <script>
+  import countTo from 'vue-count-to';
   export default {
     components: {
       //BaseTestScatter, BaseTable, BaseLineBar
     },
     data() {
       return {
+        contentLoading:false,
         questionList: [],
+        dataList: [...new Array(6).keys()],
+        hasCondition:false,
+        examList: [],
+        filterList:[],
+        filterConditions: {}, //筛选条件
+        filterData: {},
         searchValue: "",
-        filterGrade:"all",
-        filterTerm:"all",
-        filterType:"all",
-        filterSubject:"all",
+        searchList: [],
+        filterPeriod: "全部",
+        filterGrade: "全部",
+        filterTerm: "全部",
+        filterType: "全部",
+        filterArea: "全部",
+        filterFeedback: "全部",
+        filterSubject: "全部",
       }
     },
+    components: { countTo },
     created() {
       let classList = this.$store.state.totalAnalysis.classList;
       let examList = this.$store.state.totalAnalysis.examList;
+      this.filterData = this.$store.state.totalAnalysis.filterData;
       this.examList = examList;
       this.rightTableData = classList;
+      this.dataList = this.filterData.typeList.slice(1, 7);
+
+      this.searchList = examList.map(item => item.name);
+
+      //this.examList = this.examList.filter(item => item.period == '初中' && item.grade == '初一');
+
     },
 
     methods: {
-      filterGradeChange() {
+      handleSearch() {
+        let that = this;
+        this.contentLoading = true;
+        let value = this.searchValue;
+        let examList = this.$store.state.totalAnalysis.examList;
+        this.examList = examList.filter(item => item.name.indexOf(value) !== -1);
+        setTimeout(function () {
+          that.contentLoading = false;
+        },500)
+      },
+      handleChange() {
+        let that = this;
+        let value = this.searchValue;
+        let examList = this.$store.state.totalAnalysis.examList;
+        this.examList = examList.filter(item => item.name.indexOf(value) !== -1);
+      },
+      handleAutoSelect(val) {
+        let examList = this.$store.state.totalAnalysis.examList;
+        this.examList = examList.filter(item => item.name == val);
+      },
+      //handleFilter(type, val) {
+
+      //},
+
+      handleRemove(index,name) {
+        this.filterList.splice(index, 1);
+        switch (name) {
+          case 'period':
+            this.filterPeriod = '全部';
+            this.filterConditions.period = null;
+            break;
+          case 'grade':
+            this.filterGrade = '全部';
+            this.filterConditions.grade = null;
+            break;
+          case 'term':
+            this.filterTerm = '全部';
+            this.filterConditions.term = null;
+            break;
+          case 'type': 
+            this.filterType = '全部';
+            this.filterConditions.type = null;
+            break;
+          case 'area':
+            this.filterArea = '全部';
+            this.filterConditions.area = null;
+            break;
+          case 'feedback':
+            this.filterFeedback = '全部';
+            this.filterConditions.feedback = null;
+            break;
+          case 'subject':
+            this.filterSubject = '全部';
+            this.filterConditions.subject = null;
+            break;
+          default:
+            break;
+        }
 
+        //console.log(this.filterList);
+        this.doFilter();
       },
-      filterTermChange() {
 
+      filterPeriodChange() {
+        this.filterConditions.period = this.filterPeriod == '全部' ? null : this.filterPeriod;
+        this.doFilter();
+      },
+      filterGradeChange() {
+        this.filterConditions.grade = this.filterGrade == '全部' ? null : this.filterGrade;
+        this.doFilter();
+      },
+      filterTermChange() {
+        this.filterConditions.term = this.filterTerm == '全部' ? null : this.filterTerm;
+        this.doFilter();
       },
       filterTypeChange() {
-
+        this.filterConditions.type = this.filterType == '全部' ? null : this.filterType;
+        this.doFilter();
+      },
+      filterAreaChange() {
+        this.filterConditions.area = this.filterArea == '全部' ? null : this.filterArea;
+        this.doFilter();
+      },
+      filterFeedbackChange() {
+        this.filterConditions.feedback = this.filterFeedback == '全部' ? null : this.filterFeedback;
+        this.doFilter();
       },
       filterSubjectChange() {
-
+        this.filterConditions.subject = this.filterSubject == '全部' ? null : this.filterSubject;
+        this.doFilter();
       },
+
       handleExportTables() {
 
       },
 
-      handleChooseExam(item,index) {
-        this.$router.push({ path: '/total', query: { index:index }});
+      doFilter() {
+        let examList = this.$store.state.totalAnalysis.examList;
+        //将条件转换成数组便于渲染
+        this.filterList = this.objToArr(this.filterConditions);
+        //根据条件过滤所有的测验数据
+        this.examList = examList.filter(item => {
+          return item.period.indexOf(this.filterConditions.period || '') > -1 &&
+            item.grade.indexOf(this.filterConditions.grade || '') > -1 &&
+            item.term.indexOf(this.filterConditions.term || '') > -1 &&
+            item.examType.indexOf(this.filterConditions.type || '') > -1 &&
+            item.examArea.indexOf(this.filterConditions.area || '') > -1 &&
+            item.feedback.indexOf(this.filterConditions.feedback || '') > -1 &&
+            item.subject.indexOf(this.filterConditions.subject || '') > -1 
+
+        })
+      },
+
+      objToArr(obj) {
+        var arr = []
+        for(var key in obj) {
+          arr.push({keyName:key,val:obj[key]})
+        }
+        return arr;
+      },
+
+      handleChooseExam(item, index) {
+        this.$router.push({ path: '/total', query: { index: index } });
       }
 
 
     },
 
     mounted() {
-       //this.$refs.rightRateTable.$el.childNodes[0].style.borderRight = "0";
+      //this.$refs.rightRateTable.$el.childNodes[0].style.borderRight = "0";
     },
+    watch: {
+      filterList(val) {
+        let list = val.map(item => item.val);
+        this.hasCondition = list.filter(item => item !== null).length;
+      }
+    }
   }
 </script>
 
@@ -126,7 +297,7 @@
 
 <style>
 
-.total-container .el-tools .ivu-input {
+  .total-container .el-tools .ivu-input {
     background: transparent;
     border: 1px solid #a2a2a2;
     height: 32px;
@@ -136,28 +307,105 @@
     color: #a2a2a2;
     box-shadow: none;
     border-radius: 5px;
-    margin-bottom:3px;
+    margin-bottom: 3px;
   }
 
     .total-container .el-tools .ivu-input::-webkit-input-placeholder {
-      color:#a2a2a2;
+      color: #a2a2a2;
     }
 
-    .total-container .el-tools .basic-tool-export {
-        padding:7px 15px;
-        background: #447a94;
-        border-radius: 5px;
-        cursor:pointer;
-        margin-left:20px;
-        margin-top:2px;
-        display:inline-block;
-    }
-    .total-content .el-tools .ivu-icon {
-      font-size: 18px;
-      vertical-align:sub;
-     }
+  .total-container .el-tools .basic-tool-export {
+    padding: 7px 15px;
+    background: #447a94;
+    border-radius: 5px;
+    cursor: pointer;
+    margin-left: 20px;
+    margin-top: 2px;
+    display: inline-block;
+  }
+
+  .total-content .el-tools .ivu-icon {
+    font-size: 18px;
+    vertical-align: sub;
+  }
 
   .export-modal .ivu-modal-header {
     display: none;
   }
+
+
+  .evaluation-list-container .ivu-collapse {
+    width:100%;
+    background:#404040;
+    border:0;
+    padding-bottom:18px;
+    margin-top:-70px;
+    border-radius: 5px;
+  }
+
+  .evaluation-list-container .ivu-collapse-item  .ivu-collapse-header{
+    color:#e4eadb;
+    font-size:14px;
+    margin-left:530px;
+    display: inline-block;
+  }
+
+   .evaluation-list-container .ivu-collapse-item  .ivu-collapse-header .ivu-icon{
+     margin-right:3px;
+     margin-bottom:3px;
+     transition:none;
+     transform:none;
+   }
+
+  .evaluation-list-container .ivu-collapse > .ivu-collapse-item.ivu-collapse-item-active > .ivu-collapse-header > i {
+    transform:none;
+  }
+  
+  .evaluation-list-container .ivu-collapse-content{
+    background:#404040;
+  }
+
+  .evaluation-list-container .ivu-collapse > .ivu-collapse-item.ivu-collapse-item-active > .ivu-collapse-header {
+    border-bottom:none;
+  }
+
+
+  /*搜索框部分样式重写*/
+
+  .evaluation-list-container .el-search-wrap .ivu-input {
+    background: #404040;
+    height: 40px;
+    border-color: #6f6f6f;
+    color: #dcdcdc;
+    font-size: 14px;
+  }
+
+    .evaluation-list-container .el-search-wrap .ivu-input:focus {
+      border-color: #6f6f6f;
+      box-shadow: none;
+    }
+
+  .evaluation-list-container .el-search-wrap .ivu-input-icon {
+    line-height: 40px;
+  }
+
+  .evaluation-list-container .el-search-wrap .ivu-select-item {
+    padding: 15px;
+  }
+
+      .evaluation-list-container .ivu-spin-dot {
+        width: 120px;
+        height: 120px;
+        background: #05c9da;
+    }
+
+    .no-data-text {
+        width: 100%;
+        height: 100%;
+        font-size: 30px;
+        font-weight: bold;
+        color: #959595;
+        text-align: center;
+        padding-top: 30px;
+    }
 </style>

+ 1 - 1
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/KnowledgeAnalysis.css

@@ -9,7 +9,7 @@
     .scatter-container .component-title {
         font-size: 20px;
         color: #f1f1f1;
-        margin:30px 0 60px 60px;
+        margin:30px 0 30px 60px;
         display:block;
     }
 

+ 63 - 19
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/KnowledgeAnalysis.vue

@@ -14,19 +14,22 @@
     </Row>
     <Divider />
     <Row>
-      <span class="component-title">得分率关系表</span>
+      <span class="component-title">得分率关系表
+      <span style="font-size:14px;font-weight:bold;margin-left:20px;color:#66cccc">当前知识块:{{currentBlock}}
+        <Icon type="ios-close-circle-outline" @click="refresh" style="cursor:pointer;" v-show="currentBlock != '全部'"/>
+       </span>
+      </span>
       <div style="padding:20px 50px;position:relative">
         <!--<span class="btn-class-score" @click="handleGoDetails">查看班级得分<Icon type="ios-arrow-dropright" /></span>-->
         <BaseMyTable :columns="tableColumns" :tableDatas="knowledgeData"></BaseMyTable>
       </div>
     </Row>
     <Divider />
-    <ScoreDetails></ScoreDetails>
+    <ScoreDetails ref="detailsRef"></ScoreDetails>
   </div>
 </template>
 
 <script>
-  import newKnowledgeList from '@/static/newKnowledgeList.json'
   import BasePie from '@/components/student-analysis/total/BasePie.vue'
   import BaseKnowledgeBar from '@/components/student-analysis/total/BaseKnowledgeBar.vue'
   import BaseRadar from '@/components/student-analysis/total/BaseRadar.vue'
@@ -38,14 +41,15 @@
     },
     data() {
       return {
-        isShowPie:true,
+        isShowPie: true,
+        currentBlock:"全部",
         tableData: [],
         classDatas: [],
         tableColumns: [
           {
             title: '知识点',
             key: 'knowledgePoint',
-            width:250
+            width:200
           },
           {
             title: '认知层次',
@@ -59,49 +63,61 @@
             width:150
           },
           {
-            title: '1班/100人',
+            title: '1班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
           {
-            title: '2班/100人',
+            title: '2班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
           {
-            title: '3班/100人',
+            title: '3班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
           {
-            title: '4班/100人',
+            title: '4班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
                     {
-            title: '1班/100人',
+            title: '5班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
           {
-            title: '2班/100人',
+            title: '6班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
           {
-            title: '3班/100人',
+            title: '7班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
           {
-            title: '4班/100人',
+            title: '8班',
+            key: 'gradeScoreRate',
+            sortable: true,
+            width:120
+          },
+          {
+            title: '9班',
+            key: 'gradeScoreRate',
+            sortable: true,
+            width:120
+          },
+          {
+            title: '10班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
@@ -115,6 +131,8 @@
       this.tableData = classList;
       this.knowledgeData = exerciseList;
 
+      this.isShowPie = !(this.knowledgeData.length > 10);
+
       let knowList = ['方程与不等式','图形的性质','统计与概率','函数','图形的相似','锐角三角函数','几何图形初步','投影与视图']
       let levelList = ['知识','理解','评鉴','综合','分析','应用']
       let typeList = ['单选','多选','判断','问答','填空','问答']
@@ -130,7 +148,7 @@
     },
 
     methods: {
-            randomNum(minNum, maxNum) {
+      randomNum(minNum, maxNum) {
         switch (arguments.length) {
           case 1:
             return parseInt(Math.random() * minNum + 1, 10);
@@ -156,16 +174,42 @@
 
       //点击玫瑰图某个知识点事件
       handleItemClick(item) {
-        //console.log(item);
-        console.log(this.$store.state.totalAnalysis.knowledgeList);
-        this.$store.state.totalAnalysis.knowledgeList = newKnowledgeList;
-        this.knowledgeData = this.$store.state.totalAnalysis.knowledgeList
-        console.log(this.$store.state.totalAnalysis.knowledgeList);
+        let exerciseList = this.$store.state.totalAnalysis.exerciseList;
+        this.currentBlock = item.data.name;
+        let blockId = item.data.id;
+        this.knowledgeData = exerciseList.filter(item => item.blockId == blockId);
+        this.$refs.detailsRef.knowledgeData = this.knowledgeData;
+      },
+
+      refresh() {
+        this.currentBlock = '全部';
+        this.knowledgeData = this.$store.state.totalAnalysis.exerciseList;
+        this.$refs.detailsRef.knowledgeData = this.$store.state.totalAnalysis.exerciseList;;
       }
 
     },
     mounted() {
+      this.$refs.detailsRef.knowledgeData = this.$store.state.totalAnalysis.exerciseList;
     },
+    computed: {
+      //获取最新柱状图数据
+      getPointsData() {
+        let list = this.$store.state.totalAnalysis.exerciseList;
+        this.knowledgeData = list;
+        let a = list.map(item => item.y);
+        return list;
+      }
+    },
+    watch: {
+      getPointsData(val) {
+        this.knowledgeData = [...this.$store.state.totalAnalysis.exerciseList];
+        let tempItem = { data: { name: this.knowledgeData[0].knowledgePoint, id: this.knowledgeData[0].blockId } };
+        this.handleItemClick(tempItem);
+        this.refresh();
+
+
+    }
+  }
   }
 </script>
 

+ 125 - 42
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/ScoreDetails.vue

@@ -2,22 +2,23 @@
   <div class="scatter-container">
     <Row>
       <Col span="12">
-        <span class="component-title">知识点得分率统计</span>
-        <BaseDetailBar :echartData="knowledgeData" @handleItemClick="handleItemClick"></BaseDetailBar>
+      <span class="component-title">知识点得分率统计</span>
+      <BaseDetailBar :echartData="knowledgeData" @handleItemClick="handleItemClick" ref="detailsBar"></BaseDetailBar>
       </Col>
       <Col span="12">
       <span class="component-title">知识点得分详情<span style="font-size:14px;font-weight:bold;margin-left:20px;color:#66cccc">当前知识点:{{currentPoint}}</span></span>
       <div style="padding:0 50px;">
         <BaseMyTable :columns="detailsColumns" :tableDatas="tableData" ref="detailsTable"></BaseMyTable>
       </div>
-        </Col>
+      </Col>
     </Row>
     <Divider />
     <Row>
-      <span class="component-title">班级得分明细表</span>
+      <span class="component-title">错题率关系表</span>
       <div style="padding:20px 50px;">
-        <BaseMyTable :columns="tableColumns" :tableDatas="numData" ref="numTable"></BaseMyTable>
+        <BaseMyTable :columns="tableColumns" :tableDatas="numData" ref="numTable" :tips="tipContent"></BaseMyTable>
       </div>
+      <!--<span style="/*font-size:14px;font-weight:bold;margin-left:60px;color:#66cccc*/"></span>-->
     </Row>
   </div>
 </template>
@@ -28,111 +29,193 @@
   import BaseMyTable from '@/components/student-analysis/total/BaseMyTable.vue'
   export default {
     components: {
-      BaseDetailBar,BaseMyTable
+      BaseDetailBar, BaseMyTable
     },
     data() {
       return {
         tableData: [],
         classDatas: [],
-        currentPoint:"",
+        currentPoint: "",
+        tipContent: "* RH:高分区段  /  RL:低分区段",
         knowledgeData: [],
-        numData:[],
+        numData: [],
         tableColumns: [
-          {
-            title: '题号',
-            key: 'id',
-          },
+          //{
+          //  title: '题号',
+          //  key: 'id',
+          //  width:100
+          //},
           {
             title: '知识点',
             key: 'knowledgePoint',
+            minWidth: 150
           },
           {
             title: '分值',
             key: 'score',
+            minWidth: 100
+          },
+          {
+            title: '涉及题号',
+            key: 'hardList',
+            renderType: 'renderHard',
+            width: 250
           },
           {
             title: '平均得分率',
             key: 'averageScoreRate',
+            renderType: function (h, params) {
+              return h('span', params.row.averageScoreRate + '%');
+            },
+            sortable: true,
+            minWidth: 100
           },
           {
             title: '错题人数',
             key: 'falseNum',
-          },
-          {
-            title: '120以上错题人数',
-            key: 'falseNum',
             sortable: true,
+            minWidth: 100
           },
           {
-            title: '90-120分错题人数',
-            key: 'falseNum',
+            title: 'RH错题人数',
+            key: 'RH',
             sortable: true,
+            minWidth: 100
           },
           {
-            title: '90分以下错题人数',
-            key: 'falseNum',
+            title: 'RL错题人数',
+            key: 'RL',
             sortable: true,
+            minWidth: 100
           },
         ],
         detailsColumns: [
-          {
-            title: '学号',
-            key: 'memberId',
-            width:120
-          },
           {
             title: '姓名',
             key: 'name',
+            minWidth: 100
           },
           {
-            title: '分值',
+            title: '班级',
+            key: 'className',
+            width: 120
+          },
+          {
+            title: '座号',
             key: 'id',
+            width: 120
+          },
+          {
+            title: '分值',
+            key: 'score',
+            minWidth: 100
           },
           {
             title: '本节得分',
-            key: 'id',
+            key: 'score',
+            minWidth: 100,
+            renderType: function (h, params) {
+              return h('span', params.row.score - Math.floor(Math.random() * 4))
+            }
           },
           {
             title: '得分率',
-            key: 'id',
+            key: 'scoreRate',
+            renderType: 'renderPercent',
+            minWidth: 100
           },
           //{
           //  title: '历次得分率趋势',
           //  renderType:"renderLineChange"
           //},
-          
+
         ]
       }
     },
     created() {
       let memberList = this.$store.state.totalAnalysis.memberList;
-      let knowledgeList = this.$store.state.totalAnalysis.knowledgeList;
-      this.tableData = memberList.slice(0,7);
-      this.knowledgeData = knowledgeList;
+      let scatter = this.$store.state.totalAnalysis.scatter;
+      let testScatter = this.$store.state.totalAnalysis.testScatter;
+      let knowledgeArr = testScatter.map(item => item.tableData);
+      //this.numData = knowledgeArr;
+
+      this.tableData = Mock.mock({
+        'list|60': [{
+          "id|+1": 1,
+          "className|1": ['初一5班'],
+          "name": '@cname',
+          "score": 4,
+          "averageScoreRate|40-80": 40,
+          "scoreRate|50-100": 50
+        }],
+      }).list;
 
       this.numData = Mock.mock({
         'list|10': [{
-          "id|+1": 1,   
-          "knowledgePoint|1": ['算法平均值','一元二次方程','全等三角形性质'],  
-          "score|5-20": 20,     
-          "averageScoreRate|40-80": 40,    
-          "falseNum|10-20":20
-        }], 
+          "id|+1": 1,
+          "knowledgePoint|1": ['算法平均值', '一元二次方程', '全等三角形性质'],
+          "score|1": ['4', '5', '10'],
+          "averageScoreRate|40-80": 40,
+          "falseNum|15-30": 20,
+          "RH|5-15": 20,
+          "RL|5-15": 20,
+        }],
       }).list;
 
+
+      this.numData.forEach((item, index) => {
+        item.knowledgePoint = this.knowPoints[index].knowledgePoint;
+        item.score = knowledgeArr[index].score;
+        item.hardList = scatter[index].hardList;
+      })
     },
 
     methods: {
-       //点击柱状图某个点事件
+      //点击柱状图某个点事件
       handleItemClick(item) {
-        console.log(item);
         this.currentPoint = item.name;
+        let newList = Mock.mock({
+          'list|60': [{
+            "id|+1": 1,
+            "className|1": ['初一5班'],
+            "name": '@cname',
+            "score|1-10": 1,
+            "averageScoreRate|40-80": 40,
+            "scoreRate|50-100": 50
+          }],
+        }).list;
+        let randomVal = 4 + Math.floor(Math.random() * 6);
+        this.tableData.forEach((item, index) => {
+          item.score = randomVal;
+          item.scoreRate = newList[index].scoreRate;
+        })
       }
     },
     mounted() {
-      this.$refs.detailsTable.$el.childNodes[0].style.borderRight = "0";
-      this.$refs.numTable.$el.childNodes[0].style.borderRight = "0";
+      this.$refs.detailsTable.$el.childNodes[2].style.borderRight = "0";
+      this.$refs.numTable.$el.childNodes[2].style.borderRight = "0";
+    },
+    computed: {
+      knowPoints() {
+        return this.$store.state.totalAnalysis.exerciseList;
+      }
     },
+    watch: {
+      knowledgeData(val) {
+        this.knowledgeData = val;
+        this.currentPoint = val[0].knowledgePoint;
+      },
+      knowPoints(val) {
+        let scatter = this.$store.state.totalAnalysis.scatter;
+        let testScatter = this.$store.state.totalAnalysis.testScatter;
+        let knowledgeArr = testScatter.map(item => item.tableData);
+        this.numData.forEach((item, index) => {
+          item.knowledgePoint = val[index].knowledgePoint;
+          item.score = knowledgeArr[index].score;
+          item.hardList = scatter[index].hardList;
+        })
+      }
+    }
   }
 </script>
 

+ 2 - 2
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/ScatterAnalysis/ScatterAnalysis.css

@@ -9,7 +9,7 @@
     .scatter-container .component-title {
         font-size: 20px;
         color: #f1f1f1;
-        margin:30px 0 60px 60px;
+        margin:30px 0 30px 60px;
         display:block;
     }
 
@@ -21,7 +21,7 @@
 
 
 .scatter-statistics {
-    margin-top:160px;
+    margin-top:130px;
 }
 
 .scatter-statistics .ivu-divider-horizontal {

+ 47 - 13
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/ScatterAnalysis/ScatterAnalysis.vue

@@ -55,7 +55,7 @@
     <Row>
       <span class="component-title">学生稳定度统计表</span>
       <div style="padding:20px 50px;">
-        <BaseTable :columns="tableColumns" :tableDatas = "tableData" ref="scatterTable"></BaseTable>
+        <BaseTable :columns="tableColumns" :tableDatas = "tableData" ref="scatterTable" showSelect @onSelectChange="onSelectChange"></BaseTable>
       </div>
     </Row>
   </div>
@@ -64,6 +64,7 @@
 <script>
   import BaseScatter from '@/components/student-analysis/total/BaseScatter.vue'
   import BaseTable from '@/components/student-analysis/total/BaseMyTable.vue'
+import { Set } from 'core-js';
   export default {
     components: {
       BaseScatter, BaseTable
@@ -74,11 +75,13 @@
         tableColumns: [
           {
             title: '姓名',
-            key: 'name'
+            key: 'name',
+            minWidth:100
           },
           {
             title: '班级',
-            key: 'className'
+            key: 'className',
+            minWidth:100
           },
           {
             title: '座号',
@@ -88,7 +91,8 @@
           {
             title: '分数',
             sortable: true,
-            key: 'score'
+            key: 'score',
+            minWidth:100
           },
           {
             title: '答对题数',
@@ -107,7 +111,7 @@
             renderType: 'renderHard'
           },
           {
-            title: '小心题号',
+            title: '小心题号',
             key: 'carefulList',
             width:220,
             renderType: 'renderCareful'
@@ -116,39 +120,69 @@
             title: '稳定程度',
             key: 'x',
             sortable: true,
+            minWidth:120
           },
           {
             title: '落点区域',
             key: 'areaName',
+            minWidth:100
           },
-          {
-            title: '排名情况',
-            key:'rank',
-            renderType: 'renderRank'
-          }
+          //{
+          //  title: '排名情况',
+          //  key:'rank',
+          //  renderType: 'renderRank'
+          //}
         ]
       }
     },
     created() {
       let memberList = this.$store.state.totalAnalysis.scatter;
       this.tableData = memberList;
+      this.onSelectChange(1);
     },
 
     methods: {
 
       //点击落点图某个点事件
       handleItemClick(item) {
-        console.log(item);
+        let memberId = item.data[item.data.length - 1];
+        let member = this.tableData.filter(item => item.id == memberId)[0];
+              this.tableData.unshift(member);
+      },
+
+
+      onSelectChange(val) {
+        let memberList = this.$store.state.totalAnalysis.scatter;
+        let list = ['A', 'A-', 'B', 'B-', 'C', 'C-'];
+        memberList.forEach(item => {
+          item.score = 90 - Math.ceil(Math.random() * 30);
+          item.trueNum = 20 - Math.ceil(Math.random() * 10);
+          item.falseNum = 20 - item.trueNum;
+          item.hardList = this.getRandomArr();
+          item.carefulList = this.getRandomArr();
+          item.x = (Math.ceil(Math.random() * 100) * 0.01).toFixed(2);
+          item.areaName = list[Math.ceil(Math.random() * 5)];
+        })
+        this.tableData = memberList;
+      },
+
+      getRandomArr() {
+        let arr = [];
+        for (let i = 0; i < 4; i++) {
+          arr.push(Math.ceil(Math.random() * 19))
+        }
+
+        return [...new Set(arr)].sort(function (a, b) { return a-b});
       }
 
     },
 
     mounted() {
-       this.$refs.scatterTable.$el.childNodes[0].style.borderRight = "0";
+       this.$refs.scatterTable.$el.childNodes[2].style.borderRight = "0";
     },
   }
 </script>
-
+ 
 
 <style src="./ScatterAnalysis.css" scoped></style>
 

+ 37 - 21
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/QuestionList.css

@@ -10,6 +10,7 @@
 }
 
 .ql-left-box {
+    position:relative;
     width:80%;
     background:#fff;
     color:#525252;
@@ -24,21 +25,26 @@
     border-bottom: 1px solid #e0e0e0;
 }
 
-    .ql-left-box .ql-item:hover {
-        /*box-shadow: 0px 0px 5px 3px #9e9e9e;*/
-    }
+    /*.ql-left-box .ql-item:hover {
+        box-shadow: 0px 0px 5px 3px #9e9e9e;
+    }*/
 
 
-.ql-item .btn-back {
-    position:absolute;
-    right:30px;
-    top:10px;
-    font-size:16px;
-    cursor:pointer;
-    display:none;
-}
+    .ql-left-box .btn-back {
+        position: absolute;
+        right: 15px;
+        top: 20px;
+        font-size: 14px;
+        cursor: pointer;
+        background: #3c8fa2;
+        box-shadow: 0px 2px 3px 0px #8f8f8f;
+        padding: 10px 30px;
+        color: #fff;
+        /*border-radius: 5px;*/
+        z-index: 999;
+    }
 
-    .ql-item .btn-back .ivu-icon {
+    .ql-left-box .btn-back .ivu-icon {
        display:inline-block;
        margin-right:5px;
        margin-top:-4px;
@@ -46,29 +52,41 @@
 
 .ql-item .item-type {
     background: #06a9bb;
-    margin: 0 5px;
     padding: 2px 8px;
     border-radius: 5px;
     color: #fff;
     font-size: 14px;
 }
 
-.ql-item .item-question{
-    font-weight:bold;
-    font-size:16px;
+.ql-item .item-question {
+    font-weight: bold;
+    font-size: 16px;
+    position: relative;
+    width:85%;
 }
 
 .ql-item .item-question p{
     display:inline-block;
 }
 
+.ql-item .item-question-score {
+    position:absolute;
+    right:21px;
+    display:inline-block;
+    top:30px;
+}
 
+.ql-item .analysis-charts {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-around;
+}
 
 .ql-item .item-option-wrap {
-    display:flex;
-    flex-direction:column;
+    display: flex;
+    flex-direction: row;
     /*justify-content:space-around;*/
-    margin:20px 0;
+    margin: 20px 0;
 }
 
 .ql-item .item-option {
@@ -78,7 +96,6 @@
 /*.ql-item .item-option:first-child {
     margin-left: 10px;
 }*/
-
 .ql-item .item-answer {
     margin:20px 0;
 }
@@ -87,7 +104,6 @@
     width: 100px;
     min-width: 100px;
     color: #06a9bb;
-    font-weight:bold;
 }
 
 .ql-item .item-explain {

+ 291 - 80
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/QuestionList.vue

@@ -2,14 +2,24 @@
   <div class="question-list-container" ref="questionContainer">
     <!-- 左侧题目列表清单 -->
     <div class="ql-left-box">
-      <p style="font-size:28px;text-align:center;margin:20px 0">芳草小学2019年5月期中考试数学试卷</p>
-      <p style="font-size:16px;text-align:center">考试时间:120分钟&nbsp;&nbsp;&nbsp;出卷人:张纪中</p>
+      <!--<p style="font-size:28px;text-align:center;margin:20px 0">芳草小学2019年5月期中考试数学试卷</p>
+  <p style="font-size:16px;text-align:center">考试时间:120分钟&nbsp;&nbsp;&nbsp;出卷人:张纪中</p>-->
 
+      <span class="btn-back" @click="handleBackTo" ref="btnBack"><Icon type="ios-arrow-back" />返回</span>
 
       <div class="ql-item" v-for="(question,index) in questionList">
-        <span class="btn-back" @click="handleBackTo"><Icon type="ios-arrow-back" />返回</span>
-        <div class="item-question">
-          <p>{{index+1}} : <span class="item-type">{{question.questionType}}</span><span v-html="question.question"></span></p>
+        <div>
+          <div class="item-question">
+            <p>
+              <span>{{index+1}} :</span>
+              <span v-html="question.question"></span>
+            </p>
+
+          </div>
+          <div class="item-question-score">
+            <span class="item-type">{{question.questionType}}</span>
+            <span class="item-type" style="background: #05b454;">{{question.score}}分</span>
+          </div>
         </div>
         <div class="item-option-wrap">
           <div v-for="(option,optionIndex) in question.option" class="item-option">
@@ -26,11 +36,6 @@
             <p>{{String.fromCharCode(64 + parseInt(childOptionIndex+1))}} : <span v-html="childOption.value"></span></p>
           </div>
           <div class="item-concept" style="margin-top:20px;">
-            <div class="question-answer-info">
-              <span class="fl-row">【知识点】: 实数的运用</span>
-              <span class="fl-row"><span>班级得分率:</span><Progress :percent="75" stroke-color="#06a9bb" /><Icon type="ios-arrow-down" /></span>
-              <span class="fl-row"><span>年级得分率:</span><Progress :percent="50" stroke-color="#00ab89" /></span>
-            </div>
           </div>
           <div class="item-answer">
             <span class="item-header-title">【答案】:</span>
@@ -44,68 +49,77 @@
           </div>
         </div>
 
-
-          <!-- 答案与解析部分选择是否展示 -->
-          <div class="item-concept">
-            <div class="question-answer-info" v-show="question.type != 'Compose'">
-              <span class="fl-row">【知识点】: 实数的运用</span>
-              <span class="fl-row"><span>班级得分率:</span><Progress :percent="75" stroke-color="#06a9bb" /><Icon type="ios-arrow-down" /></span>
-              <span class="fl-row"><span>年级得分率:</span><Progress :percent="50" stroke-color="#00ab89"/></span>
+        <Collapse simple @on-change="handleCollapseChange" v-model="activeCollapseIndex">
+          <Panel :name="index+'answer'">
+            <span>查看答案及解析</span>
+            <div class="answerAndExplain" slot="content" style="margin-top:10px;margin-left: 25px;">
+              <div class="item-answer" v-show="question.type != 'Compose'">
+                <span class="item-header-title">【参考答案】</span>
+                <span v-html="question.answer[0] || question.answer" v-if="question.type == 'Subjective'"></span>
+                <span :class="[ question.type == 'Complete' ? 'item-answer-item':'']" v-for="answer in question.answer" v-else-if="question.type == 'Complete'" v-html="answer"></span>
+                <span :class="[ question.type == 'Complete' ? 'item-answer-item':'']" v-for="answer in question.answer" v-else>{{answer}}</span>
+              </div>
+              <div class="item-explain" v-show="question.type != 'Compose'">
+                <div class="item-header-title">【答题解析】</div>
+                <div v-html="question.explain"></div>
+              </div>
             </div>
-          </div>
-          <div class="item-answer" v-show="question.type != 'Compose'">
-            <span class="item-header-title">【参考答案】</span>
-            <span v-html="question.answer[0] || question.answer" v-if="question.type == 'Subjective'"></span>
-            <span :class="[ question.type == 'Complete' ? 'item-answer-item':'']" v-for="answer in question.answer" v-else-if="question.type == 'Complete'" v-html="answer"></span>
-            <span :class="[ question.type == 'Complete' ? 'item-answer-item':'']" v-for="answer in question.answer" v-else>{{answer}}</span>
-          </div>
-          <div class="item-explain" v-show="question.type != 'Compose'">
-            <div class="item-header-title">【答题解析】</div>
-            <div v-html="question.explain"></div>
-          </div>
-        </div>
-    </div>
-
+          </Panel>
+          <Panel :name="index+''">
+            <span>查看数据分析</span>
+            <div class="answerAndExplain" slot="content" style="margin-top:10px" v-if="collapseList.indexOf(index.toString()) > -1">
+              <Table :columns="dataColumns" :data="tableData.filter((item,index2) => index2 == index)"></Table>
+              <Table :columns="optionColumns" :data="optionsData" style="margin-top:20px"></Table>
+              <!-- 每个题目的数据分析折线图 -->
+              <div class="analysis-charts">
+                <BaseLine :ids="'myLine' + index" :echartsData="tableData[index]"></BaseLine>
+                <BaseRateLine :ids="'myRateLine' + index" :echartsData="optionsData"></BaseRateLine>
+              </div>
+            </div>
+          </Panel>
+        </Collapse>
 
+      </div>
+    </div>
 
     <!-- 右侧题目列表题型概览 -->
     <div class='ql-right-box' ref="rightBox">
       <div class="ql-right-score">
-        试卷总分 :<span>150分</span>
+        试卷总分 :<span>100分</span>
       </div>
       <div class="ql-right-list">
         <div class="ql-right-part" v-if="SingleList.length">
-          <span class="ql-right-part-title"><span class="ql-line"></span>单项选择题(30分)</span>
+          <span class="ql-right-part-title"><span class="ql-line"></span>单项选择题({{sumArr(SingleList.map(item => item.score))}}分)</span>
           <div class="ql-right-items">
             <span class="ql-right-item" v-for="(item,index) in SingleList" :key="index" @click="handleItemClick(item,$event)">{{index + 1}}</span>
           </div>
         </div>
         <div class="ql-right-part" v-if="MultipleList.length">
-          <span class="ql-right-part-title"><span class="ql-line"></span>多项选择题(30分)</span>
+          <span class="ql-right-part-title"><span class="ql-line"></span>多项选择题({{sumArr(MultipleList.map(item => item.score))}}分)</span>
           <div class="ql-right-items">
             <span class="ql-right-item" v-for="(item,index) in MultipleList" :key="index" @click="handleItemClick(item,$event)">{{index + 1}}</span>
           </div>
         </div>
         <div class="ql-right-part" v-if="JudgeList.length">
-          <span class="ql-right-part-title"><span class="ql-line"></span>判断题(30分)</span>
+          <span class="ql-right-part-title"><span class="ql-line"></span>判断题({{sumArr(JudgeList.map(item => item.score))}}分)</span>
           <div class="ql-right-items">
             <span class="ql-right-item" v-for="(item,index) in JudgeList" :key="index" @click="handleItemClick(item,$event)">{{index + 1}}</span>
           </div>
         </div>
         <div class="ql-right-part" v-if="CompleteList.length">
-          <span class="ql-right-part-title"><span class="ql-line"></span>填空题(30分)</span>
+          <span class="ql-right-part-title"><span class="ql-line"></span>填空题({{sumArr(CompleteList.map(item => item.score))}}分)</span>
           <div class="ql-right-items">
             <span class="ql-right-item" v-for="(item,index) in CompleteList" :key="index" @click="handleItemClick(item,$event)">{{index + 1}}</span>
           </div>
         </div>
         <div class="ql-right-part" v-if="SubjectiveList.length">
-          <span class="ql-right-part-title"><span class="ql-line"></span>问答题(30分)</span>
+          <span class="ql-right-part-title"><span class="ql-line"></span>问答题({{sumArr(SubjectiveList.map(item => item.score))}}分)</span>
           <div class="ql-right-items">
             <span class="ql-right-item" v-for="(item,index) in SubjectiveList" :key="index" @click="handleItemClick(item,$event)">{{index + 1}}</span>
           </div>
         </div>
         <div class="ql-right-part" v-if="ComposeList.length">
-          <span class="ql-right-part-title"><span class="ql-line"></span>综合题(30分)</span>
+          <span class="ql-right-part-title"><span class="ql-line"></span>综合题({{sumArr(ComposeList.map(item => item.score))}}分)</span>
           <div class="ql-right-items">
             <span class="ql-right-item" v-for="(item,index) in ComposeList" :key="index" @click="handleItemClick(item,$event)">{{index + 1}}</span>
           </div>
@@ -116,19 +130,24 @@
 </template>
 
 <script>
-  import questions from '@/view/evaluation/index/list.json'
-  import classList from '@/static/classList.json'
   import BaseTestScatter from '@/components/student-analysis/total/BaseTestScatter.vue'
-  import BaseTable from '@/components/student-analysis/total/BaseMyTable.vue'
   import BaseLineBar from '@/components/student-analysis/total/BaseLineBar.vue'
+  import BaseLine from '@/components/student-analysis/total/BaseLine.vue'
+  import BaseRateLine from '@/components/student-analysis/total/BaseRateLine.vue'
 import { setTimeout } from 'timers';
   export default {
     components: {
-      BaseTestScatter, BaseTable, BaseLineBar
+      BaseTestScatter, BaseRateLine, BaseLineBar,BaseLine
     },
     data() {
       return {
-        isFixed:false,
+        activeCollapseIndex:[],
+        isFixed: false,
+        isLoadingEcharts:false,
+        isShowAnswerExplain: false,
+        tableData: [],
+        optionsData:[],
+        collapseList:[],
         questionList: [],
         SingleList: [],
         MultipleList:[],
@@ -145,14 +164,130 @@ import { setTimeout } from 'timers';
           "Compose":"综合"
         },
         diffColors: ['#32CF74', '#E8BE15', '#F19300', '#EB5E00', '#D30000'],
+        dataColumns: [
+          {
+            title: '知识点',
+            key: 'knowledgePoint',
+            align:'center',
+            width:150
+          },
+          {
+            title: '落点区域',
+            key: 'areaName',
+            align: 'center',
+          },
+          {
+            title: '配分',
+            key: 'score',
+            align:'center',
+          },
+          {
+            title: '难易度',
+            key: 'diff',
+            align:'center',
+          },
+          {
+            title: '鉴别度',
+            key: 'identify',
+            align:'center',
+          },
+          {
+            title: '正答率',
+            align:'center',
+            key: 'classScoreRate',
+          },
+          {
+            title: '高分组正答率',
+            align:'center',
+            key: 'PH',
+          },
+          {
+            title: '低分组正答率',
+            align:'center',
+            key: 'PL',
+          },
+          {
+            title: 'R1',
+            align:'center',
+            key: 'R1',
+          },
+          {
+            title: 'R2',
+            key: 'R2',
+            align:'center',
+          },
+          {
+            title: 'R3',
+            align:'center',
+            key: 'R3',
+          },
+          {
+            title: 'R4',
+            align:'center',
+            key: 'R4',
+          },
+          {
+            title: 'R5',
+            align:'center',
+            key: 'R5',
+          },
+          {
+            title: 'R6',
+            align:'center',
+            key: 'R6',
+          }
+        ],
+        optionColumns: [
+          {
+            title: '选项',
+            key: 'option',
+            align:'center',
+            width:150
+          },
+          {
+            title: '选答人数',
+            key: 'num',
+            align: 'center',
+          },
+          {
+            title: '选答率',
+            key: 'rate',
+            align: 'center',
+            render: (h, params) => {
+              return h('div', [
+                  h('Progress', {
+                      props: {
+                        percent: params.row.rate,
+                        strokeColor:params.row.isTrue?'#14db14':'#b5bcbe'
+                      }
+                  }),
+              ]);
+          }
+          },
+          {
+            title: '高分组选答率',
+            align:'center',
+            key: 'PH',
+            render: function (h, params) {
+              return h('span',params.row.PH + '%')
+            }
+          },
+          {
+            title: '低分组选答率',
+            align:'center',
+            key: 'PL',
+            render: function (h, params) {
+              return h('span',params.row.PL + '%')
+            }
+          },
+        ],
+        
+
       }
     },
     created() {
-      this.rightTableData = classList;
-      questions.result.data.forEach(item => {
-        item.questionType = this.typeTransfer[item.type];
-      })
-      this.questionList = questions.result.data;
+      this.rightTableData = this.$store.state.totalAnalysis.classList;
+      this.questionList = this.$store.state.totalAnalysis.questions;
       this.SingleList = this.questionList.filter(item => item.type == 'Single');
       this.MultipleList = this.questionList.filter(item => item.type == 'Multiple');
       this.JudgeList = this.questionList.filter(item => item.type == 'Judge');
@@ -160,7 +295,54 @@ import { setTimeout } from 'timers';
       this.SubjectiveList = this.questionList.filter(item => item.type == 'Subjective');
       this.ComposeList = this.questionList.filter(item => item.type == 'Compose');
 
+      let testScatter = this.$store.state.totalAnalysis.testScatter;
+      let list = testScatter.map(item => item.tableData);
+
+      //list.forEach((item, index) => {
+      //  item.type = questions[index].type;
+      //  item.stem = '';
+      //})
 
+      //console.log(JSON.stringify(testScatter));
+
+      //数据分析表格数据
+      let knowledgeArr = testScatter.map(item => item.tableData);
+      this.tableData = knowledgeArr;
+
+      this.optionsData = [
+        {
+          option: "A",
+          isTrue:false,
+          num: 12,
+          rate: 40,
+          PH: 10,
+          PL:60
+        },
+        {
+          option: "B",
+          isTrue:false,
+          num: 6,
+          rate: 20,
+          PH: 10,
+          PL:23
+        },
+        {
+          option: "C",
+          isTrue:true,
+          num: 9,
+          rate: 30,
+          PH: 70,
+          PL:10
+        },
+        {
+          option: "D",
+          isTrue:false,
+          num: 3,
+          rate: 10,
+          PH: 10,
+          PL:7
+        }
+      ]
     },
 
     methods: {
@@ -179,17 +361,17 @@ import { setTimeout } from 'timers';
 
       //点击右边题序 获取到题目DOM 进行滚动操作
       handleItemClick(item, e) {
-        let currentSpan = e.target;
+        let currentSpan = e.target || e;
         let allList = document.getElementsByClassName('ql-right-item');
         let questionList = document.getElementsByClassName('ql-item');
         let itemIndex = this.questionList.indexOf(item);
         let questionDom = questionList[itemIndex];
         //选中题目高亮显示
-        questionDom.style.boxShadow = "0px 0px 5px 3px #9e9e9e";
-        setTimeout(function () {
-          questionDom.style.boxShadow = "none";
-        }, 2000);
-        let scrollDistance = questionDom.offsetTop + 83; //相对父级容器高度加上头部高度即为滚动距离
+        //questionDom.style.boxShadow = "0px 0px 5px 3px #9e9e9e";
+        //setTimeout(function () {
+        //  questionDom.style.boxShadow = "none";
+        //}, 2000);
+        let scrollDistance = questionDom.offsetTop + 134; //相对父级容器高度加上头部高度即为滚动距离
         this.scrollToTop(this.$parent.$refs.dataContainer, itemIndex == 0 ? 0 : scrollDistance, 500);
         //伪数组处理统一背景颜色
         Array.prototype.slice.call(allList).forEach(item => {
@@ -199,46 +381,60 @@ import { setTimeout } from 'timers';
         currentSpan.style.background = "#139c51";
       },
 
-      //根据传过来的题目编号进行位置滚动
-      handleIndexScroll(index) {
-        let allList = document.getElementsByClassName('ql-right-item');
-        let questionList = document.getElementsByClassName('ql-item');
-        let questionDom = questionList[index];
-        //选中题目高亮显示
-        questionDom.style.boxShadow = "0px 0px 5px 3px #9e9e9e";
-        questionDom.getElementsByClassName('btn-back')[0].style.display = 'inline-block';
-        setTimeout(function () {
-          questionDom.style.boxShadow = "none";
-        }, 2000);
-        let scrollDistance = questionDom.offsetTop + 83; //相对父级容器高度加上头部高度即为滚动距离
-        this.scrollToTop(this.$parent.$refs.dataContainer, index == 0 ? 0 : scrollDistance, 500);
-        //伪数组处理统一背景颜色
-        Array.prototype.slice.call(allList).forEach(item => {
-          item.style.background = "#3c8fa2";
-        })
-        //将当前选中项修改选中色
-        allList[index].style.background = "#139c51";
-      },
+      //点击返回
       handleBackTo() {
+        this.$refs.btnBack.style.display = 'none';
         this.$parent.isShowQuestions = false;
         this.$router.back(-1);
+      },
+
+
+      //折叠面板点击事件
+      handleCollapseChange(val) {
+        let questionIndex = val[0];
+        if (questionIndex == "999") return;
+        if (questionIndex && this.collapseList.indexOf(questionIndex) == -1 && questionIndex != "999") {
+          this.collapseList.push(questionIndex);
+          this.activeCollapseIndex = questionIndex;
+        } else if (questionIndex == 0) {
+          this.collapseList.push(questionIndex);
+          this.activeCollapseIndex = questionIndex;
+        } else {
+          //console.log("加入异常", questionIndex);
+          //console.log("加入异常", this.collapseList.indexOf(questionIndex));
+        }
+        console.log(this.collapseList);
+        this.activeCollapseIndex = this.collapseList;
+      },
+
+      //返回题目区域总分 字符串换算
+      sumArr(arr) {
+        return eval(arr.join('+'));
       }
     },
 
     mounted() {
+      this.$parent.isShowQuestions = true;
+      //this.isLoadingEcharts = true;
       let box = this.$refs.rightBox;
+      let btnBack = this.$refs.btnBack;
+      //页面滚动时 右侧题目序号以及返回按钮的滚动
       this.$parent.$refs.dataContainer.addEventListener('scroll', () => {
-        let isOverHeight = this.$parent.$refs.dataContainer.scrollTop >= 129;
+        let isOverHeight = this.$parent.$refs.dataContainer.scrollTop >= 129; //判定右侧序号滚动距离是否到达临界值
+        let isBackHeight = this.$parent.$refs.dataContainer.scrollTop >= 129; //判定右侧序号滚动距离是否到达临界值
         let t = 232 - this.$parent.$refs.dataContainer.scrollTop;
         box.style.top = isOverHeight ? "100px" : (t + 'px');
+        btnBack.style.top = isBackHeight ? (this.$parent.$refs.dataContainer.scrollTop - 152)  + 'px' : '-1px';
+        //btnBack.style.top = this.$parent.$refs.dataContainer.scrollTop > 146 ? (this.$parent.$refs.dataContainer.scrollTop - 146)  + 'px' : '20px';
       }, false)
 
-      if (this.$route.query.index) {
-        this.handleIndexScroll(this.$route.query.index - 1);
+      if (this.$route.query.QIndex) {
+        let index = this.$route.query.QIndex - 1;
+        let allList = document.getElementsByClassName('ql-right-item');
+        this.handleCollapseChange([index.toString()]);
+        this.activeCollapseIndex.push(index + 'answer');
+        this.handleItemClick(this.questionList[index], allList[index]);
       }
-      this.$parent.isShowQuestions = true;
-
-
     },
   }
 </script>
@@ -246,4 +442,19 @@ import { setTimeout } from 'timers';
 
 <style src="./QuestionList.css" scoped></style>
 
+<style>
+  .ql-item .ivu-collapse {
+    border:0;
+  }
+
+    .ql-item .ivu-collapse > .ivu-collapse-item > .ivu-collapse-header {
+      color:#06a9bb;
+    }
+    .ql-item .ivu-collapse > .ivu-collapse-item > .ivu-collapse-header > .ivu-icon {
+      vertical-align:unset;
+    }
 
+    .ql-item .ivu-collapse > .ivu-collapse-item {
+      border-top:0;
+    }
+</style>

+ 11 - 2
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/TestAnalysis.css

@@ -54,8 +54,17 @@
         cursor:pointer;
         font-size:16px;
         margin: 0 3px;
-        color:aqua;
-        border-bottom:1px solid aqua;
+        /*color:aqua;*/
+        /*border-bottom:1px solid aqua;*/
+    }
+
+    .scatter-statistics .scatter-exercise-index:hover {
+        padding: 0 5px;
+        cursor: pointer;
+        font-size: 16px;
+        margin: 0 3px;
+        color: aqua;
+        border-bottom: 1px solid aqua;
     }
 
     .fl-col-center {

+ 124 - 36
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/TestAnalysis.vue

@@ -46,38 +46,35 @@
     </Row>
     <Divider />
     <Row>
-      <Col span="12">
       <span class="component-title">年级单题得分率统计 <span style="font-size:14px;font-weight:bold;margin-left:20px;color:#66cccc">所选题号:{{currentExerciseIndex}}</span></span>
       <div>
-        <BaseLineBar :echartData="rightTableData"></BaseLineBar>
+        <BaseLineBar :echartData="rightTableData" ref="lineBar"></BaseLineBar>
       </div>
-      </Col>
-      <Col span="12">
+      <!--<Col span="12">
       <span class="component-title"></span>
-      <div style="padding:120px 30px 0 30px">
+      <div style="padding:55px 30px 0 30px">
         <BaseTable :columns="rightRateColumns" :tableDatas="rightTableData" ref="rightRateTable"></BaseTable>
       </div>
-      </Col>
+      </Col>-->
     </Row>
     <Divider />
     <Row>
       <span class="component-title">试题分析总表</span>
       <div style="padding:20px 50px;">
-        <BaseTable :columns="tableColumns" :tableDatas="tableData" ref="scatterTable"></BaseTable>
+        <BaseTable :columns="tableColumns" :tableDatas="tableData" ref="analysisTable" :tips="'* R1-R6:排名区间'"></BaseTable>
       </div>
     </Row>
     <Divider />
     <Row>
       <span class="component-title">试题得分率表</span>
       <div style="padding:20px 50px;">
-        <BaseTable :columns="exerciseColumns" :tableDatas="tableData" ref="scatterTable"></BaseTable>
+        <BaseTable :columns="exerciseColumns" :tableDatas="tableData" ref="scoreRateTable" :tips="'* 单位:得分率'"></BaseTable>
       </div>
     </Row>
   </div>
 </template>
 
 <script>
-  import testScatter from '@/static/testScatter.json'
   import BaseTestScatter from '@/components/student-analysis/total/BaseTestScatter.vue'
   import BaseTable from '@/components/student-analysis/total/BaseMyTable.vue'
   import BaseLineBar from '@/components/student-analysis/total/BaseLineBar.vue'
@@ -98,94 +95,174 @@
           {
             title: '题号',
             key: 'id',
-            width:100
+            width: 100,
+            renderType:'renderEventIndex'
           },
           {
             title: '题型',
             key: 'type',
+            minWidth:100
           },
-          {
-            title: '题干',
-            key: 'knowledgePoint',
-          },
+          //{
+          //  title: '题干',
+          //  key: 'stem',
+          //},
           {
             title: '知识点',
             key: 'knowledgePoint',
+            minWidth:150
           },
           {
             title: '落点区域',
             key: 'areaName',
+            minWidth:100
           },
           {
             title: '配分',
             key: 'score',
+            minWidth:100
           },
           {
             title: '难易度',
             key: 'diff',
+            minWidth:100
           },
           {
             title: '鉴别度',
             key: 'identify',
+            minWidth:100
+          },
+          {
+            title: 'R1',
+            key: 'R1',
+            sortable: true,
+            minWidth:100
+          },
+          {
+            title: 'R2',
+            key: 'R2',
+            sortable: true,
+            minWidth:100
+          },
+          {
+            title: 'R3',
+            sortable: true,
+            key: 'R3',
+            minWidth:100
+          },
+          {
+            title: 'R4',
+            sortable: true,
+            key: 'R4',
+            minWidth:100
           },
+          {
+            title: 'R5',
+            sortable: true,
+            key: 'R5',
+            minWidth:100
+          },
+          {
+            title: 'R6',
+            sortable: true,
+            key: 'R6',
+            minWidth:100
+          }
         ],
         exerciseColumns: [
           {
             title: '题号',
             key: 'id',
-            width:100
+            width: 100,
+            renderType:'renderEventIndex'
           },
           {
-            title: '班级得分率',
+            title: '班级',
             key: 'classScoreRate',
             sortable: true,
             width:150
           },
           {
-            title: '年级得分率',
+            title: '年级',
             key: 'gradeScoreRate',
             sortable: true,
             width:150
           },
           {
-            title: '区级得分率',
+            title: '区级',
             key: 'areaScoreRate',
             sortable: true,
             width:150
           },
           {
-            title: '高分得分率',
+            title: '高分',
             key: 'highScoreRate',
             sortable: true,
             width:150
           },
           {
-            title: '低分组得分率',
+            title: '低分组',
             key: 'lowScoreRate',
             sortable: true,
             width:150
           },
           {
-            title: '1班/100人',
-            key: 'id',
+            title: '1班',
+            key: 'R1',
             sortable: true,
             width:150
           },
           {
-            title: '2班/100人',
-            key: 'id',
+            title: '2班',
+            key: 'R2',
             sortable: true,
             width:150
           },
           {
-            title: '3班/100人',
-            key: 'id',
+            title: '3班',
+            key: 'R3',
             sortable: true,
             width:150
           },
           {
-            title: '4班/100人',
-            key: 'id',
+            title: '4班',
+            key: 'R4',
+            sortable: true,
+            width:150
+          },
+          {
+            title: '5班',
+            key: 'R5',
+            sortable: true,
+            width:150
+          },
+          {
+            title: '6班',
+            key: 'R6',
+            sortable: true,
+            width:150
+          },
+          {
+            title: '7班',
+            key: 'R1',
+            sortable: true,
+            width:150
+          },
+          {
+            title: '8班',
+            key: 'R2',
+            sortable: true,
+            width:150
+          },
+          {
+            title: '9班',
+            key: 'R3',
+            sortable: true,
+            width:150
+          },
+          {
+            title: '10班',
+            key: 'R4',
             sortable: true,
             width:150
           }
@@ -198,7 +275,10 @@
           {
             title: '得分率',
             key: 'entryRate',
-            sortable: true
+            sortable: true,
+            renderType: function (h, params) {
+               return h('span', params.row.entryRate + '%');
+            }
           },
           {
             title: '总人数',
@@ -214,31 +294,39 @@
       }
     },
     created() {
-      let memberList = this.$store.state.totalAnalysis.memberList;
       let classList = this.$store.state.totalAnalysis.classList;
-      let knowledgeList = this.$store.state.totalAnalysis.knowledgeList;
-
+      let testScatter = this.$store.state.totalAnalysis.testScatter;
       let knowledgeArr = testScatter.map(item => item.tableData);
       this.tableData = knowledgeArr;
       this.rightTableData = classList;
+
     },
 
     methods: {
        //点击落点图某个点事件
       handleItemClick(item) {
-        console.log(item);
+        //console.log(item);
         this.currentExerciseIndex = item.data[item.data.length - 1];
-        this.$router.push({ path: '/total/questionList', query: { index : item.data[item.data.length - 1] }})
+        let classList = this.$store.state.totalAnalysis.classList;
+        classList.forEach(item => {
+          item.entryRate = 90 - Math.ceil(Math.random() * 30);
+        })
+
+        this.$refs.lineBar.drawLine(classList);
+        this.$refs.lineBar.gradeRate = 90 - Math.ceil(Math.random() * 30);
+        this.$refs.lineBar.areaRate = 90 - Math.ceil(Math.random() * 30);
       },
 
       handleIndexClick(index) {
-        this.$router.push({ path: '/total/questionList', query: { index : index}})
+        this.$router.push({ path: '/total/questionList', query: { QIndex : index}})
       }
 
     },
 
     mounted() {
-       this.$refs.rightRateTable.$el.childNodes[0].style.borderRight = "0";
+      this.$refs.analysisTable.$el.childNodes[2].style.borderRight = "0";
+      this.handleItemClick({data:[1]});
+
     },
   }
 </script>

+ 36 - 9
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/index.css

@@ -6,6 +6,7 @@ body, html, .total-container {
     width: 100%;
     height: 100%;
     min-width:1266px;
+    user-select:none !important;
 }
 
 .total-container {
@@ -101,6 +102,23 @@ body, html, .total-container {
     border: 1px solid #fbd103;
     vertical-align:super;
 }
+.total-content .basic-info .info-subject {
+    padding: 5px 10px;
+    color: #eee;
+    border-radius: 5px;
+    vertical-align: super;
+    margin-left: 10px;
+    background: #419901;
+}
+
+.total-content .basic-info .info-grade {
+    padding: 5px 10px;
+    color: #eee;
+    border-radius: 5px;
+    vertical-align: super;
+    margin-left: 10px;
+    background: #018b99;
+}
 
 .total-content .basic-info .info-name {
     color:#fff;
@@ -153,17 +171,25 @@ body, html, .total-container {
 
 
 .total-content .data-select {
-    margin:25px 20px;
-    color:#9e9e9e;
-    font-size:14px;
-    font-weight:bold;
+    padding: 25px 22px;
+    /*padding: 18px 0px 10px 0;*/
+    color: #9e9e9e;
+    font-size: 14px;
+    font-weight: bold;
+    /*position: fixed;
+    top: 220px;
+    width: 78%;
+    background: #282828;
+    z-index: 9999;
+    margin-left: 30px;
+    border-bottom: 0px solid #444;*/
 }
 
-    .total-content .data-select span {
-        padding:8px;
-        margin-left:50px;
-        cursor:pointer;
-    }
+.total-content .data-select-items span {
+    padding: 8px;
+    margin-left: 50px;
+    cursor: pointer;
+}
 
     .total-content .data-select .data-select-active {
         color:#fff;
@@ -175,6 +201,7 @@ body, html, .total-container {
     width:100%;
     padding-left:20px;
     padding-bottom:30px;
+    /*margin-top:80px;*/
 }
 
 

+ 79 - 41
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/index.vue

@@ -59,30 +59,40 @@
         <div class="basic-info" v-if="!isShowEvaluations">
           <p>
             <span class="info-type" :style="{color:colorTransfer[currentExamItem.examType] || 'red',borderColor:colorTransfer[currentExamItem.examType]|| 'red'}">{{currentExamItem.examType}}</span>
-            <span class="info-name" @click="showQuestionList">{{currentExamItem.name}}</span>
+            <span class="info-name">{{currentExamItem.name}}</span>
+            <span class="info-grade">{{currentExamItem.period + currentExamItem.grade}}</span>
+            <span class="info-subject" v-for="subject in subjectSplitList">{{subject.substr(0,1)}}</span>
           </p>
           <p class="info-date-person">
             <span class="info-person">参与人数:<span style="color:#fff">{{currentExamItem.joinNum}}人</span></span>
             <span class="info-date">施测日期:<span style="color:#fff">{{currentExamItem.date}}</span></span>
           </p>
           <div class="basic-tools">
-            <span v-show="dataSelectIndex != 0" class="select-title">选择学科:</span>
+            <!--<span v-show="dataSelectIndex != 0" class="select-title">选择学科:</span>
             <Select v-show="dataSelectIndex != 0" v-model="subjectSelectVal" style="width:150px">
               <Option v-for="(item,index) in subjectList" :value="index" :key="index">{{ item.name }}</Option>
-            </Select>
+            </Select>-->
             <!--<Input v-show="dataSelectIndex != 0" v-model="searchValue" placeholder="输入学生姓名或学号..." style="width: 200px" search @on-search="handleSearch" />-->
             <span class="basic-tool-export" @click="handleExportTables"> 导出表格 <Icon type="md-archive" /></span>
 
           </div>
         </div>
-        <div class="data-select" v-if="!isShowQuestions">
-          <span :class="this.$route.path == '/total' || this.$route.path.indexOf('/total/achievement') > -1 ? 'data-select-active' : ''" @click="handleDataSelect('0')">成绩分析</span>
-          <span :class="this.$route.path.indexOf('/total/scatter') > -1 ? 'data-select-active' : ''" @click="handleDataSelect('1')">落点分析</span>
-          <span :class="this.$route.path.indexOf('/total/test') > -1 ? 'data-select-active' : ''" @click="handleDataSelect('2')">试题分析</span>
-          <span :class="this.$route.path.indexOf('/total/knowledge') > -1 ? 'data-select-active' : ''" @click="handleDataSelect('3')">知识点掌握</span>
+        <div class="data-select" v-if="!isShowQuestions" ref="dataSelect">
+          <div class="data-select-items" style="display:inline-block">
+            <span :class="this.$route.path == '/total' || this.$route.path.indexOf('/total/achievement') > -1 ? 'data-select-active' : ''" @click="handleDataSelect('0')">成绩分析</span>
+            <span :class="this.$route.path.indexOf('/total/scatter') > -1 ? 'data-select-active' : ''" @click="handleDataSelect('1')">落点分析</span>
+            <span :class="this.$route.path.indexOf('/total/test') > -1 ? 'data-select-active' : ''" @click="handleDataSelect('2')">试题分析</span>
+            <span :class="this.$route.path.indexOf('/total/knowledge') > -1 ? 'data-select-active' : ''" @click="handleDataSelect('3')">知识点掌握</span>
+          </div>
+            <span style="float:right;margin-bottom:4px;"  v-show="dataSelectIndex != 0">
+              <span class="select-title">当前学科:</span>
+              <Select  v-model="subjectSelectVal" style="width:150px" @on-change="handleSubjectChange">
+                <Option v-for="(item,index) in getSubjectList" :value="index" :key="index" :label="item"></Option>
+              </Select>
+          </span>
         </div>
-        <div class="data-container" style="position:relative">
-          <Loading :top="300" :borderWidth="4" v-show="dataLoading"></Loading>
+        <div class="data-container" style="position:relative" ref="routerView">
+          <Loading :top="300" :borderWidth="4" :borderTopWidth="8" v-show="dataLoading"></Loading>
           <transition name="fade">
             <router-view />
           </transition>
@@ -125,33 +135,25 @@
         isSubMenuShow: false,
         isExportTables:false,
         currentExamItem: {},
-        subjectSelectVal:0,
-        subjectList: [
-          {
-            name:"语文"
-          },
-          {
-            name:"数学"
-          },
-          {
-            name:"英语"
-          },
-          {
-            name:"生物"
-          },
-          {
-            name:"化学"
-          },
-        ],
+        subjectSelectVal: 0,
+        subjectSplitList:[],
+        subjectList: [],
         colorTransfer: {
           '模拟测验':'#fbd103',
-          '校内测验':'#baecff',
+          '诊断测验':'#baecff',
           '全国测验':'#00ff8a'
         }
       }
     },
     created() {
+      this.subjectList = this.$store.state.totalAnalysis.subjectList;
+    },
 
+    computed:{
+      getSubjectList() {
+        let list = this.$store.state.totalAnalysis.subjectList;
+        return list.length ? list : this.subjectSplitList;
+      }
     },
 
     methods: {
@@ -177,10 +179,11 @@
           default:
             break;
         }
-        this.$router.push(path);
         setTimeout(function () {
           that.dataLoading = false;
-        },1000)
+        }, 1000)
+        this.$router.push(path);
+
       },
 
       //指定容器滚动到指定位置
@@ -198,16 +201,27 @@
       //选中某次测验
       chooseExam(item) {
         let that = this;
+        let percentList = this.$store.state.totalAnalysis.subjectPercent;
         this.contentLoading = true;
         this.isShowQuestions = false;
         this.isShowEvaluations = false;
         this.currentExamItem = item;
+        this.subjectSplitList = this.currentExamItem.subject.split(',');
+        this.$store.commit('updateSubjectList', this.subjectSplitList);
         sessionStorage.setItem('c_exam', JSON.stringify(item));
         //this.handleDataSelect(0);
         this.scrollToTop(this.$refs.dataContainer, 0, 100);
         setTimeout(function () {
-          that.contentLoading = false;
-        },1000)
+          //通过VUEX修改存放在store的科目及格率百分比值
+            that.$store.commit('updatePercent', percentList);
+            that.$store.commit('updateBaseBarData');
+            that.$store.commit('updateEntryData',item.joinNum);
+            that.$store.commit('updateSubjectPercent',item.subject.split(','));
+            that.contentLoading = false;
+        }, 1000)
+
+        this.subjectSelectVal = 0;
+        this.handleSubjectChange(0);
 
       },
 
@@ -241,19 +255,43 @@
         if (this.searchValue) {
           //console.log(this.searchValue);
         }
+      },
+
+      //切换科目时更换页面图表数据
+      handleSubjectChange(val) {
+        if (val == 0 || val == 1) {
+          this.$store.commit('updateScatterData',this.$store.state.totalAnalysis.scatter);
+          this.$store.commit('updateTestScatterData',this.$store.state.totalAnalysis.testScatter);
+          this.$store.commit('updatePieData',val);
+          this.$store.commit('updateRadarData');
+        }
       }
 
     },
     mounted() {
       let examIndex = this.$route.query.index;
+
+      //如果路由跳转到成绩分析页面带有考试序号参数则跳转到当前考试
       if (examIndex || examIndex == 0) {
         this.currentExamItem = this.$refs.examListRef.examList[this.$route.query.index];
         this.$refs.examListRef.examIndex = this.$route.query.index;
-      }else if (!examIndex && examIndex != 0) {
-        this.currentExamItem = this.$refs.examListRef.examList[0];
-        this.$refs.examListRef.examIndex = 0;
+        let percentList = this.$store.state.totalAnalysis.subjectPercent;
+        //修改当前考试的及格率等图表数据
+        this.$store.commit('updatePercent', percentList);
+        this.$store.commit('updateBaseBarData');
+
+
+      } else if (!examIndex && examIndex != 0) {  //如果是首次进入则读取上次考试,如果没有上次考试则默认读取第一个
+        let existExam = JSON.parse(sessionStorage.getItem('c_exam'));
+        let list = this.$refs.examListRef.examList;
+        this.currentExamItem = existExam || this.$refs.examListRef.examList[0]; //如果没有上次考试则默认读取第一个
+        this.$refs.examListRef.examIndex = existExam ? list.indexOf(list.filter(item => item.id == existExam.id)[0]) : 0;
       }
 
+      this.subjectSplitList = this.currentExamItem.subject.split(',');
+      this.subjectSelectVal = 0;
+      this.handleSubjectChange(0);
+
 
     },
     //监听部分路由变化
@@ -301,7 +339,7 @@
       height: 30px;
   }
 
-  .total-content .basic-tools .ivu-select-single .ivu-select-selection {
+  .total-content .ivu-select-single .ivu-select-selection {
       height: 30px;
       background: transparent;
       border: 1px solid #595959;
@@ -309,11 +347,11 @@
       color:#cecece; 
   }
 
-  .total-content .basic-tools .ivu-select-single .ivu-select-arrow {
+  .total-content  .ivu-select-single .ivu-select-arrow {
       top:76%;
   }
 
-  .total-content .basic-tools .ivu-select-single .ivu-select-placeholder {
+  .total-content  .ivu-select-single .ivu-select-placeholder {
       height: 30px;
       line-height: 30px;
       font-size: 16px;
@@ -329,8 +367,8 @@
   }
 
   .export-modal .ivu-modal-content {
-    background:#757575;
-    color:#fff;
+    background:#fff;
+    color:#757575;
   }
 
 </style>

+ 39 - 0
TEAMModelOS/ClientApp/view/teachermgmt/Index.less

@@ -0,0 +1,39 @@
+#teachermgmt{    
+    width: 100%;
+    height: 100%;
+    color: #fff;
+    padding: 1%;
+    overflow-x: auto;
+    overflow-y: hidden;
+    .main{
+        white-space: nowrap;
+        display: -webkit-box;
+        display: -ms-flexbox;
+        display: flex;
+        height:95%;
+        .pane{
+            height: 100%;
+            padding:10px;
+            background-color: #282828;
+            border:1px solid #666;
+            position: relative;
+            z-index:10;
+            &-box{
+                overflow: auto;
+                height: 88%;
+                &-colum{
+                    padding: 15px 10px 10px 15px;
+                    background-color: #66666629;
+                    cursor: pointer;
+                    margin-bottom: 5px;
+                    &:hover, &.active{
+                        background: -webkit-linear-gradient(right, rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -o-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -moz-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: linear-gradient(to right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                    }
+                }
+            }
+        }
+    }
+}

+ 66 - 0
TEAMModelOS/ClientApp/view/teachermgmt/Index.vue

@@ -0,0 +1,66 @@
+<style lang="less" scoped>
+  @import './Index.less';
+</style>
+
+<template>
+    <div id="teachermgmt" class="backdrop">
+        <Row class="main">
+            <Col class="pane" :span="3">                
+                 <Row class="scrollstyle pane-box">
+                    <Col>
+                        <div class="pane-box-colum" @click="paneBtn('AccountMgmt')"  :class="{ 'active': menuStr === 'AccountMgmt' }">
+                            AccountMgmt 帳號管你
+                        </div>
+                        <div class="pane-box-colum" @click="paneBtn('Authorization')" :class="{ 'active': menuStr === 'Authorization' }">
+                            Authorization 權限管你
+                        </div>
+                    </Col>
+                </Row>
+            </Col>
+            <transition name="leftInOut">
+                <div v-on:closeComp="close()" :is="menu"></div>
+            </transition>
+        </Row>        
+    </div>
+</template>
+
+<script>
+
+import AccountMgmt from './menu/accountmgmt/Index.vue'
+import Authorization  from './menu/authorization/Index.vue'
+
+export default {
+  data () {
+    return {
+        menu:'',
+        menuStr: '',
+    }
+  },
+  components:{
+    AccountMgmt,
+    Authorization,
+  },
+  computed:{
+  },
+  methods:{
+    async paneBtn(pane){
+        if(this.menu !='' && this.menu != pane){
+           this.menu = '' 
+           this.menuStr = pane; 
+           await this.sleep(700);
+           this.menu = pane;              
+        } else {
+            this.menu = pane;
+            this.menuStr = pane;            
+        }
+    },
+    sleep (time) {
+        return new Promise((resolve) => setTimeout(resolve, time));
+    },
+    close(e){
+        this.menu = '';
+        this.menuStr = '';        
+    }
+  }
+}
+</script>

+ 69 - 0
TEAMModelOS/ClientApp/view/teachermgmt/menu/accountmgmt/Index.less

@@ -0,0 +1,69 @@
+#accountMgmt{    
+    width: 100%;
+    height: 100%;
+    color: #fff;
+    overflow-x: auto;
+    overflow-y: hidden;
+    .main{
+        white-space: nowrap;
+        display: -webkit-box;
+        display: -ms-flexbox;
+        display: flex;
+        height:100%;
+        .pane{
+            height: 100%;
+            padding:10px;
+            background-color: #282828;
+            border:1px solid #666;
+            position: relative;
+            z-index:10;
+            box-shadow: 2px 0 2px 0px rgba(81, 90, 110, 0.5);
+            .title{
+                height:5%;
+            }
+            .head{
+                border-bottom: 1px solid rgb(148, 153, 138);
+                padding-bottom: 10px                
+            }
+            .conet{
+                overflow: auto;
+                height: 94%;
+                width: 100%;
+                .user{
+                    &:hover, &.active{
+                        background: -webkit-linear-gradient(right, rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -o-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -moz-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: linear-gradient(to right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                    }
+                    padding: 15px 10px 10px 25px;
+                    background-color: #66666629;
+                    cursor: pointer;
+                    margin-bottom:5px;
+                    .box{
+                        height: 50px;
+                        .name{
+                            h3{
+                                font-size: 1.5em
+                            }
+                            span{
+                                font-size: 1em;color: #dcdee2;
+                            }
+                        }
+                        .nickName{
+                            span{
+                                font-size: 1em
+                            }
+                        }
+                        .play{
+                            text-align: right;
+                        }
+                    }
+                }
+            }
+        }
+        .pane-z-index-1{
+            z-index:1;
+        }
+    }
+}

+ 188 - 0
TEAMModelOS/ClientApp/view/teachermgmt/menu/accountmgmt/Index.vue

@@ -0,0 +1,188 @@
+<style lang="less" scoped>
+  @import './Index.less';
+</style>
+
+<template>
+  <div id="accountMgmt">
+    <Row class="main">
+      <Col class="pane" :span="7" style="z-index: 11;">
+        <Row class="head">
+            <Col :span="14">
+              <Row :gutter="10">
+                  <Col :span="5">
+                      <Button @click="addTeacher = true" icon="md-add" style="margin-right: 5px;" />
+                  </Col>
+                  <Col :span="19">
+                      <Input v-model="filterName" suffix="ios-search" placeholder="ID / Name" />
+                  </Col>
+              </Row>     
+            </Col>
+            <Col :span="10">
+                <a style="color:#fff;float: right;"  @click="closeBtn()"><Icon size="17" type="md-close" /></a>
+            </Col>
+        </Row>
+        <div class="conet scrollstyle">
+            <div v-for="(user, index) in filterLists" :key="index" class="user">
+                <Row class="box" type="flex" justify="center" align="middle">
+                    <Col class="name" :span="8">
+                        <h3>{{user.id}}</h3>
+                        <span>{{user.name}}</span>
+                    </Col>
+                    <Col class="nickName" :span="8"><span>{{user.nickName}}</span></Col>
+                    <Col class="play" :span="8">
+                        <Button @click="delTeacher(user.name)" size="small">刪除</Button>
+                    </Col>
+                </Row>
+            </div>
+        </div>
+      </Col>
+      <transition name="leftInOut">
+      <Col v-if="addTeacher" class="pane" :span="5">
+        <Row style="border-bottom: 1px solid #94998a;padding-bottom: 10px;    min-height: 44px;">
+            <Col :span="12">
+              <h3>
+                  是否讓以下的老師加入:
+                  <!-- 老師加入後給予預設的權限 -->
+              </h3>
+            </Col>
+            <Col :span="12">
+              <a style="color:#fff;float: right;"  @click="addTeacher = false"><Icon size="17" type="md-close" /></a>
+            </Col>                    
+        </Row>
+        <Row class="scrollstyle"  style="margin-top: 10px;overflow: auto;height: 88%;">
+            <Col>
+                <div style="padding: 15px 10px 10px 15px;background-color: #66666629;;cursor: pointer;margin-bottom: 5px;">
+                  <h3>JEFF-<small>JEFF#1234</small></h3>
+                    <RadioGroup>
+                      <Radio true-value="01" label="通過"></Radio>
+                      <Radio true-value="10" label="拒絕"></Radio>
+                  </RadioGroup>
+                </div>
+                <div style="padding: 15px 10px 10px 15px;background-color: #66666629;cursor: pointer;margin-bottom: 5px;">
+                  <h3>Mickey-<small>Mikey#1234</small></h3>
+                  <RadioGroup>
+                      <Radio true-value="01" label="通過"></Radio>
+                      <Radio true-value="10" label="拒絕"></Radio>
+                  </RadioGroup>
+                </div>
+            </Col>
+        </Row>
+        <Row >
+            <Col style="text-align: right;">
+                <Button>確定</Button>
+            </Col>
+        </Row>
+      </Col>
+      </transition>
+    </Row>  
+  </div>
+</template>
+
+<script>
+
+export default {
+  data () {
+    return {
+      deleteID: '',
+      addTeacher: false,
+      filterName: '',
+      userList:[ // UserLIST
+        {
+          id: 'Osbert#1234',
+          name: '歐斯柏',
+          nickName: '老師',
+          authList:[
+            {
+              path: '/smartschooldashboard',
+              component: 'smartschooldashboard',
+              access: {  // 小組件權限
+                'fun1': true, 
+                'fun2': false
+              },
+              permissions: true // true: 有權訪問, false: 無權訪問
+            },
+            {
+              path: '/smartclassdashboard',
+              component: 'smartclassdashboard',
+              access: {  // 小組件權限
+                'fun1': true, 
+                'fun2': false
+              },
+              permissions: true // true: 有權訪問, false: 無權訪問
+            },
+            {
+              path: '/guidelines',
+              component: 'guidelines',
+              access: {  // 小組件權限
+                'fun1': true, 
+                'fun2': false
+              },
+              permissions: true // true: 有權訪問, false: 無權訪問
+            },
+          ]
+        },
+        {
+          id: 'James#1234',
+          name: '詹姆士',
+          nickName: '老師',
+          authList:[
+            {
+              path: '/smartschooldashboard', // 頁面
+              component: 'smartschooldashboard', //組件名
+              access: {  // 小組件權限
+                'fun1': false, 
+                'fun2': false
+              },
+              permissions: true // true: 有權訪問, false: 無權訪問
+            },
+            {
+              path: '/smartclassdashboard',
+              component: 'smartclassdashboard',
+              access: {  // 小組件權限
+                'fun1': true, 
+                'fun2': false
+              },
+              permissions: true // true: 有權訪問, false: 無權訪問
+            },
+            {
+              path: '/guidelines',
+              component: 'guidelines',
+              access: {  // 小組件權限
+                'fun1': false, 
+                'fun2': false
+              },
+              permissions: false // true: 有權訪問, false: 無權訪問
+            },
+          ]
+        },
+      ],
+    }
+  },
+  computed:{
+    filterLists: function(){
+    // 通通轉小寫比對。
+    let filterName = this.filterName.toLowerCase();
+
+    return ( filterName.trim() !== '' ) ?
+        this.userList.filter(function(d){ return (d.name.toLowerCase().indexOf(filterName) > -1 || d.id.toLowerCase().indexOf(filterName) > -1); }) :
+        this.userList;
+    },
+  },
+  methods:{
+    closeBtn: function(){
+      this.$emit("closeComp","");
+    },
+    delTeacher: function(name){
+      this.$Modal.confirm({
+        title: '刪除確認',
+        content: '<p>請問是否要刪除 ' + name + '</p>',
+        onOk: () => {
+        },
+        onCancel: () => {
+        }
+      }); 
+    }
+  }
+}
+</script>
+            

+ 111 - 0
TEAMModelOS/ClientApp/view/teachermgmt/menu/authorization/Index.less

@@ -0,0 +1,111 @@
+#authMgmt{    
+    .list-group {
+        display: -ms-flexbox;
+        display: -webkit-box;
+        display: flex;
+        -ms-flex-direction: column;
+        -webkit-box-orient: vertical;
+        -webkit-box-direction: normal;
+        flex-direction: column;
+        padding-left: 0;
+        margin-bottom: 0;
+    }
+    .list-group-item:first-child {
+        border-top-left-radius: .25rem;
+        border-top-right-radius: .25rem;
+    }
+    .list-group-item {
+        position: relative;
+        display: block;
+        padding: .75rem 1.25rem;
+        margin-bottom: -1px;
+        background-color: #fff;
+        color: #333;
+        border: 1px solid rgba(0,0,0,.125);
+    }
+    .list-group-item {
+        cursor: move;
+    }
+
+    width: 100%;
+    height: 100%;
+    color: #fff;
+    overflow-x: auto;
+    overflow-y: hidden;
+    .main{
+        white-space: nowrap;
+        display: -webkit-box;
+        display: -ms-flexbox;
+        display: flex;
+        height:100%;
+        .pane{
+            height: 100%;
+            padding:10px;
+            background-color: #282828;
+            border:1px solid #666;
+            position: relative;
+            z-index:10;
+            .title{
+                height:5%;
+            }
+            .head{
+                border-bottom: 1px solid rgb(148, 153, 138);
+                padding-bottom: 10px                
+            }
+            .conet{
+                overflow: auto;
+                height: 94%;
+                width: 100%;
+                .user{
+                    &:hover, &.active{
+                        background: -webkit-linear-gradient(right, rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -o-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -moz-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: linear-gradient(to right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                    }
+                    padding: 15px 10px 10px 25px;
+                    background-color: #66666629;
+                    cursor: pointer;
+                    margin-bottom:5px;
+                    .box{
+                        height: 50px;
+                        .name{
+                            h3{
+                                font-size: 1.5em
+                            }
+                            span{
+                                font-size: 1em;color: #dcdee2;
+                            }
+                        }
+                        .nickName{
+                            span{
+                                font-size: 1em
+                            }
+                        }
+                        .play{
+                            text-align: right;
+                        }
+                    }
+                }
+            }
+            .listRow{
+                .listItem{
+                    padding: 15px 10px 10px 15px;
+                    background-color: #66666629;
+                    cursor: pointer;
+                    margin-bottom: 5px;
+                    text-align:center;
+                    &:hover, &.active{
+                        background: -webkit-linear-gradient(right, rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -o-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: -moz-linear-gradient(right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                        background: linear-gradient(to right,rgba(147, 166, 150, 0), rgba(147, 166, 150, 0.42));
+                    }
+                }
+            }
+        }
+        .pane-z-index-1{
+            z-index:1;
+        }
+    }
+}

+ 456 - 0
TEAMModelOS/ClientApp/view/teachermgmt/menu/authorization/Index.vue

@@ -0,0 +1,456 @@
+<style lang="less" scoped>
+  @import './Index.less';
+</style>
+
+
+<template>
+  <div id="authMgmt">
+    <Row class="main">
+        <Col v-if="mainPane" class="pane" :span="7">
+            <Row class="head">
+                <Col :span="14">
+                    <Row :gutter="10">
+                        <Col :span="19">
+                            <Input v-model="filterName" suffix="ios-search" placeholder="ID / Name" />
+                        </Col>
+                        <Col :span="5">
+                            <Button @click="batchSwitch()" icon="ios-photos"/>
+                        </Col>
+                    </Row>                                        
+                </Col>
+                <Col :span="10">
+                    <a style="color:#fff;float: right;"  @click="closeAuth()"><Icon size="17" type="md-close" /></a>
+                </Col>
+            </Row>
+            <div class="conet scrollstyle">
+                <div v-for="(user, index) in filterLists" :key="index" class="user" :class="{ 'active': user.id === userSelect }" @click="userAuthSeting(user.id)">
+                    <Row class="box" type="flex" justify="center" align="middle">
+                        <Col class="name" :span="8">
+                            <h3>{{user.id}}</h3>
+                            <span>{{user.name}}</span>
+                        </Col>
+                        <Col class="nickName" :span="8"><span>{{user.nickName}}</span></Col>
+                        <Col class="play" :span="8"><Icon size="20" type="md-play" /></Col>
+                    </Row>
+                </div>
+            </div>
+        </Col>
+        <transition name="leftInOut">
+            <Col class="pane"  style=" z-index:9;" v-if="userPane" :span="5">
+                <Row style="border-bottom: 1px solid #94998a;padding-bottom: 10px;    min-height: 44px;">
+                    <Col :span="12">
+                        <h3>
+                            {{userAuth.name}}
+                            <small>{{userAuth.id}}</small>
+                        </h3>                        
+                    </Col>
+                    <Col :span="12">
+                        <a style="color:#fff;float: right;"  @click="closeBtn()"><Icon size="17" type="md-close" /></a>
+                    </Col>                    
+                </Row>
+                <Row style="margin-top: 10px;">
+                    <Col :span="21">
+                        <Input size="small">
+                            <span slot="prepend">稱謂</span>
+                        </Input>
+                    </Col>                    
+                    <Col :span="3" style="text-align: right;">
+                        <Button size="small" icon="md-copy" @click="copyUserAuthFlag = true"></Button>
+                    </Col>
+                </Row>
+                <Row class="scrollstyle"  style="margin-top: 10px;overflow: auto;height: 84%;">
+                    <Col v-for="(item, authKey) in userAuth.authList" :key="authKey">
+                        <div style="padding: 15px 10px 10px 25px;background-color: #66666629;cursor: pointer;margin-bottom: 5px;">
+                            <Checkbox v-model="item.permissions"> {{item.path}}</Checkbox>
+                        </div>
+                        <transition name="leftInOut">
+                            <div v-if="item.permissions == 1">                 
+                                <ul style="margin-left: 15px;list-style-type: none;">
+                                    <li v-for="(value, name) in item.access">
+                                        <div style="padding: 15px 10px 10px 25px;background-color: #66666629;cursor: pointer;margin-bottom: 5px;">                                            
+                                            <Checkbox v-model="item.access[name]">{{ name }}</Checkbox>
+                                        </div>
+                                    </li>
+                                </ul>
+                            </div>    
+                        </transition>
+                    </Col>                    
+                </Row>
+                <Row >
+                    <Col style="text-align: right;">
+                        <Button>確定</Button>
+                    </Col>
+                </Row>
+                <Spin size="large" fix v-if="authSpin">
+                    <Icon type="ios-loading" size=18 class="spin-icon-load"></Icon>
+                    <div>Loading</div>
+                </Spin>
+            </Col>           
+        </transition>
+        <transition name="leftInOut">
+            <Col class="pane" style=" z-index:8;" v-if="copyUserAuthFlag" :span="4">
+                <Row style="border-bottom: 1px solid #94998a;padding-bottom: 10px;    min-height: 44px;">
+                    <Col :span="12">
+                        <h3>權限複製</h3>                        
+                    </Col>
+                    <Col :span="12">
+                        <a style="color:#fff;float: right;"  @click="copyUserAuthFlag = false"><Icon size="17" type="md-close" /></a>
+                    </Col>                    
+                </Row>
+                <Row style="margin-top: 10px;">
+                    <Col>
+                        <Input v-model="filterNameBycopy" suffix="ios-search" placeholder="ID / Name" />                
+                    </Col>
+                </Row>
+                <Row class="scrollstyle listRow"  style="margin-top: 10px;overflow: auto;height: 88%;">
+                    <Col v-for="(item, key) in filterCopyName" :key="key">
+                        <div class="listItem" @click="copyAuth(item.id, item.name)">
+                            {{item.name}}
+                        </div>                        
+                    </Col>
+                </Row>
+            </Col>
+        </transition>
+        <transition name="leftInOut">
+            <Col v-if="batchPane" class="pane" style=" z-index:8;" :span="12">
+                <Row style="border-bottom: 1px solid #94998a;padding-bottom: 10px;min-height: 44px;">
+                    <Col :span="12">
+                        <h3>批次設定</h3>                        
+                    </Col>
+                    <Col :span="12">
+                        <a style="color:#fff;float: right;"  @click="batchSwitch"><Icon size="17" type="md-close" /></a>
+                    </Col>                    
+                </Row>
+                <Row style="height: 90%;">
+                    <Col :span="8" style="height: 100%;padding: 10px;border-right: 1px solid #94998a;">
+                        <div style="height: 10%;">
+                            <h3>權限</h3>
+                        </div>
+                        <Row class="scrollstyle"  style="margin-top: 10px;overflow: auto;height: 84%;">
+                            <Col v-for="(item, authKey) in basicAuth" :key="authKey">
+                                <div style="padding: 15px 10px 10px 25px;background-color: #66666629;cursor: pointer;margin-bottom: 5px;">
+                                    <Checkbox v-model="item.permissions"> {{item.path}}</Checkbox>
+                                </div>
+                                <transition name="leftInOut">
+                                    <div v-if="item.permissions == 1">                 
+                                        <ul style="margin-left: 15px;list-style-type: none;">
+                                            <li v-for="(value, name) in item.access">
+                                                <div style="padding: 15px 10px 10px 25px;background-color: #66666629;cursor: pointer;margin-bottom: 5px;">                                                    
+                                                    <Checkbox v-model="item.access[name]">{{ name }}</Checkbox>
+                                                </div>
+                                            </li>
+                                        </ul>
+                                    </div>    
+                                </transition>
+                            </Col>                    
+                        </Row>
+                    </Col>       
+                    <Col :span="8" style="height: 100%;padding: 10px;">
+                        <div style="height: 10%;">
+                            <h3>老師列表</h3>
+                            <Input v-model="filterName" suffix="ios-search" placeholder="ID / Name" style="margin: 10px 0px;" />
+                        </div>                        
+                        <draggable :list="userList" group="people" @change="log" class="conet scrollStyle" style="border: 1px solid #fefefe;padding: 10px;height: 90%;padding: 10px;    border-radius: 10px;">
+                            <div
+                            class="user"
+                            v-for="(element, index) in filterLists"
+                            :key="element.name"
+                            >
+                            {{ element.name }} {{ index }}
+                            </div>
+                        </draggable>                  
+                    </Col>
+                    <Col :span="8" style="height: 100%;padding: 10px;">
+                        <div style="height: 10%;">
+                            <h3>要修改的老師</h3>
+                        </div>
+                        <draggable :list="list2" group="people" @change="log" class="conet" style="border: 1px solid #fefefe;padding: 10px;height: 90%;padding: 10px;    border-radius: 10px;">
+                            <div
+                            class="user"
+                            v-for="(element, index) in list2"
+                            :key="element.name"
+                            >
+                            {{ element.name }} {{ index }}
+                            </div>
+                        </draggable>
+                    </Col>                   
+                </Row>                
+                <Row >
+                    <Col style="text-align: right;">
+                        <Button>確定</Button>
+                    </Col>
+                </Row>
+            </Col>
+        </transition>
+    </Row>
+  </div>
+</template>
+
+<script>
+import draggable from 'vuedraggable';
+
+export default {
+    components: {
+        draggable
+    },
+    data () {
+    return {
+ list1: [
+        { name: "John", id: 1 },
+        { name: "Joao", id: 2 },
+        { name: "Jean", id: 3 },
+        { name: "Gerard", id: 4 }
+      ],
+      list2: [
+       
+      ],
+
+        mainPane: true,
+        batchPane: false,
+        copyUserAuthFlag: false,
+        filterName:'',
+        filterNameBycopy: '',
+        userSelect:'', // 被點選的人
+        userPane: '', // 啟動的功能頁紀錄
+        authSpin: false, // 權限頁Spin
+        userList:[ // UserLIST
+            {
+                id: 'Osbert#1234',
+                name: '歐斯柏',
+                nickName: '老師',
+                authList:[
+                    {
+                        path: '/smartschooldashboard',
+                        component: 'smartschooldashboard',
+                        access: {  // 小組件權限
+                            'fun1': true, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/smartclassdashboard',
+                        component: 'smartclassdashboard',
+                        access: {  // 小組件權限
+                            'fun1': true, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/guidelines',
+                        component: 'guidelines',
+                        access: {  // 小組件權限
+                            'fun1': true, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                ]
+            },
+            {
+                id: 'James#1234',
+                name: '詹姆士',
+                nickName: '老師',
+                authList:[
+                    {
+                        path: '/smartschooldashboard', // 頁面
+                        component: 'smartschooldashboard', //組件名
+                        access: {  // 小組件權限
+                            'fun1': false, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/smartclassdashboard',
+                        component: 'smartclassdashboard',
+                        access: {  // 小組件權限
+                            'fun1': true, 
+                            'fun2': false
+                        },
+                        permissions: true // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/guidelines',
+                        component: 'guidelines',
+                        access: {  // 小組件權限
+                            'fun1': false, 
+                            'fun2': false
+                        },
+                        permissions: false // true: 有權訪問, false: 無權訪問
+                    },
+                ]
+            },
+            {
+                id: 'Mickey#2345',
+                name: '米奇',
+                nickName: '老師',
+                authList:[
+                    {
+                        path: '/smartschooldashboard', // 頁面
+                        component: 'smartschooldashboard', //組件名
+                        access: {  // 小組件權限
+                            'fun1': false, 
+                            'fun2': false
+                        },
+                        permissions: false // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/smartclassdashboard',
+                        component: 'smartclassdashboard',
+                        access: {  // 小組件權限
+                            'fun1': false, 
+                            'fun2': false
+                        },
+                        permissions: false // true: 有權訪問, false: 無權訪問
+                    },
+                    {
+                        path: '/guidelines',
+                        component: 'guidelines',
+                        access: {  // 小組件權限
+                            'fun1': false, 
+                            'fun2': false
+                        },
+                        permissions: false // true: 有權訪問, false: 無權訪問
+                    },
+                ]
+            },
+        ],
+        userAuth:{ // 使用者個人權限顯示
+            id: '',
+            name: '',
+            nickName: '',
+            authList:[]
+        },
+        basicAuth:[
+            {
+                path: '/smartschooldashboard', // 頁面
+                component: 'smartschooldashboard', //組件名
+                access: {  // 小組件權限
+                    'fun1': false, 
+                    'fun2': false
+                },
+                permissions: false // true: 有權訪問, false: 無權訪問
+            },
+            {
+                path: '/smartclassdashboard',
+                component: 'smartclassdashboard',
+                access: {  // 小組件權限
+                    'fun1': false, 
+                    'fun2': false
+                },
+                permissions: false // true: 有權訪問, false: 無權訪問
+            },
+            {
+                path: '/guidelines',
+                component: 'guidelines',
+                access: {  // 小組件權限
+                    'fun1': false, 
+                    'fun2': false
+                },
+                permissions: false // true: 有權訪問, false: 無權訪問
+            },
+        ]
+        
+    }
+  },
+  computed:{
+    filterLists: function(){
+    // 通通轉小寫比對。
+    let filterName = this.filterName.toLowerCase();
+
+    return ( filterName.trim() !== '' ) ?
+        this.userList.filter(function(d){ return (d.name.toLowerCase().indexOf(filterName) > -1 || d.id.toLowerCase().indexOf(filterName) > -1); }) :
+        this.userList;
+    },
+    filterCopyName: function(){
+        let _this = this;
+        let newList = this.userList.filter(function(item){
+            return (item.id != _this.userAuth.id)
+        });
+        // 通通轉小寫比對。
+        let filterName = this.filterNameBycopy.toLowerCase();
+
+        return ( filterName.trim() !== '' ) ?
+        newList.filter(function(d){ return (d.name.toLowerCase().indexOf(filterName) > -1 || d.id.toLowerCase().indexOf(filterName) > -1); }) :
+        newList;
+    }
+  },
+  methods:{
+    closeBtn: function(){
+        this.userPane = false;
+        this.userSelect = '';
+        this.copyUserAuthFlag = false;
+    },    
+    sleep: function(time) {
+        return new Promise((resolve) => setTimeout(resolve, time));
+    },
+    userAuthSeting: async function(id){
+        this.userPane = true;
+        this.authSpin = true;
+        await this.sleep(2000);
+        let auth = this.userList.find(function(item){
+            return item.id == id
+        });
+        this.userAuth.id = auth.id;
+        this.userAuth.name = auth.name;
+        this.userAuth.nickName = auth.nickName;
+        this.userAuth.authList = auth.authList;        
+        this.authSpin = false;
+    },
+    closeAuth: function(){
+        this.$emit("closeComp","");
+    },
+    copyAuth: function(id, name){
+        this.$Modal.confirm({
+            title: '複製確認',
+            content: '<p>請問是否要複製 ' + name +' 的權限</p>',
+            onOk: () => {
+                let user = this.userList.filter(function(item){
+                    return (item.id == id)
+                })
+                this.userAuth.authList = user[0].authList
+            },
+            onCancel: () => {
+            }
+        });        
+    },
+    batchSwitch: function(){
+        this.filterName = '';
+        this.batchPane = !this.batchPane;
+        this.mainPane = !this.mainPane;
+        this.copyUserAuthFlag = false;
+        this.userPane = false;
+    },
+    
+
+     add: function() {
+      this.list.push({ name: "Juan" });
+    },
+    replace: function() {
+      this.list = [{ name: "Edgard" }];
+    },
+    clone: function(el) {
+      return {
+        name: el.name + " cloned"
+      };
+    },
+    log: function(evt) {
+      window.console.log(evt);
+    }
+  },
+}
+</script>
+<style scoped>
+.leftInOut-enter-active, .leftInOut-leave-active {
+    transition: all 0.7s;
+}
+.leftInOut-enter, .leftInOut-leave-to /* .list-leave-active below version 2.1.8 */ {
+    opacity: 0;
+    transform: translateX(-150px);    
+}
+.spin-icon-load{
+    animation: ani-demo-spin 1s linear infinite;
+}
+</style>

+ 10 - 1
TEAMModelOS/Controllers/Core/FileController.cs

@@ -107,7 +107,16 @@ namespace TEAMModelOS.Controllers.Core
             await _azureBlobModelService.SaveAll<AzureBlobModel>(list);
             return new Dictionary<string, object> { { "errno", 0 }, { "data", list.Select(x=>x.BlobUrl)}};
         }
-
+        [HttpPost("uptest")]
+        [RequestSizeLimit(102_400_000_00)] //最大10000m左右
+        public async Task<Dictionary<string, Object>> uptest([FromForm] IFormFile file)
+        {
+            //IFormFileCollection s =  Request.Form.Files;
+            JsonRPCResponseBuilder responseBuilder = new JsonRPCResponseBuilder();
+            AzureBlobModel list = await _azureBlobDBRepository.UploadFileByFolder(file.OpenReadStream(),"aaaaa",file.FileName,"pptx",false);
+            return new Dictionary<string, object> { { "errno", 0 }, { "data", list } };
+        }
+        
         //[HttpPost("uploadWord")]
         //[RequestSizeLimit(102_400_000_00)] //最大10000m左右
         //public async Task<BaseJosnRPCResponse> uploadWord([FromForm] IFormFile file)

+ 2 - 2
TEAMModelOS/Controllers/Core/GradeController.cs

@@ -25,7 +25,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("FindGradesByDict")]
         public async Task<BaseJosnRPCResponse> FindGradesByDict(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+            //request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<Grade> Grades = await _GradeSeservice.FindListByDictHasAll<Grade>(request.@params);
             return builder.Data(Grades).build();
@@ -33,7 +33,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("FindSchoolGradesByDict")]
         public async Task<BaseJosnRPCResponse> FindSchoolGradesByDict(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+           // request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<SchoolGrade> Grades = await _GradeSeservice.FindListByDict<SchoolGrade>(request.@params);
             return builder.Data(Grades).build();

+ 3 - 3
TEAMModelOS/Controllers/Core/PeriodController.cs

@@ -32,7 +32,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("DeleteInfo")]
         public async Task<BaseJosnRPCResponse> Delete(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+           // request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             int count  = await _periodService.DeleteAll<Period>(request.@params);
             return builder.Data(count).build();
@@ -41,7 +41,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("FindPeriodsByDict")]
         public async Task<BaseJosnRPCResponse> FindPeriodsByDict(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+           // request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<Period> data = await _periodService.FindListByDictHasAll<Period>(request.@params);
             return builder.Data(data).build();
@@ -50,7 +50,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("FindSchoolPeriodsByDict")]
         public async Task<BaseJosnRPCResponse> FindSchoolPeriodsByDict(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+           // request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<SchoolPeriod> data = await _periodService.FindListByDict<SchoolPeriod>(request.@params);
             return builder.Data(data).build();

+ 10 - 4
TEAMModelOS/Controllers/Core/RoleController.cs

@@ -30,7 +30,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("FindRoleByDict")]
         public async Task<BaseJosnRPCResponse> FindRoleByDict(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+           // request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<Role> roles = await _roleSeservice.FindListByDictHasAll<Role>(request.@params);
             return builder.Data(roles).build();
@@ -48,7 +48,8 @@ namespace TEAMModelOS.Controllers.Core
                     if (role != null && !string.IsNullOrEmpty(role.RowKey))
                     {
                         List<RoleIdentityClaim> identityClaims = await _roleSeservice.FindListByDict<RoleIdentityClaim>(new Dictionary<string, object> {
-                            {"PartitionKey",request.lang },{"RoleCode",role.RowKey },{"RoleLevel",role.Level }
+                          //  {"PartitionKey",request.lang },
+                            { "RoleCode",role.RowKey },{"RoleLevel",role.Level }
                         });
                         roles.Add(role);
                     }
@@ -70,7 +71,10 @@ namespace TEAMModelOS.Controllers.Core
                 foreach (string code in rolecodes)
                 {
                     List<RoleIdentityClaimValue> claimValues=  await _roleSeservice.FindListByDict<RoleIdentityClaimValue>(
-                    new Dictionary<string, object> { { "RoleCode", code },{ "TeamModelId", Id[0]}, { "PartitionKey", request.lang} });
+                    new Dictionary<string, object> { { "RoleCode", code },{ "TeamModelId", Id[0]}
+                        //  ,  { "PartitionKey", request.lang}
+                    }
+                    );
                     List<string> keys = new List<string>();
                     List<Dictionary<string, object>> claims = new List<Dictionary<string, object>>();
                     foreach (IGrouping<string, RoleIdentityClaimValue> group in claimValues.GroupBy(c =>c.GroupKey))
@@ -88,7 +92,9 @@ namespace TEAMModelOS.Controllers.Core
                     Dictionary<string, object> roleClaim = new Dictionary<string, object>
                     {
                         { "roleClaim", claims },
-                        { "role", await _roleSeservice.FindOneByDict<Role>(new Dictionary<string, object> { { "RowKey", code }, { "PartitionKey", request.lang } }) }
+                        { "role", await _roleSeservice.FindOneByDict<Role>(new Dictionary<string, object> { { "RowKey", code },
+                            //{ "PartitionKey", request.lang }
+                        }) }
                     };
                     roleClaims.Add(roleClaim);
                 }

+ 3 - 3
TEAMModelOS/Controllers/Core/SubjectController.cs

@@ -40,7 +40,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("DeleteInfo")]
         public async Task<BaseJosnRPCResponse> Delete(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+            //request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             int count = await _subjectService.DeleteAll<Subject>(request.@params);
             return builder.Data(count).build();
@@ -49,7 +49,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("FindSubjectsByDict")]
         public async Task<BaseJosnRPCResponse> FindList(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+            //request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<Subject> data = await _subjectService.FindListByDictHasAll<Subject>(request.@params);
             return builder.Data(data).build();
@@ -58,7 +58,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("FindSchoolSubjectsByDict")]
         public async Task<BaseJosnRPCResponse> FindSchoolSubjectsByDict(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+           // request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<SchoolSubject> Grades = await _subjectService.FindListByDict<SchoolSubject>(request.@params);
             return builder.Data(Grades).build();

+ 2 - 2
TEAMModelOS/Controllers/Core/TermController.cs

@@ -33,7 +33,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("DeleteInfo")]
         public async Task<BaseJosnRPCResponse> Delete(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+           //request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             int count = await _termService.DeleteAll<SchoolTerm>(request.@params);
             return builder.Data(count).build();
@@ -44,7 +44,7 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("FindSchoolTermsByDict")]
         public async Task<BaseJosnRPCResponse> FindSchoolTermsByDict(JosnRPCRequest<Dictionary<string, object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+           // request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<SchoolTerm> Grades = await _termService.FindListByDict<SchoolTerm>(request.@params);
             return builder.Data(Grades).build();

+ 20 - 11
TEAMModelOS/Controllers/Syllabus/KnowledgeController.cs

@@ -42,7 +42,7 @@ namespace TEAMModelOS.Controllers.Syllabus
         [HttpPost("FindKnowledgePointByDict")]
         public async Task<BaseJosnRPCResponse> FindKnowledgePointByDict(JosnRPCRequest<KnowledgeDto> request)
         {
-            request.@params.PointParams.TryAdd("PartitionKey", request.lang);
+           // request.@params.PointParams.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<KnowledgePoint> data = new List<KnowledgePoint>();
             if (request.@params != null && request.@params.PointParams.TryGetValue("SubjectCode", out _))
@@ -62,7 +62,7 @@ namespace TEAMModelOS.Controllers.Syllabus
         [HttpPost("FindKnowledgeBlockAndPointByDict")]
         public async Task<BaseJosnRPCResponse> FindKnowledgeBlockAndPointByDict(JosnRPCRequest<KnowledgeDto> request)
         {
-            request.@params.PointParams.TryAdd("PartitionKey", request.lang);
+           //request.@params.PointParams.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<BlockPointDto> data = new List<BlockPointDto>();
             if (request.@params != null && request.@params.PointParams.TryGetValue("SubjectCode", out _))
@@ -83,7 +83,7 @@ namespace TEAMModelOS.Controllers.Syllabus
         [HttpPost("FindSchoolPointByDict")]
         public async Task<BaseJosnRPCResponse> FindSchoolPointByDict(JosnRPCRequest<Dictionary<string,object>> request)
         {
-            request.@params.TryAdd("PartitionKey", request.lang);
+        // request.@params.TryAdd("PartitionKey", request.lang);
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<SchoolPoint> data = new List<SchoolPoint>();
             if (request.@params != null && request.@params.TryGetValue("SubjectCode", out _) && request.@params.TryGetValue("SchoolCode", out _))
@@ -104,7 +104,10 @@ namespace TEAMModelOS.Controllers.Syllabus
         [HttpPost("FindSchoolBlockAndPointByDict")]
         public async Task<BaseJosnRPCResponse> FindSchoolBlockAndPointByDict(JosnRPCRequest<KnowledgeDto> request)
         {
-            request.@params.PointParams.TryAdd("PartitionKey", request.lang);
+
+            //request.@params.PartitionKey = "zh-CN";
+           //request.@params.PointParams.TryAdd("PartitionKey", request.lang);
+            request.@params.PointParams.TryAdd("PartitionKey", "zh-CN");
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<SchoolKnowledgeDto> data = new List<SchoolKnowledgeDto>(); 
             if (request.@params != null && request.@params.PointParams.TryGetValue("SubjectCode", out _) && request.@params.PointParams.TryGetValue("SchoolCode", out _))
@@ -124,7 +127,8 @@ namespace TEAMModelOS.Controllers.Syllabus
         /// <returns></returns>
         [HttpPost("SaveOrUpdateSchoolKnowledgeAsStdKnowledge")]
         public async Task<BaseJosnRPCResponse> SaveOrUpdateSchoolBlockAsKnowledgeBlock(JosnRPCRequest<Dictionary<string ,object>> request) {
-            request.@params.TryAdd("PartitionKey", request.lang);
+            //request.@params.TryAdd("PartitionKey", request.lang);
+            request.@params.TryAdd("PartitionKey", "zh-CN");
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             List<SchoolKnowledgeDto> data = new List<SchoolKnowledgeDto>();
             if (request.@params != null && request.@params.TryGetValue("KnowledgeId", out _)
@@ -151,7 +155,8 @@ namespace TEAMModelOS.Controllers.Syllabus
             {
                 SchoolBlock m = request.@params;
                 m.RowKey = m.RowKey = m.SchoolCode + "-" + m.SubjectCode + "-" + m.KnowledgeId.Replace("-", ""); 
-                m.PartitionKey = request.lang;
+              // m.PartitionKey = request.lang;
+                m.PartitionKey = "zh-CN";
                 m.Type = 0;
                 SchoolBlock data = await knowledgeService.SaveOrUpdate<SchoolBlock>(request.@params);
                 builder.Data(data);
@@ -171,7 +176,8 @@ namespace TEAMModelOS.Controllers.Syllabus
                 List<SchoolPoint> schoolPoints = new List<SchoolPoint>();
                 request.@params.ForEach(m => {
                     m.RowKey = m.SchoolCode + "-" + m.SubjectCode + "-" + m.KnowledgeId.Replace("-", "")+"-"+m.Pid.Replace("-","") ; 
-                    m.PartitionKey = request.lang;
+                    //m.PartitionKey = request.lang;
+                    m.PartitionKey = "zh-CN";
                     m.Type = 1;
                     schoolPoints.Add(new SchoolPoint {
                         RowKey =m.SchoolCode+"-"+m.SubjectCode+"-"+m.KnowledgeId.Replace("-",""),
@@ -204,7 +210,8 @@ namespace TEAMModelOS.Controllers.Syllabus
         [HttpPost("SaveOrUpdateAllSchoolPoint")]
         public async Task<BaseJosnRPCResponse> SaveOrUpdateAll(JosnRPCRequest<SchoolPoint> request)
         {
-            request.@params.PartitionKey = request.lang;
+            request.@params.PartitionKey = "zh-CN";
+           // request.@params.PartitionKey = request.lang;
             request.@params.RowKey = request.@params.SchoolCode + "-" + request.@params.SubjectCode + "-" + request.@params.KnowledgeId.Replace("-", "") ;
             request.@params.Source = 1;
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
@@ -220,7 +227,7 @@ namespace TEAMModelOS.Controllers.Syllabus
         public async Task<BaseJosnRPCResponse> RemoveSchoolBlockPoint(JosnRPCRequest<Dictionary<string,object>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            request.@params.TryAdd("PartitionKey", request.lang);
+          //  request.@params.TryAdd("PartitionKey", request.lang);
             if (request.@params != null &&
                 request.@params.TryGetValue("SubjectCode", out _) &&
                 request.@params.TryGetValue("SchoolCode", out _)&&
@@ -248,7 +255,8 @@ namespace TEAMModelOS.Controllers.Syllabus
             if (request.@params.IsNotEmpty()) {
                 request.@params.ForEach(m=> {
                     m.RowKey = m.SubjectCode + "-" + m.TagId.Replace("-", "").Substring(0, 16) + "-" + m.KnowledgeId.Replace("-", "").Substring(0, 16)+m.TagType;
-                    m.PartitionKey = request.lang;
+                   // m.PartitionKey = request.lang;
+                    m.PartitionKey = "zh-CN";
                 });
             }
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
@@ -267,7 +275,8 @@ namespace TEAMModelOS.Controllers.Syllabus
             {
                 request.@params.ForEach(m => {
                     m.RowKey =  m.SubjectCode + "-" + m.TagId.Replace("-","").Substring(0,16) + "-" +m.KnowledgeId.Replace("-","").Substring(0,16) + m.TagType;
-                    m.PartitionKey = request.lang;
+                    //m.PartitionKey = request.lang;
+                    m.PartitionKey = "zh-CN";
                 });
             }
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();

+ 8 - 2
TEAMModelOS/Controllers/Syllabus/SyllabusController.cs

@@ -30,14 +30,20 @@ namespace TEAMModelOS.Controllers.Syllabus
         public async Task<BaseJosnRPCResponse> SaveOrUpdateAll(JosnRPCRequest<List<SyllabusTree>> request )
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            List<SyllabusTree> data = await syllabusService.SaveOrUpdateAll(request.@params , request.lang);
+            List<SyllabusTree> data = await syllabusService.SaveOrUpdateAll(request.@params ,
+                "zh-CN"
+                //  request.lang
+
+                );
             return builder.Data(data).build(); 
         }
         [HttpPost("SaveOrUpdate")]
         public async Task<BaseJosnRPCResponse> SaveOrUpdate(JosnRPCRequest<SyllabusNode> request)
         {
             if (request.@params != null) {
-                request.@params.PartitionKey = request.lang;
+                // request.@params.PartitionKey = request.lang;
+
+                request.@params.PartitionKey = "zh-CN";
                 if (string.IsNullOrEmpty(request.@params.RowKey)) {
                     request.@params.RowKey = Guid.NewGuid().ToString();
                 }

+ 0 - 0
TEAMModelOS/Controllers/Syllabus/VolumeController.cs


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä