Explorar o código

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

liqk %!s(int64=5) %!d(string=hai) anos
pai
achega
5d68d06b10
Modificáronse 84 ficheiros con 6626 adicións e 2322 borrados
  1. 161 0
      TEAMModelOS.SDK/Context/Constant/ContentTypeDict.cs
  2. 1 1
      TEAMModelOS.SDK/Extension/JwtAuth/JwtHelper/JwtHelper.cs
  3. 396 0
      TEAMModelOS.SDK/Helper/Common/ColorHelper/ColorConverter.cs
  4. 7 18
      TEAMModelOS.SDK/Helper/Common/ColorHelper/ColorHelper.cs
  5. 22 0
      TEAMModelOS.SDK/Helper/Common/StringHelper/StringHelper.cs
  6. 18 0
      TEAMModelOS.SDK/Module/AzureBlob/Container/AzureBlobModel.cs
  7. 82 0
      TEAMModelOS.SDK/Module/AzureBlob/Implements/AzureBlobDBRepository.cs
  8. 3 0
      TEAMModelOS.SDK/Module/AzureBlob/Interfaces/IAzureBlobDBRepository.cs
  9. 0 6
      TEAMModelOS.SDK/Module/PowerPointX/Model/PPTXSlide.cs
  10. 0 1
      TEAMModelOS.SDK/Module/PowerPointX/Model/PPTXText.cs
  11. 3 5
      TEAMModelOS.SDK/Module/PowerPointX/PresentationConvert.cs
  12. 2 2
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  13. 8 1
      TEAMModelOS.sln
  14. 54 4
      TEAMModelOS/ClientApp/app.js
  15. 0 2
      TEAMModelOS/ClientApp/common/BaseExamList.vue
  16. 7 5
      TEAMModelOS/ClientApp/common/loading.vue
  17. 93 26
      TEAMModelOS/ClientApp/components/public/main/index.less
  18. 159 177
      TEAMModelOS/ClientApp/components/public/main/index.vue
  19. 372 273
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseBar.vue
  20. 42 25
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseEntryBar.vue
  21. 18 14
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseKnowledgeDetail.vue
  22. 61 71
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseLine.vue
  23. 12 11
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseLineBar.vue
  24. 112 15
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseMyTable.vue
  25. 56 56
      TEAMModelOS/ClientApp/components/student-analysis/total/BasePie.vue
  26. 26 12
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseRadar.vue
  27. 289 0
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseRateLine.vue
  28. 46 14
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseScatter.vue
  29. 46 11
      TEAMModelOS/ClientApp/components/student-analysis/total/BaseTestScatter.vue
  30. 32 5
      TEAMModelOS/ClientApp/css/site.css
  31. 4 2
      TEAMModelOS/ClientApp/filters/http.js
  32. 18 2
      TEAMModelOS/ClientApp/mock/index.js
  33. 1 0
      TEAMModelOS/ClientApp/router/_import_file.js
  34. 14 17
      TEAMModelOS/ClientApp/router/routes.js
  35. 102 0
      TEAMModelOS/ClientApp/static/chinesePoint.json
  36. 34 53
      TEAMModelOS/ClientApp/static/classList.json
  37. 18 6
      TEAMModelOS/ClientApp/static/examList.json
  38. 13 13
      TEAMModelOS/ClientApp/static/exerciseList.json
  39. 5 5
      TEAMModelOS/ClientApp/static/filter.json
  40. 38 0
      TEAMModelOS/ClientApp/static/percent.json
  41. 737 627
      TEAMModelOS/ClientApp/static/questionList.json
  42. 180 60
      TEAMModelOS/ClientApp/static/scatter.json
  43. 7 28
      TEAMModelOS/ClientApp/static/tableList.json
  44. 237 57
      TEAMModelOS/ClientApp/static/testScatter.json
  45. 9 0
      TEAMModelOS/ClientApp/store/index.js
  46. 13 0
      TEAMModelOS/ClientApp/store/module/authorization.js
  47. 121 5
      TEAMModelOS/ClientApp/store/module/totalAnalysis.js
  48. 71 0
      TEAMModelOS/ClientApp/view/authorization/Index.less
  49. 315 0
      TEAMModelOS/ClientApp/view/authorization/Index.vue
  50. 19 6
      TEAMModelOS/ClientApp/view/smartclassdashboard/Index.vue
  51. 18 2
      TEAMModelOS/ClientApp/view/smartschooldashboard/Index.vue
  52. 45 20
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/AchievementAnalysis.css
  53. 85 73
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/AchievementAnalysis.vue
  54. 247 60
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/EarlyWarning.vue
  55. 127 124
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/AchievementAnalysis/EntryTables.vue
  56. 85 33
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/EvaluationList/EvaluationList.css
  57. 226 69
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/EvaluationList/EvaluationList.vue
  58. 53 15
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/KnowledgeAnalysis.vue
  59. 87 50
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/ScoreDetails.vue
  60. 1 1
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/ScatterAnalysis/ScatterAnalysis.css
  61. 42 12
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/ScatterAnalysis/ScatterAnalysis.vue
  62. 37 21
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/QuestionList.css
  63. 290 80
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/QuestionList.vue
  64. 73 46
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/TestAnalysis/TestAnalysis.vue
  65. 36 9
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/index.css
  66. 77 39
      TEAMModelOS/ClientApp/view/student-analysis/total-analysis/index.vue
  67. 39 0
      TEAMModelOS/ClientApp/view/teachermgmt/Index.less
  68. 66 0
      TEAMModelOS/ClientApp/view/teachermgmt/Index.vue
  69. 69 0
      TEAMModelOS/ClientApp/view/teachermgmt/menu/accountmgmt/Index.less
  70. 188 0
      TEAMModelOS/ClientApp/view/teachermgmt/menu/accountmgmt/Index.vue
  71. 111 0
      TEAMModelOS/ClientApp/view/teachermgmt/menu/authorization/Index.less
  72. 456 0
      TEAMModelOS/ClientApp/view/teachermgmt/menu/authorization/Index.vue
  73. 10 1
      TEAMModelOS/Controllers/Core/FileController.cs
  74. 2 2
      TEAMModelOS/Controllers/Core/GradeController.cs
  75. 3 3
      TEAMModelOS/Controllers/Core/PeriodController.cs
  76. 10 4
      TEAMModelOS/Controllers/Core/RoleController.cs
  77. 3 3
      TEAMModelOS/Controllers/Core/SubjectController.cs
  78. 2 2
      TEAMModelOS/Controllers/Core/TermController.cs
  79. 20 11
      TEAMModelOS/Controllers/Syllabus/KnowledgeController.cs
  80. 8 2
      TEAMModelOS/Controllers/Syllabus/SyllabusController.cs
  81. 2 2
      TEAMModelOS/Controllers/Syllabus/VolumeController.cs
  82. 20 0
      TEAMModelOS/Controllers/TestAPIController.cs
  83. 2 2
      TEAMModelOS/Views/Shared/_Layout.cshtml
  84. 2 0
      TEAMModelOS/package.json

+ 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/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));
+
+        }
+
+    }
+}

+ 7 - 18
TEAMModelOS.SDK/Helper/Common/ColorHelper/ColorHelper.cs

@@ -205,12 +205,12 @@ namespace TEAMModelOS.SDK.Helper.Common.ColorHelper
         /// <param name="lumMod"></param>
         /// <param name="lumOff"></param>
         /// <returns></returns>
-        public static Color GetColorLumModAndLumOff(Color color, int lumMod = 0, int lumOff = 0)
+        public static string GetColorLumModAndLumOff(Color color, int lumMod = 0, int lumOff = 0)
         {
             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 Color.FromArgb(colorRGB.R, colorRGB.G, colorRGB.B);
+            return ColorTranslator.ToHtml(Color.FromArgb(colorRGB.R, colorRGB.G, colorRGB.B)).Replace("#","");
         }
 
         /// <summary>
@@ -220,29 +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)
+        public static string  GetShadeOrTintColor(Color color, double val, string Type)
         {
-            double rw = 0, gw = 0, bw = 0;
-            int ra = color.R, ga = color.G, ba = color.B;
+            ColorConverter converter = new ColorConverter();
             if (Type.Equals("Shade"))
             {
-                rw = 0; gw = 0; bw = 0;
-                double rn = rw * (1 - pa) + ra * (1 + pa);
-                double gn = gw * (1 - pa) + ga * (1 + pa);
-                double bn = bw * (1 - pa) + ba * (1 + pa);
-                return Color.FromArgb(int.Parse(Math.Round(rn, 0) + ""), int.Parse(Math.Round(gn, 0) + ""), int.Parse(Math.Round(bn, 0) + ""));
+                return converter.SetShade(color, val);
             }
             else if (Type.Equals("Tint"))
             {
-                rw = 255; gw = 255; bw = 255;
-                double rn = rw * (1 - pa) + ra * (1 + pa);
-                double gn = gw * (1 - pa) + ga * (1 + pa);
-                double bn = bw * (1 - pa) + ba * (1 + pa);
-                return Color.FromArgb(int.Parse(Math.Round(rn, 0) + ""), int.Parse(Math.Round(gn, 0) + ""), int.Parse(Math.Round(bn,0) + ""));
+                return converter.SetTint(color, val);
             }
-            else { return color; }
-            //double pw = 1 - pa;
-           
+            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 - 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.GetColorLumModAndLumOff(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 - 2
TEAMModelOS.SDK/TEAMModelOS.SDK.csproj

@@ -4,8 +4,8 @@
     <TargetFramework>netcoreapp2.2</TargetFramework>
     <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
     <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
-    <Version>1.0.7</Version>
-    <PackageReleaseNotes>更新跨域组件的问题</PackageReleaseNotes>
+    <Version>1.0.14</Version>
+    <PackageReleaseNotes>增加两个字符串截取及文件类型获得扩展名</PackageReleaseNotes>
   </PropertyGroup>
 
   <ItemGroup>

+ 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}

+ 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;
 });

+ 0 - 2
TEAMModelOS/ClientApp/common/BaseExamList.vue

@@ -73,13 +73,11 @@
         let that = this;
         this.examIndex = 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, 53.3, 85.8 , 215.5],
-              ['初一2班', 83.1, 73.4 , 50, 43.3, 75.8 , 215.5],
-              ['初一3班', 86.4, 35.2 , 60, 73.3, 85.8 , 215.5],
-              ['初一4班', 83.3, 25.2 , 30, 43.3, 65.5 , 215.5],
-              ['初一5班', 66.4, 62.2 , 60, 83.8, 84.8 , 215.5],
-              ['初一6班', 86.4, 65.2 , 70, 43.3, 65.8 , 215.5],
-              ['初一7班', 86.7, 45.2 , 40, 93.3, 82.5 , 215.5],
-              ['初一8班', 86.4, 25.2 , 70, 73.6, 85.8 , 215.5],
-              ['初一9班', 86.5, 65.2 , 35, 63.3, 71.8 , 215.5],
-              ['初一10班', 76.4, 35.2 , 30, 43.3, 85.8 , 215.5],
-              ['初一11班', 76.3, 45.2 , 60, 63.7, 75.8 , 215.5],
-              ['初一12班', 83.4, 65.2 , 70, 73.3, 75.6 , 215.5],
-              ['初一13班', 53.4, 75.2 , 30, 53.5, 85.8 , 215.5]
-            ] 
-        },
-        // ---- 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("暂不支持查看其它班级数据!")
+      //  }
+      //})
     }
   }
 };

+ 18 - 14
TEAMModelOS/ClientApp/components/student-analysis/total/BaseKnowledgeDetail.vue

@@ -11,7 +11,7 @@
         knowledgeData:[],
         x: [],
         y: [],
-        activeItemIndex: ""
+        activeItemIndex: 0
       };
     },
 
@@ -26,9 +26,9 @@
 
     methods: {
       drawLine() {
+        let _this = this;
         // 基于准备好的dom,初始化echarts实例
         let myBar = this.$echarts.init(document.getElementById("knowledgeBar"));
-
         // 指定图表的配置项和数据
         var option = {
           tooltip: {
@@ -48,7 +48,7 @@
               color: "#fff"
             },
             formatter: function (value) {
-              console.log(value);
+              //console.log(value);
               return value[0].name + ' : ' + value[0].data + '%';
              }
           },
@@ -138,19 +138,23 @@
           series: [
             {
               type: "bar",
+              animation: false,
               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";
-                //    }
-                //},
+                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
             }]
@@ -166,7 +170,7 @@
         myBar.on('click', function (params) {
           that.activeItemIndex = params.dataIndex;
           that.$emit('handleItemClick', params);
-
+          myBar.setOption(option);
         })
       }
     },

+ 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>

+ 12 - 11
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,6 +61,12 @@ 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>'
             }
           },
           grid: {
@@ -128,14 +136,7 @@ export default {
                     {type : 'min', name: '最小值'}
                 ],
               },
-              //markLine: {
-              //  data: [
-              //      {type : 'average', name: '平均值'},
-              //  ],
-              //  textStyle: {
-              //    color:"#ebebeb"
-              //  }
-              //},
+              barWidth:50,
               data: echartData.map(item => item.entryRate)
             },
             {
@@ -159,7 +160,7 @@ export default {
                   type: "dashed"
                 }
               },
-              data: echartData.map(item => 60)
+              data: echartData.map(item => this.gradeRate)
             },
             {
               name:'区级得分率',
@@ -182,7 +183,7 @@ export default {
                   type: "dashed"
                 }
               },
-              data: echartData.map(item => 88)
+              data: echartData.map(item => this.areaRate)
             },
           ]
         };

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

@@ -1,9 +1,11 @@
 <template>
   <div class="myTable">
-    <div class="table-subject-select">
-      <Select v-model="subjectSelectVal" style="width:100px">
+    <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">
@@ -22,7 +24,32 @@
 </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,
@@ -48,7 +75,6 @@
             name:"化学"
           },
         ],
-        pageSize: 10
       }
     },
     created() {
@@ -58,10 +84,6 @@
         item.render = typeof item.renderType == 'function' ? item.renderType : 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)]
-      })
-
       this.pageChange(1);
 
 
@@ -80,6 +102,10 @@
         this.pageChange(1);
       },
 
+      onSelectChange(val) {
+        this.$emit('onSelectChange', val);
+      },
+
       renderSimple() {
 
       },
@@ -89,7 +115,7 @@
         return h('span', {
           on: {
             click: function () {
-              that.$router.push('/total/achievement/earlyWarning')
+              that.$router.push({ name: 'earlyWarning', params: { name : params.row.name } })
             }
           },
           style: {
@@ -100,6 +126,23 @@
         }, 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;
@@ -171,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: {
@@ -183,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;
@@ -218,7 +285,7 @@
             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 ? '' : ' , '))
@@ -240,7 +307,7 @@
             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.carefulList.length - 1 ? '' : ' , '))
@@ -273,7 +340,7 @@
   .myTable {
     width: 100%;
     /*height: 400px;*/
-    padding: 20px 0;
+    /*padding: 20px 0;*/
     margin: 0 auto;
     display: block;
     user-select: none !important;
@@ -404,6 +471,24 @@
       height: 0;
     }
 
+  .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;
@@ -428,6 +513,18 @@
       }
 
 
+  .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;

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

@@ -3,77 +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: 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'} },
-            ]
+            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>

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

@@ -9,7 +9,8 @@
     data() {
       return {
         originArr:[],
-        dataArr:[]
+        dataArr: [],
+        activeItemIndex:0
       };
     },
     created() {
@@ -33,8 +34,7 @@
 
     },
     mounted() {
-      this.drawLine();
-
+      this.drawLine(this.dataArr);
     },
     methods: {
 
@@ -51,7 +51,6 @@
                   break; 
           } 
       },
-
       areaName(x, y) {
         if (x <= 0.5 && y <= 50) {
           return 'C';
@@ -67,12 +66,10 @@
           return 'A-'
         }
       },
-
       random() {
         var r = Math.floor(Math.random() * 100 );
         return r;
       },
-       
       randomDataArray() {
         var d = [];
         var len = 60;
@@ -82,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 = {
@@ -103,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]}
                        `;
@@ -179,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"
@@ -340,9 +348,9 @@
         });
 
         let that = this;
-
         myScatter.on('click', function (item) {
-          that.$emit('handleItemClick', item);
+          that.activeItemIndex = item.dataIndex;
+          //that.$emit('handleItemClick', item);
         })
 
         //缩放后显示还原按钮
@@ -363,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 - 2
TEAMModelOS/ClientApp/filters/http.js

@@ -1,9 +1,11 @@
 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 => {
@@ -75,7 +77,7 @@ export function fetch(url, params) {
       })
       .catch(err => {
         reject(err);
-        this.$Message.error('数据访问错误!');
+        Message.error('数据访问错误!');
       })
   })
 }

+ 18 - 2
TEAMModelOS/ClientApp/mock/index.js

@@ -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
   }
 ]

+ 18 - 6
TEAMModelOS/ClientApp/static/examList.json

@@ -6,8 +6,10 @@
     "date": "2019-05-11",
     "examType": "诊断测验",
     "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "初中",
-    "grade": "初一",
+    "grade": "一年级",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "上学期"
   },
   {
@@ -18,7 +20,9 @@
     "examType": "诊断测验",
     "examArea": "校内测验",
     "period": "高中",
-    "grade": "高一",
+    "grade": "一年级",
+    "feedback": "考试分析",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "下学期"
   },
   {
@@ -28,8 +32,10 @@
     "date": "2019-07-21",
     "examType": "诊断测验",
     "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "初中",
-    "grade": "初一",
+    "grade": "一年级",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "上学期"
   },
   {
@@ -39,8 +45,10 @@
     "date": "2019-08-15",
     "examType": "模拟测验",
     "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "初中",
-    "grade": "初一",
+    "grade": "一年级",
+    "subject": "语文,数学,英语",
     "term": "上学期"
   },
   {
@@ -50,8 +58,10 @@
     "date": "2019-09-19",
     "examType": "诊断测验",
     "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "高中",
-    "grade": "高一",
+    "grade": "一年级",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "上学期"
   },
   {
@@ -61,8 +71,10 @@
     "date": "2019-10-10",
     "examType": "诊断测验",
     "examArea": "校内测验",
+    "feedback": "考试分析",
     "period": "初中",
-    "grade": "初一",
+    "grade": "二年级",
+    "subject": "语文,数学,英语,物理,化学,生物",
     "term": "上学期"
   }
 

+ 13 - 13
TEAMModelOS/ClientApp/static/exerciseList.json

@@ -1,9 +1,9 @@
 [
   {
     "id": "1",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "问答",
-    "knowledgePoint": "一元一次方程",
+    "knowledgePoint": "统计与概率",
     "blockId": 1,
     "level": "评鉴",
     "gradeScoreRate": "90%",
@@ -11,17 +11,17 @@
   },
   {
     "id": "2",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "多选",
     "blockId": 1,
-    "knowledgePoint": "二元一次方程组",
+    "knowledgePoint": "几何图形初步",
     "level": "理解",
     "gradeScoreRate": "77%",
     "poperData": [ 18, 46, 60 ]
   },
   {
     "id": "3",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
     "blockId": 1,
     "knowledgePoint": "一元二次方程",
@@ -31,7 +31,7 @@
   },
   {
     "id": "4",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
     "blockId": 2,
     "knowledgePoint": "几何图形初步",
@@ -41,17 +41,17 @@
   },
   {
     "id": "5",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "多选",
     "blockId": 2,
-    "knowledgePoint": "三角形",
+    "knowledgePoint": "函数",
     "level": "应用",
     "gradeScoreRate": "62%",
     "poperData": [ 40, 40, 68 ]
   },
   {
     "id": "6",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
     "blockId": 3,
     "knowledgePoint": "数据分析",
@@ -61,7 +61,7 @@
   },
   {
     "id": "7",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "问答",
     "blockId": 3,
     "knowledgePoint": "数据的收集与整理",
@@ -71,7 +71,7 @@
   },
   {
     "id": "8",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
     "blockId": 4,
     "knowledgePoint": "函数的基础知识",
@@ -81,7 +81,7 @@
   },
   {
     "id": "9",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
     "blockId": 4,
     "knowledgePoint": "一次函数",
@@ -91,7 +91,7 @@
   },
   {
     "id": "10",
-    "name": "求复平面内对应的坐标",
+    "name": "",
     "type": "判断",
     "blockId": 5,
     "knowledgePoint": "图形的相似",

+ 5 - 5
TEAMModelOS/ClientApp/static/filter.json

@@ -83,11 +83,11 @@
       "key": "end"
     },
     {
-      "name": "诊断",
+      "name": "诊断测验",
       "key": "diagnosis"
     },
     {
-      "name": "模拟",
+      "name": "模拟测验",
       "key": "simulation"
     }
   ],
@@ -119,15 +119,15 @@
       "key": "all"
     },
     {
-      "name": "校内测验",
+      "name": "班级测验",
       "key": "school"
     },
     {
-      "name": "区域测验",
+      "name": "校级测验",
       "key": "area"
     },
     {
-      "name": "全国测验",
+      "name": "区级测验",
       "key": "country"
     }
   ],

+ 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%"
+  }
+]

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 737 - 627
TEAMModelOS/ClientApp/static/questionList.json


+ 180 - 60
TEAMModelOS/ClientApp/static/scatter.json

@@ -35,7 +35,9 @@
       "areaRank": 109,
       "areaPR": "84%",
       "className": "初一5班",
-      "poperData": [ 50, 94, 15 ]
+      "poperData": [ 50, 94, 15 ],
+      "changesStatus": 1,
+      "changesVal": 3
     },
     "className": "初一5班",
     "changesVal": 3,
@@ -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"

+ 237 - 57
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": ""
     }
   },
   {
@@ -134,7 +179,7 @@
       "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": "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": ""
     }
   },
   {
@@ -182,9 +245,9 @@
     "tableData": {
       "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": ""
     }
   },
   {
@@ -207,9 +279,9 @@
     "tableData": {
       "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": ""
     }
   },
   {
@@ -232,9 +313,9 @@
     "tableData": {
       "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": ""
     }
   },
   {
@@ -259,7 +349,7 @@
       "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": ""
     }
   },
   {
@@ -282,9 +381,9 @@
     "tableData": {
       "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": ""
     }
   },
   {
@@ -307,9 +415,9 @@
     "tableData": {
       "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": ""
     }
   },
   {
@@ -332,9 +449,9 @@
     "tableData": {
       "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": ""
     }
   },
   {
@@ -357,9 +483,9 @@
     "tableData": {
       "id": "15",
       "name": "算法平均值",
-      "type": "填空",
+      "type": "判断",
       "areaName": "B",
-      "score": 3,
+      "score": 4,
       "diff": 0.13,
       "identify": "0.40",
       "classScoreRate": "53%",
@@ -371,11 +497,20 @@
       "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,
@@ -384,7 +519,7 @@
       "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": ""
     }
   },
   {
@@ -407,9 +551,9 @@
     "tableData": {
       "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": ""
     }
   },
   {
@@ -432,9 +585,9 @@
     "tableData": {
       "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": ""
     }
   },
   {
@@ -457,9 +619,9 @@
     "tableData": {
       "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": ""
     }
   },
   {
@@ -482,9 +653,9 @@
     "tableData": {
       "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: {
+        
+    }
+}

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

@@ -1,32 +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,
+    testScatter: testScatter,
     exerciseList: exerciseList,
-    filterData: filter
+    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>

+ 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;
         }
 

+ 85 - 73
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.$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>
 

+ 247 - 60
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,59 +46,208 @@
     data() {
       return {
         echartData: [],
-        tableData:[],
+        tableData: [],
         warningIndex: 0,
-        sortValue:0,
-        sortArr:["默认排序","分数从高到低","分数从低到高"],
+        sortValue: 0,
+        className:"",
+        sortArr: ["默认排序", "分数从高到低", "分数从低到高"],
         earlyPercentColumns: [
           {
             title: '姓名',
             key: 'name',
-            fixed: "left"
-          },
-          {
-            title: '班级',
-            key: 'className'
+            fixed: "left",
+            minWidth:100
           },
           {
             title: '座号',
-            key: 'id'
+            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: [
@@ -115,11 +273,12 @@
             title: '班级排名',
             key: 'classRank',
             sortable: true,
+            renderType: 'renderRank'
           },
           {
             title: '班级排名变化',
             key: 'classRank',
-            renderType: 'renderRankChange'
+            renderType: 'renderRank'
           },
           {
             title: '年级排名',
@@ -130,28 +289,26 @@
             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 = this.$store.state.totalAnalysis.memberList;
       this.echartData = memberList;
@@ -165,15 +322,35 @@
       handleSort(index) {
         let memberList = [...this.$store.state.totalAnalysis.memberList];
         if (index == 0) {
-          this.echartData = memberList.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 = memberList.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 = memberList.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 = {
@@ -222,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: {
@@ -252,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,
@@ -283,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",
@@ -320,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",
@@ -343,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",
@@ -366,7 +553,7 @@
                   type: "dashed"
                 }
               },
-              data: echartData.map(item => item.score - 160)
+              data: echartData.map(item => 485)
             },
           ]
         };
@@ -381,11 +568,10 @@
     },
 
     mounted() {
-
+      this.$parent.isShowQuestions = true;
       this.drawLine(this.echartData);
-
       this.$refs.percentTable.$el.childNodes[2].style.borderRight = "0";
-      this.$refs.scoreTable.$el.childNodes[2].style.borderRight = "0";
+      //this.$refs.scoreTable.$el.childNodes[2].style.borderRight = "0";
     },
   }
 </script>
@@ -416,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;
@@ -454,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>
 

+ 127 - 124
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,6 +280,18 @@
 
     },
 
+    computed: {
+      getEntryData() {
+        //console.log(this.$store.state.totalAnalysis.entryData)
+        return this.$store.state.totalAnalysis.entryData;
+      }
+    },
+    watch: {
+      getEntryData(val) {
+
+      }
+    },
+
     mounted() {
       this.$refs.rateTable.$el.childNodes[2].style.borderRight = "0";
     },

+ 85 - 33
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,19 +22,46 @@
 
     }
 
+    .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;
+        /*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 20px;
+        padding: 10px 20px 20px 0px;
         background: #404040;
     }
 
@@ -45,39 +74,62 @@
     }
 
     .evaluation-list-container .el-bread {
+        position:relative;
         width: 100%;
         height:30px;
         padding-left:10px;
         line-height:70px;
-        font-size:16px;
+        font-size:14px;
         text-align:left;
      }
+        .evaluation-list-container .el-bread .list-length {
+           position:absolute;
+           right:30px;
+        }
 
-    .evaluation-list-container .el-bread .ivu-icon{
+    .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{
         font-size: 18px;
         margin-right:10px;
         margin-bottom:5px;
-    }
+    }*/
 
-    .evaluation-list-container .el-item{
+    .evaluation-list-container .el-item {
         width: 100%;
         padding: 10px 20px;
-        border: 1px solid #808080;
+        border: 1px solid #646363;
         margin-top: 10px;
-        cursor:pointer;
-        display:flex;
-        justify-content:space-between;
-        align-items:center;
+        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: 22px;
-            font-weight: bold;
+            /*font-weight: bold;*/
             display: inline-block;
+            max-width:60%;
         }
 
             .evaluation-list-container .el-item .el-item-name .ivu-icon {
@@ -118,31 +170,30 @@
         }
         .evaluation-list-container .el-item .el-item-area {
             font-size: 14px;
-            border: 1px solid #31f253;
-            color: #31f253;
-            margin-left:10px;
-            padding: 1px 10px;
+            /*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: #31f253;
+            /*border: 1px solid #31f253;*/
+            color: #fff;
             margin-left: 10px;
-            padding: 1px 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;
@@ -155,6 +206,7 @@
     width: 70px;
     text-align: end;
     display: inline-block;
+    color: #e4eadb;
 }
 
 .el-filter-wrap .ivu-radio-group {
@@ -187,7 +239,7 @@
 }
 
 .el-filter-wrap .ivu-radio-wrapper-checked {
-    background: #447a94 !important;
+    background: #0087af !important;
     box-shadow: none !important;
     color: white;
 }

+ 226 - 69
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/EvaluationList/EvaluationList.vue

@@ -3,76 +3,99 @@
     <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="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-search-wrap">
       <Input v-model="searchValue"
              placeholder="输入考试名称..."
              @on-click="handleSearch"
+             @on-change="handleChange"
              @on-enter="handleSearch"
              icon="ios-search"
              style="width:500px">
       </Input>
     </div>
 
-    <div class="el-filter-wrap">
-      <div class="el-filter-item">
-        <span class="el-filter-title">关注学段:</span>
-        <RadioGroup v-model="filterPeriod" type="button" @on-change="filterGradeChange">
-          <Radio v-for="(item,index) in filterData.periodList" :label="item.key" :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.key" :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.key" :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.key" :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.key" :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.key" :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.key" :key="index">{{item.name}}</Radio>
-        </RadioGroup>
-      </div>
-    </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" />当前筛选条件:无</div>
+
+    <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="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">数学</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-people" />参与人数:{{item.joinNum}} 人</span>
@@ -87,6 +110,7 @@
 </template>
 
 <script>
+  import countTo from 'vue-count-to';
   export default {
     components: {
       //BaseTestScatter, BaseTable, BaseLineBar
@@ -95,36 +119,39 @@
       return {
         contentLoading:false,
         questionList: [],
-        examList:[],
+        dataList: [...new Array(6).keys()],
+        hasCondition:false,
+        examList: [],
+        filterList:[],
+        filterConditions: {}, //筛选条件
         filterData: {},
         searchValue: "",
         searchList: [],
-        filterPeriod: "all",
-        filterGrade: "all",
-        filterTerm: "all",
-        filterType: "all",
-        filterArea: "all",
-        filterFeedback: "all",
-        filterSubject: "all",
+        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: {
-      filterMethod(value, option) {
-        //return option.toUpperCase().indexOf(value.toUpperCase()) !== -1;
-        //console.log(value, option);
-        //let examList = this.$store.state.totalAnalysis.examList;
-        //this.examList = examList.filter(item => item.name.indexOf(value) !== -1);
-      },
       handleSearch() {
         let that = this;
         this.contentLoading = true;
@@ -135,35 +162,117 @@
           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);
       },
-      filterPeriodChange() {
+      //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();
+      },
 
+      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() {
 
       },
 
+      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 } });
       }
@@ -174,6 +283,12 @@
     mounted() {
       //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>
 
@@ -219,6 +334,42 @@
   }
 
 
+  .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 {
@@ -242,6 +393,12 @@
     padding: 15px;
   }
 
+      .evaluation-list-container .ivu-spin-dot {
+        width: 120px;
+        height: 120px;
+        background: #05c9da;
+    }
+
     .no-data-text {
         width: 100%;
         height: 100%;

+ 53 - 15
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/KnowledgeAnalysis.vue

@@ -14,7 +14,11 @@
     </Row>
     <Divider />
     <Row>
-      <span class="component-title">得分率关系表 <span style="font-size:14px;font-weight:bold;margin-left:20px;color:#66cccc">当前知识块:{{currentBlock}}</span></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>
@@ -26,7 +30,6 @@
 </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'
@@ -46,7 +49,7 @@
           {
             title: '知识点',
             key: 'knowledgePoint',
-            width:250
+            width:200
           },
           {
             title: '认知层次',
@@ -60,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: '5班/100人',
+            title: '5班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
           {
-            title: '6班/100人',
+            title: '6班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
           {
-            title: '7班/100人',
+            title: '7班',
             key: 'gradeScoreRate',
             sortable: true,
             width:120
           },
           {
-            title: '8班/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
@@ -116,6 +131,8 @@
       this.tableData = classList;
       this.knowledgeData = exerciseList;
 
+      this.isShowPie = !(this.knowledgeData.length > 10);
+
       let knowList = ['方程与不等式','图形的性质','统计与概率','函数','图形的相似','锐角三角函数','几何图形初步','投影与视图']
       let levelList = ['知识','理解','评鉴','综合','分析','应用']
       let typeList = ['单选','多选','判断','问答','填空','问答']
@@ -131,7 +148,7 @@
     },
 
     methods: {
-            randomNum(minNum, maxNum) {
+      randomNum(minNum, maxNum) {
         switch (arguments.length) {
           case 1:
             return parseInt(Math.random() * minNum + 1, 10);
@@ -162,16 +179,37 @@
         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>
 

+ 87 - 50
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/KnowledgeAnalysis/ScoreDetails.vue

@@ -2,23 +2,23 @@
   <div class="scatter-container">
     <Row>
       <Col span="12">
-        <span class="component-title">知识点得分率统计</span>
-        <BaseDetailBar :echartData="knowledgeData" @handleItemClick="handleItemClick" ref="detailsBar"></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>
       <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">* RH:高分区段  /  RL:低分区段</span>
+      <!--<span style="/*font-size:14px;font-weight:bold;margin-left:60px;color:#66cccc*/"></span>-->
     </Row>
   </div>
 </template>
@@ -29,154 +29,191 @@
   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',
-            width:100
-          },
+          //{
+          //  title: '题号',
+          //  key: 'id',
+          //  width:100
+          //},
           {
             title: '知识点',
             key: 'knowledgePoint',
+            minWidth: 150
           },
           {
             title: '分值',
             key: 'score',
+            minWidth: 100
           },
           {
             title: '涉及题号',
             key: 'hardList',
             renderType: 'renderHard',
-            width:250
+            width: 250
           },
           {
             title: '平均得分率',
             key: 'averageScoreRate',
+            renderType: function (h, params) {
+              return h('span', params.row.averageScoreRate + '%');
+            },
+            sortable: true,
+            minWidth: 100
           },
           {
             title: '错题人数',
             key: 'falseNum',
+            sortable: true,
+            minWidth: 100
           },
           {
             title: 'RH错题人数',
             key: 'RH',
             sortable: true,
+            minWidth: 100
           },
           {
             title: 'RL错题人数',
             key: 'RL',
             sortable: true,
+            minWidth: 100
           },
         ],
         detailsColumns: [
           {
             title: '姓名',
             key: 'name',
+            minWidth: 100
           },
           {
             title: '班级',
             key: 'className',
-            width:120
+            width: 120
           },
           {
             title: '座号',
             key: 'id',
-            width:120
+            width: 120
           },
           {
             title: '分值',
             key: 'score',
+            minWidth: 100
           },
           {
             title: '本节得分',
             key: 'score',
+            minWidth: 100,
+            renderType: function (h, params) {
+              return h('span', params.row.score - Math.floor(Math.random() * 4))
+            }
           },
           {
             title: '得分率',
             key: 'scoreRate',
-            renderType: 'renderPercent'
+            renderType: 'renderPercent',
+            minWidth: 100
           },
           //{
           //  title: '历次得分率趋势',
           //  renderType:"renderLineChange"
           //},
-          
+
         ]
       }
     },
     created() {
       let memberList = this.$store.state.totalAnalysis.memberList;
       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|10': [{
-          "id|+1": 1,   
+        'list|60': [{
+          "id|+1": 1,
           "className|1": ['初一5班'],
-          "name":'@cname',
-          "score|1-10": 1,     
-          "averageScoreRate|40-80": 40,    
-          "scoreRate|50-100":50
-        }], 
+          "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,
-          "RH|10-20":20,
-          "RL|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;
       })
-
-      console.log(this.numData);
-
     },
 
     methods: {
-       //点击柱状图某个点事件
+      //点击柱状图某个点事件
       handleItemClick(item) {
         this.currentPoint = item.name;
         let newList = Mock.mock({
-          'list|10': [{
-            "id|+1": 1,   
+          'list|60': [{
+            "id|+1": 1,
             "className|1": ['初一5班'],
-            "name":'@cname',
-            "score|1-10": 1,     
-            "averageScoreRate|40-80": 40,    
-            "scoreRate|50-100":50
-          }], 
+            "name": '@cname',
+            "score|1-10": 1,
+            "averageScoreRate|40-80": 40,
+            "scoreRate|50-100": 50
+          }],
         }).list;
-        this.tableData.forEach((item,index) => {
-          item.score = newList[index].score;
+        let randomVal = 4 + Math.floor(Math.random() * 6);
+        this.tableData.forEach((item, index) => {
+          item.score = randomVal;
           item.scoreRate = newList[index].scoreRate;
-        })  
+        })
       }
     },
     mounted() {
-      console.log(this.$refs.numTable);
       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){
+      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;
+        })
       }
     }
   }

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

@@ -21,7 +21,7 @@
 
 
 .scatter-statistics {
-    margin-top:160px;
+    margin-top:130px;
 }
 
 .scatter-statistics .ivu-divider-horizontal {

+ 42 - 12
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,33 +120,59 @@
             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);
-        console.log(this.tableData[0]);
+      },
+
+
+      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});
       }
 
     },

+ 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:row;
+    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 {

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

@@ -3,13 +3,23 @@
     <!-- 左侧题目列表清单 -->
     <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: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 '@/static/questionList.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,15 +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];
-        item.score = Math.ceil(Math.random() * 10);
-      })
-      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');
@@ -161,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: {
@@ -180,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 => {
@@ -200,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>
@@ -247,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>

+ 73 - 46
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" ref="lineBar"></BaseLineBar>
       </div>
-      </Col>
-      <Col span="12">
+      <!--<Col span="12">
       <span class="component-title"></span>
       <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="analysisTable"></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="scoreRateTable"></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,148 +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: 'classScoreRate',
+            key: 'R1',
             sortable: true,
+            minWidth:100
           },
           {
             title: 'R2',
-            key: 'classScoreRate',
+            key: 'R2',
             sortable: true,
+            minWidth:100
           },
           {
             title: 'R3',
             sortable: true,
-            key: 'classScoreRate',
+            key: 'R3',
+            minWidth:100
           },
           {
             title: 'R4',
             sortable: true,
-            key: 'classScoreRate',
+            key: 'R4',
+            minWidth:100
           },
           {
             title: 'R5',
             sortable: true,
-            key: 'classScoreRate',
+            key: 'R5',
+            minWidth:100
           },
           {
             title: 'R6',
             sortable: true,
-            key: 'classScoreRate',
+            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: 'areaScoreRate',
+            title: '1班',
+            key: 'R1',
             sortable: true,
             width:150
           },
           {
-            title: '2班/100人',
-            key: 'areaScoreRate',
+            title: '2班',
+            key: 'R2',
             sortable: true,
             width:150
           },
           {
-            title: '3班/100人',
-            key: 'areaScoreRate',
+            title: '3班',
+            key: 'R3',
             sortable: true,
             width:150
           },
           {
-            title: '4班/100人',
-            key: 'areaScoreRate',
+            title: '4班',
+            key: 'R4',
             sortable: true,
             width:150
           },
           {
-            title: '5班/100人',
-            key: 'areaScoreRate',
+            title: '5班',
+            key: 'R5',
             sortable: true,
             width:150
           },
           {
-            title: '6班/100人',
-            key: 'areaScoreRate',
+            title: '6班',
+            key: 'R6',
             sortable: true,
             width:150
           },
           {
-            title: '7班/100人',
-            key: 'areaScoreRate',
+            title: '7班',
+            key: 'R1',
             sortable: true,
             width:150
           },
           {
-            title: '8班/100人',
-            key: 'areaScoreRate',
+            title: '8班',
+            key: 'R2',
+            sortable: true,
+            width:150
+          },
+          {
+            title: '9班',
+            key: 'R3',
+            sortable: true,
+            width:150
+          },
+          {
+            title: '10班',
+            key: 'R4',
             sortable: true,
             width:150
           }
@@ -271,10 +294,8 @@
       }
     },
     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;
@@ -286,17 +307,23 @@
       handleItemClick(item) {
         //console.log(item);
         this.currentExerciseIndex = item.data[item.data.length - 1];
-        this.$refs.lineBar.drawLine(this.rightTableData);
+        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[2].style.borderRight = "0";
       this.$refs.analysisTable.$el.childNodes[2].style.borderRight = "0";
       this.handleItemClick({data:[1]});
 

+ 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;*/
 }
 
 

+ 77 - 39
TEAMModelOS/ClientApp/view/student-analysis/total-analysis/index.vue

@@ -59,7 +59,9 @@
         <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" >{{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>
@@ -75,14 +77,22 @@
 
           </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,24 +135,9 @@
         isSubMenuShow: false,
         isExportTables:false,
         currentExamItem: {},
-        subjectSelectVal:1,
-        subjectList: [
-          {
-            name:"语文"
-          },
-          {
-            name:"数学"
-          },
-          {
-            name:"英语"
-          },
-          {
-            name:"生物"
-          },
-          {
-            name:"化学"
-          },
-        ],
+        subjectSelectVal: 0,
+        subjectSplitList:[],
+        subjectList: [],
         colorTransfer: {
           '模拟测验':'#fbd103',
           '诊断测验':'#baecff',
@@ -151,7 +146,14 @@
       }
     },
     created() {
+      this.subjectList = this.$store.state.totalAnalysis.subjectList;
+    },
 
+    computed:{
+      getSubjectList() {
+        let list = this.$store.state.totalAnalysis.subjectList;
+        return list.length ? list : this.subjectSplitList;
+      }
     },
 
     methods: {
@@ -160,7 +162,7 @@
         let path = "";
         let that = this;
         this.dataSelectIndex = index;
-        //this.dataLoading = true;
+        this.dataLoading = true;
         switch (Number(index)) {
           case 0:
             path = "/total";
@@ -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();
                 }

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

@@ -37,7 +37,7 @@ namespace TEAMModelOS.Controllers.Syllabus
         [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 _volumeService.DeleteAll<SchoolTerm>(request.@params);
             return builder.Data(count).build();
@@ -46,7 +46,7 @@ namespace TEAMModelOS.Controllers.Syllabus
         [HttpPost("FindSchoolVolumesByDict")]
         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<SchoolVolume> Grades = await _volumeService.FindListByDict<SchoolVolume>(request.@params);
             return builder.Data(Grades).build();

+ 20 - 0
TEAMModelOS/Controllers/TestAPIController.cs

@@ -5,6 +5,7 @@ using Newtonsoft.Json.Linq;
 using System.Threading.Tasks;
 using System.Text;
 using System.Net;
+using Newtonsoft.Json;
 
 namespace DashBoard.Controllers
 {
@@ -24,6 +25,25 @@ namespace DashBoard.Controllers
             return await Task.Run(() => JObject.Parse(content));
         }
 
+        [HttpGet("[action]")]
+        public async Task<JObject> GetTestAuth()
+        {
+            string auth = @"{
+                'data':[
+                    {
+                        'path': '/smartschooldashboard',
+                        'component': 'smartschooldashboard',
+                        'access':{
+                            'fun1': true,
+                            'fun2': false
+                        },
+                    }
+                ]
+            }";
+
+            return await Task.Run(() => JObject.Parse(auth));
+        }
+
         [HttpGet("[action]/{schoolShortCode}")]
         public async Task<JObject> GetTestIoTData(string schoolShortCode)
         {

+ 2 - 2
TEAMModelOS/Views/Shared/_Layout.cshtml

@@ -6,7 +6,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>@ViewData["Title"]TEAM Model OS</title>
     <link rel="stylesheet" href="~/dist/style.css" asp-append-version="true" />
-    <link rel="icon" type="image/x-icon" class="js-site-favicon" href="https://account.habookaclass.biz/dist/6854ccd21afb6b1f994e1556c2360dd8.ico">
+    @*<link rel="icon" type="image/x-icon" class="js-site-favicon" href="https://account.habookaclass.biz/dist/6854ccd21afb6b1f994e1556c2360dd8.ico">*@
     @*<link rel="stylesheet" href="~/dist/vendor.css" asp-append-version="true" />
         <environment names="Staging,Production">
             <link rel="stylesheet" href="~/dist/site.css" asp-append-version="true" />
@@ -16,7 +16,7 @@
 <body>
     @RenderBody()
     <script src="~/dist/vendor.js" asp-append-version="true"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML" asp-append-version="true"></script>
+    @*<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML" asp-append-version="true"></script>*@
 
     @RenderSection("scripts", required: false)
 </body>

+ 2 - 0
TEAMModelOS/package.json

@@ -32,6 +32,7 @@
     "videojs-contrib-hls.js": "^3.2.0",
     "vue": "^2.6.9",
     "vue-ckeditor5": "^0.4.1",
+    "vue-count-to": "^1.0.13",
     "vue-happy-scroll": "^2.1.0",
     "vue-infinite-loading": "^2.4.4",
     "vue-router": "^3.0.7",
@@ -39,6 +40,7 @@
     "vue-server-renderer": "^2.6.9",
     "vue-template-compiler": "^2.6.9",
     "vue-video-player": "^5.0.2",
+    "vuedraggable": "^2.23.0",
     "vuex": "^3.1.1",
     "vuex-router-sync": "^5.0.0",
     "wangeditor": "^3.1.1"