瀏覽代碼

合併成都團隊變更:Blob size計算、班級學生學年修正

jeff 4 年之前
父節點
當前提交
dcda789e06
共有 100 個文件被更改,包括 7117 次插入1541 次删除
  1. 3 1
      TEAMModelAPI/Controllers/WeatherForecastController.cs
  2. 4 4
      TEAMModelAPI/Properties/launchSettings.json
  3. 25 9
      TEAMModelAPI/Startup.cs
  4. 1 1
      TEAMModelAPI/TEAMModelAPI.csproj
  5. 68 5
      TEAMModelFunction/ActivityHttpTrigger.cs
  6. 42 0
      TEAMModelFunction/MonitorServicesBus.cs
  7. 11 1
      TEAMModelFunction/TriggerExam.cs
  8. 32 5
      TEAMModelOS.SDK/Extension/JwtAuthExtension.cs
  9. 6 1
      TEAMModelOS.SDK/Models/Cosmos/Api/OpenApi.cs
  10. 18 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Bloblog.cs
  11. 2 0
      TEAMModelOS.SDK/Models/Cosmos/Common/ItemInfo.cs
  12. 1 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Survey.cs
  13. 1 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Vote.cs
  14. 4 0
      TEAMModelOS.SDK/Models/Cosmos/School/ExamInfo.cs
  15. 2 0
      TEAMModelOS.SDK/Models/Cosmos/School/Paper.cs
  16. 40 9
      TEAMModelOS.SDK/Models/Cosmos/School/School.cs
  17. 1 1
      TEAMModelOS.SDK/Models/Cosmos/Student/Student.cs
  18. 2 0
      TEAMModelOS.SDK/Models/Cosmos/Teacher/Teacher.cs
  19. 5 5
      TEAMModelOS.sln
  20. 1 0
      TEAMModelOS/ClientApp/package.json
  21. 1 1
      TEAMModelOS/ClientApp/public/index.html
  22. 95 3
      TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html
  23. 19 3
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css
  24. 1 1
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js
  25. 28 0
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json
  26. 二進制
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf
  27. 二進制
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff
  28. 二進制
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2
  29. 1 1
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/billboard-lightbox.css
  30. 7 2
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/common.css
  31. 1 3
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/home-view.css
  32. 30 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/lesson-testReport.css
  33. 36 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/lesson-testReport.less
  34. 42 8
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-test.css
  35. 9 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-view.css
  36. 51 0
      TEAMModelOS/ClientApp/src/common/BaseAreaPicker.vue
  37. 17 1
      TEAMModelOS/ClientApp/src/common/BaseLayout.less
  38. 266 157
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  39. 1 2
      TEAMModelOS/ClientApp/src/common/EmptyData.vue
  40. 2 0
      TEAMModelOS/ClientApp/src/common/Loading.vue
  41. 55 12
      TEAMModelOS/ClientApp/src/common/UploadModal.vue
  42. 1 1
      TEAMModelOS/ClientApp/src/components/coursemgt/StudentList.vue
  43. 2 2
      TEAMModelOS/ClientApp/src/components/student-web/EventView/BillBoardandLightBox.vue
  44. 71 23
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReport.vue
  45. 168 50
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue
  46. 13 10
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperView.vue
  47. 20 13
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/QuesNaire.vue
  48. 7 6
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Vote.vue
  49. 3 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue
  50. 201 145
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeView.vue
  51. 2 2
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/MissionListCard.vue
  52. 1 0
      TEAMModelOS/ClientApp/src/css/site.css
  53. 2 2
      TEAMModelOS/ClientApp/src/locale/lang/en-US/schoolBaseInfo.js
  54. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/teachContent.js
  55. 3 3
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/schoolBaseInfo.js
  56. 8 2
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/settings.js
  57. 2 2
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/stuAccount.js
  58. 2 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/studentWeb.js
  59. 4 3
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/system.js
  60. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/teachContent.js
  61. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/totalAnalysis.js
  62. 3 3
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/schoolBaseInfo.js
  63. 8 2
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/settings.js
  64. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachContent.js
  65. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/totalAnalysis.js
  66. 3 1
      TEAMModelOS/ClientApp/src/router/routes.js
  67. 2 0
      TEAMModelOS/ClientApp/src/service/User.js
  68. 42 3
      TEAMModelOS/ClientApp/src/static/baseDataDefault.json
  69. 11 0
      TEAMModelOS/ClientApp/src/store/module/answerSheet.js
  70. 2 2
      TEAMModelOS/ClientApp/src/store/module/studentWeb.js
  71. 49 16
      TEAMModelOS/ClientApp/src/store/module/teachers.js
  72. 12 12
      TEAMModelOS/ClientApp/src/store/module/user.js
  73. 1 1
      TEAMModelOS/ClientApp/src/utils/blobTool.js
  74. 4407 0
      TEAMModelOS/ClientApp/src/utils/distpicker.js
  75. 2 0
      TEAMModelOS/ClientApp/src/utils/evTools.js
  76. 0 371
      TEAMModelOS/ClientApp/src/utils/items.json
  77. 2 0
      TEAMModelOS/ClientApp/src/utils/jquery.js
  78. 184 31
      TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue
  79. 2 2
      TEAMModelOS/ClientApp/src/view/answersheet/BaseSvgBg.vue
  80. 1 1
      TEAMModelOS/ClientApp/src/view/answersheet/SheetBaseInfo.vue
  81. 14 4
      TEAMModelOS/ClientApp/src/view/answersheet/SheetComplete.vue
  82. 348 335
      TEAMModelOS/ClientApp/src/view/answersheet/SheetObjective.vue
  83. 0 1
      TEAMModelOS/ClientApp/src/view/answersheet/SheetSubjective.vue
  84. 297 83
      TEAMModelOS/ClientApp/src/view/answersheet/index.vue
  85. 16 13
      TEAMModelOS/ClientApp/src/view/evaluation/bank/index.vue
  86. 7 7
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseExerciseList.vue
  87. 9 0
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseImport.vue
  88. 1 1
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreatePaper.vue
  89. 23 0
      TEAMModelOS/ClientApp/src/view/homepage/HomePage.less
  90. 103 77
      TEAMModelOS/ClientApp/src/view/homepage/HomePage.vue
  91. 0 2
      TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue
  92. 38 22
      TEAMModelOS/ClientApp/src/view/learnactivity/ManualCreate.vue
  93. 7 1
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.less
  94. 23 10
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.vue
  95. 7 1
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.less
  96. 32 26
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue
  97. 9 4
      TEAMModelOS/ClientApp/src/view/learnactivity/PaperScore.vue
  98. 1 1
      TEAMModelOS/ClientApp/src/view/learnactivity/Scoring.vue
  99. 5 0
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.less
  100. 0 0
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue

+ 3 - 1
TEAMModelAPI/Controllers/WeatherForecastController.cs

@@ -1,9 +1,10 @@
-using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Logging;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using TEAMModelOS.Filter;
 
 namespace TEAMModelAPI.Controllers
 {
@@ -24,6 +25,7 @@ namespace TEAMModelAPI.Controllers
         }
 
         [HttpGet]
+        [ApiToken]
         public IEnumerable<WeatherForecast> Get()
         {
             var rng = new Random();

+ 4 - 4
TEAMModelAPI/Properties/launchSettings.json

@@ -4,15 +4,15 @@
     "windowsAuthentication": false,
     "anonymousAuthentication": true,
     "iisExpress": {
-      "applicationUrl": "http://localhost:47420",
-      "sslPort": 44371
+      "applicationUrl": "http://localhost:4109",
+      "sslPort": 44304
     }
   },
   "profiles": {
     "IIS Express": {
       "commandName": "IISExpress",
       "launchBrowser": true,
-      "launchUrl": "swagger",
+      "launchUrl": "weatherforecast",
       "environmentVariables": {
         "ASPNETCORE_ENVIRONMENT": "Development"
       }
@@ -21,7 +21,7 @@
       "commandName": "Project",
       "dotnetRunMessages": "true",
       "launchBrowser": true,
-      "launchUrl": "swagger",
+      "launchUrl": "weatherforecast",
       "applicationUrl": "https://localhost:5001;http://localhost:5000",
       "environmentVariables": {
         "ASPNETCORE_ENVIRONMENT": "Development"

+ 25 - 9
TEAMModelAPI/Startup.cs

@@ -6,16 +6,17 @@ using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Hosting;
 using Microsoft.Extensions.Logging;
-using Microsoft.OpenApi.Models;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI;
 
 namespace TEAMModelAPI
 {
     public class Startup
     {
+        readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
         public Startup(IConfiguration configuration)
         {
             Configuration = configuration;
@@ -26,12 +27,29 @@ namespace TEAMModelAPI
         // This method gets called by the runtime. Use this method to add services to the container.
         public void ConfigureServices(IServiceCollection services)
         {
-
-            services.AddControllers();
-            services.AddSwaggerGen(c =>
+            //設定跨域請求
+            services.AddCors(options =>
             {
-                c.SwaggerDoc("v1", new OpenApiInfo { Title = "TEAMModelAPI", Version = "v1" });
+                options.AddPolicy(MyAllowSpecificOrigins,
+                builder =>
+                {
+                    builder.WithOrigins("http://teammodelos-test.chinacloudsites.cn",
+                                        "https://www.teammodel.cn", "https://localhost:5001",
+                                        "http://localhost:5000", "http://localhost:64524",
+                                        "https://localhost:44341", "https://localhost:8888", "http://localhost:8888")
+                    .AllowAnyHeader()
+                    .AllowAnyMethod();
+                });
             });
+            services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = false; });
+            services.AddAzureStorage(Configuration.GetValue<string>("Azure:Storage:ConnectionString"));
+            services.AddAzureRedis(Configuration.GetValue<string>("Azure:Redis:ConnectionString"));
+            services.AddAzureCosmos(Configuration.GetValue<string>("Azure:Cosmos:ConnectionString"));
+            services.AddMemoryCache();
+            services.AddSnowflakeId(Convert.ToInt64(Configuration.GetValue<string>("Option:LocationNum")), 1);
+            services.AddHttpClient();
+            services.AddHttpClient<DingDing>();
+            services.AddAzureServiceBus(Configuration.GetValue<string>("Azure:ServiceBus:ConnectionString"));
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -40,16 +58,14 @@ namespace TEAMModelAPI
             if (env.IsDevelopment())
             {
                 app.UseDeveloperExceptionPage();
-                app.UseSwagger();
-                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TEAMModelAPI v1"));
             }
 
             app.UseHttpsRedirection();
 
             app.UseRouting();
-
+            app.UseCors(MyAllowSpecificOrigins); //使用跨域設定
+            app.UseAuthentication();
             app.UseAuthorization();
-
             app.UseEndpoints(endpoints =>
             {
                 endpoints.MapControllers();

+ 1 - 1
TEAMModelAPI/TEAMModelAPI.csproj

@@ -5,7 +5,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
+    <ProjectReference Include="..\TEAMModelOS\TEAMModelOS.csproj" />
   </ItemGroup>
 
 </Project>

+ 68 - 5
TEAMModelFunction/ActivityHttpTrigger.cs

@@ -6,7 +6,6 @@ using Microsoft.Azure.WebJobs;
 using Microsoft.Azure.WebJobs.Extensions.Http;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
-using Newtonsoft.Json;
 using TEAMModelOS.SDK.DI;
 using Azure.Cosmos;
 using System.Text.Json;
@@ -117,7 +116,7 @@ namespace TEAMModelFunction
         {
             log.LogInformation("fix-exam-activity...");
             string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
-            List<string> datas = JsonConvert.DeserializeObject<List<string>>(requestBody);
+            List<string> datas = JsonSerializer.Deserialize<List<string>>(requestBody);
             var client = _azureCosmos.GetCosmosClient();
            
             var query = $"select  *  from c ";
@@ -214,7 +213,7 @@ namespace TEAMModelFunction
 
             log.LogInformation("fix-vote-activity...");
             string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
-            List<string> datas = JsonConvert.DeserializeObject<List<string>>(requestBody);
+            List<string> datas = JsonSerializer.Deserialize<List<string>>(requestBody);
             var client = _azureCosmos.GetCosmosClient();
 
             var query = $"select  *  from c ";
@@ -294,6 +293,7 @@ namespace TEAMModelFunction
             }
             return new OkObjectResult(new { });
         }
+
         /// <summary>
         /// 设置问卷调查未初始化学生列表的业务
         /// </summary>
@@ -307,7 +307,7 @@ namespace TEAMModelFunction
         {
             log.LogInformation("fix-survey-activity...");
             string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
-            List<string> datas = JsonConvert.DeserializeObject<List<string>>(requestBody);
+            List<string> datas = JsonSerializer.Deserialize<List<string>>(requestBody);
             var client = _azureCosmos.GetCosmosClient();
 
             var query = $"select  *  from c ";
@@ -398,7 +398,7 @@ namespace TEAMModelFunction
             ILogger log)
         {
             string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
-            dynamic json = JsonConvert.DeserializeObject<dynamic>(requestBody);
+            dynamic json = JsonSerializer.Deserialize<dynamic>(requestBody);
             string id = json.id;
             string code = json.code;
             if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(code)) {
@@ -470,5 +470,68 @@ namespace TEAMModelFunction
                 return new BadRequestResult();
             }
         }
+        /// <summary>
+        ///获取单个目录的大小,用于获取评测,试题,试卷,问卷,投票等 文件层级超过两层的文件。
+        ///例如 /exam/uuid/xxx  /item/uuid/xxx   /paper/uuid/xxx  /vote/uuid/xxx  /suervy/uuid/xxx
+        /// {"name":"hbcn","/item/uuid/xxx"}
+        /// </summary>
+        /// <param name="req"></param>
+        /// <param name="log"></param>
+        /// <returns></returns>
+        [FunctionName("get-prefixsize")]
+        public async Task<IActionResult> GetPrefixsize(
+            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
+            ILogger log)
+        {
+            try {
+                string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
+                var data = System.Text.Json.JsonSerializer.Deserialize<JsonElement>(requestBody);
+                if (data.TryGetProperty("name", out JsonElement name) && data.TryGetProperty("root", out JsonElement root))
+                {
+                    var size = await _azureStorage.GetBlobContainerClient($"{name}").GetBlobsSize($"{root}");
+                    return new OkObjectResult(new { size = size });
+                }
+                else
+                {
+                    return new BadRequestResult();
+                }
+            } catch (Exception ex) {
+                await _dingDing.SendBotMsg($"TEAMModelFunction,ActivityHttpTrigger,get-prefixsize()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
+                return new BadRequestResult();
+            }
+
+        }
+        /// <summary>
+        ///获取多个blob路径的文件大小
+        /// {"name":"hbcn","blobs":["/paper/uuid/xxx.json","/paper/uuid/aaa.json"]}
+        /// </summary>
+        /// <param name="req"></param>
+        /// <param name="log"></param>
+        /// <returns></returns>
+        [FunctionName("get-blobsize")]
+        public async Task<IActionResult> GetBlobsize(
+            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
+            ILogger log)
+        {
+            try { 
+                string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
+                var data = System.Text.Json.JsonSerializer.Deserialize<JsonElement>(requestBody);
+                if (data.TryGetProperty("name", out JsonElement name) && data.TryGetProperty("blobs", out JsonElement blob))
+                {
+                    List<string> blobs = JsonSerializer.Deserialize<List<string>>(blob.ToJsonString());
+                   var size= await _azureStorage.GetBlobContainerClient($"{name}").GetBlobsSize(blobs);
+                    return new OkObjectResult(new { size = size });
+                }
+                else {
+                    return new BadRequestResult();
+                }
+              
+            } catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"TEAMModelFunction,ActivityHttpTrigger,get-blobsize()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
+                return new BadRequestResult();
+            }
+        }
     }
+  
 }

+ 42 - 0
TEAMModelFunction/MonitorServicesBus.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
 using Azure.Cosmos;
@@ -143,6 +144,47 @@ namespace TEAMModelFunction
                 await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Blob()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
             }
         }
+        /// <summary>
+        /// 根据容器的根目录刷新redis并获取redis的最新使用情况
+        /// </summary>
+        /// <param name="msg"></param>
+        /// <returns></returns>
+        [FunctionName("BlobRoot")]
+        public async Task BlobRoot([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "blobroot", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
+        {
+            try
+            {
+                var jsonMsg = JsonDocument.Parse(msg);
+                if (jsonMsg.RootElement.TryGetProperty("name", out JsonElement name) && name.ValueKind == JsonValueKind.String
+                    && jsonMsg.RootElement.TryGetProperty("root", out JsonElement root) && root.ValueKind == JsonValueKind.String)
+                {
+                    List<Dictionary<string, double?>> list = new List<Dictionary<string, double?>>();
+                    string u = System.Web.HttpUtility.UrlDecode($"{root}", Encoding.UTF8).Split("/")[0];
+                    var client = _azureStorage.GetBlobContainerClient($"{name}");
+                    var size = await client.GetBlobsSize(u);
+                    await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{name}", u);
+                    await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{name}", u, size.HasValue ? size.Value : 0);
+                    var scores = await _azureRedis.GetRedisClient(8).SortedSetRangeByRankWithScoresAsync($"Blob:Catalog:{name}");
+                    double blobsize = 0;
+                    if (scores != default && scores != null)
+                    {
+                        foreach (var score in scores)
+                        {
+                            blobsize = blobsize + score.Score;
+                        }
+                    }
+                    await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", new RedisValue($"{name}"), new RedisValue($"{blobsize}"));
+
+                    await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Blob() 容器:{name}使用:{root},文件分类:{list.ToJsonString()}",
+                        GroupNames.成都开发測試群組);
+                }
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Blob()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
+            }
+        }
+
 
         /// <summary>
         /// 完善课程变更,StuListChange,  originCode是学校编码 则表示名单是学校自定义名单,如果是tmdid则表示醍摩豆的私有名单,scope=school,private。

+ 11 - 1
TEAMModelFunction/TriggerExam.cs

@@ -423,6 +423,16 @@ namespace TEAMModelFunction
                             info.standard = Math.Round(examResults[0].studentIds.Count > 0 ? Math.Pow(powSum / examResults[0].studentIds.Count, 0.5) : 0, 2);
                             double NewsRate = allScore > 0 ? Math.Round(NewsRateScore / allScore * 100, 2) : 0;
                             info.lostStu = losStu;
+                            /*//补充历史数据的容器名称
+                            if (string.IsNullOrEmpty(info.cn)) {
+                                if (info.scope.Equals("school"))
+                                {
+                                    info.cn = info.school;
+                                }
+                                else {
+                                    info.cn = info.creatorId;
+                                }
+                            }*/
                             //判断均分是否发生变化,便于实时的更新评测基本信息
                             if (info.sRate != NewsRate || info.average != NewsRateScore)
                             {
@@ -433,7 +443,7 @@ namespace TEAMModelFunction
                         }
                         catch (Exception e)
                         {
-                            await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-评测finish状态异常{e.Message}\n{e.StackTrace}", GroupNames.成都开发測試群組);
+                            await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测finish状态异常{e.Message}\n{e.StackTrace}", GroupNames.成都开发測試群組);
                         }
                         break;
                 }

+ 32 - 5
TEAMModelOS.SDK/Extension/JwtAuthExtension.cs

@@ -42,14 +42,18 @@ namespace TEAMModelOS.SDK.Extension
 
             return serializeToken;
         }
-        public static string CreateAppToken(string issuer, string id,  string salt, string schoolID = "", int expire = 1)
+        public static string CreateApiToken(string issuer, string id,  string salt,string  name , string schoolID = "", int expire = 1)
         {
+           
             // 設定要加入到 JWT Token 中的聲明資訊(Claims)  
             var payload = new JwtPayload {
-                { JwtRegisteredClaimNames.Iss, issuer }, //發行者
-                { JwtRegisteredClaimNames.Sub, id }, // 用戶ID                  
+                { JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者
+                { JwtRegisteredClaimNames.Sub, id }, // APPID sub: jwt所面向的用户
+                { JwtRegisteredClaimNames.Aud, "" }, // aud: 接收jwt的一方
                 { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話
-                { JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString()},  // 到期的時間,必須為數字
+                {JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString() },
+                { "name",name}, // 用戶的顯示名稱
+                //{ JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString()},  // 到期的時間,必須為數字
                 //{ "name",name}, // 用戶的顯示名稱
                 //{ "picture",picture}, // 用戶頭像
                 //{ "roles",roles}, // 登入者的角色,角色類型 (Admin、Teacher、Student) 
@@ -70,7 +74,30 @@ namespace TEAMModelOS.SDK.Extension
 
             return serializeToken;
         }
-
+        public static bool ValidateApiToken(string token, string salt)
+        {
+            try
+            {
+                var handler = new JwtSecurityTokenHandler();
+                var validationParameters = new TokenValidationParameters
+                {
+                    RequireExpirationTime = true,
+                    ValidateIssuer = false,
+                    ValidateAudience = false,
+                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
+                    //ValidateLifetime = false,
+                    //LifetimeValidator = LifetimeValidator,
+                    ClockSkew = TimeSpan.Zero
+                };
+                ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
+                return true;
+            }
+            catch (Exception)
+            {
+                //Trace.WriteLine(ex.Message);
+                return false;
+            }
+        }
         public static bool ValidateAuthToken(string token, string salt)
         {
             try

+ 6 - 1
TEAMModelOS.SDK/Models/Cosmos/Api/OpenApi.cs

@@ -26,7 +26,7 @@ namespace TEAMModelOS.SDK.Models
     {
         public OpenApi() {
 
-            PartitionKey = "OpenApi";
+            PartitionKey = "IES5-API";
         } 
         public string name { get; set; }
         public string url { get; set; }
@@ -36,11 +36,16 @@ namespace TEAMModelOS.SDK.Models
     }
 
     public class OpenApp : CosmosEntity {
+        public string icon { get; set; }
         public string name { get; set; }
         public string descr { get; set; }
         public List<string> apis { get; set; } = new List<string>();
         public string school { get; set; }
         public string token { get; set; }
+        /// <summary>
+        /// 0禁用,1正常,2 token封禁
+        /// </summary>
+        public int status { get; set; }
         public OpenApp()
         {
             pk = "OpenApp";

+ 18 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Bloblog.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models
+{
+    /// <summary>
+    /// 内容上传记录
+    /// </summary>
+    public class Bloblog :CosmosEntity
+    {
+        public string name { get; set; }
+        public string url { get; set; }
+        public string time { get; set; }
+        public long  size { get; set; }
+        public string period { get; set; }
+    }
+}

+ 2 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/ItemInfo.cs

@@ -30,5 +30,7 @@ namespace TEAMModelOS.SDK.Models
         //使用次数
         public int useCount { get; set; }
         public string blob { get; set; }
+        //记录试题大小
+        public long? size { get; set; } = 0;
     }
 }

+ 1 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Survey.cs

@@ -84,6 +84,7 @@ namespace TEAMModelOS.SDK.Models
         /// TTL删除改变状态使用
         /// </summary>
         public int? status { get; set; } = 0;
+        public long? size { get; set; } = 0;
     }
 
     /// <summary>

+ 1 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Vote.cs

@@ -103,6 +103,7 @@ namespace TEAMModelOS.SDK.Models
         /// TTL删除改变状态使用
         /// </summary>
         public int? status { get; set; } = 0;
+        public long? size { get; set; } = 0;
     }
     /// <summary>
     /// 投票选项

+ 4 - 0
TEAMModelOS.SDK/Models/Cosmos/School/ExamInfo.cs

@@ -89,6 +89,10 @@ namespace TEAMModelOS.SDK.Models
         //缺考人数
         public List<string> lostStu { get; set; } = new List<string>();
         public double standard { get; set; }
+        //记录该评测内容下blob大小
+        public long? size { get; set; } = 0;
+        //容器名称 container name
+        //public string cn { get; set; }
     }
     public class Custom {
         public string id { get; set; }

+ 2 - 0
TEAMModelOS.SDK/Models/Cosmos/School/Paper.cs

@@ -60,6 +60,8 @@ namespace TEAMModelOS.SDK.Models
         public double score { get; set; }
         public string scope { get; set; }
         public int multipleRule { get; set; }
+        //记录试卷大小
+        public long? size { get; set; } = 0;
         /// <summary>
         /// type:{
         ///     pointkey:[num1,num2....]

+ 40 - 9
TEAMModelOS.SDK/Models/Cosmos/School/School.cs

@@ -8,38 +8,69 @@ using TEAMModelOS.SDK.Context.Attributes.Azure;
 using TEAMModelOS.SDK.DI;
 
 namespace TEAMModelOS.SDK.Models
-{    
+{
     public class School : CosmosEntity
-    {        
+    {
         public School()
         {
             pk = "Base";
             timeZone = new TimeZone();
             period = new List<Period>();
         }
-        
+
+        /// <summary>
+        /// 学校编码
+        /// </summary>
         public string schoolCode { get; set; }
+        /// <summary>
+        /// 学校名称
+        /// </summary>
         public string name { get; set; }
+        /// <summary>
+        /// 学段
+        /// </summary>
         public List<Period> period { get; set; }
-        public List<Campus> campuses { get; set; }  
-        
+        /// <summary>
+        /// 校区
+        /// </summary>
+        public List<Campus> campuses { get; set; }
+        /// <summary>
+        /// 地区
+        /// </summary>
         public string region { get; set; }
         public string province { get; set; }
+        /// <summary>
+        /// 省份
+        /// </summary>
         public string city { get; set; }
+        /// <summary>
+        ///授权给 学校的Blob 容器空间大小 单位为G
+        ///1252748378/1024/1024/1024
+        ///1GB=1024MB,1MB=1024KB,1KB=1024B  存储最小单位为B字节
+        /// </summary>
         public int size { get; set; }
-
-
+        /// <summary>
+        /// 地址
+        /// </summary>
         public string address { get; set; }
+        /// <summary>
+        /// Logo
+        /// </summary>
         public string picture { get; set; }
-
+        /// <summary>
+        /// 时区
+        /// </summary>
         public TimeZone timeZone { get; set; }
         /// <summary>
         /// 1 普教,2 高职教
         /// </summary>
         public int type { get; set; }
+      
 
     }
-
+    /// <summary>
+    /// 课表计划
+    /// </summary>
     public class TimeTable
     {
         public string id { get; set; }

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/Student/Student.cs

@@ -15,7 +15,7 @@ namespace TEAMModelOS.SDK.Models
         public string schoolId { get; set; }
         public string pw { get; set; }
         public string salt { get; set; }
-        public string year { get; set; }
+        public int year { get; set; }
         //座位号
         public string no { get; set; }
         //绑定班级Id

+ 2 - 0
TEAMModelOS.SDK/Models/Cosmos/Teacher/Teacher.cs

@@ -12,12 +12,14 @@ namespace TEAMModelOS.SDK.Models
         public int size { get; set; }
         public string defaultSchool { get; set; }
         public List<School> schools { get; set; }
+       
 
         public class School
         {
             public string schoolId { get; set; }
             public string name { get; set; }
             public string status { get; set; }
+            public long time { get; set; }
         }
     }
 

+ 5 - 5
TEAMModelOS.sln

@@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TEAMModelGrpc", "TEAMModelG
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TEAMModelFunction", "TEAMModelFunction\TEAMModelFunction.csproj", "{78470113-6261-4F9A-9EF3-E315F060813D}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TEAMModelAPI", "TEAMModelAPI\TEAMModelAPI.csproj", "{DE4FED83-02BE-40B5-9F81-910DCFD00C61}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TEAMModelAPI", "TEAMModelAPI\TEAMModelAPI.csproj", "{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -35,10 +35,10 @@ Global
 		{78470113-6261-4F9A-9EF3-E315F060813D}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{78470113-6261-4F9A-9EF3-E315F060813D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{78470113-6261-4F9A-9EF3-E315F060813D}.Release|Any CPU.Build.0 = Release|Any CPU
-		{DE4FED83-02BE-40B5-9F81-910DCFD00C61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{DE4FED83-02BE-40B5-9F81-910DCFD00C61}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{DE4FED83-02BE-40B5-9F81-910DCFD00C61}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{DE4FED83-02BE-40B5-9F81-910DCFD00C61}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 1 - 0
TEAMModelOS/ClientApp/package.json

@@ -54,6 +54,7 @@
 		"svg-sprite-loader": "^5.0.0",
 		"unsplash-js": "^6.0.0",
 		"v-calendar": "^1.0.8",
+		"v-distpicker": "^1.2.12",
 		"video.js": "^7.12.1",
 		"videojs-contrib-hls": "^5.15.0",
 		"videojs-contrib-hls.js": "^3.2.0",

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

@@ -6,7 +6,7 @@
 		<meta name="viewport" content="width=device-width,initial-scale=1.0">
 		<link rel="icon" href="<%= BASE_URL %>favicon.ico">
 		<link id="theme" type="text/css" rel="stylesheet" href="<%= BASE_URL %>theme/dark-theme.css">
-		<title>IES5 云平台</title>
+		<title>醍摩豆云平台 TEAM Model Cloud</title>
 		<script>
 		MathJax = {
 		  loader: {load: ["input/tex", "output/svg"]},

+ 95 - 3
TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html

@@ -54,6 +54,30 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe603;</span>
+                <div class="name">手机未认证</div>
+                <div class="code-name">&amp;#xe603;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6b5;</span>
+                <div class="name">手机认证</div>
+                <div class="code-name">&amp;#xe6b5;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe64e;</span>
+                <div class="name">未认证</div>
+                <div class="code-name">&amp;#xe64e;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe68c;</span>
+                <div class="name">已认证</div>
+                <div class="code-name">&amp;#xe68c;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe62a;</span>
                 <div class="name">公式</div>
@@ -750,9 +774,9 @@
 <pre><code class="language-css"
 >@font-face {
   font-family: 'iconfont';
-  src: url('iconfont.woff2?t=1620811886189') format('woff2'),
-       url('iconfont.woff?t=1620811886189') format('woff'),
-       url('iconfont.ttf?t=1620811886189') format('truetype');
+  src: url('iconfont.woff2?t=1621999720250') format('woff2'),
+       url('iconfont.woff?t=1621999720250') format('woff'),
+       url('iconfont.ttf?t=1621999720250') format('truetype');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -778,6 +802,42 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont icon-phone-unverify"></span>
+            <div class="name">
+              手机未认证
+            </div>
+            <div class="code-name">.icon-phone-unverify
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-phone-verify"></span>
+            <div class="name">
+              手机认证
+            </div>
+            <div class="code-name">.icon-phone-verify
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-unverify"></span>
+            <div class="name">
+              未认证
+            </div>
+            <div class="code-name">.icon-unverify
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-verify"></span>
+            <div class="name">
+              已认证
+            </div>
+            <div class="code-name">.icon-verify
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont icon-formula"></span>
             <div class="name">
@@ -1822,6 +1882,38 @@
       <div class="content symbol">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-phone-unverify"></use>
+                </svg>
+                <div class="name">手机未认证</div>
+                <div class="code-name">#icon-phone-unverify</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-phone-verify"></use>
+                </svg>
+                <div class="name">手机认证</div>
+                <div class="code-name">#icon-phone-verify</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-unverify"></use>
+                </svg>
+                <div class="name">未认证</div>
+                <div class="code-name">#icon-unverify</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-verify"></use>
+                </svg>
+                <div class="name">已认证</div>
+                <div class="code-name">#icon-verify</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#icon-formula"></use>

+ 19 - 3
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 2000444 */
-  src: url('iconfont.woff2?t=1620811886189') format('woff2'),
-       url('iconfont.woff?t=1620811886189') format('woff'),
-       url('iconfont.ttf?t=1620811886189') format('truetype');
+  src: url('iconfont.woff2?t=1621999720250') format('woff2'),
+       url('iconfont.woff?t=1621999720250') format('woff'),
+       url('iconfont.ttf?t=1621999720250') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,22 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-phone-unverify:before {
+  content: "\e603";
+}
+
+.icon-phone-verify:before {
+  content: "\e6b5";
+}
+
+.icon-unverify:before {
+  content: "\e64e";
+}
+
+.icon-verify:before {
+  content: "\e68c";
+}
+
 .icon-formula:before {
   content: "\e62a";
 }

文件差異過大導致無法顯示
+ 1 - 1
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js


+ 28 - 0
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json

@@ -5,6 +5,34 @@
   "css_prefix_text": "icon-",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "21777109",
+      "name": "手机未认证",
+      "font_class": "phone-unverify",
+      "unicode": "e603",
+      "unicode_decimal": 58883
+    },
+    {
+      "icon_id": "10055797",
+      "name": "手机认证",
+      "font_class": "phone-verify",
+      "unicode": "e6b5",
+      "unicode_decimal": 59061
+    },
+    {
+      "icon_id": "1167192",
+      "name": "未认证",
+      "font_class": "unverify",
+      "unicode": "e64e",
+      "unicode_decimal": 58958
+    },
+    {
+      "icon_id": "3216607",
+      "name": "已认证",
+      "font_class": "verify",
+      "unicode": "e68c",
+      "unicode_decimal": 59020
+    },
     {
       "icon_id": "10352314",
       "name": "公式",

二進制
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf


二進制
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff


二進制
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2


+ 1 - 1
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/billboard-lightbox.css

@@ -112,7 +112,7 @@
   }
 }
 .dec {
-  margin-top: 10px;
+  margin-top: 20px;
 }
 .dec .referlink {
   color: #24b880;

+ 7 - 2
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/common.css

@@ -375,9 +375,14 @@ body,
 }
 .title-rect-name {
   font-size: 20px;
-  position: relative;
+  /* position: relative;
   top: -5px;
-  left: 10px;
+  left: 10px; */
+  border-left: 10px solid #24b880;
+  padding-left: 10px;
+  height: 20px;
+  line-height: 20px;
+  margin-bottom: 10px;
 }
 .base-info {
   text-align: right;

+ 1 - 3
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/home-view.css

@@ -175,9 +175,7 @@
 .home-view .calenderCard .title {
   font-weight: bolder;
 }
-.home-view .calenderCard .title-rect-name {
-  color: #515a6e;
-}
+
 .home-view .calenderCard .classtitle {
   font-size: 18px;
   /*font-family: Arial Rounded MT Bold;*/

+ 30 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/lesson-testReport.css

@@ -0,0 +1,30 @@
+.filterBtn .ivu-checkbox-group {
+  display: inline-block;
+}
+.filterBtn .ivu-checkbox-group .ivu-checkbox-wrapper {
+  height: 26px;
+  line-height: 26px;
+  border-radius: 4px;
+  font-weight: bolder;
+  border: 1px solid #c5c5c5;
+  padding: 0 10px;
+  margin-right: 10px;
+}
+.filterBtn .ivu-checkbox-group .ivu-checkbox-wrapper .ivu-checkbox {
+  display: none;
+}
+.filterBtn .ivu-checkbox-group .ivu-checkbox-wrapper-checked {
+  color: #fff;
+}
+.filterBtn .ivu-checkbox-group .ivu-checkbox-wrapper-checked:nth-child(1) {
+  background: #00ad6c;
+  border-color: #00ad6c;
+}
+.filterBtn .ivu-checkbox-group .ivu-checkbox-wrapper-checked:nth-child(2) {
+  background: #ff5508;
+  border-color: #ff5508;
+}
+.filterBtn .ivu-checkbox-group .ivu-checkbox-wrapper-checked:nth-child(3) {
+  background: #b7b7b7;
+  border-color: #b7b7b7;
+}

+ 36 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/lesson-testReport.less

@@ -0,0 +1,36 @@
+.filterBtn .ivu-checkbox-group {
+    display: inline-block;
+
+    .ivu-checkbox-wrapper {
+        height: 26px;
+        line-height: 26px;
+        border-radius: 4px;
+        font-weight: bolder;
+        border: 1px solid rgb(197, 197, 197);
+        padding: 0 10px;
+        margin-right: 10px;
+
+        .ivu-checkbox {
+            display: none;
+        }
+    }
+
+    .ivu-checkbox-wrapper-checked {
+        color: #fff;
+
+        &:nth-child(1) {
+            background: #00ad6c;
+            border-color: #00ad6c;
+        }
+
+        &:nth-child(2) {
+            background: #ff5508;
+            border-color: #ff5508;
+        }
+
+        &:nth-child(3) {
+            background: #b7b7b7;
+            border-color: #b7b7b7;
+        }
+    }
+}

+ 42 - 8
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-test.css

@@ -159,6 +159,7 @@
   height: 95.5vh;
   background-color: #ffffff;
   left: 0px;
+  font-size: 20px;
 }
 
 .lesson-test-pop .questionContent {
@@ -176,8 +177,8 @@
 .lesson-test-pop .questioDes {
     margin-top:20px;
     font-weight: 900;
-    font-size: 14px;
-    height:500px;
+    font-size: 20px;
+    /* height:500px; */
     overflow-y:scroll;
     /*border:2px solid red;*/
 }
@@ -192,7 +193,7 @@
 .lesson-test-pop .que-items {
     width: 100%;
     /*border:1px solid lightblue;*/
-    max-height: 200px;
+    /* max-height: 200px; */
     margin-left:10px;
     /*max-height: 200px;*/
     overflow-y: scroll;
@@ -203,11 +204,12 @@
 }
 .lesson-test-pop .answers{
     width: 100%;
+    margin-top: 20px;
 }
 .lesson-test-pop .answers-box {
     max-height: 400px;
     width: 100%;
-    height: 400px;
+    /* height: 400px; */
     overflow-y: scroll;
 }
 .lesson-test-pop .select-box {
@@ -235,14 +237,14 @@
 .compose-item {
     display: flex;
     margin-left: 10px;
-    max-height: 300px;
+    /* max-height: 300px; */
     overflow-y: scroll;
 }
 
 .compose-content {
     /*margin-top: 30px;*/
     width: 100%;
-    height: 200px;
+    /* height: 200px; */
     z-index: 0;
 }
 
@@ -341,6 +343,22 @@
   color: white;
   border: none;
 }
+.lesson-test-pop .analysis{
+  margin-top: 20px;
+  z-index: 2;
+  font-size: 20px;
+  transition: opacity 0.2s ease-in;
+  opacity: 0;
+}
+/* 滑出动效 */
+.lesson-test-pop .active{
+  opacity: 1;
+}
+.lesson-test-pop .pageCtl2 .disable{
+  background: #EEEEEE;
+  color: #ABABAB;
+  cursor: not-allowed;
+}
 .lesson-test-pop .checkAnswer {
     margin-top: 30px;
     min-height: 600px;
@@ -377,6 +395,19 @@
   background-color: #24b880 !important;
   border: none;
 }
+
+
+.lesson-test-pop .testButn .ivu-radio-wrapper-checked {
+    background: #24b880;
+}
+
+.lesson-test-pop .testButn .ivu-radio {
+    display: none;
+}
+
+
+
+
 .lesson-test-pop .testbg {
   z-index: 2;
   text-align: left;
@@ -509,7 +540,7 @@
     .compose-item {
         display: flex;
         margin-left: 10px;
-        max-height: 200px;
+        /* max-height: 200px; */
         overflow-y: scroll;
     }
     .compose-content {
@@ -605,8 +636,11 @@
     }
 }
 @media screen and (max-width: 767px) {
+    .lesson-test-pop .questionArea {
+        font-size: 18px;
+    }
     .lesson-test-pop .questioDes {
         overflow-y: scroll;
-        font-size: 12px;
+        font-size: 18px;
     }
 }

+ 9 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-view.css

@@ -29,6 +29,15 @@
   height: auto;
 }
 
+/* .lesson-test .title-rect-name {
+  border-left: 10px solid #24b880;
+  padding-left: 10px;
+  height: 20px;
+  line-height: 20px;
+  left: 0;
+  margin-bottom: 10px;
+} */
+
 
 .paper-tasks {
     border: 1px solid #919191;

+ 51 - 0
TEAMModelOS/ClientApp/src/common/BaseAreaPicker.vue

@@ -0,0 +1,51 @@
+<template>
+	<div class="">
+		<v-distpicker @province="onProvinceChange" @city="onCityChange" @area="onAreaChange"></v-distpicker>
+	</div>
+</template>
+<script>
+	import VDistpicker from 'v-distpicker'
+	export default {
+		name: 'BaseAreaPicker',
+		props: ['path', 'tips'],
+		components: {
+			VDistpicker
+		},
+		data() {
+			return {
+				pickResult: {
+					province: null,
+					city: null,
+					area: null
+				}
+			}
+		},
+		created() {
+			// console.log(this.top);
+		},
+		methods: {
+			onProvinceChange(val) {
+				this.pickResult.province = val.code ? val.value : null
+			},
+			onCityChange(val) {
+				this.pickResult.city = val.code ? val.value : null
+			},
+			onAreaChange(val) {
+				this.pickResult.area = val.code ? val.value : null
+			},
+		}
+	}
+</script>
+<style>
+	.distpicker-address-wrapper select {
+		background-color: #575757;
+		color: #cacaca;
+		margin: 5px 0;
+		font-size: 14px;
+		height: 35px;
+		border: 0;
+		display: inline-block;
+		position: relative;
+		outline: none;
+	}
+</style>

+ 17 - 1
TEAMModelOS/ClientApp/src/common/BaseLayout.less

@@ -28,6 +28,7 @@
         top: 70px;
         left: 0px;
         z-index: 999;
+        overflow: hidden;
         background: var(--header-bg);
     }
 
@@ -120,7 +121,7 @@
     margin-left: -4px;
 }
 .menu-item {
-    height: ~"calc(100% - 35px)";
+    height: ~"calc(100% - 60px)";
     user-select:none;
 }
 .collapse-icon-box {
@@ -183,4 +184,19 @@
     width: 118px;
     vertical-align: top;
     transition: width 0.1s ease 0.1s;
+}
+.copyright-info{
+    font-size: 12px;
+    text-align: center;
+    user-select: none;
+    line-height: 25px;
+    border-top: 1px solid #2c2f36;
+}
+.school-menu-tips{
+    color: #ff9900;
+    font-size: 12px;
+    padding-left: 28px;
+    min-height: 40px;
+    line-height: 30px;
+    white-space: nowrap;
 }

+ 266 - 157
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -3,7 +3,7 @@
         <!-- 头部菜单栏 -->
         <Header class="header">
             <div class="logo-wrap">
-                <img src="../assets/ies5.png" :class="isCollapsed ? 'collapsed-logo-width unit-logo':'collapsed-logo-width  unit-logo'" />
+                <img src="../assets/ies5.png" :class="isCollapsed ? 'collapsed-logo-width unit-logo':'collapsed-logo-width  unit-logo'" v-show="isShowLogo" />
             </div>
             <div class="school-wrap">
                 <BaseSelectSchool></BaseSelectSchool>
@@ -15,40 +15,83 @@
             <div class="collapse-icon-box" @click="changeMenuStatus">
                 <Icon :class="rotateIcon" custom="iconfont icon-arrow" style="color:var(--primary-text-color)" @click.stop="changeMenuStatus" size="12" />
             </div>
-            <Menu width="auto" :class="menuitemClasses" accordion :active-name="activeName" :open-names="openNames">
+            <Menu width="auto" :class="['menu-item', isCollapsed ? 'collapsed-menu' : '']" accordion :active-name="activeName" :open-names="openNames">
                 <vuescroll :ops="ops">
-                    <div v-for="(item,index) in menuTree" :key="index">
-                        <Submenu :name="item.subName" v-if="$access.ability(item.role,item.permission).validateAll && item.child.length" v-show="(index == 0 && $store.state.userInfo.hasSchool) || index > 0">
-                            <template slot="title">
+                    <MenuGroup title="学校">
+                        <!-- 暂未提供判断是否购买服务的字段 -->
+                        <p class="school-menu-tips" v-if="$store.state.userInfo.schoolPay && !isCollapsed">*当前学校暂未购买服务</p>
+                        <p class="school-menu-tips" v-else-if="!$store.state.userInfo.hasSchool && !isCollapsed">*暂未加入学校,无法使用学校功能</p>
+                        <div v-else-if="!$store.state.userInfo.schoolPay && $store.state.userInfo.hasSchool">
+                            <div v-for="(item,index) in schoolMenu" :key="index">
+                                <Submenu :name="item.subName" v-if="$access.ability(item.role,item.permission).validateAll && item.child.length" v-show="(index == 0 && $store.state.userInfo.hasSchool) || index > 0">
+                                    <template slot="title">
+                                        <Tooltip :content="item.name" placement="right" transfer v-show="isCollapsed">
+                                            <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="20" />
+                                        </Tooltip>
+                                        <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="20" />
+                                        <span>{{item.name}}</span>
+                                    </template>
+                                    <MenuItem class="sub-item-wrap sub-item-wrap-active" :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll">
+                                    <Tooltip :content="menuItem.name" placement="right" transfer v-show="isCollapsed">
+                                        <Icon class="sub-menu-icon" :custom="menuItem.icon" size="18" />
+                                    </Tooltip>
+                                    <Icon v-show="!isCollapsed" class="sub-menu-icon" :custom="menuItem.icon" size="18" />
+                                    <span>
+                                        {{menuItem.name}}
+                                        <span style="color: aqua;margin-left: 2px;font-size: 12px;vertical-align: text-top;">
+                                            {{menuItem.tag}}
+                                        </span>
+                                    </span>
+                                    </MenuItem>
+                                </Submenu>
+                                <MenuItem :name="item.menuName" v-else-if="$access.ability(item.role,item.permission).validateAll" :to="item.router">
                                 <Tooltip :content="item.name" placement="right" transfer v-show="isCollapsed">
-                                    <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="20" />
+                                    <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="22" />
                                 </Tooltip>
-                                <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="20" />
+                                <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="22" />
                                 <span>{{item.name}}</span>
-                            </template>
-                            <MenuItem class="sub-item-wrap sub-item-wrap-active" :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-if="$access.ability(menuItem.role,menuItem.permission).validateAll">
-                            <Tooltip :content="menuItem.name" placement="right" transfer v-show="isCollapsed">
-                                <Icon class="sub-menu-icon" :custom="menuItem.icon" size="18" />
-                            </Tooltip>
-                            <Icon v-show="!isCollapsed" class="sub-menu-icon" :custom="menuItem.icon" size="18" />
-                            <span>
-                                {{menuItem.name}}
-                                <span style="color: aqua;margin-left: 2px;font-size: 12px;vertical-align: text-top;">
-                                    {{menuItem.tag}}
+                                </MenuItem>
+                            </div>
+                        </div>
+                    </MenuGroup>
+                    <MenuGroup title="个人">
+                        <div v-for="(item,index) in teacherMenu" :key="index">
+                            <Submenu :name="item.subName" v-if="$access.ability(item.role,item.permission).validateAll && item.child.length" v-show="(index == 0 && $store.state.userInfo.hasSchool) || index > 0">
+                                <template slot="title">
+                                    <Tooltip :content="item.name" placement="right" transfer v-show="isCollapsed">
+                                        <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="20" />
+                                    </Tooltip>
+                                    <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="20" />
+                                    <span>{{item.name}}</span>
+                                </template>
+                                <MenuItem class="sub-item-wrap sub-item-wrap-active" :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll && menuItem.isShow">
+                                <Tooltip :content="menuItem.name" placement="right" transfer v-show="isCollapsed">
+                                    <Icon class="sub-menu-icon" :custom="menuItem.icon" size="18" />
+                                </Tooltip>
+                                <Icon v-show="!isCollapsed" class="sub-menu-icon" :custom="menuItem.icon" size="18" />
+                                <span>
+                                    {{menuItem.name}}
+                                    <span style="color: aqua;margin-left: 2px;font-size: 12px;vertical-align: text-top;">
+                                        {{menuItem.tag}}
+                                    </span>
                                 </span>
-                            </span>
+                                </MenuItem>
+                            </Submenu>
+                            <MenuItem :name="item.menuName" v-else-if="$access.ability(item.role,item.permission).validateAll && item.isShow" :to="item.router">
+                            <Tooltip :content="item.name" placement="right" transfer v-show="isCollapsed">
+                                <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="22" />
+                            </Tooltip>
+                            <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="22" />
+                            <span>{{item.name}}</span>
                             </MenuItem>
-                        </Submenu>
-                        <MenuItem :name="item.menuName" v-else-if="$access.ability(item.role,item.permission).validateAll" :to="item.router">
-                        <Tooltip :content="item.name" placement="right" transfer v-show="isCollapsed">
-                            <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="22" />
-                        </Tooltip>
-                        <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="22" />
-                        <span>{{item.name}}</span>
-                        </MenuItem>
-                    </div>
+                        </div>
+                    </MenuGroup>
+
                 </vuescroll>
             </Menu>
+            <p class="copyright-info" v-show="!isCollapsed">
+                ©2021 Powered by 醍摩豆
+            </p>
         </Sider>
         <!-- Body内容部分 -->
         <Layout :class="isCollapsed ?'collapsed-padding content-wrap':'content-wrap'">
@@ -69,18 +112,22 @@ export default {
                 bar: { opacity: 0 }
             },
             isCollapsed: false,
-            menuTree: []
+            menuTree: [],
+            schoolMenu: [],
+            teacherMenu: [],
+            isShowLogo: true
         }
     },
     methods: {
         initMenu() {
-            this.menuTree = [
-                // 智慧校园
+            //判断当前学校是否购买服务 暂未提供字段
+            this.schoolMenu = !this.$store.state.userInfo.schoolPay ? [
+                // 学校管理
                 {
                     icon: 'iconfont icon-school',
-                    name: this.$t('system.menu.smartSc'),
+                    name: this.$t('system.menu.schoolMgt'),
                     router: '',
-                    subName: 'smartSchool',
+                    subName: 'schoolMgt',
                     role: 'admin',
                     permission: 'schoolSetting-read|teacher-read|student-read|classroom-read|auth-read|course-read|syllabus-read|content-read|exercise-read|knowledge-read',
                     child: [
@@ -114,7 +161,7 @@ export default {
                             permission: 'student-upd|student-read',
                             menuName: 'studentAccount'
                         },
-                        // 教室管理
+                        // // 教室管理
                         {
                             icon: 'iconfont icon-class-mgt',
                             name: this.$t('system.menu.classMgt'),
@@ -143,24 +190,35 @@ export default {
                             role: 'admin',
                             permission: 'auth-read|auth-upd',
                             menuName: 'serviceDriveAuth'
-                        },
+                        }
+                    ]
+                },
+                // 学校资源
+                {
+                    icon: 'iconfont icon-textbook',
+                    name: this.$t('system.menu.schoolRes'),
+                    router: '',
+                    subName: 'schoolRes',
+                    role: 'admin|teacher',
+                    permission: 'schoolSetting-read|teacher-read|student-read|classroom-read|auth-read|course-read|syllabus-read|content-read|exercise-read|knowledge-read',
+                    child: [
                         // 校本课纲
-                        {
-                            icon: 'iconfont icon-syllabus',
-                            name: this.$t('system.menu.scSyllabus'),
-                            router: '/home/syllabus',
-                            tag: this.$t('system.menu.preview'),
-                            role: 'admin',
-                            permission: 'syllabus-read|syllabus-upd',
-                            menuName: 'syllabus'
-                        },
+                        // {
+                        //     icon: 'iconfont icon-syllabus',
+                        //     name: this.$t('system.menu.scSyllabus'),
+                        //     router: '/home/syllabus',
+                        //     tag: this.$t('system.menu.preview'),
+                        //     role: 'admin|teacher',
+                        //     permission: 'syllabus-read|syllabus-upd',
+                        //     menuName: 'syllabus'
+                        // },
                         // 校本内容
                         {
                             icon: 'iconfont icon-file',
                             name: this.$t('system.menu.scContent'),
                             router: '/home/schoolcontent',
                             tag: '',
-                            role: 'admin',
+                            role: 'admin|teacher',
                             permission: 'content-read|content-upd',
                             menuName: 'schoolcontent'
                         },
@@ -170,7 +228,7 @@ export default {
                             name: this.$t('system.menu.scQuBack'),
                             router: '/home/evaluation/schoolBank',
                             tag: '',
-                            role: 'admin',
+                            role: 'admin|teacher',
                             permission: 'exercise-read|exercise-upd',
                             menuName: 'schoolBank'
                         },
@@ -180,41 +238,12 @@ export default {
                             name: this.$t('system.menu.kdBack'),
                             router: '/home/knowledge',
                             tag: '',
-                            role: 'admin',
+                            role: 'admin|teacher',
                             permission: 'knowledge-read|knowledge-upd',
                             menuName: 'knowledge'
                         }
                     ]
                 },
-                // 统计分析
-                {
-                    icon: 'iconfont icon-analysis',
-                    name: this.$t('system.menu.staAna'),
-                    router: '',
-                    role: 'admin',
-                    subName: 'analysis',
-                    permission: 'analysis-read|scboard-read',
-                    child: [
-                        {
-                            icon: 'iconfont icon-xueqing',
-                            name: this.$t('system.menu.evAna'),
-                            router: '/totalIndex',
-                            tag: '',
-                            role: 'admin',
-                            permission: 'analysis-read',
-                            menuName: 'totalIndex'
-                        },
-                        {
-                            icon: 'iconfont icon-school-analysis',
-                            name: this.$t('system.menu.scAna'),
-                            router: '/home/scboard',
-                            tag: this.$t('system.menu.preview'),
-                            role: 'admin',
-                            permission: 'scboard-read',
-                            menuName: 'scboard'
-                        }
-                    ]
-                },
                 // 校园活动
                 {
                     icon: 'iconfont icon-activityS',
@@ -222,9 +251,7 @@ export default {
                     router: '',
                     role: 'admin',
                     permission: 'schoolAc-read|schoolAc-upd',
-                    // role: 'admin',
-                    // permission: '',
-                    subName:'scAc',
+                    subName: 'scAc',
                     child: [
                         {
                             icon: 'iconfont icon-test',
@@ -255,24 +282,95 @@ export default {
                         },
                     ]
                 },
-                // 课程教材
+                // 统计分析 暂时隐藏,只保留学情分析
+                // {
+                //     icon: 'iconfont icon-analysis',
+                //     name: this.$t('system.menu.staAna'),
+                //     router: '',
+                //     role: 'admin',
+                //     subName: 'analysis',
+                //     permission: 'analysis-read|scboard-read',
+                //     child: [
+                //         // 学情分析
+                //         {
+                //             icon: 'iconfont icon-xueqing',
+                //             name: this.$t('system.menu.evAna'),
+                //             router: '/totalIndex',
+                //             tag: '',
+                //             role: 'admin',
+                //             permission: 'analysis-read',
+                //             menuName: 'totalIndex'
+                //         },
+                //         // 校园分析
+                //         {
+                //             icon: 'iconfont icon-school-analysis',
+                //             name: this.$t('system.menu.scAna'),
+                //             router: '/home/scboard',
+                //             tag: this.$t('system.menu.preview'),
+                //             role: 'admin',
+                //             permission: 'scboard-read',
+                //             menuName: 'scboard'
+                //         }
+                //     ]
+                // },
+
+                // 学情分析
+                {
+                    icon: 'iconfont icon-xueqing',
+                    name: this.$t('system.menu.evAna'),
+                    router: '/totalIndex',
+                    tag: '',
+                    role: 'admin',
+                    permission: 'analysis-read',
+                    menuName: 'totalIndex',
+                    child: []
+                },
+
+            ] : []
+            this.teacherMenu = [
+                // 我的班级
+                {
+                    icon: 'iconfont icon-class-self',
+                    name: this.$t('system.menu.myClass'),
+                    router: '/home/manageClass',
+                    tag: '',
+                    role: 'teacher',
+                    permission: '',
+                    child: [],
+                    menuName: 'manageClass',
+                    isShow: this.$store.state.userInfo.hasSchool && this.$store.state.userInfo.isHeadmaster
+                },
+                // 我的课程
+                {
+                    icon: 'iconfont icon-course-self',
+                    name: this.$t('system.menu.myCus'),
+                    router: '/home/myCourse',
+                    tag: '',
+                    role: 'teacher',
+                    permission: '',
+                    child: [],
+                    menuName: 'myCourse',
+                    isShow: true
+                },
+                // 我的资源
                 {
                     icon: 'iconfont icon-textbook',
                     name: this.$t('system.menu.cusContent'),
                     router: '',
                     role: 'teacher',
                     permission: '',
-                    subName:'cusContent',
+                    subName: 'cusContent',
                     child: [
-                        {
-                            icon: 'iconfont icon-syllabus',
-                            name: this.$t('system.menu.prtSyllabus'),
-                            router: '/home/personalSyllabus',
-                            tag: this.$t('system.menu.preview'),
-                            role: 'teacher|admin',
-                            permission: '',
-                            menuName: 'personalSyllabus'
-                        },
+                        // {
+                        //     icon: 'iconfont icon-syllabus',
+                        //     name: this.$t('system.menu.prtSyllabus'),
+                        //     router: '/home/personalSyllabus',
+                        //     tag: this.$t('system.menu.preview'),
+                        //     role: 'teacher|admin',
+                        //     permission: '',
+                        //     menuName: 'personalSyllabus',
+                        //     isShow: true
+                        // },
                         {
                             icon: 'iconfont icon-file',
                             name: this.$t('system.menu.prtContent'),
@@ -280,7 +378,8 @@ export default {
                             tag: '',
                             role: 'teacher|admin',
                             permission: '',
-                            menuName: 'personalcontent'
+                            menuName: 'personalcontent',
+                            isShow: true
                         },
                         {
                             icon: 'iconfont icon-question-bank',
@@ -289,7 +388,8 @@ export default {
                             tag: '',
                             role: 'teacher|admin',
                             permission: '',
-                            menuName: 'personalBank'
+                            menuName: 'personalBank',
+                            isShow: true
                         }
                     ]
                 },
@@ -300,7 +400,7 @@ export default {
                     router: '',
                     role: 'teacher|admin',
                     permission: '',
-                    subName:'stuAc',
+                    subName: 'stuAc',
                     child: [
                         {
                             icon: 'iconfont icon-test',
@@ -309,7 +409,8 @@ export default {
                             tag: '',
                             role: 'teacher|admin',
                             permission: '',
-                            menuName: 'privateEvaluation'
+                            menuName: 'privateEvaluation',
+                            isShow: true
                         },
                         {
                             icon: 'iconfont icon-vote',
@@ -318,7 +419,8 @@ export default {
                             tag: '',
                             role: 'teacher|admin',
                             permission: '',
-                            menuName: 'personalVote'
+                            menuName: 'personalVote',
+                            isShow: true
                         },
                         {
                             icon: 'iconfont icon-questionnaire',
@@ -327,50 +429,33 @@ export default {
                             tag: '',
                             role: 'teacher|admin',
                             permission: '',
-                            menuName: 'personalSurvey'
+                            menuName: 'personalSurvey',
+                            isShow: true
                         },
-                        {
-                            icon: 'iconfont icon-learning-self',
-                            name: this.$t('system.menu.selfLearn'),
-                            router: '/home/SelfLearn',
-                            tag: this.$t('system.menu.preview'),
-                            role: 'teacher|admin',
-                            permission: '',
-                            menuName: 'selfLearn'
-                        },
-                        {
-                            icon: 'iconfont icon-hw',
-                            name: this.$t('system.menu.homework'),
-                            router: '/home/manageHomeWork',
-                            tag: this.$t('system.menu.preview'),
-                            role: 'teacher|admin',
-                            permission: '',
-                            menuName: 'manageHomeWork'
-                        }
+                        // 自主学习和作业活动暂时隐藏
+                        // {
+                        //     icon: 'iconfont icon-learning-self',
+                        //     name: this.$t('system.menu.selfLearn'),
+                        //     router: '/home/SelfLearn',
+                        //     tag: this.$t('system.menu.preview'),
+                        //     role: 'teacher|admin',
+                        //     permission: '',
+                        //     menuName: 'selfLearn',
+                        // isShow:true
+                        // },
+                        // {
+                        //     icon: 'iconfont icon-hw',
+                        //     name: this.$t('system.menu.homework'),
+                        //     router: '/home/manageHomeWork',
+                        //     tag: this.$t('system.menu.preview'),
+                        //     role: 'teacher|admin',
+                        //     permission: '',
+                        //     menuName: 'manageHomeWork',
+                        // isShow:true
+                        // }
                     ]
                 },
-                // 我的班级
-                {
-                    icon: 'iconfont icon-class-self',
-                    name: this.$t('system.menu.myClass'),
-                    router: '/home/manageClass',
-                    tag: '',
-                    role: 'teacher',
-                    permission: '',
-                    child: [],
-                    menuName: 'manageClass'
-                },
-                // 我的课程
-                {
-                    icon: 'iconfont icon-course-self',
-                    name: this.$t('system.menu.myCus'),
-                    router: '/home/myCourse',
-                    tag: '',
-                    role: 'teacher',
-                    permission: '',
-                    child: [],
-                    menuName: 'myCourse'
-                },
+
                 // 任务列表
                 {
                     icon: 'iconfont icon-task',
@@ -380,7 +465,8 @@ export default {
                     role: 'teacher',
                     permission: '',
                     child: [],
-                    menuName: 'taskList'
+                    menuName: 'taskList',
+                    isShow: this.$store.state.userInfo.hasSchool
                 }
             ]
         },
@@ -392,12 +478,10 @@ export default {
     computed: {
         rotateIcon() {
             return ["collapse-icon", this.isCollapsed ? "rotate-icon" : ""]
-        },
-        menuitemClasses() {
-            return ["menu-item", this.isCollapsed ? "collapsed-menu" : ""]
         }
     },
     created() {
+        console.log('权限',this.$access)
         this.initMenu()
         let cloudSetting = localStorage.getItem('cloudSetting')
         if (cloudSetting) {
@@ -405,24 +489,41 @@ export default {
             if (cloudSetting.menuStatus == 'close') {
                 this.isCollapsed = true
             }
+			this.isShowLogo = cloudSetting.logoStatus === 'open'
         }
     },
+    mounted() {
+        this.$EventBus.$off('onLogoStatusChange')
+        this.$EventBus.$on('onLogoStatusChange', val => {
+            this.isShowLogo = val === 'open'
+        })
+    },
     watch: {
         $route: {
             handler(val, oldval) {
-                if (this.menuTree.length == 0) {
+                if (this.schoolMenu.length == 0) {
                     this.initMenu()
                 }
-                console.log(val)
                 let metaName = val.meta.activeName
                 this.activeName = metaName
                 this.openNames = []
-                for (let i in this.menuTree) {
-                    if (this.menuTree[i].child.length) {
-                        for (let j in this.menuTree[i].child) {
-                            if (this.menuTree[i].child[j].menuName == metaName) {
+                for (let i in this.schoolMenu) {
+                    if (this.schoolMenu[i].child.length) {
+                        for (let j in this.schoolMenu[i].child) {
+                            if (this.schoolMenu[i].child[j].menuName == metaName) {
+                                this.activeName = metaName
+                                this.openNames.push(this.schoolMenu[i].subName)
+                                break
+                            }
+                        }
+                    }
+                }
+                for (let i in this.teacherMenu) {
+                    if (this.teacherMenu[i].child.length) {
+                        for (let j in this.teacherMenu[i].child) {
+                            if (this.teacherMenu[i].child[j].menuName == metaName) {
                                 this.activeName = metaName
-                                this.openNames.push(this.menuTree[i].subName)
+                                this.openNames.push(this.teacherMenu[i].subName)
                                 break
                             }
                         }
@@ -445,6 +546,17 @@ export default {
 @import "./BaseLayout.less";
 </style>
 <style lang="less">
+.biz-menu .ivu-menu-vertical .ivu-menu-item-group-title {
+    font-size: 12px;
+    line-height: 30px;
+    height: 30px;
+}
+.biz-menu .ivu-menu-item-group:first-child {
+    margin-top: 0px;
+}
+.biz-menu .ivu-menu-item-group {
+    margin-top: 10px;
+}
 .layout .ivu-layout-header {
     padding: 0px;
 }
@@ -466,24 +578,20 @@ export default {
 }
 
 .collapsed-menu span {
-    overflow: hidden;
-    text-overflow: ellipsis;
-    /* width: 118px; */
-}
-.collapsed-menu span {
-    width: 0px;
+    position: absolute;
+    opacity: 0;
     float: right;
-    transition: width 0.1s ease;
+    width: 0px;
 }
 .menu-item span {
     display: inline-block;
-    /* overflow: hidden; */
-    /* text-overflow: ellipsis; */
     white-space: nowrap;
     font-size: 16px;
-    /* width: 118px; */
+    position: absolute;
+    width: ~"calc(100% - 50px)";
+    max-width: 150px;
     vertical-align: top;
-    transition: width 0.1s ease 0.1s;
+    transition: width 0.2s;
     font-family: Roboto, -apple-system, BlinkMacSystemFont, Segoe UI,
         Microsoft JhengHei !important;
 }
@@ -518,6 +626,7 @@ export default {
     position: absolute;
     top: -5px;
     font-size: 12px;
+    opacity: 0.8;
     color: #1cc0f3;
 }
 

+ 1 - 2
TEAMModelOS/ClientApp/src/common/EmptyData.vue

@@ -48,8 +48,7 @@
     }
 
         .empty-container span {
-            font-size: 18px;
-            font-weight: bold;
+            font-size: 14px;
             color: #848484;
         }
 </style>

+ 2 - 0
TEAMModelOS/ClientApp/src/common/Loading.vue

@@ -2,6 +2,7 @@
     <div class="loading-container" :style="{'background': !hideMask ? bgColor : 'transparent'}">
         <div id="loadingBox" :style="{'margin-top':top+'px'}">
             <v-icon class="upload-loading-icon" :style="{'width':width+'px','height':width+'px'}" :iconClass="imgSrc" />
+			<p style="color: #aaaaaa;">加载中</p>
         </div>
     </div>
 </template>
@@ -82,6 +83,7 @@
         width: 100px;
         height: 100px;
         display:flex;
+		flex-direction: column;
         justify-content:center;
         align-items:center;
     }

+ 55 - 12
TEAMModelOS/ClientApp/src/common/UploadModal.vue

@@ -1,6 +1,8 @@
 <template>
-    <Modal v-model="uploadStatus" :ok-text="textLoading ? $t('updModal.uploading') : isComplete ? $t('updModal.complete'):$t('updModal.comfirmUpd')" :cancel-text="$t('updModal.cancelUpd')" :title="$t('teachContent.btnUpload')" class="upload-modal dark-iview-modal" width="660" :mask-closable="false" :closable="false" @on-ok="modalOk" @on-cancel="modalCancel" :loading="modalLoading">
+    <Modal v-model="uploadStatus" :ok-text="textLoading ? $t('updModal.uploading') : isComplete ? $t('updModal.complete'):$t('updModal.comfirmUpd')" :cancel-text="$t('updModal.cancelUpd')" :title="$t('teachContent.btnUpload')" class="upload-modal dark-iview-modal" width="800" :mask-closable="false" :closable="false" @on-ok="modalOk" @on-cancel="modalCancel" :loading="modalLoading">
         <div class="upload-file-box">
+            <!-- <p>上传到:{{pdInfo.filterPeriodName}}</p> -->
+            <ResBelong v-show="routerScope == 'school'" showLabel class="upd-to-pd" :pdId="pdId"></ResBelong>
             <Upload type="drag" action="" :show-upload-list="false" multiple :before-upload="customUpload" class="upload-wrap" :disabled="textLoading">
                 <Icon class="upload-icon" custom="iconfont icon-upload" v-show="!uploadedList.length" />
                 <p class="upload-text" :style="{marginTop: uploadedList.length ? '25px':'0px'}">
@@ -9,9 +11,9 @@
                 </p>
                 <p class="upload-text" style="font-size:12px;">{{$t('updModal.tips1')}}</p>
                 <p class="upload-text" :style="{fontSize:'12px',marginBottom: uploadedList.length ? '25px':'50px'}">
-                    {{$t('updModal.tips2')}}
-                    <Icon custom="iconfont icon-convert" size="12" class="is-parse-htex" />
-                    {{$t('updModal.tips3')}}
+                    <!-- {{$t('updModal.tips2')}}
+                    <Icon custom="iconfont icon-convert" size="12" class="is-parse-htex" /> -->
+                    * {{$t('updModal.tips3')}}
                 </p>
             </Upload>
             <div class="upload-file-box">
@@ -44,15 +46,20 @@
                         <span class="upload-info-wrap">
                             {{getSizeByBytes(item.loadedBytes)+'/'+getSizeByBytes(item.size)}}
                         </span>
-                        <span v-if="item.extension == 'PPTX'" class="upload-info-wrap parse-label" @click="item.isParse = !item.isParse" :style="{color:item.isParse ? '#1cc0f3':'#808080'}">
+                        <!-- <span v-if="item.extension == 'PPTX'" class="upload-info-wrap parse-label" @click="item.isParse = !item.isParse" :style="{color:item.isParse ? '#1cc0f3':'#808080'}">
                             <Icon class="is-parse-htex" size="12" custom="iconfont icon-convert" />
                             {{$t('updModal.resolve')}}
-                        </span>
+                        </span> -->
+                        <!-- pptx是否转换 -->
+                        <Checkbox class="upload-info-wrap parse-label" v-if="item.extension == 'PPTX'" v-model="item.isParse">
+                            {{$t('updModal.resolve')}}
+                        </Checkbox>
                         <Progress style="top:-10px;" v-if="item.status == 0" :percent="item.loadedBytes * 100 / item.size" status="active" stroke-color="#1CC0F3" :stroke-width="2" hide-info />
                     </div>
-                    <div class="upload-item-right">
+                    <!-- 暂时去掉删除功能 -->
+                    <!-- <div class="upload-item-right">
                         <Icon type="ios-close" class="delete-btn" color="red" size="30" style="float:right;" @click="deleteFile(index)" />
-                    </div>
+                    </div> -->
                 </div>
             </div>
         </div>
@@ -60,8 +67,12 @@
 
 </template>
 <script>
-import BlobTool from '@/utils/blobTool.js';
+import BlobTool from '@/utils/blobTool.js'
+import ResBelong from '@/view/teachcontent/ResBelong.vue'
 export default {
+    components: {
+        ResBelong
+    },
     data() {
         return {
             uploadedList: [],
@@ -117,6 +128,11 @@ export default {
                 return []
             },
             type: Array
+        },
+        //资源所属学段
+        pdId: {
+            default: '',
+            type: String
         }
     },
     methods: {
@@ -365,7 +381,7 @@ export default {
                 err => {
                     console.log(this.$t('updModal.compressImgErr'))
                 }
-            ).finally(()=>{
+            ).finally(() => {
                 this.counterReduce()
             })
         },
@@ -374,7 +390,6 @@ export default {
             let n = file.name.substring(0, file.name.lastIndexOf('.'))
             let dataUrl = await this.$jsFn.createVideoPoster(file.url + this.sasString, file.name, 0.1)
             let f = this.$jsFn.dataURLtoFile(dataUrl, n + '.png')
-            console.log(f)
             this.containerClient.upload(f, 'thum').then(
                 res => {
                     console.log(this.$t('updModal.posterOk'))
@@ -382,7 +397,7 @@ export default {
                 err => {
                     console.log(this.$t('updModal.posterErr'))
                 }
-            ).finally(()=>{
+            ).finally(() => {
                 this.counterReduce()
             })
         }
@@ -443,6 +458,9 @@ export default {
 
 </script>
 <style scoped>
+.upd-to-pd{
+    margin-bottom: 10px;
+}
 .upload-text {
     margin: 10px 0px;
     font-size: 24px;
@@ -505,8 +523,33 @@ export default {
     cursor: pointer;
     font-size: 12px;
     user-select: none;
+    color: white;
 }
+
 .is-parse-htex {
     vertical-align: baseline;
 }
 </style>
+<style>
+.parse-label .ivu-checkbox-inner {
+    background: transparent;
+    width: 14px;
+    height: 14px;
+    border-color: #909090;
+}
+.parse-label .ivu-checkbox-checked .ivu-checkbox-inner:after {
+    content: "";
+    display: block;
+    width: 8px;
+    height: 13px;
+    border-right: 2px solid #fff;
+    border-bottom: 2px solid #fff;
+    transform: rotate(35deg);
+    position: absolute;
+    top: -4px;
+    left: 3px;
+    border-radius: 0;
+    background-color: initial;
+    border-color: #0094ff;
+}
+</style>

+ 1 - 1
TEAMModelOS/ClientApp/src/components/coursemgt/StudentList.vue

@@ -17,7 +17,7 @@
             <!-- 字串模糊搜尋 -->
             <Input v-model="searchText" clearable :placeholder="$t('stuAccount.searchHolder')" style="width: 220px;margin-left:20px;" search @on-search="filterData" @on-clear="filterData"></Input>
         </div>
-        <div class="sc-content dark-iview-table" style="position:relative">
+        <div class="dark-iview-table" style="position:relative">
             <Scroll :on-reach-bottom="scrollLoad" height="600" :distance-to-edge="[15,15]">
                 <Table ref="stuSelection" :columns="tableColumns" :data="tableShowData" @on-selection-change="getSelectInfo">
                     <template slot-scope="{ row,index }" slot="status">

+ 2 - 2
TEAMModelOS/ClientApp/src/components/student-web/EventView/BillBoardandLightBox.vue

@@ -1,14 +1,14 @@
 <template>
     <div class="billboard-and-LightBox">
         <div class="title-rect-group">
-            <div class="title-rect" />
+            <!-- <div class="title-rect" /> -->
             <h2 class="title-rect-name">{{$t('studentWeb.billboard.description')}}</h2>
         </div>
         <div class="dec">
             <p><span v-html="activityData.description"></span></p>
         </div>
         <div class="title-rect-group" v-if="this.$store.getters.getItemTitle.eventType  === 'vote'">
-            <div class="title-rect" />
+            <!-- <div class="title-rect" /> -->
             <h2 class="title-rect-name">{{$t("studentWeb.vote.voteRecord")}}</h2>
         </div>
         <div class="dec" v-if="this.$store.getters.getItemTitle.eventType == 'vote'">

+ 71 - 23
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReport.vue

@@ -5,7 +5,9 @@
                 <svg-icon icon-class="handonHint" class="warm-icon" />
                 <span class="warm-hint">{{ $t("studentWeb.exam.timeoutHint") }}</span>
             </div>
-            <span v-show="$store.getters.getItemTitle.progress != 'finish' && testState == 1" @click="showTest" style="color: #03966a;width: 100%;cursor: pointer;font-size:18px;font-weight: 800;text-align: center">{{$t("studentWeb.exam.report.anwser")}}</span>
+            <span v-show="$store.getters.getItemTitle.progress != 'finish' && testState == 1" @click="showTest" style="color: #03966a;width: 100%;cursor: pointer;font-size:18px;font-weight: 800;text-align: center">
+                {{$t("studentWeb.exam.report.anwser")}}
+            </span>
             <h4 v-show='testState == 2'>{{$t("studentWeb.exam.report.noRes")}}</h4>
             <Row :gutter="20" v-if='testState == 3'>
                 <i-col :xs="24" :sm="24" :md="24" :lg="12">
@@ -14,7 +16,7 @@
                             <Card class="score-card">
                                 <p class="card-title">{{$t('studentWeb.exam.score')}}</p>
                                 <div class="card-content">
-                                    <span class="myscore">{{testScore}}</span> / 100
+                                    <span class="myscore">{{testScore}}</span> / {{ paperInfo.score }}
                                 </div>
                             </Card>
                         </i-col>
@@ -69,11 +71,22 @@
         </div>
         <div class="QAsheet" v-if='testState != 1'>
             <div class='title-rect-group '>
-                <div class="title-rect" />
                 <h2 class="title-rect-name" @click="checkedAnsFilter">{{$t("studentWeb.exam.report.answerBack")}}</h2>
             </div>
             <div class="filterBtn">
-                <label class="checkAns">
+                <CheckboxGroup v-model="checkedAns">
+                    <Checkbox label="right">
+                        {{$t("studentWeb.exam.report.right")}}: {{rightAns.right}}
+                    </Checkbox>
+                    <Checkbox label="wrong">
+                        {{$t("studentWeb.exam.report.wrong")}}: {{rightAns.wrong}}
+                    </Checkbox>
+                    <Checkbox label="noAns">
+                        {{$t("studentWeb.exam.report.noScore")}}: {{rightAns.noAns}}
+                    </Checkbox>
+                </CheckboxGroup>
+                
+                <!-- <label class="checkAns">
                     <input type="checkbox" value="right" v-model="checkedAns" />
                     <span>{{$t("studentWeb.exam.report.right")}}: {{rightAns.right}}</span>
                     <div class="rightBtn"></div>
@@ -87,17 +100,20 @@
                     <input type="checkbox" value="noAns" v-model="checkedAns" />
                     <span>{{$t("studentWeb.exam.report.noScore")}}: {{ rightAns.noAns}}</span>
                     <div class="noAnsBtn"></div>
-                </label>
-            </div>
-            <div @click="closeDetail">
+                </label> -->
                 <svg-icon icon-class="AnsWerDetail" :class="{ ansDetail: !closeAnsDetail, closeAnsDetail: closeAnsDetail,}" />
+                <button :class="['wrong-exercises', rightAns.wrong != 0 ? 'wrong' : 'nowrong']" @click="showTest">
+                    {{$t("studentWeb.exam.report.wrongPractice")}}
+                </button>
             </div>
+            
             <br style="clear:both" />
             <div class="qcontent" ref="qcontent" v-if="paperData.length">
                 <div class="qcol"
                      v-for="(question, index) in paperData"
                      v-show="checkedAnsFilter(index)"
                      :key="index">
+                     <!-- 题目 -->
                     <Row :gutter="10">
                         <i-col :xs="1" :sm="1" :md="1" :lg="1">
                             <div class="qAnsCondition">
@@ -143,19 +159,21 @@
                     <div class="qAnaly" :class="{ hideqAnaly: closeAnsDetail }">
                         <div class="rightAns">
                             <div class="qAnserlist">
-                                <div v-for="(item,index) in question.option" style="display:flex;margin-top:5px;">
+                                <div v-for="(item,index) in question.option" :key="index" style="display:flex;margin-top:5px;">
                                     ({{item.code}})<div style="margin-left:10px" v-html="item.value"></div>
                                 </div>
+                                <!-- 作答结果 -->
                                 <div class="TitleRec1"><span style="margin:5px;color:#1472c7">{{$t("studentWeb.exam.report.ansRes")}}:</span></div>
                                 <br />
                                 <div v-if="ansData[index]" style="margin-left:10px" v-html="ansData[index].length > 0 ? ansData[index][0] : $t('studentWeb.exam.report.noAns')"></div>
                             </div>
                         </div>
+                        <!-- 参考答案、解析 -->
                         <div class="rightAnalys">
                             <div class="TitleRec2"><span style="margin-left:5px">{{$t("studentWeb.exam.report.testAns")}}:</span></div>
                             <br />
                             <div style="display:flex">
-                                <div v-for="(item,iundex) in question.answer" v-html="item" style="margin-left:10px;"></div>
+                                <div v-for="(item,index) in question.answer" :key="index" v-html="item" style="margin-left:10px;"></div>
                             </div>
                             <div class="TitleRec2"><span style="margin-left:5px">{{$t("studentWeb.exam.report.testAnalyse")}}:</span></div>
                             <br />
@@ -189,12 +207,12 @@
                                                         <div style="width:100%">
                                                             <span style="margin-right:10px;">
                                                                 <Icon v-if="item.fileType == 'zip'" custom="iconfont icon-zip" size="20" />
-                                                                <Icon v-else-if="item.fileType == 'zip'" color="#8199AF" custom="iconfont icon-zip" size="20" />
+                                                                <!-- <Icon v-else-if="item.fileType == 'zip'" color="#8199AF" custom="iconfont icon-zip" size="20" /> -->
                                                                 <Icon v-else-if="item.fileType == 'pdf'" color="#FF6464" custom="iconfont icon-pdf" size="20" />
                                                                 <Icon v-else-if="item.fileType == 'ppt'|| item.fileType == 'pptx'" color="#FF8976" custom="iconfont icon-ppt" size="20" />
                                                                 <Icon v-else-if="item.fileType == 'mp3'" color="#FF5562" custom="iconfont icon-mp3" size="20" />
                                                                 <Icon v-else-if="item.fileType == 'mp4'" color="#8E4C9E" custom="iconfont icon-video1" size="20" />
-                                                                <Icon v-else-if="item.fileType == 'zip'" custom="iconfont icon-video1" size="20" />
+                                                                <!-- <Icon v-else-if="item.fileType == 'zip'" custom="iconfont icon-video1" size="20" /> -->
                                                                 <Icon v-else-if="item.fileType == 'doc'||item.fileType =='docx'" color="#6CCBFF" custom="iconfont icon-word" size="20" />
                                                                 <Icon v-else-if="item.fileType == 'csv'||item.fileType =='xlsx'||item.fileType =='xls'" color="#25C273" custom="iconfont icon-xlsx" size="20" />
                                                                 <Icon v-else-if="item.fileType == 'jpg'||item.fileType =='png'||item.fileType =='jpeg'" color="#30D1CA" custom="iconfont icon-jpg" size="20" />
@@ -219,6 +237,7 @@
                 </div>
             </div>
         </div>
+        <!-- 补救资源 -->
         <Modal v-model="previewStatus" footer-hide width="65%" @on-cancel="closePreview">
             <p slot="header" 
                style="color:#f60;text-align:center">
@@ -288,8 +307,8 @@
                 //loading畫面
                 closeAnsDetail: false,
                 checkedAns: ["right", "wrong", "noAns"],
-                testState: 0,
-                paperData: [],
+                testState: 0,// 表示有没有作答
+                paperData: [], //所有题目信息
                 ansData: [],
                 repairSource: {
                     normal: [],
@@ -388,6 +407,7 @@
             },
             showTest() {
                 if (this.examInfo.subject !== undefined) {
+                    console.log(this.examInfo);
                     this.$store.commit("ToggleLessonTestPopWithSubject", this.examInfo)
                 }
             },
@@ -427,8 +447,8 @@
                 if (data !== undefined) {
                     let codes = this.$store.getters.getItemTitle
                     let code = {
-                        scope: this.$store.getters.getExamInfo.scope,
-                        code: codes.scope == 'school' ? codes.school : codes.creatorId,
+                        scope: codes.scope,
+                        code: codes.scope === 'school' ? codes.school : codes.creatorId,
                         blob: data
                     }
                     let blob = this.formUrl(code)
@@ -452,7 +472,7 @@
                 }
                 return a 
             },
-           async formPaper() {
+            async formPaper() {
                 let paper = []
                 this.paperData.length = 0
                 this.ansData.length = 0
@@ -524,7 +544,8 @@
                     info = {
                         all: this.examInfo.stuScore.length,
                         right: 0,
-                        noAns:0
+                        noAns:0,
+                        wrong:0,
                     }
                     if (this.paperData[0]!= undefined) {
                         for (let i = 0; i < this.examInfo.stuScore.length; i++) {
@@ -532,6 +553,8 @@
                                 info.noAns++
                             } else if (this.examInfo.stuScore[i] == this.paperData[i].score && this.examInfo.stuScore[i] != -1) {
                                 info.right++
+                            } else {
+                                info.wrong++
                             }
                         }
                     }
@@ -562,6 +585,10 @@
     };
 </script>
 
+<style>
+    @import "~@/assets/student-web/component_styles/lesson-testReport.css";
+</style>
+
 <style scoped>
     .lesson-test-report {
         min-height: 600px;
@@ -580,9 +607,9 @@
         padding: 44px 50px;
     }
 
-        .scoreboard .ivu-card {
-            margin-bottom: 20px;
-        }
+    .scoreboard .ivu-card {
+        margin-bottom: 20px;
+    }
 
     .card-title {
         font-size: 16px;
@@ -764,9 +791,30 @@
 
     /**對問題進行篩選 */
     .filterBtn {
-        display: inline-block;
+        /* display: inline-block; */
     }
 
+    .filterBtn .wrong-exercises{
+        /* border: 1px solid #515A6E; */
+        border: none;
+        border-radius: 4px;
+        padding: 0 10px;
+        height: 26px;
+        color: white;
+        margin-right: 25px;
+        font-weight: bolder;
+        float: right;
+    }
+    .filterBtn .wrong{
+        background: #FF5508;
+        cursor: pointer;
+    }
+    .filterBtn .nowrong{
+        background: #b7b7b7;
+        cursor: not-allowed;
+    }
+
+
     .checkAns {
         display: inline-block;
         margin-left: 10px;
@@ -832,8 +880,8 @@
         float: right;
         height: 28px;
         width: 28px;
-        margin-top: -40px;
-        margin-bottom: -40px;
+        /* margin-top: -40px;
+        margin-bottom: -40px; */
         color: #03966a;
         cursor: pointer;
     }

+ 168 - 50
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue

@@ -49,14 +49,15 @@
                 <svg-icon icon-class="logout" />
             </span>
             <span class="testTitleText">{{$t("studentWeb.home.exam")}}:{{ $store.getters.getItemTitle.name }}</span>
-            <div class="myProgressBar">
+            <div class="myProgressBar" v-if="!isWrong">
                 <span class="myTestProgresstitle">{{$t("studentWeb.exam.testpop.completion")}}</span>
                 <Progress style="margin-top:15px" :percent="completeRate" />
             </div>
-            <button v-if="closeTest" class="submitBtn" @click="openWarmMessage(2)" :class="{ hintClick:hintHandon() }">{{$t("studentWeb.exam.testpop.submitted")}}</button>
+            <button v-if="closeTest && !isWrong" class="submitBtn" @click="openWarmMessage(2)" :class="{ hintClick:hintHandon() }">{{$t("studentWeb.exam.testpop.submitted")}}</button>
             <button v-if="!closeTest" class="submitBtn" :class="{ hintClick:hintHandon()  }">{{$t("studentWeb.exam.testpop.finish")}}</button>
         </div>
         <Row :gutter="30">
+            <!-- 题干 -->
             <i-col class="questionArea"
                    :xs="24"
                    :sm="24"
@@ -71,17 +72,17 @@
                         </Tooltip>
                     </span>
                     <div class="questioDes">
-                        <div class="questionType" v-if="getQue(queNo).parent == undefined">
+                        <div class="questionType" v-if="!getQue(queNo).parent">
                             <span>{{getTestType(getQue(queNo).type)}}</span>
                         </div>
-                        <div class="que-item" v-if="getQue(queNo).type != 'compose' && getQue(queNo).parent == undefined">
+                        <div class="que-item" v-if="getQue(queNo).type != 'compose' && !getQue(queNo).parent">
                             <span>{{ queNo +1 }}.</span>
                             <!--题目渲染-->
                             <div id="answer-box" v-html="getQue(queNo).question"></div>
                         </div>
                         <!--综合题-->
-                        <div v-if="getQue(queNo).type == 'compose' || getQue(queNo).parent != undefined">
-                            <div class="compose-content" v-if="getQue(queNo).parent !== undefined">
+                        <div v-if="getQue(queNo).type == 'compose' || getQue(queNo).parent">
+                            <div class="compose-content" v-if="getQue(queNo).parent">
                                 <div class="questionType">
                                     <span>{{getTestType(getQue(queNo).parentInfo.type)}}</span>
                                 </div>
@@ -111,6 +112,12 @@
                             </div>
                             <!--判断题选项-->
                             <div v-if="getQue(queNo).type == 'judge'" align="center">
+                                <!-- <div class="testButn">
+                                    <Radio-group v-model="checkers[queNo][0]">
+                                        <Radio label="A"><Icon type="md-checkmark" /></Radio>
+                                        <Radio label="B"><Icon type="md-close" /></Radio>
+                                    </Radio-group>
+                                </div> -->
                                 <label class="testBtn yesNoBtn">
                                     <input type="radio" value="A" v-model="checkers[queNo][0]" :disabled="!closeTest" />
                                     <div class="testbg">
@@ -145,6 +152,26 @@
                             </div>
                         </div>
                     </div>
+                    <!-- <div :style="isCheckAns ? 'height: 250px' : ''"></div> -->
+                    <!-- 答案解析 -->
+                    <div v-if="isWrong" :class="['analysis', isCheckAns && checkers[queNo].length > 0 ? 'active' : '']">
+                        <div>
+                            <div class="questionNo">{{$t("studentWeb.exam.report.ansRes")}}</div>
+                            <div v-for="(item, index) in checkers[queNo]" :key="index" v-html="item"></div>
+                        </div>
+                        <div>
+                            <div class="questionNo">{{$t("studentWeb.exam.report.testAns")}}</div>
+                            <div v-for="(item, index) in examInfo[queNo].answer" :key="index" v-html="item"></div>
+                        </div>
+                        <div>
+                            <div class="questionNo">{{$t("studentWeb.exam.report.testAnalyse")}}</div>
+                            <div v-html="examInfo[queNo].explain != '' ? examInfo[queNo].explain : $t('studentWeb.exam.report.noAnalyse')"></div>
+                        </div>
+                        <div>
+                            <div class="questionNo">{{$t("studentWeb.exam.report.repairSource")}}</div>
+                            <div v-html="examInfo[queNo].repair.length != 0 ? examInfo[queNo].repair : $t('studentWeb.exam.report.noSource')"></div>
+                        </div>
+                    </div>
                 </div>
             </i-col>
             <!--答题卡-->
@@ -159,19 +186,29 @@
                     <br />
                     <span style="margin-top:10px;font-weight:800">{{$t("studentWeb.exam.testpop.qNo")}}</span>
                     <div class="que-box">
-                        <div v-for="(item,index) in examInfo" :class="[checkers[index].length > 0 ? 'has-ans':'ans-box',index == queNo ?'select-item':'']" @click="gototheQues(index +1)">
+                        <div v-for="(item,index) in examInfo" :key="index"
+                             @click="gototheQues(index +1)"
+                             :class="[(checkers[index] && checkers[index].length > 0) ? 'has-ans':'ans-box',index == queNo ?'select-item':'']">
                             <span style="padding:5px 5px;cursor:pointer"> {{ item.parent == undefined ? index +1 : item.paperIndex }}</span>
                         </div>
                     </div>
                 </div>
                 <!--切換頁-->
                 <div class="pageCtl2">
-                    <button @click="preQ()" v-show="queNo != 0">
+                    <button @click="preQ()" :disabled="queNo == 0" :class="{disable: queNo == 0}">
                         <Icon type="ios-arrow-back" />{{$t("studentWeb.exam.testpop.previous")}}
                     </button>
+                    <button @click="changeAnalysisType(true)"
+                            style="margin: 0"
+                            v-if="isWrong"
+                            :disabled="!checkers[queNo].length > 0"
+                            :class="checkers[queNo] == '' ? 'disable' : ''"
+                    >
+                        {{$t("studentWeb.exam.testpop.showAns")}}
+                    </button>
                     <button @click="nextQ()"
-                            v-show="queNo != (examInfo.length-1)"
-                            :class="{ hintClick:queNo != (examInfo.length-1) && checkers[queNo] != ''}">
+                            :disabled="queNo == (examInfo.length-1)"
+                            :class="{ hintClick:queNo != (examInfo.length-1) && checkers[queNo] != '',disable: queNo == (examInfo.length-1)}">
                         {{$t("studentWeb.exam.testpop.next")}}
                         <Icon type="ios-arrow-forward" />
                     </button>
@@ -207,8 +244,18 @@
             this.showMessageNum = 0;
         },
         mounted() {
-            this.formPaper()
             this.getPaper()
+            this.formPaper()
+            //如果进入页面不进行点击等操作,直接关闭,会不触发
+            window.onbeforeunload = function (e) {
+                e = e || window.event;
+                // 兼容IE8和Firefox 4之前的版本
+                if (e) {
+                    e.returnValue = "关闭提示";
+                }
+                // Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
+                return "关闭提示";
+            }
         },
         props: {
             papers: {
@@ -226,10 +273,10 @@
                 showMessageNum: 0,
                 WarmMessageisOpen: false,
                 checkers: [],
-                queNo: 0,
+                queNo: 0, // 当前第几题
                 undo: 0,
                 closeTest: true,
-                paperData: {},
+                paperData: {}, // 试卷信息,类型、id,学生得分、答案
                 testType: [
                     {
                         label: this.$t('studentWeb.exam.queType.single'),
@@ -264,47 +311,61 @@
                         value: "connector"
                     },
                 ],
-                examInfo: [],
+                examInfo: [], // 所有题目信息
                 judgeSelect: "",
                 imgPreview: {
                     img: "",
                     show: false
-                }
+                },
+                isWrong: false, // 错题练习
+                isCheckAns: false, // 选中答案
             };
         },
-        methods: { 
+        methods: {
             //初始化試卷信息
             formPaper() {
                 let paper = []
                 this.examInfo.length = []
                 let data = this.$store.getters.getPaperInfo.item
                 let exam = [...data]
-                this.$store.getters.getPaperInfo.item
                 if (this.$store.getters.getPaperInfo.item.length) {
-                        for (let i = 0; i < exam.length; i++) {
-                            if (exam[i].type == 'compose') {
-                                let k = 1
-                                if (exam[i].children.length > 0) {
-                                    for (let items of exam[i].children) {
-                                        items.parentInfo = exam[i]
-                                        items.parent = i
-                                        items.paperIndex = (i + 1) + '-' + k
-                                        paper.push(items)
-                                        k++
-                                    }
+                    for (let i = 0; i < exam.length; i++) {
+                        if (exam[i].type == 'compose') {
+                            let k = 1
+                            if (exam[i].children.length > 0) {
+                                for (let items of exam[i].children) {
+                                    items.parentInfo = exam[i]
+                                    items.parent = i
+                                    items.paperIndex = (i + 1) + '-' + k
+                                    paper.push(items)
+                                    k++
                                 }
-                            } else {
-                                exam[i].paperIndex = i
-                                paper.push(exam[i])
-                            }
+                            } 
+                        } else {
+                            exam[i].paperIndex = i
+                            paper.push(exam[i])
+                        }
                     }
+                }
+                // 有得分情况,就表示当前是错题练习
+                if (this.paperData.stuAns[0] !== undefined) {
+                    this.isWrong = true
+                    let wrongData = [] // 存放错题
+                    for (let i = 0; i < this.paperData.stuScore.length; i++) {
+                        if (this.paperData.stuScore[i] != paper[i].score && this.paperData.stuScore[i] != -1) {
+                            wrongData.push(paper[i])
+                        }
                     }
-                this.examInfo = [...paper]
+                    console.log(wrongData);
+                    this.examInfo = [...wrongData]
+                } else {
+                    this.examInfo = [...paper]
+                }
             },
             //獲取富文本返回數據
             getComposeAns(data, index) {
                 if (index !== undefined) {
-                    this.checkers[index] = []
+                    this.checkers[index].splice(0)
                     if (data !== "") {
                         this.checkers[index].push(data)
                     }
@@ -319,6 +380,7 @@
                 let paper = this.$store.getters.getCurrentSubject
                 this.paperData = { ...paper }
             },
+            // 判断题型
             getTestType(data) {
                 for (let item of this.testType) {
                     if (item.value == data) {
@@ -332,16 +394,25 @@
                         return this.examInfo[index];
                     } else {
                         return {
-                            type: ''
+                            type: '',
                         }
                     }
+                } else {
+                    // 初始化时,this.examInfo 还没有赋值
+                    return {
+                        type:'',
+                        parent:''
+                    }
                 }
             },
+            // 获得选择题——选中的答案
             getAns(data, index) {
                 if (this.getQue(this.queNo).type == "single") {
                     this.checkers[data].length = 0
                     this.checkers[data].push(this.getQue(this.queNo).option[index].code)
+                    console.log(this.getQue(this.queNo).option[index].code);
                 }
+                // this.changeAnalysisType(true)
             },
             //显示知识点(暂未对接)
             hintHandon() {
@@ -355,14 +426,22 @@
                 if (undoQuestion != 0) return false
                 else return true
             },
+            // 点击答题卡跳转
             gototheQues(index) {
                 this.queNo = index - 1
+                this.changeAnalysisType(false)
             },
             preQ() {
-                if (this.queNo > 0) this.queNo--
+                if (this.queNo > 0) {
+                    this.queNo--
+                    this.changeAnalysisType(false)
+                }
             },
             nextQ() {
-                if (this.queNo < (this.examInfo.length - 1)) this.queNo++
+                if (this.queNo < (this.examInfo.length - 1)) {
+                    this.queNo++
+                    this.changeAnalysisType(false)
+                }
             },
             //打开提示信息
             openWarmMessage(showMessageNum) {
@@ -390,7 +469,7 @@
                 this.WarmMessageisOpen = false
                 if (this.checkers.length) {
                     this.isLoading = true;
-                    let codes = this.$store.getters.getItemTitle.code.split('-')
+                    let codes = this.$store.getters.getItemTitle.scope == 'school' ? this.$store.getters.getItemTitle.school : this.$store.getters.getItemTitle.creatorId
                     let req = {
                         id: this.$store.getters.getItemTitle.id,
                         answer: this.checkers,
@@ -399,7 +478,7 @@
                         subjectId: this.$store.getters.getExamInfo.subject.id,
                         multipleRule: this.$store.getters.getExamInfo.multipleRule,
                         paperId: this.$store.getters.getPaperInfo.id,
-                        code: codes[1],
+                        code: codes,
                         scode: this.$store.getters.getItemTitle.scode
                     }
                     this.$api.studentWeb.SaveStuExamPaper(req).then(res => {
@@ -435,12 +514,29 @@
                         code: key[(key.length - 1)],
                         blob: data
                     }
+                    let blob = this.formUrl(code)
+                    code.blob = blob
+                    console.log(code);
                     datas = await this.$evTools.getComposeItem(code)
+                    console.log(datas);
                     return datas
                 } else {
                     return []
                 }
             },
+            //处理学生作答数据blob地址
+            formUrl(data) { 
+                let a = ""
+                if (data.blob.indexOf('https://teammodelstorage') > -1) {
+                    a = data.blob
+                } else {
+                    let blobUrl = JSON.parse(decodeURIComponent(localStorage.student_profile, "utf-8")).blob_uri
+                    let studentBlob = blobUrl.split('/')
+                    let url = data.scope == 'school' ? blobUrl : "https://" + studentBlob[studentBlob.length - 2] + '/' + this.$store.getters.getItemTitle.creatorId
+                    a = `${url}/exam/${data.blob}`
+                }
+                return a 
+            },
             //放大图片
             showImg(e) {
                 this.imgPreview = {
@@ -452,25 +548,33 @@
                     this.imgPreview.show = true
                 }
             },
+            // 错题模式下的解析
+            changeAnalysisType(type) {
+                if (this.isWrong) {
+                    this.isCheckAns = type
+                    // “我的作答” 跳转到顶部
+                    if (type) {
+                        document.getElementsByClassName("answers")[0].scrollIntoView();
+                    }
+                }
+            },
         },
 
         watch: {
             papers: {
-               async handler(newV, oldV) {
+                async handler(newV, oldV) {
                     if (newV.item.length) {
                         this.checkers.length = 0
                         this.closeTest = true
                         if (this.$store.getters.getCurrentSubject.stuAns[0] !== undefined) {
-                            let data = []
-                            data = await this.getItem(this.$store.getters.getCurrentSubject.stuAns[0])
-                            if (data.length) {
-                                this.checkers = [...data]
-                            } else this.$Message.warning(this.$t('studentWeb.exam.msgWarning'))
-                            this.closeTest = false
-                            } else {
                             for (let i = 0; i < this.$store.getters.getCurrentSubject.stuScore.length; i++) {
-                                    this.checkers == this.checkers.push([])
-                                }
+                                this.checkers == this.checkers.push([])
+                            }
+                            // this.closeTest = false
+                        } else {
+                            for (let i = 0; i < this.$store.getters.getCurrentSubject.stuScore.length; i++) {
+                                this.checkers == this.checkers.push([])
+                            }
                         }
                     }
                 },
@@ -489,7 +593,21 @@
                 }
 
             }
-        }
+        },
+        // 导航守卫监听
+        /* beforeRouteLeave(to, from, next) {
+            console.log(1111111111);
+            this.$Modal.confirm({
+                title: $t("studentWeb.exam.testpop.exitQuizhint"),
+                content: "cwsdgrtht",
+                onOk: () => {
+                    next(true)
+                },
+                onCancel: () => {
+                    next(false)
+                },
+            })
+        }, */
     }
 </script>
 

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

@@ -13,9 +13,10 @@
             </div>
             <EventBasicInfo :paper="paperData" />
             <Tabs :value="selectTab" v-if="paperData.length">
+                <!-- 评测内容 -->
                 <TabPane :label='$t("studentWeb.exam.examData")' name="test">
                     <div class="title-rect-group">
-                        <div class="title-rect" />
+                        <!-- <div class="title-rect" /> -->
                         <h2 class="title-rect-name">{{$t("studentWeb.exam.examLink")}}</h2>
                     </div>
                     <!--多學科試卷-->
@@ -35,15 +36,16 @@
                     </div>
                     <div class="title-rect-group">
                         <div v-if="chooseData.subject !== undefined">
-                            <div class="title-rect" />
+                            <!-- <div class="title-rect" /> -->
                             <h2 class="title-rect-name">{{$t("studentWeb.exam.subjectNow")}}:{{chooseData.subject.name}}</h2>
                             <LessonTestReport :paperInfo="selectData" :examInfo="chooseData" />
                         </div>
                     </div>
                 </TabPane>
+                <!-- 成绩分析 -->
                 <TabPane :label="$t('studentWeb.exam.gradeReport')" v-if="isTestOver" name="analyse">
                     <div class="title-rect-group">
-                        <div class="title-rect" />
+                        <!-- <div class="title-rect" /> -->
                         <h2 class="title-rect-name">{{$t("studentWeb.exam.gradeAnalyse")}}</h2>
                     </div>
                     <div class="student-score">
@@ -88,14 +90,15 @@
                 showHint: false,
                 paperData: [],
                 openEva: false,
-                selectData: {},
+                selectData: {}, // 存放完整试卷接口的返回值
                 isExamDown: false,
                 chooseData: {},
                 examData: [],
                 isLoad: false,
                 stuData: {},
                 isTestOver: false,
-                selectTab: "test"
+                selectTab: "test",
+                paperCtn: null, // 当前评测的scope
             };
         },
         methods: {
@@ -107,13 +110,14 @@
                 this.isLoad = true
                 if (this.$store.getters.getItemTitle.name !== undefined) {
                     let paper = this.$store.getters.getItemTitle
-                    let codes = this.$store.getters.getItemTitle.code.split('-')
+                    let codes = this.$store.getters.getItemTitle.scope == 'school' ? this.$store.getters.getItemTitle.school : this.$store.getters.getItemTitle.creatorId
                     let req = {
                         id: paper.id,
                         studentId: this.$store.state.userInfo.sub,
-                        code: codes[1],
+                        code: codes,
                         scode: paper.scode
                     }
+                    this.paperCtn = paper.scope
                     let isTest = 0
                     this.$api.studentWeb.FindStudentPaper(req).then(res => {
                         console.log(res)
@@ -142,7 +146,7 @@
                                         let k = 0
                                         for (let item of resData.stuScore[i]) {
                                             if (item == -1) {   //有未打分
-                                                k++
+                                                k++ // 没有打分+1
                                             }
                                         }
                                         if (k == 0 && this.paperData[i].progress == 'finish') {
@@ -181,7 +185,6 @@
                 }
             },
             async getPaper(data) {
-                console.log('321651231',data)
                 this.isExamDown = false
                 this.isLoad = true
                 this.selectData = {}
@@ -189,7 +192,7 @@
                 let codes = this.$store.getters.getItemTitle.scope == 'school' ? data.school : data.creatorId
                 if (data.blob !== undefined && data.blob !== "") {
                     let code = {
-                        scope: data.scope,
+                        scope: this.paperCtn,
                         code: codes,
                         blob: data.blob,
                         examId: codes

+ 20 - 13
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/QuesNaire.vue

@@ -36,11 +36,12 @@
 		</div> -->
 		<br />
 		<EventBasicInfo />
+		<!-- 已提交 -->
 		<div v-if="alreadyAnswered" style="text-align: center;padding-top: 15%;">
 			<Icon type="md-checkmark-circle-outline" color="#00ad6c" size="80"/>
 			<p style="font-size: 30px;color:#00ad6c;font-weight: 600; margin:20px;">{{ $t('survey.studentWeb.already') }}</p>
 		</div>
-		
+		<!-- 活动结束 -->
 		<div v-if="!alreadyAnswered && surveyInfo.progress === 'finish'" style="text-align: center;padding-top: 15%;">
 			<Icon type="md-stopwatch" color="#00ad6c" size="80"/>
 			<p style="font-size: 30px;color:#00ad6c;font-weight: 600; margin:20px;">{{ $t('survey.studentWeb.overtime') }}</p>
@@ -51,26 +52,29 @@
 		<div v-if="surveyInfo.progress !== 'finish' && !alreadyAnswered">
 			<BillBoardandLightBox :activityData="surveyInfo" />
 			<div class="title-rect-group">
-				<div class="title-rect" />
+				<!-- <div class="title-rect" /> -->
 				<h2 class="title-rect-name">{{ $t('survey.studentWeb.content') }}</h2>
 			</div>
 			<br />
-
+			<!-- 问卷内容 -->
 			<div v-for="(item, index) in surveyInfo.items" :key="index" class="survey-item">
-				<br />
+				<!-- <br /> -->
 				<div style="display: flex;font-weight: bold;">
 					<span>{{ index + 1 }}. </span>
 					<span v-html="item.question"></span>({{ typeList[item.type] }})<span></span>
 				</div>
+				<!-- 非问答 -->
 				<div v-if="item.type !== 'subjective'">
-					<label class="unitTestBtn" v-for="(option, optionIndex) in item.option" :key="optionIndex">
+					<div class="unitTestBtn" v-for="(option, optionIndex) in item.option" :key="optionIndex">
 						<div class="unitTestbg" @click="onOptionClick(item,index,option.code)"
 							:style="{ backgroundColor: submitArr[index].includes(option.code) ?  '#24b880' : 'transparent' }">
-							{{ option.code }}. <span v-html="option.value" style="margin-left: 10px;"></span></div>
-					</label>
+							{{ option.code }}. <span v-html="option.value" style="margin-left: 10px;"></span>
+						</div>
+					</div>
 				</div>
+				<!-- 问答 -->
 				<div v-if="item.type === 'subjective'">
-					<Input v-model="submitArr[index][0]" type="textarea" :rows="8" :placeholder="$t('stuentWeb.exam.inputAnswers')" />
+					<Input v-model="submitArr[index][0]" type="textarea" :rows="8" :placeholder="$t('studentWeb.exam.inputAnswers')" />
 				</div>
 				<Divider v-if="index != surveyInfo.items.length - 1" />
 			</div>
@@ -99,11 +103,11 @@
 		},
 		data(vm) {
 			return {
-				surveyInfo: {
+				surveyInfo: { //问卷信息
 					items: []
 				},
 				checkers: [],
-				alreadyAnswered:false,
+				alreadyAnswered:false, //提交状态
 				undo: 0,
 				showMessageNum: 0,
 				WarmMessageisOpen: false,
@@ -116,7 +120,7 @@
 					'judge': vm.$t('survey.questionaire.judge'),
 					'subjective': vm.$t('survey.questionaire.subjective')
 				},
-				submitArr: []
+				submitArr: [] //填写的数据
 			};
 		},
 
@@ -221,6 +225,7 @@
 			},
 			
 			//获取投票数据
+			// 获取surveyInfo的数据
 			async getSurveyInfo() {
 				if (this.$store.getters.getItemTitle.id) {
 					let params = {
@@ -229,6 +234,7 @@
 					}
 					let isAnswerd = await this.isAnswerd(params)
 					if(!isAnswerd){
+						// 没有提交
 						this.$api.studentWeb.getSurveyInfo(params).then(async res => {
 							if (res) {
 								this.surveyInfo = res.survey
@@ -252,7 +258,7 @@
 				console.log(this.surveyInfo)
 			},
 
-			// 获取blob里的试题数据
+			// 获取blob里的问卷内容
 			getBlobItems(qnItem) {
 				return new Promise(async (resolve, reject) => {
 					let schoolBlobHost = JSON.parse(decodeURIComponent(localStorage.student_profile, "utf-8")).blob_uri
@@ -287,7 +293,7 @@
 				})
 			},
 			
-			// 获取blob里的试题数据
+			// 获取blob里的问卷信息
 			getBlobJsonFile(scope,url,container){
 				return new Promise(async (resolve,reject) => {
 					let blobUrl = JSON.parse(decodeURIComponent(localStorage.student_profile, "utf-8")).blob_uri
@@ -319,6 +325,7 @@
 		watch: {
 			$route: {
 				handler() {
+					this.alreadyAnswered = false
 					this.getSurveyInfo()
 				},
 				// 深度观察监听

+ 7 - 6
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Vote.vue

@@ -29,7 +29,7 @@
                 <BillBoardandLightBox :activityData="voteInfo" :voteRes="voteResData" />
                 <div class="vote-title">
                     <div class="title-rect-group">
-                        <div class="title-rect" />
+                        <!-- <div class="title-rect" /> -->
                         <h2 class="title-rect-name">{{ $t("studentWeb.vote.bollotbox") }}</h2>
                         <p v-if="voteInfo.repeat" style="margin-left:15px;margin-top:2px">{{ $t("studentWeb.vote.surplusTickets")}} <span style="font-size:16px">{{voteCount}}</span><span> {{ $t("studentWeb.vote.tickets")}} </span></p>
                     </div>
@@ -37,7 +37,7 @@
                         <span style="margin-left:5px">{{$t("studentWeb.vote.voteRes")}}</span>
                     </Button>
                 </div>
-                <!--和評測模組一樣-->
+                <!-- 投票内容 -->
                 <div class="question-box"><span v-html="voteInfo.description"></span></div>
                 <div>
                     <div class="checkAnswer" v-for="(item, index) in voteInfo.options" :key="index">
@@ -69,6 +69,7 @@
 
             </div>
         </div>
+        <!-- 投票结果 -->
         <div class="voteResults" v-if="showResult">
             <h3 class="voteResultsMainRow ">
                 {{ $t("studentWeb.vote.voteResult") }}
@@ -116,13 +117,13 @@
                 voteChecked: [],
                 WarmMessageisOpen: false,
                 clickbutnoChoose: false,
-                voteInfo: {},
+                voteInfo: {}, //投票信息
                 voteRes: {},
                 voteResData: [],
                 isVote: false,
                 voteStatus:false,
                 voteNum: 0,
-                showResult: false,
+                showResult: false, //显示投票结果
                 chooseVoteRes: {},
                 isLoad: false,
                 isResult: false,
@@ -233,8 +234,8 @@
                 return val1.code.toLowerCase() < val2.code.toLowerCase()
              },
             showRes() {
-            this.showResult = !this.showResult
-             },
+                this.showResult = !this.showResult
+            },
             //获取投票结果
             getVote(data) {
                 if (!this.voteInfo.repeat) {

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

@@ -21,7 +21,7 @@
                             <Icon type="ios-arrow-down"></Icon>
                         </a>
                         <DropdownMenu slot="list">
-                            <div @click="sentEventStatus(item)" v-for="(item,index) in $t('studentWeb.state')">
+                            <div @click="sentEventStatus(item)" v-for="(item,index) in $t('studentWeb.state')" :key="index">
                                 <DropdownItem>{{ item.status }}</DropdownItem>
                             </div>
                         </DropdownMenu>
@@ -167,8 +167,8 @@
                 selectedEventStatusNow: this.$t('studentWeb.event.allStatus'),
                 hideIconbtn: false,
                 isListNoItem: false, //清單為空
-                eventList: [],
-                eventShow: [],
+                eventList: [], //活动数据
+                eventShow: [], //展示的活动数据
                 dateTime: Date.parse(new Date())
             };
         },

+ 201 - 145
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeView.vue

@@ -3,56 +3,61 @@
         <Row :gutter="30" v-if="spanCharts == false">
             <i-col :xs="0" :sm="0" :md="0" :lg="1"></i-col>
             <i-col :xs="24" :sm="24" :md="12" :lg="7">
+                <!-- 行事历 -->
                 <Card :bordered="true" class="calenderCard" @click.native="noData">
                     <p slot="title">
                         <svg-icon class="titleIcon" icon-class="calander" />
                         <span class="title">{{ $t("studentWeb.calenderCardTitle") }}</span>
                     </p>
                     <div>
-                        <div class="title-rect" />
+                        <!-- <div class="title-rect" /> -->
                         <p class="title-rect-name">{{ $t("studentWeb.recentClass") }}</p>
-                        <p class="classtitle">{{ $t("studentWeb.defaultRecentClass") }}</p>
+                        <p class="classtitle">{{ $t("evaluation.noData") }}</p>
+                        <!-- <p class="classtitle">{{ $t("studentWeb.defaultRecentClass") }}</p>
                         <p class="time">{{ $t("studentWeb.defaultClassTime") }}</p>
-                        <p class="place">{{ $t("studentWeb.defaultClassPlace") }}</p>
+                        <p class="place">{{ $t("studentWeb.defaultClassPlace") }}</p> -->
                     </div>
                     <div class="todaydayline">
                         <div class="todaydaylinewraptitle">
-                            <div class="title-rect" />
+                            <!-- <div class="title-rect" /> -->
                             <p class="title-rect-name">
                                 {{ $t("studentWeb.todaydeadlineList") }}
                                 <Icon type="ios-arrow-forward" />
                             </p>
+                            <p class="classtitle">
+                                {{ $t("evaluation.noData") }}
+                            </p>
                         </div>
                         <div class="todaydaylineList">
                             <div class="list-block"
-                                 :style="{ 'max-height': todaydaylineListHeight + 'px' }">
+                                 :style="{'max-height': todaydaylineListHeight + 'px',}">
                                 <li :id="`tditem${index}`"
                                     class="list-item"
                                     v-for="(item, index) in mockdata"
                                     :key="index"
-                                    v-show="eventPageType.includes(item.eventType) == true &&item.isDone == false && index < 8 ">
+                                    v-show="eventPageType.includes(item.eventType) == true && item.isDone == false && index < 8"
+                                >
                                     <ul>
                                         <li class="list-item-icon">
                                             <svg-icon v-if="item.eventType == 'homework'"
-                                                      icon-class="doc" />
+                                                      icon-class="doc"/>
                                             <svg-icon v-if="item.eventType == 'preview'"
-                                                      icon-class="selflearninginTime" />
+                                                      icon-class="selflearninginTime"/>
                                             <svg-icon v-if="item.eventType == 'exam'"
                                                       icon-class="test"
-                                                      class="reset-testIcon" />
+                                                      class="reset-testIcon"/>
                                             <svg-icon v-if="item.eventType == 'vote'"
-                                                      icon-class="vote" />
+                                                      icon-class="vote"/>
                                             <svg-icon v-if="item.eventType == 'survey'"
-                                                      icon-class="quesnaire" />
+                                                      icon-class="quesnaire"/>
                                         </li>
                                         <li class="list-item-info">
-                                            <p class="list-item-title"
-                                               :class="{ 'list-item-titleEn': getCurrentLang() == 'en', }">
+                                            <p class="list-item-title" :class="{'list-item-titleEn': getCurrentLang() == 'en',}">
                                                 <span class="list-item-typeMark">{{ item.eventType }}</span>
                                                 <span>{{ item.eventName }}</span>
                                             </p>
                                             <p class="list-item-time">
-                                                {{ $t("studentWeb.endsTodayTime") }}
+                                                {{ $t( "studentWeb.endsTodayTime") }}
                                             </p>
                                         </li>
                                         <li class="list-item-unDone"></li>
@@ -63,6 +68,7 @@
                     </div>
                 </Card>
                 <br />
+                <!-- 课程清单 -->
                 <router-link to="/studentWeb/courseList">
                     <Card style="overflow: hidden">
                         <h3 style="color: #575757; font-weight: 700">
@@ -70,20 +76,36 @@
                             {{ $t("studentWeb.coursesCardTitle") }}
                             <Icon type="ios-arrow-forward" />
                         </h3>
-                        <p class="course-new">{{ $t("studentWeb.newAddCourse") }}</p>
+                        <p class="course-new">{{ $t("evaluation.noData") }}</p>
+                        <!-- <p class="course-new">{{ $t("studentWeb.newAddCourse") }}</p> -->
                     </Card>
                 </router-link>
                 <br />
             </i-col>
             <i-col :xs="24" :sm="24" :md="12" :lg="8">
+                <!-- 活动任务清单 -->
                 <MissionListCard />
             </i-col>
             <i-col :xs="24" :sm="24" :md="12" :lg="7">
                 <Card :bordered="true">
-                    <div class="spanAllchartBtn" @click="setSpanCharts()">
-                        <svg-icon class="spanAllchartIcon" icon-class="dimensions" />
+                    <div class="no-data-text">
+                        <img
+                            src="@/assets/icon/no_data_evaluation.png"
+                            width="120"
+                        />
+                        <span style="margin-top: 15px; color: #808080">{{
+                            $t("evaluation.noData")
+                        }}</span>
                     </div>
-                    <ChartCarousel />
+                    <!-- <div style="position: relative">
+                        <div class="spanAllchartBtn" @click="setSpanCharts()">
+                            <svg-icon
+                                class="spanAllchartIcon"
+                                icon-class="dimensions"
+                            />
+                        </div>
+                        <ChartCarousel />
+                    </div> -->
                 </Card>
                 <br />
                 <Card class="bar-card" @click.native="noData">
@@ -97,26 +119,40 @@
                             {{ MyEventData }}
                             <span style="font-size: 20px">&nbsp;%</span>
                         </span>
-                        <div class="myTestProgressContent"
-                             :style="{ width: MyEventData + '%' }"
-                             style="background: #00ad6c"></div>
+                        <div
+                            class="myTestProgressContent"
+                            :style="{ width:MyEventData == '--' ? '0' : MyEventData + '%' }"
+                            style="background: #00ad6c"
+                        ></div>
                         <div class="myTestProgress"></div>
                     </div>
                 </Card>
                 <br />
                 <Card class="bar-card" @click.native="noData">
                     <h3 style="color: #575757; font-weight: 700">
-                        <svg-icon class="titleIcon studyIcon" icon-class="note" />
+                        <svg-icon
+                            class="titleIcon studyIcon"
+                            icon-class="note"
+                        />
                         {{ $t("studentWeb.myProgressBar.selfStudyClickRate") }}
                     </h3>
                     <div class="myProgressBar">
                         <span class="myTestProgressNum">
-                            {{ 22 }}
+                            <!-- {{ 22 }} -->
+                            --
                             <span style="font-size: 20px">&nbsp;%</span>
                         </span>
-                        <div class="myTestProgressContent"
-                             :style="{ width: 22 + '%' }"
-                             style="background: linear-gradient(90deg, #ffa400, #fa6400)"></div>
+                        <div
+                            class="myTestProgressContent"
+                            :style="{ width: 0 + '%' }"
+                            style="
+                                background: linear-gradient(
+                                    90deg,
+                                    #ffa400,
+                                    #fa6400
+                                );
+                            "
+                        ></div>
                         <div class="myTestProgress"></div>
                     </div>
                 </Card>
@@ -127,8 +163,14 @@
             <i-col :xs="24" :sm="24" :md="24" :lg="22">
                 <div class="allcharts">
                     <Row :gutter="30">
-                        <div class="spanAllchartBtn isOpen" @click="setSpanCharts()">
-                            <svg-icon class="spanAllchartIconNow" icon-class="dimensions" />
+                        <div
+                            class="spanAllchartBtn isOpen"
+                            @click="setSpanCharts()"
+                        >
+                            <svg-icon
+                                class="spanAllchartIconNow"
+                                icon-class="dimensions"
+                            />
                         </div>
                         <i-col :xs="24" :sm="24" :md="24" :lg="8">
                             <h3>{{ $t("studentWeb.chartNames[0]") }}</h3>
@@ -163,135 +205,149 @@
 </template>
 
 <script>
-    import ChartCarousel from "./ChartCarousel/ChartCarousel";
-    import MissionListCard from "./MissionListCard";
-    import StudyTimeChart from "../HomeView/ChartCarousel/StudyTimeChart";
-    import EventPieChart from "../HomeView/ChartCarousel/EventPieChart";
-    import TwoLineChart from "../HomeView/ChartCarousel/TwoLineChart";
-    import StackBarChart from "../HomeView/ChartCarousel/StackBarChart";
-    import SplineAreaChart from "../HomeView/ChartCarousel/SplineAreaChart";
-    import StudyHeatMap from "../HomeView/ChartCarousel/StudyHeatMap";
-
-    export default {
-        name: "HomeView",
-        components: {
-            ChartCarousel,
-            MissionListCard,
-            SplineAreaChart,
-            StackBarChart,
-            TwoLineChart,
-            EventPieChart,
-            StudyHeatMap,
-            StudyTimeChart,
-        },
+import ChartCarousel from "./ChartCarousel/ChartCarousel";
+import MissionListCard from "./MissionListCard";
+import StudyTimeChart from "../HomeView/ChartCarousel/StudyTimeChart";
+import EventPieChart from "../HomeView/ChartCarousel/EventPieChart";
+import TwoLineChart from "../HomeView/ChartCarousel/TwoLineChart";
+import StackBarChart from "../HomeView/ChartCarousel/StackBarChart";
+import SplineAreaChart from "../HomeView/ChartCarousel/SplineAreaChart";
+import StudyHeatMap from "../HomeView/ChartCarousel/StudyHeatMap";
 
-        data() {
-            return {
-                eventPageType: ["preview", "exam", "homework", "vote", "survey"], //本頁出現的類型
-                MyNo: "1", //接收NavBar 選定的那一頁icon標示
-                MyName: "",
-                mockdata: [
-                    {
-                        "eventSubject": "英文",
-                        "eventID": "360000198305204644",
-                        "eDes": "眼技先准角期几要毛精且将已己拉省。制力叫了连并情权了类资格深外表量。领值术农除存给么连什通单问。",
-                        "eventName": "党华前置亲从性常但给",
-                        "teacher": "阎娟",
-                        "startTime": "2020.01.14",
-                        "endTime": "2020.02.31",
-                        "isDone": false,
-                        "isOverEndTime": true,
-                        "eventType": "作業"
-                    },
-                    {
-                        "eventSubject": "國文",
-                        "eventID": "420000200302184824",
-                        "eDes": "回全导色即院给深育完东两会白任斗了利。取。之部个变型自重周间情六天确史这节族么易。",
-                        "eventName": "一斯在管石门",
-                        "teacher": "薛洋",
-                        "startTime": "2020.01.09",
-                        "endTime": "2020.02.28",
-                        "isDone": false,
-                        "isOverEndTime": true,
-                        "eventType": "課前預習"
-                    },
-                    {
-                        "eventSubject": "英文",
-                        "eventID": "32000020030706692X",
-                        "eDes": "适会商你济标张或程道称育口海率。己织南系完群百相系她两意对该亲。门车个解争包看听文变声反先。",
-                        "eventName": "动主利全这还便划九",
-                        "teacher": "谭强",
-                        "startTime": "2020.01.06",
-                        "endTime": "2020.02.27",
-                        "allowRetryNow": true,
-                        "isDone": false,
-                        "isOverEndTime": false,
-                        "eventType": "問卷"
-                    }
-                ],
-                MyEventData: parseFloat(this.$store.getters.getCountedIsDonePercent).toFixed(0),
-                spanCharts: false,
-                todaydaylineListHeight: 0,
-            };
-        },
+export default {
+    name: "HomeView",
+    components: {
+        ChartCarousel,
+        MissionListCard,
+        SplineAreaChart,
+        StackBarChart,
+        TwoLineChart,
+        EventPieChart,
+        StudyHeatMap,
+        StudyTimeChart,
+    },
 
-        methods: {
-            noData() {
-                this.$Message.warning(this.$t('studentWeb.public.notice'))
+    data() {
+        return {
+            eventPageType: ["preview", "exam", "homework", "vote", "survey"], //本頁出現的類型
+            MyNo: "1", //接收NavBar 選定的那一頁icon標示
+            MyName: "",
+            mockdata: [
+                {
+                    eventSubject: "英文",
+                    eventID: "360000198305204644",
+                    eDes:
+                        "眼技先准角期几要毛精且将已己拉省。制力叫了连并情权了类资格深外表量。领值术农除存给么连什通单问。",
+                    eventName: "党华前置亲从性常但给",
+                    teacher: "阎娟",
+                    startTime: "2020.01.14",
+                    endTime: "2020.02.31",
+                    isDone: false,
+                    isOverEndTime: true,
+                    eventType: "作業",
+                },
+                {
+                    eventSubject: "國文",
+                    eventID: "420000200302184824",
+                    eDes:
+                        "回全导色即院给深育完东两会白任斗了利。取。之部个变型自重周间情六天确史这节族么易。",
+                    eventName: "一斯在管石门",
+                    teacher: "薛洋",
+                    startTime: "2020.01.09",
+                    endTime: "2020.02.28",
+                    isDone: false,
+                    isOverEndTime: true,
+                    eventType: "課前預習",
+                },
+                {
+                    eventSubject: "英文",
+                    eventID: "32000020030706692X",
+                    eDes:
+                        "适会商你济标张或程道称育口海率。己织南系完群百相系她两意对该亲。门车个解争包看听文变声反先。",
+                    eventName: "动主利全这还便划九",
+                    teacher: "谭强",
+                    startTime: "2020.01.06",
+                    endTime: "2020.02.27",
+                    allowRetryNow: true,
+                    isDone: false,
+                    isOverEndTime: false,
+                    eventType: "問卷",
+                },
+            ],
+            // MyEventData: parseFloat(this.$store.getters.getCountedIsDonePercent).toFixed(0),
+            MyEventData: "--", // 没有数据用--表示,后面再从vuex里拿
+            spanCharts: false,
+            todaydaylineListHeight: 0,
+        };
+    },
 
-            },
-            getCurrentLang() {
-                return localStorage.getItem("lang");
-            },
-            sentSelectedEventTitle: function (item) {
-                this.$router.push("/studentWeb/eventView#" + item.eventID);
-                this.$store.commit("ChangeItemName", item);
-            },
-            setSpanCharts() {
-                this.spanCharts = !this.spanCharts;
-            },
+    methods: {
+        noData() {
+            this.$Message.warning(this.$t("studentWeb.public.notice"))
         },
-
-        created() {
-            (this.MyName = this.$t("studentWeb.homeView-title")),
-                this.$emit("onNavNo", this.MyNo);
-            this.$emit("onNavName", this.MyName);
+        getCurrentLang() {
+            return localStorage.getItem("lang")
         },
-        mounted() {
-            if (document.getElementById("tditem0") != "") {
-                document.getElementById("tditem0").style.display = "block";
-                var item1Height = document.getElementById("tditem0").offsetHeight;
-                document.getElementById("tditem0").style.display = "none";
-            }
-            if (document.getElementById("tditem1") != "") {
-                document.getElementById("tditem1").style.display = "block";
-                var item2Height = document.getElementById("tditem1").offsetHeight;
-                document.getElementById("tditem1").style.display = "none";
-            }
-            this.todaydaylineListHeight = item1Height + item2Height + 20;
+        sentSelectedEventTitle: function (item) {
+            this.$router.push("/studentWeb/eventView#" + item.eventID)
+            this.$store.commit("ChangeItemName", item)
         },
-    };
+        setSpanCharts() {
+            this.spanCharts = !this.spanCharts
+        },
+    },
+
+    created() {
+        (this.MyName = this.$t("studentWeb.homeView-title")),
+            this.$emit("onNavNo", this.MyNo)
+        this.$emit("onNavName", this.MyName)
+    },
+    mounted() {
+        if (document.getElementById("tditem0") != "") {
+            document.getElementById("tditem0").style.display = "block"
+            var item1Height = document.getElementById("tditem0").offsetHeight
+            document.getElementById("tditem0").style.display = "none"
+        }
+        if (document.getElementById("tditem1") != "") {
+            document.getElementById("tditem1").style.display = "block"
+            var item2Height = document.getElementById("tditem1").offsetHeight
+            document.getElementById("tditem1").style.display = "none"
+        }
+        this.todaydaylineListHeight = item1Height + item2Height + 20
+    },
+}
 </script>
 
 <style scoped>
-    @import "~@/assets/student-web/component_styles/home-view.css";
-    @keyframes born {
-        from {
-            width: 0;
-        }
+@import "~@/assets/student-web/component_styles/home-view.css";
+@keyframes born {
+    from {
+        width: 0;
+    }
 
-        to {
-            width: MyEventData + "%";
-        }
+    to {
+        width: MyEventData + "%";
     }
+}
 
-    @keyframes fadein {
-        from {
-            opacity: 0;
-        }
+@keyframes fadein {
+    from {
+        opacity: 0;
+    }
 
-        to {
-            opacity: 1;
-        }
+    to {
+        opacity: 1;
     }
+}
+.no-data-text {
+    width: 100%;
+    padding: 30px;
+    background: #fff;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    margin-top: 10px;
+    font-size: 16px;
+}
 </style>

+ 2 - 2
TEAMModelOS/ClientApp/src/components/student-web/HomeView/MissionListCard.vue

@@ -44,7 +44,7 @@
                                 {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
                             </p>
                         </li>
-                </ul>
+                    </ul>
                 </div>
             </Scroll>
             <div class="list-end"></div>
@@ -64,7 +64,7 @@
                 listblockHeight: 0,
                 mockdataOriginal: "",
                 mockdata: "",
-                testData: [],
+                testData: [], // 活动数据
                 templistArray: [],
                 eventPageType: ["preview", "exam", "homework", "vote", "questionnare"] //本頁出現的類型
             };

+ 1 - 0
TEAMModelOS/ClientApp/src/css/site.css

@@ -179,6 +179,7 @@ audio::-internal-media-controls-overflow-button {
 	color: #000;
 	display: flex;
 	align-items: center;
+	min-width: 240px;
 }
 
 .richText-audio .audio-name {

+ 2 - 2
TEAMModelOS/ClientApp/src/locale/lang/en-US/schoolBaseInfo.js

@@ -91,7 +91,7 @@ export default {
   uploadPlan: '上传平面图',
   hiteachList: 'HiTeach序号列表',
   codeSearchHolder: '请输入关键字搜索',
-  classroomCodeHolder: 'eg: HBCN0101',
+  classroomCodeHolder: 'eg: 1',
   classroomNameHolder: 'eg: 一年级一班',
   headmasterHolder: '可通过名字搜索...',
   hiTeachHolder: '请在右侧列表选择可用序号...',
@@ -142,7 +142,7 @@ export default {
   noEnable: '此序号尚未启用',
   onClassStu: '专科教室没有固定学生名单!',
   classNoErr: '教室编码不能为空!',
-  classNoErr1: '教室编码只能由字母和数字组成!',
+  classNoErr1: '班级只能是数字!',
   classAttr1: '常规教室(有固定学生)',
   classAttr2: '专科教室(无固定学生)',
   nameWarning: '请输入教室名称',

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

@@ -31,7 +31,7 @@ export default {
   props7: '存儲空間不足!',
   uploadText: '點擊或者拖拽上傳',
 
-  resTips: 'HiTeach生成的課件,不包含PPT等其他檔案',
+  resTips: 'HiTeach生成的課件,只支持HTEX格式的教材預覽',
   space: '空間:',
   calcing: '計算中…',
   blobFull: '(已滿)',

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

@@ -113,7 +113,7 @@ export default {
   uploadPlan: '上传平面图',
   hiteachList: 'HiTeach序号列表',
   codeSearchHolder: '请输入关键字搜索',
-  classroomCodeHolder: 'eg: HBCN0101',
+  classroomCodeHolder: 'eg: 1',
   classroomNameHolder: 'eg: 一年级一班',
   headmasterHolder: '可通过名字搜索...',
   hiTeachHolder: '请在右侧列表选择可用序号...',
@@ -164,12 +164,12 @@ export default {
   noEnable: '此序号尚未启用',
   onClassStu: '专科教室没有固定学生名单!',
   classNoErr: '教室编码不能为空!',
-  classNoErr1: '教室编码只能由字母和数字组成!',
+  classNoErr1: '班级只能是数字!',
   classAttr1: '常规教室(有固定学生)',
   classAttr2: '专科教室(无固定学生)',
   nameWarning: '请输入名称',
   typeWarning: '请设置教室属性',
-  gradeWarning: '请设置级',
+  gradeWarning: '请设置级',
   expireLabel1: '已到期',
   expireLabel2: '无限期',
   findStuErr: '查询班级学生名单失败!',

+ 8 - 2
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/settings.js

@@ -11,6 +11,10 @@ export default {
 	menuTips:'选择左侧Menu在网站载入时的预设显示模式',
 	menuOpen:'预设展开显示',
 	menuClose:'预设关闭显示',
+	logoSetting:'Logo显示设置',
+	logoTips:'选择是否隐藏左上角平台Logo',
+	logoOpen:'预设显示',
+	logoHide:'预设隐藏',
 	defaultSchool:'默认学校',
 	curSchool:'当前学校',
 	courseNum:'课程数',
@@ -19,7 +23,8 @@ export default {
 	requestStatus:'送出添加邀请',
 	goSchool:'前往学校',
 	agreeJoin:'同意加入',
-	cancelAdd:'取消添加',
+	cancelAdd:'拒绝加入',
+	undoJoin:'撤销申请',
 	requestJoin:'申请加入',
 	inputSearch:'输入要搜索的学校名称',
 	modalTip1:'注意',
@@ -30,7 +35,8 @@ export default {
 	columnId:'校代码',
 	columnTool:'操作',
 	modalTip4:'温馨提示',
-	modalTip5:'确认申请加入',
+	modalTip5:'确认加入',
+	modalTip6:'确认取消加入',
 	submitSucTips:'提交成功',
 	submitFailTips:'操作失败',
 	joinSucTips:'加入成功!',

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

@@ -3,8 +3,8 @@ export default {
   seatNo: '座号',
   account: '账号资讯',
   stuName: '姓名',
-  classroomCode: '教室编码',
-  classroomName: '教室名称',
+  classroomCode: '班级',
+  classroomName: '班级名称',
   period: '学段',
   grade: '年级',
   authStatus: '授权状态',

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

@@ -330,7 +330,8 @@ export default {
             fileView: '文件预览',
             noReview: '该文件暂不支持预览,请下载查看!',
             pdfErr: 'pdf 加载失败',
-            noAnalyse: '暂无解析'
+            noAnalyse: '暂无解析',
+            wrongPractice: '错题练习',
         },
         timeoutHint: '评量活动时间已结束,逾时将以0分计算,或等待教师开放补考。',
         contentPage: '评量内容',

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

@@ -1,6 +1,7 @@
 export default {
     menu:{
-        smartSc:'智慧校园',
+        schoolMgt:'学校管理',
+        schoolRes:'校本资源',
         baseSetting:'基础设置',
         teacherMgt:'教师管理',
         stuMgt:'学生管理',
@@ -23,11 +24,11 @@ export default {
         classCus:'班级课程',
         myClass:'我的班级',
         myCus:'我的课程',
-        cusContent:'课程教材',
+        cusContent:'我的资源',
         prtSyllabus:'个人课纲',
         prtContent:'个人内容',
         prtQuBack:'个人题库',
-        stuAc:'学习活动',
+        stuAc:'我的活动',
         prtEv:'个人评测',
         prtVote:'个人投票',
         prtQu:'个人问卷',

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

@@ -31,7 +31,7 @@ export default {
   props7: '存储空间不足!',
   uploadText: '点击或者拖拽上传',
 
-  resTips:'HiTeach生成的课件,不包含PPT等其他文件',
+  resTips:'HiTeach生成的课件,只支持HTEX格式的教材预览',
   space:'空间:',
   calcing:'计算中...',
   blobFull:'(已满)',

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

@@ -35,7 +35,7 @@ export default {
     condition5: '考试范围',
     condition6: '评测来源',
     condition7: '考试学科',
-
+	condition8: '发布年份',
     // totalIndex.vue
     ti_title1: '基本数据统计',
     ti_title2: '评测数据统计',

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

@@ -86,7 +86,7 @@ export default {
   uploadPlan: '上傳平面圖',
   hiteachList: 'HiTeach序號清單',
   codeSearchHolder: '請輸入關鍵字搜尋',
-  classroomCodeHolder: 'eg: HBCN0101',
+  classroomCodeHolder: 'eg: 1',
   classroomNameHolder: 'eg:一年級一班',
   headmasterHolder: '可通過名字搜尋…',
   hiTeachHolder: '請在右側清單選擇可用序號…',
@@ -137,12 +137,12 @@ export default {
   noEnable: '此序號尚未啟用',
   onClassStu: '專科教室沒有固定學生名單!',
   classNoErr: '教室編碼不能為空!',
-  classNoErr1: '教室編碼只能由字母和數位組成!',
+  classNoErr1: '教室編碼只能是數字!',
   classAttr1: '班級教室(有固定學生)',
   classAttr2: '專科教室(無固定學生)',
   nameWarning: '請輸入教室名稱',
   typeWarning: '請設定教室内容',
-  gradeWarning: '請設定級',
+  gradeWarning: '請設定級',
   expireLabel1: '已到期',
   expireLabel2: '無限期',
   findStuErr: '査詢班級學生名單失敗!',

+ 8 - 2
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/settings.js

@@ -11,6 +11,10 @@ export default {
 	menuTips: '選擇左側Menu在網站載入時的預設顯示模式',
 	menuOpen: '預設展開顯示',
 	menuClose: '預設關閉顯示',
+	logoSetting:'Logo顯示設定',
+	logoTips:'選擇是否隱藏左上角平臺Logo',
+	logoOpen:'預設顯示',
+	logoHide:'預設隱藏',
 	defaultSchool: '預設學校',
 	curSchool: '當前學校',
 	courseNum: '課程數',
@@ -19,7 +23,8 @@ export default {
 	requestStatus: '送出加入邀請',
 	goSchool: '前往學校',
 	agreeJoin: '同意加入',
-	cancelAdd: '取消加入',
+	cancelAdd:'拒絕加入',
+	undoJoin:'撤銷申請',
 	requestJoin: '申請加入',
 	inputSearch: '輸入要檢索的學校名稱',
 	modalTip1: '注意',
@@ -30,7 +35,8 @@ export default {
 	columnId: '校程式碼',
 	columnTool: '操作',
 	modalTip4: '溫馨提示',
-	modalTip5: '確認申請加入',
+	modalTip5: '確認加入',
+	modalTip6:'確認取消加入',
 	submitSucTips: '提交成功',
 	submitFailTips: '操作失敗',
 	joinSucTips: '加入成功!',

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

@@ -31,7 +31,7 @@ export default {
   props7: '儲存空間不足!',
   uploadText: '點按或者拖移上傳',
 
-  resTips: 'HiTeach生成的教材,不包含PPT等其他檔案',
+  resTips: 'HiTeach生成的課件,只支持HTEX格式的教材預覽',
   space: '空間:',
   calcing: '計算中…',
   blobFull: '(已滿)',

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

@@ -35,6 +35,7 @@ export default {
 	condition5: '考試範圍',
 	condition6: '評量來源',
 	condition7: '考試學科',
+	condition8: '發佈年份',
 
 	// totalIndex.vue
 	ti_title1: '基本資料統計',

+ 3 - 1
TEAMModelOS/ClientApp/src/router/routes.js

@@ -375,7 +375,7 @@ export const routes = [
 			component: resolve => require(['@/view/newcourse/MyCourse.vue'], resolve),
 			meta: {
 				activeName: 'myCourse',
-				isKeep: true
+				// isKeep: true
 			}
 		},
 		{
@@ -714,6 +714,7 @@ export const routes = [
 			component: resolve => require(['@/components/student-web/EventView/EventOverView/EventLatest'], resolve),
 		},
 		{
+			// 自主学习
 			name: "studyView",
 			path: "studyView",
 			component: resolve => require(['@/components/student-web/StudyView/StudyView'], resolve),
@@ -724,6 +725,7 @@ export const routes = [
 			component: resolve => require(['@/components/student-web/HiteachView/HiteachView'], resolve),
 		},
 		{
+			// 通知
 			name: "informView",
 			path: "informView",
 			component: resolve => require(['@/components/student-web/InformView/InformView'], resolve),

+ 2 - 0
TEAMModelOS/ClientApp/src/service/User.js

@@ -77,6 +77,8 @@ export class User {
           localStorage.removeItem('school_profile')
           localStorage.removeItem('student_profile')
           localStorage.removeItem('filterConditions')
+          localStorage.removeItem('cacheSchoolFiles')
+          localStorage.removeItem('cachePrivFiles')
           
           // 重置登录状态
           User.$access.reset();

+ 42 - 3
TEAMModelOS/ClientApp/src/static/baseDataDefault.json

@@ -20,7 +20,20 @@
                 "alias": "小学三年级"
             }
         ],
-        "subjects": [],
+        "subjects": [
+            {
+                "id":"1",
+                "name":"语文"
+            },
+            {
+                "id":"2",
+                "name":"数学"
+            },
+            {
+                "id":"3",
+                "name":"英语"
+            }
+        ],
         "semesters": [
             {
                 "name": "上学期",
@@ -54,7 +67,20 @@
                 "name": "三年級"
             }
         ],
-        "subjects": [],
+        "subjects": [
+            {
+                "id":"1",
+                "name":"語文"
+            },
+            {
+                "id":"2",
+                "name":"數學"
+            },
+            {
+                "id":"3",
+                "name":"英語"
+            }
+        ],
         "semesters": [
             {
                 "name": "上學期",
@@ -74,7 +100,20 @@
         "lang": "en-US",
         "name": "United States",
         "alias": "English",
-        "subjects": [],
+        "subjects": [
+            {
+                "id":"1",
+                "name":"Languagearts"
+            },
+            {
+                "id":"2",
+                "name":"Mathematics"
+            },
+            {
+                "id":"3",
+                "name":"Science"
+            }
+        ],
         "grades": [
             {
                 "id": "1",

+ 11 - 0
TEAMModelOS/ClientApp/src/store/module/answerSheet.js

@@ -27,6 +27,7 @@ export default {
 		count: 0,
 		pages: 1,
 		isNewPage: false,
+		isAutoCreate:false,
 		needFixArr: [26],
 		paperItem:{
 			name:''
@@ -65,9 +66,19 @@ export default {
 	},
 
 	mutations: {
+		setCreateModal(state,val){
+			state.isAutoCreate = val === 'auto'
+		},
 		setPaper(state,val){
 			state.paperItem = val
 		},
+		setPaperItems(state,val){
+			state.paperItem.item = val
+		},
+		deleteItem(state,val){
+			let index = state.paperItem.item.map(i => i.id).indexOf(val)
+			state.paperItem.item.splice(index,1)
+		},
 		addPage(state) {
 			state.pages++
 		},

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

@@ -24,13 +24,13 @@ export default {
             roles: []
         },
         paperInfo: {},
-        Item: {}, //存放活動相關的狀態
+        Item: {}, //存放当前活動相關的狀態
         examInfo: {},
         tempfinishedItem: [], //用來暫存目前完成的項目ID
         tempfinishedItemtime: [],
         CountedIsDonePercent: myMockData.initialfinishResult, //存放活動完成度值,初始值先從Api抓資料,後續透過vuex抓狀態變化
         filterType: "all", //存放篩選活動類型
-        isSelectedNow: false,
+        isSelectedNow: false, //是否选中活动
 
         CurrentSelectedReadingName: " ", //存放課前預習活動目前所選中的教材名稱
         isSelectedReadingNow: false,

+ 49 - 16
TEAMModelOS/ClientApp/src/store/module/teachers.js

@@ -18,31 +18,24 @@ export default {
                 (resolve, reject) => {
                     if (context.state.teacherList.length == 0) {
                         apiTools.courseMgmt.getSchoolTeacher({
-                            'school_code': context.rootState.userInfo.schoolCode 
+                            'school_code': context.rootState.userInfo.schoolCode
                         }).then(
                             (res) => {
                                 if (res) {
-                                    if (res.teachers.length > 0) {
-                                        context.commit('setTeacherList', res.teachers)
-                                        resolve({
-                                            code: 1,
-                                            message: '数据请求成功'
-                                        })
-                                    } else {
-                                        resolve({
-                                            code: 2,
-                                            message: '请求成功,数据为空'
-                                        })
-                                    }
-                                } else {
+                                    context.commit('setTeacherList', res.teachers)
                                     resolve({
+                                        data: res.teachers,
+                                        message: '数据请求成功'
+                                    })
+                                } else {
+                                    reject({
                                         code: 0,
                                         message: '请求失败,API error!'
                                     })
                                 }
                             },
                             (err) => {
-                                resolve({
+                                reject({
                                     code: 0,
                                     message: '请求失败,API error!'
                                 })
@@ -50,11 +43,51 @@ export default {
                         )
                     } else {
                         resolve({
-                            code: 3,
+                            data: context.state.teacherList,
                             message: '数据已请求,无需重复请求'
                         })
                     }
                 }
+                // (resolve, reject) => {
+                //     if (context.state.teacherList.length == 0) {
+                //         apiTools.courseMgmt.getSchoolTeacher({
+                //             'school_code': context.rootState.userInfo.schoolCode 
+                //         }).then(
+                //             (res) => {
+                //                 if (res) {
+                //                     if (res.teachers.length > 0) {
+                //                         context.commit('setTeacherList', res.teachers)
+                //                         resolve({
+                //                             code: 1,
+                //                             message: '数据请求成功'
+                //                         })
+                //                     } else {
+                //                         resolve({
+                //                             code: 2,
+                //                             message: '请求成功,数据为空'
+                //                         })
+                //                     }
+                //                 } else {
+                //                     resolve({
+                //                         code: 0,
+                //                         message: '请求失败,API error!'
+                //                     })
+                //                 }
+                //             },
+                //             (err) => {
+                //                 resolve({
+                //                     code: 0,
+                //                     message: '请求失败,API error!'
+                //                 })
+                //             }
+                //         )
+                //     } else {
+                //         resolve({
+                //             code: 3,
+                //             message: '数据已请求,无需重复请求'
+                //         })
+                //     }
+                // }
             )
         }
     }

+ 12 - 12
TEAMModelOS/ClientApp/src/store/module/user.js

@@ -232,29 +232,29 @@ export default {
         setSchoolCode(state, data) {
             state.schoolCode = data
         },
-        addClasses(state, data) {
+        addRoom(state, data) {
             let school_profile = localStorage.getItem('school_profile')
             if(school_profile){
                 let schoolProfile = JSON.parse(decodeURIComponent(school_profile,"utf-8"))
-                schoolProfile.school_classes.unshift(data)
-                state.schoolProfile.school_classes = schoolProfile.school_classes
+                schoolProfile.school_rooms.unshift(data)
+                state.schoolProfile.school_rooms = schoolProfile.school_rooms
                 localStorage.setItem('school_profile', encodeURIComponent(JSON.stringify(schoolProfile), "utf-8"))
             }
         },
-        delClasses(state, id) {
+        delRoom(state, id) {
             let school_profile = localStorage.getItem('school_profile')
             if(school_profile){
                 let schoolProfile = JSON.parse(decodeURIComponent(school_profile,"utf-8"))
                 let orgIndex = -1;
 
-                for (let i in schoolProfile.school_classes) {
-                    if (schoolProfile.school_classes[i].id == id) {
+                for (let i in schoolProfile.school_rooms) {
+                    if (schoolProfile.school_rooms[i].id == id) {
                         orgIndex = i
                         break
                     }
                 }
-                schoolProfile.school_classes.splice(orgIndex, 1) // 刪掉指定教室
-                state.schoolProfile.school_classes = schoolProfile.school_classes
+                schoolProfile.school_rooms.splice(orgIndex, 1) // 刪掉指定教室
+                state.schoolProfile.school_rooms = schoolProfile.school_rooms
                 localStorage.setItem('school_profile', encodeURIComponent(JSON.stringify(schoolProfile), "utf-8"))
             }
         },
@@ -734,13 +734,13 @@ export default {
         },
         
         // 新增教室
-        addSchoolClasses(context, data) {
-            context.commit('addClasses', data)
+        addSchoolRoom(context, data) {
+            context.commit('addRoom', data)
         },
 
         // 刪除教室
-        delSchoolClasses(context, id) {
-            context.commit('delClasses', id)
+        delSchoolRoom(context, id) {
+            context.commit('delRoom', id)
         },
     }
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/utils/blobTool.js

@@ -272,7 +272,7 @@ export default class BlobTool {
         let parseRes = []
         let names = []
         fileList.forEach((item, index) => {
-            if (item.url.indexOf('/res/') > 0) {
+            if (item.url.indexOf('/res/') > 0 && item.url.indexOf('.HTE') < 0) {
                 let fileItem = {}
                 let startIndex = JsFn.findChartIndex(item.blob, '/', 1)
                 let endIndex = JsFn.findChartIndex(item.blob, '/', 2)

文件差異過大導致無法顯示
+ 4407 - 0
TEAMModelOS/ClientApp/src/utils/distpicker.js


+ 2 - 0
TEAMModelOS/ClientApp/src/utils/evTools.js

@@ -320,6 +320,8 @@ export default {
 	
 	/* 获取完整的试卷数据 */
 	getFullPaper(paper,examScope){
+		console.log(paper)
+		console.log(examScope)
 		let curScope = examScope || paper.examScope || paper.scope
 		return new Promise(async (r,j) => {
 			let blobHost = curScope === 'school' ?  JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")).blob_uri :  JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8")).blob_uri

+ 0 - 371
TEAMModelOS/ClientApp/src/utils/items.json

@@ -1,371 +0,0 @@
-[
-    {
-        "id":1,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":2,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":3,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":4,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":5,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":6,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":7,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":8,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":9,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":10,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":11,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":12,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":13,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":14,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "single",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":15,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":5,
-        "answer": [],
-        "explain": null,
-        "type": "judge",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":16,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "multiple",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":17,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1],
-        "answer": [],
-        "explain": null,
-        "type": "multiple",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":18,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1],
-        "answer": [],
-        "explain": null,
-        "type": "multiple",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":19,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":1,
-        "answer": [],
-        "explain": null,
-        "type": "complete",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":20,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":1,
-        "answer": [],
-        "explain": null,
-        "type": "complete",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":21,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":1,
-        "answer": [],
-        "explain": null,
-        "type": "complete",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":22,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":1,
-        "answer": [],
-        "explain": null,
-        "type": "complete",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":23,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":1,
-        "answer": [],
-        "explain": null,
-        "type": "complete",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":24,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":1,
-        "answer": [],
-        "explain": null,
-        "type": "complete",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":25,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "complete",
-        "scope": "school",
-        "score":8
-    },
-    
-    {
-        "id":26,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":27,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":28,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":29,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":30,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":31,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":32,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":33,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":34,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    },
-    {
-        "id":35,
-        "question": " 下列语句中加点的成语使用不正确的一项是",
-        "option": [1,1,1,1,1],
-        "blankCount":2,
-        "answer": [],
-        "explain": null,
-        "type": "subjective",
-        "scope": "school",
-        "score":8
-    }
-]

文件差異過大導致無法顯示
+ 2 - 0
TEAMModelOS/ClientApp/src/utils/jquery.js


+ 184 - 31
TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue

@@ -3,13 +3,13 @@
 		<div :id="ids + 'btn'" class="base-editor-tools" v-show="isShowTools">
 <!-- 		<div :id="ids + 'btn'" class="base-editor-tools" v-show="isShowTools" @mouseenter="isShowTools = true" @mouseleave="isShowTools = false"> -->
 			<span class="select-model" @click="onSelectModal" v-if="type !== '0'">编辑</span>
-			<span class="select-model btn-delete" @click="onDeleteBlock">删除</span>
+			<span class="select-model btn-delete" @click="onDeleteBlock" v-if="!isAutoCreate">删除</span>
 		</div>
 		<p class="margin-block"></p>
 		<!-- <div @mouseenter="isShowTools = true" @mouseleave="isShowTools = false"> -->
 		<div >
 			<div :id="ids" class="sheet-Editor" ></div>
-			<div v-for="(item,index) in fixArr" :id="ids + 'fix' + index" class="sheet-Editor" v-show="type !== '0'"></div>
+			<div v-for="(item,index) in fixArr" :id="ids + 'fix' + index" class="sheet-Editor"></div>
 		</div>
 
 		<Modal v-model="isShowSelectModel" title="设置内容格式" width="600px" @on-ok="doSelectModel">
@@ -69,10 +69,6 @@
 				type: Array,
 				default: () => [],
 			},
-			allItems: {
-				type: Array,
-				default: () => [],
-			},
 			type: {
 				type: String,
 				default: "",
@@ -80,6 +76,7 @@
 		},
 		data() {
 			return {
+				preTop:0,
 				fixArr:[],
 				pArr:[],
 				isShowTools:false,
@@ -92,7 +89,8 @@
 				completeItems: [],
 				isNewPage: false,
 				pageCount: 1,
-				curEditorSetting: null
+				curEditorSetting: null,
+				curItemId:null
 			};
 		},
 		methods: {
@@ -103,15 +101,22 @@
 
 			/* 删除当前富文本块 */
 			onDeleteBlock() {
+				console.log(this.curItemId)
+				if(this.type === '1'){
+					this.$store.commit('deleteItem',this.curItemId)
+					this.$parent.subjectiveItems.splice(this.$parent.subjectiveItems.map(i => i.id).indexOf(this.curItemId),1)
+				}
 				document.getElementById(this.ids).remove()
 				document.getElementById(this.ids + 'btn').remove()
 				this.myEditor.destroy()
 				this.myEditor = null
 				this.$EventBus.$emit('doRefresh')
+				this.$EventBus.$emit('deleteItem',this.type)
 			},
 
 			/* 切换富文本显示模式(简答题、语文作文、英语作文)*/
 			doSelectModel() {
+				console.log(this.curModel)
 				let editor = this.myEditor
 				editor.txt.clear()
 				let allItemIds = this.$store.state.answerSheet.paperItem.item.map(i => i.id)
@@ -167,39 +172,107 @@
 			doInsertComplete(items) {
 				let underLineSpaceCount = 45;
 				let allItemIds = this.$store.state.answerSheet.paperItem.item.map(i => i.id)
+				this.fixArr = []
 				this.$nextTick(() => {
-					console.log(this.myEditor.$textElem.elems[0].scrollHeight)
 					this.myEditor.txt.html('<span></span>')
 				})
+				let totalStr = '' // 填空题总体富文本
+				let lineBlankCount = 0 //总空格数
+				let lineStr = '' //每一行的富文本
+				// 遍历所有填空题 生成对应题目的空格
 				items.forEach((item, index) => {
 					item.blankCount = item.blankCount || 1
-					let addStr = allItemIds.indexOf(item.id) + 1 + "";
+					let addStr = this.isAutoCreate ? (allItemIds.indexOf(item.id) + 1) : item.order + "";
 					for (let blankIndex = 0; blankIndex < item.blankCount; blankIndex++) {
 						addStr =
 							addStr +
 							'<span class="underline">' +
 							new Array(underLineSpaceCount).fill("&nbsp;").join("") +
 							"</span>";
+						lineBlankCount += item.blankCount
+					}
+					// 如果空格数量默认渲染状态下到3 则需要换行
+					if(lineBlankCount % 3 !== 0){
+						lineStr += `<span class='complete-item'>${addStr}</span>`
+						// 如果是最后一排 则直接渲染 不需要排满
+						if(index === items.length - 1){
+							lineStr = '<p>' + lineStr + '</p>'
+							totalStr += lineStr
+						}
+					}else{
+						lineStr += `<span class='complete-item'>${addStr}</span>`
+						lineStr = '<p>' + lineStr + '</p>'
+						totalStr += lineStr
+						lineStr = ''
+						lineBlankCount = 0
 					}
-					this.$nextTick(() => {
-						this.myEditor.txt.append(`<span class='complete-item'>${addStr}</span>`);
-					});
 				});
 				this.$nextTick(() => {
+					this.myEditor.txt.append(totalStr);
 					this.myEditor.config.height = this.myEditor.$textElem.elems[0].clientHeight
+					let scrollDom = this.$parent.$parent.$parent.$parent.$parent.$refs["evScroll"]
+					if (!scrollDom) return
+					setTimeout(() => {
+						let editorDom = this.myEditor.$textElem.elems[0]
+						this.pArr = Array.from(editorDom.getElementsByTagName('p'))
+						let scrollDis = scrollDom.getPosition().scrollTop
+						let Y = editorDom.getBoundingClientRect().top + scrollDis - 90;
+						let paperH = PAPER_H;
+						let lastBottomGap = 20;
+						let curEditorY = Y > paperH ? +((Y % paperH).toFixed(4)) : Y;
+						let curEditorH = editorDom.clientHeight;
+						let leftHeight = paperH - curEditorY - lastBottomGap - SVG_BORDER_MB;
+						let fixHeight = curEditorH - leftHeight + 20
+						if ( curEditorY + curEditorH + lastBottomGap + SVG_BORDER_MB > PAPER_H) {
+							// 如果剩余高度不满足渲染 并且需要补充的区域 则需要进行跨页处理
+							if (leftHeight > 100) {
+								this.$store.commit("addPage");
+								let heightArr = []
+								this.myEditor.config.height = leftHeight + 20;
+								heightArr.push(leftHeight)
+								// 如果渲染的客观题高度在这个区间 才需要在下一页添加补充作答区域 其余全部按照正常 跨页处理不需要补充作答区域
+								let fixCount = Math.ceil(fixHeight / SVG_BORDER_PROP.height)
+								console.log("需要处理跨页,数量为" + fixCount);
+								console.log("剩余渲染高度" + fixHeight);
+								for(let i = 0;i < fixCount;i++){
+									this.fixArr.push(0)
+										let curFixHeight = fixHeight > SVG_BORDER_PROP.height  ? SVG_BORDER_PROP.height - 30 : fixHeight
+										heightArr.push(curFixHeight)
+										fixHeight = fixHeight - SVG_BORDER_PROP.height
+									if(i > 0) {
+										console.log('fix添加页码')
+										this.$store.commit("addPage");
+									}
+								}
+								this.$nextTick(() => {
+									let splitHtmlArr = this.getSplitHtml(this.pArr,heightArr)
+									splitHtmlArr.forEach((curEditorContent,editorIndex) => {
+										console.log('填空题富文本的分割高度',heightArr)
+										console.log('填空题富文本的分割',splitHtmlArr)
+										
+										let editorHeight = curEditorContent.html === '' ? heightArr[editorIndex] : heightArr[editorIndex]
+										// let curEditorContent = this.getSplitHtml(this.pArr,curEditorHeight)
+										if(editorIndex !== 0){
+											this.initFixEditor(this.ids + 'fix' + (editorIndex - 1), editorHeight, curEditorContent.html)
+										}else{
+											this.myEditor.txt.clear();
+											this.myEditor.txt.html('<span></span>')
+											this.myEditor.txt.append(curEditorContent.html);
+										}
+									})
+								})
+							} else {
+								// 跨页处理不需要补充作答区域
+								this.$store.commit("addPage");
+								document.getElementById(this.ids).style.marginTop = (PAPER_H - curEditorY + lastBottomGap + SVG_BORDER_PROP.y) + "px";
+								document.getElementById(this.ids + 'btn').style.top = (PAPER_H - curEditorY + lastBottomGap + SVG_BORDER_PROP.y + 20) + "px";
+							}
+						}else {
+							document.getElementById(this.ids + 'btn').style.top =  "20px";
+						}
+					})
 				});
 			},
-			
-			nodeToString ( node ) {  
-			    //createElement()返回一个Element对象
-			   var tmpNode = document.createElement( "div" ); 
-			   //appendChild()  参数Node对象   返回Node对象  Element方法
-			   //cloneNode()  参数布尔类型  返回Node对象   Element方法
-			   tmpNode.appendChild( node.cloneNode( true ) );  
-			   var str = tmpNode.innerHTML;  
-			   tmpNode = node = null; // prevent memory leaks in IE  
-			   return str;  
-			  } ,
 
 			// 渲染问答题
 			doInsertSubjective(items) {
@@ -210,38 +283,78 @@
 					let scrollDis = scrollDom.getPosition().scrollTop
 					let allItemIds = this.$store.state.answerSheet.paperItem.item.map(i => i.id)
 					let subjectiveItem = items[0];
-					let itemOrder = allItemIds.indexOf(subjectiveItem.id) + 1;
+					// 拿到当前题目序号
+					let itemOrder = this.isAutoCreate ? allItemIds.indexOf(subjectiveItem.id) + 1 : subjectiveItem.order;
+					this.curItemId = subjectiveItem.id
+					// 拿到默认序号富文本内容
 					let addStr = '<p>' +  itemOrder + "(" + (subjectiveItem.score + "分)") + '</p>'; // 渲染题号
+					
+					// 默认简答题内容
 					let defaultBrCounts = 1; // 问答题默认回答区域空行数量
 					let brHtml = new Array(defaultBrCounts).fill("<p><br></p>").join("");
 					this.myEditor.txt.html('<span></span>')
+					
+					// 如果vuex有保存 之前的文本内容 则渲染 否则按照默认只显示题号
 					let curSetting = this.hasEditorSetting(this.ids)
 					if (curSetting && curSetting.content) {
 						this.myEditor.txt.append(curSetting.content);
 					}else{
 						this.myEditor.txt.append(addStr + brHtml);
 					}
+					
+					// 如果自定义插入的是作文题 则进行对应题型渲染
+					console.log('插入的主观题',subjectiveItem)
+					if(subjectiveItem.maxWords > 0){
+						this.myEditor.txt.clear()
+						addStr = '<p>' +  itemOrder + "、 作文(" + (subjectiveItem.score + "分)") + '</p>'; 
+						let newContent = ''	
+						let wordCount = subjectiveItem.maxWords
+						let singleStr = '<span class="cell-item"></span>';
+						let lines = wordCount / 18
+						let allHtml = ''
+						for(let i = 0 ; i < lines; i++){
+							allHtml += '<p>' + singleStr.repeat(18) + '</p>'
+						}
+						this.myEditor.config.height = lines * 40 + 60
+						newContent = addStr + '<p><br></p>' + allHtml
+						this.myEditor.txt.html(newContent);
+					}else if(subjectiveItem.maxLines > 0){
+						this.myEditor.txt.clear()
+						addStr = '<p>' +  itemOrder + "、 作文(" + (subjectiveItem.score + "分)") + '</p>'; 
+						let newContent = ''
+						let lineCount = subjectiveItem.maxLines
+						let allHtml = ''
+						let singleStr = '<span class="underline" style="display:inline;line-height:35px">' + new Array(182).fill("&nbsp;").join("") + "</span>";
+						for(let i = 0 ; i < lineCount ; i++){
+							allHtml += '<p>' + singleStr+ '</p>'
+						}
+						this.myEditor.config.height = lineCount * 35 + 50
+						newContent = addStr + allHtml
+						this.myEditor.txt.html(newContent);
+					}
+					
 					this.pArr = Array.from(editorDom.getElementsByTagName('p'))
 					let scrollHeight = editorDom.scrollHeight
 					setTimeout(() => {
 						let isNewPage = this.$store.state.answerSheet.isNewPage;
 						let lastBottomGap = 20;
-						let Y = editorDom.getBoundingClientRect().top + scrollDis - 90;
+						let rectTop = editorDom.getBoundingClientRect().top
+						let Y = rectTop + scrollDis - 90;
 						let paperH = PAPER_H;
 						let curEditorY = Y > paperH ? +((Y % paperH).toFixed(4)) : Y;
 						let curEditorH = editorDom.clientHeight; // 默认200px
-						// console.log(itemOrder, '当前Y', curEditorY);
+						console.log(itemOrder, 'rectTop', rectTop);
+						console.log(itemOrder, 'scrollDis', scrollDis);
+						console.log(itemOrder, '当前Y', Y);
 						let leftHeight = paperH - curEditorY - lastBottomGap - SVG_BORDER_MB;
 						console.log(itemOrder, '高度', curEditorH)
 						console.log(itemOrder, 'LEFT高度', leftHeight)
 						let fixHeight = curEditorH - leftHeight + 20
-						// console.log(itemOrder, '需要fix的高度', fixHeight)
+						console.log(itemOrder, '需要fix的高度', fixHeight)
 						// 如果 渲染当前富文本的时候 需要渲染的高度超过当前页的剩余高度 则需要进行加页处理
-						if (
-							curEditorY + curEditorH + lastBottomGap + SVG_BORDER_MB > PAPER_H
-						) {
+						if (curEditorY + curEditorH + lastBottomGap + SVG_BORDER_MB > PAPER_H) {
 							// console.log(itemOrder, Y , curEditorY , curEditorH , '超出了')
-							// 如果剩余高度不满足渲染 并且需要补充的区域 则需要进行跨页处理
+							// 如果剩余高度满足渲染一部分区域 并且需要补充的区域 则需要进行跨页处理
 							if (leftHeight > 100) {
 								this.$store.commit("addPage");
 								console.log(itemOrder, '需要增加页码')
@@ -290,12 +403,15 @@
 							document.getElementById(this.ids + 'btn').style.top =  "20px";
 						}
 						this.$root.$children[0].spinShow = false;
+						
+						
 					}, 0);
 					
 					
 				});
 			},
 			
+			// 跨页内容分割处理
 			getSplitHtml(pArr,heightArr){
 				let result = []
 				heightArr.forEach(height => {
@@ -321,6 +437,18 @@
 				return result
 			},
 			
+			// 将NODE转换成字符串
+			nodeToString ( node ) {  
+			    //createElement()返回一个Element对象
+			   var tmpNode = document.createElement( "div" ); 
+			   //appendChild()  参数Node对象   返回Node对象  Element方法
+			   //cloneNode()  参数布尔类型  返回Node对象   Element方法
+			   tmpNode.appendChild( node.cloneNode( true ) );  
+			   var str = tmpNode.innerHTML;  
+			   tmpNode = node = null; // prevent memory leaks in IE  
+			   return str;  
+			  } ,
+			
 			define({
 				editor,
 				prop,
@@ -374,6 +502,8 @@
 					function mouseup() {
 						document.removeEventListener("mousemove", mousemove);
 						document.removeEventListener("mouseup", mouseup);
+						let editorDom = that.myEditor.$textElem.elems[0]
+						that.preTop = editorDom.getBoundingClientRect().top
 						// 如果是补充区域 则需要把高度计算到主区域 进行重新渲染
 						if(curId.includes('fix')){
 							let mainEditorId = curId.split('fix')[0]
@@ -398,6 +528,9 @@
 								content:editor.txt.html()
 							})
 						}
+						let scrollDom = that.$parent.$parent.$parent.$parent.$parent.$refs["evScroll"]
+						localStorage.setItem('scrollDis',scrollDom.getPosition().scrollTop)
+						
 						that.$EventBus.$emit('doRefresh')
 					}
 					// 将鼠标事件绑定到 document 上
@@ -609,17 +742,37 @@
 					return this.$store.state.answerSheet.editorInfos[ids]
 				}
 			},
+			// 是否为根据试卷自动生成的答题卡
+			isAutoCreate(){
+				return this.$store.state.answerSheet.isAutoCreate
+			}
 		},
 		watch: {
 			items: {
 				handler(n, o) {
 					if (n.length) {
+						console.log(n)
 						let objectiveArr = ["complete"];
 						this.completeItems = n.filter((item) =>
 							objectiveArr.includes(item.type)
 						);
 						this.curPropItem = this.type === "0" ? this.completeItems : n;
 						this.doRenderEditor(this.curPropItem);
+						if(this.type !== "0"){
+							// setTimeout(() => {
+							// 	if(n[0].maxWords > 0){
+							// 		console.log('语文作文',n.maxWords)
+							// 		this.wordCount = n[0].maxWords
+							// 		this.curModel = '3'
+							// 		this.doSelectModel()
+							// 	}else if(n[0].maxLines > 0){
+							// 		console.log('英语作文',n.maxLines)
+							// 		this.lineCount = n[0].maxLines
+							// 		this.curModel = '2'
+							// 		this.doSelectModel()
+							// 	}
+							// },3000)
+						}
 					}
 				},
 				immediate: true,

+ 2 - 2
TEAMModelOS/ClientApp/src/view/answersheet/BaseSvgBg.vue

@@ -61,8 +61,8 @@
 						)
 						.attr({
 							fill: radixArr.split('')[index] === '1' ? '#000' : "none",
-							stroke: "#000",
-							strokeWidth: 1
+							stroke: "#000000",
+							strokeWidth: radixArr.split('')[index] === '1' ? 0 : 1
 						})
 					);
 				}

+ 1 - 1
TEAMModelOS/ClientApp/src/view/answersheet/SheetBaseInfo.vue

@@ -232,7 +232,7 @@ export default {
   left: 0;
   top: 0;
   width: 750px;
-  height: 340px;
+  height: 342px;
 }
 
 /* .sheet-info-container:hover .info-edit{

+ 14 - 4
TEAMModelOS/ClientApp/src/view/answersheet/SheetComplete.vue

@@ -7,7 +7,9 @@
   >
     <!-- <p style="margin-left: 100px; font-weight: bold; color: #000">二、填空题(共{{ completeItems.length }}题,总计 {{ totalScore }} 分)</p> -->
     <!-- <BaseTitleEditor ids="completeTitleEditor" :content="'二、填空题(共' + completeItems.length + '题,总计' + totalScore + '分)'"></BaseTitleEditor> -->
-    <BaseEditor ids="completeEditor" :items="items" type="0"></BaseEditor>
+	<div  v-if="isRender">
+		<BaseEditor ids="completeEditor" :items="items" type="0"></BaseEditor>
+	</div>
   </div>
 </template>
  
@@ -50,6 +52,7 @@ export default {
   components:{ BaseEditor,BaseTitleEditor },
   data() {
     return {
+	  isRender:true,
       isShowInfoEdit: false,
       editModal: false,
       completeGroup: null,
@@ -64,9 +67,16 @@ export default {
   },
   methods: {
   },
-  mounted: function () {
-    // this.snap = Snap("#sheetCompleteSvg");
-    // this.completeGroup = this.snap.paper.g();
+  mounted() {
+    this.$EventBus.$on("doRefresh", () => {
+      this.isRender = false
+      setTimeout(() => {
+        this.$store.commit('clearFixArr')
+        this.$store.commit('clearPage')
+        // document.getElementById('pdfDom').scrollIntoView()
+        this.isRender = true
+      },)
+    });
   },
   computed:{
     totalScore(){

+ 348 - 335
TEAMModelOS/ClientApp/src/view/answersheet/SheetObjective.vue

@@ -1,352 +1,365 @@
 <template>
-  <div
-    class="sheet-objective-container"
-    ref="baseInfoRef"
-    @mouseout="isShowInfoEdit = false"
-    @mouseover="isShowInfoEdit = true"
-  >
-    <!-- <p style="margin-left: 100px; font-weight: bold; color: #000">一、选择题</p> -->
-    <!-- <BaseTitleEditor ids="objectiveTitleEditor" :content="'一、选择题(共' + objectiveItems.length + '题,总计' + totalScore + '分)'"></BaseTitleEditor> -->
-    <svg
-      id="sheetObjectiveSvg"
-      width="100%"
-      :style="'height:' + svgHeight + 'px'"
-    ></svg>
-    <div class="info-edit" v-show="isShowInfoEdit" @click="editModal = true">
-      <span>编辑</span>
-    </div>
-    <Modal v-model="editModal" title="配置基本信息项" @on-ok="onReRender">
-      <p class="edit-title">每列显示题数</p>
-      <InputNumber
-        :max="objectiveItems.length"
-        :min="3"
-        v-model="number"
-      ></InputNumber>
-    </Modal>
-  </div>
+	<div class="sheet-objective-container" ref="baseInfoRef" @mouseout="isShowInfoEdit = false"
+		@mouseover="isShowInfoEdit = true">
+		<!-- <p style="margin-left: 100px; font-weight: bold; color: #000">一、选择题</p> -->
+		<!-- <BaseTitleEditor ids="objectiveTitleEditor" :content="'一、选择题(共' + objectiveItems.length + '题,总计' + totalScore + '分)'"></BaseTitleEditor> -->
+		<svg id="sheetObjectiveSvg" width="100%" :style="'height:' + svgHeight + 'px'"></svg>
+		<div class="info-edit" v-show="isShowInfoEdit">
+			<span @click="editModal = true" style="background-color: #00a43a;">编辑</span>
+			<span @click="doDelete" style="background-color: red;" v-if="!isAutoCreate">删除</span>
+		</div>
+		<Modal v-model="editModal" title="配置基本信息项" @on-ok="onReRender">
+			<p class="edit-title">每列显示题数</p>
+			<InputNumber :max="objectiveItems.length" :min="3" v-model="number"></InputNumber>
+		</Modal>
+	</div>
 </template>
- 
+
 <script>
-import BaseTitleEditor from './BaseTitleEditor'
-import Snap from "imports-loader?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js";
-import {
-  PAPER_W,
-  PAPER_H,
-  CONTENT_MT,
-  CONTENT_ML,
-  ANCHORPROP,
-  CONTENT_START_X,
-  CONTENT_START_Y,
-  INFO_W,
-  INFO_H,
-  INFO_ITEM_GAP,
-  INFO_ITEM_MARGIN,
-  ID_LENGTH,
-  INFO_LEFT_X,
-  INFO_LEFT_W,
-  ID_TITLE_H,
-  ID_TITLE_Y,
-  NUMBER_CELL_H,
-  NUMBER_ITEM_W,
-  NUMBER_ITEM_H,
-  NUMBER_ITEM_MT,
-  NUMBER_ITEM_ML,
-  BLOCK_H
-} from "@/utils/sheetConfig.js";
-export default {
-  props: {
-    items: {
-      type: Array,
-      default: () => {
-        return [];
-      },
-    },
-  },
-  components: { BaseTitleEditor },
-  data() {
-    return {
-      isShowInfoEdit: false,
-      editModal: false,
-      objectiveGroup: null,
-      snap: null,
-      svgHeight: 0,
-      number: 5,
-      blockHeight:0,
-      objectiveItems: [],
-      leftItems:[],
-      blockList:[],
-      anchorRectY:0
-    };
-  },
-  created() {
-    this.snap = Snap("#sheetObjectiveSvg");
-  },
-  methods: {
-    // 修改每列展示题数重新渲染
-    onReRender() {
-      this.leftItems = JSON.parse(JSON.stringify(this.objectiveItems))
-      this.doRenderItems(this.objectiveItems, this.number);
-	  this.$EventBus.$emit('doRefresh')
-    },
+	import BaseTitleEditor from './BaseTitleEditor'
+	import Snap from "imports-loader?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js";
+	import {
+		PAPER_W,
+		PAPER_H,
+		CONTENT_MT,
+		CONTENT_ML,
+		ANCHORPROP,
+		CONTENT_START_X,
+		CONTENT_START_Y,
+		INFO_W,
+		INFO_H,
+		INFO_ITEM_GAP,
+		INFO_ITEM_MARGIN,
+		ID_LENGTH,
+		INFO_LEFT_X,
+		INFO_LEFT_W,
+		ID_TITLE_H,
+		ID_TITLE_Y,
+		NUMBER_CELL_H,
+		NUMBER_ITEM_W,
+		NUMBER_ITEM_H,
+		NUMBER_ITEM_MT,
+		NUMBER_ITEM_ML,
+		BLOCK_H
+	} from "@/utils/sheetConfig.js";
+	export default {
+		props: {
+			items: {
+				type: Array,
+				default: () => {
+					return [];
+				},
+			},
+		},
+		components: {
+			BaseTitleEditor
+		},
+		data() {
+			return {
+				isShowInfoEdit: false,
+				editModal: false,
+				objectiveGroup: null,
+				snap: null,
+				svgHeight: 0,
+				number: 5,
+				blockHeight: 0,
+				objectiveItems: [],
+				leftItems: [],
+				blockList: [],
+				anchorRectY: 0
+			};
+		},
+		created() {
+			this.snap = Snap("#sheetObjectiveSvg");
+		},
+		methods: {
+			doDelete() {
+				this.$EventBus.$emit('deleteItem', 'objective')
+			},
+			// 修改每列展示题数重新渲染
+			onReRender() {
+				this.leftItems = JSON.parse(JSON.stringify(this.objectiveItems))
+				this.doRenderItems(this.objectiveItems, this.number);
+				this.$EventBus.$emit('doRefresh')
+			},
+
+			// 渲染客观题区域边框
+			doRenderBorder(items, number, blockCount) {
+				let snap = this.snap;
+				let objectiveHeight = 40 + this.blockHeight * blockCount;
+				this.svgHeight = this.anchorRectY + 40;
+				// 信息框
+				let infoBox = snap
+					.rect(CONTENT_START_X, 2, INFO_W, this.anchorRectY + 20)
+					.attr({
+						fill: "rgba(0,0,0,0)",
+						stroke: "#000"
+					});
+				this.objectiveGroup.add(infoBox);
+				this.$EventBus.$emit('doRefresh')
+			},
+
+			// 渲染客观题目
+			doRenderItems(items, number) {
+				this.blockHeight = 26 * number
+				this.objectiveGroup && this.objectiveGroup.remove(); // 先清除之前的绘制内容
+				if (this.snap) {
+					this.objectiveGroup = this.snap.paper.g();
+				}
+				let snap = this.snap;
+				let MARGIN_LEFT = 25;
+				let GAP = 22;
+				let optionGap = NUMBER_ITEM_W + 5;
+				let startY = GAP + 15;
+
+				let needNewLineArr = items.map((item, index) =>
+					this.needNewLine(index, number, items)
+				);
+				let indexAndNeed = [];
+				// 提前计算 每个题目排列时 是否要进行换行 以及计算需要换到第几行 (行可以理解为选项块)
+				for (let jIndex = 0; jIndex < needNewLineArr.length; jIndex++) {
+					if (needNewLineArr[jIndex].need) {
+						indexAndNeed.push({
+							index: jIndex,
+							need: true,
+						});
+					}
+				}
+				let itemsPositionArr = [];
+				// 提前计算 每个题目排列时 是否要进行换行 以及计算需要换到第几行 (行可以理解为选项块)
+				for (let index = 0; index < items.length; index++) {
+					itemsPositionArr.push({
+						index: index,
+						needNewLine: needNewLineArr[index].need,
+						lineIndex: needNewLineArr[index].blockIndex
+					});
+				}
+				let blockList = [...new Set(itemsPositionArr.map(i => i.lineIndex))]
+				this.blockList = blockList
+
+				items.forEach((item, index) => {
+					if (index > 0 && (itemsPositionArr[index].lineIndex !== itemsPositionArr[index - 1]
+						.lineIndex)) {
+						this.leftItems = this.leftItems.slice(index, this.leftItems.length)
+					}
+					let optionX = CONTENT_START_X + MARGIN_LEFT + this.getStartX(number, this.leftItems, item.id);
+					let optionY = startY + GAP * (index + 1 <= number ? index : index % number) + ((
+						itemsPositionArr[index].lineIndex + 1) * this.blockHeight)
+					// console.log(index,optionX)
+					// 渲染选项下标
+					let itemOrder = snap
+						.text(
+							optionX,
+							optionY,
+							this.isAutoCreate ? index + 1 : item.order
+						)
+						.attr({
+							textAnchor: "end",
+							width: 40,
+							fontSize: 12,
+							fontFamily: "Times New Roman",
+						});
+					this.objectiveGroup.add(itemOrder);
 
-    // 渲染客观题区域边框
-    doRenderBorder(items, number, blockCount) {
-      let snap = this.snap;
-      let objectiveHeight = 40 + this.blockHeight * blockCount;
-      this.svgHeight = this.anchorRectY + 40;
-      // 信息框
-      let infoBox = snap
-        .rect(CONTENT_START_X, 2, INFO_W, this.anchorRectY + 20)
-        .attr({ fill: "rgba(0,0,0,0)", stroke: "#000" });
-      this.objectiveGroup.add(infoBox);
-    },
+					item.option.forEach((option, optionIndex) => {
+						let code = String.fromCharCode(
+							64 + parseInt(optionIndex + 1)
+						).toLowerCase();
+						// 渲染选项图片
+						// let img = require("../../icons/answersheet/" + code + ".svg");
+						let img = require('@/icons/answersheet/' + code + '.svg');
+						let trueSvg = require('@/icons/answersheet/t.svg');
+						let falseSvg = require('@/icons/answersheet/f.svg');
+						let c3 = snap.image(
+							item.type !== 'judge' ? img : optionIndex === 0 ? trueSvg : falseSvg,
+							optionX + NUMBER_ITEM_ML + optionGap * optionIndex,
+							optionY - 10,
+							NUMBER_ITEM_W,
+							NUMBER_ITEM_H
+						);
+						this.objectiveGroup.add(c3);
+					});
 
-    // 渲染客观题目
-    doRenderItems(items, number) {
-      this.blockHeight = 26 * number
-      this.objectiveGroup && this.objectiveGroup.remove(); // 先清除之前的绘制内容
-	  if(this.snap) {
-		 this.objectiveGroup = this.snap.paper.g();
-	  }
-      let snap = this.snap;
-      let MARGIN_LEFT = 25;
-      let GAP = 22;
-      let optionGap = NUMBER_ITEM_W + 5;
-      let startY = GAP + 15;
-      
-      let needNewLineArr = items.map((item, index) =>
-        this.needNewLine(index, number, items)
-      );
-      let indexAndNeed = [];
-      // 提前计算 每个题目排列时 是否要进行换行 以及计算需要换到第几行 (行可以理解为选项块)
-      for (let jIndex = 0; jIndex < needNewLineArr.length; jIndex++) {
-        if (needNewLineArr[jIndex].need) {
-          indexAndNeed.push({
-            index: jIndex,
-            need: true,
-          });
-        }
-      }
-      let itemsPositionArr = [];
-      // 提前计算 每个题目排列时 是否要进行换行 以及计算需要换到第几行 (行可以理解为选项块)
-      for (let index = 0; index < items.length; index++) {
-        itemsPositionArr.push({
-          index: index,
-          needNewLine: needNewLineArr[index].need,
-          lineIndex: needNewLineArr[index].blockIndex
-        });
-      }
-      console.log(itemsPositionArr)
-      let blockList = [...new Set(itemsPositionArr.map(i => i.lineIndex))]
-      this.blockList = blockList
-      
-      items.forEach((item, index) => {
-        if(index > 0 && (itemsPositionArr[index].lineIndex !== itemsPositionArr[index - 1].lineIndex)){
-          this.leftItems = this.leftItems.slice(index,this.leftItems.length)
-        }
-        let optionX = CONTENT_START_X + MARGIN_LEFT + this.getStartX(number, this.leftItems,item.id);
-        let optionY =   startY + GAP * (index + 1 <= number ? index : index % number) + ((itemsPositionArr[index].lineIndex + 1) * this.blockHeight)
-        // console.log(index,optionX)
-        // 渲染选项下标
-        let itemOrder = snap
-          .text(
-            optionX,
-            optionY,
-            index + 1
-          )
-          .attr({
-            textAnchor: "end",
-            width: 40,
-            fontSize: 12,
-            fontFamily: "Times New Roman",
-          });
-        this.objectiveGroup.add(itemOrder);
-		
-			item.option.forEach((option, optionIndex) => {
-			  let code = String.fromCharCode(
-			    64 + parseInt(optionIndex + 1)
-			  ).toLowerCase();
-			  // 渲染选项图片
-			  // let img = require("../../icons/answersheet/" + code + ".svg");
-			  let img = require('@/icons/answersheet/' + code + '.svg');
-			  let trueSvg = require('@/icons/answersheet/t.svg');
-			  let falseSvg = require('@/icons/answersheet/f.svg');
-			  let c3 = snap.image(
-			    item.type !== 'judge' ? img : optionIndex === 0 ? trueSvg : falseSvg,
-			    optionX + NUMBER_ITEM_ML + optionGap * optionIndex,
-			    optionY - 10,
-			    NUMBER_ITEM_W,
-			    NUMBER_ITEM_H
-			  );
-			  this.objectiveGroup.add(c3);
-			});
-        
-      });
+				});
 
-      let diff = this.leftItems.length - this.number
-      let refHeight = this.blockHeight * (blockList.length - 1)
-      let objectiveHeight = diff > 0 ? refHeight : refHeight - 26 * diff * -1
-      this.anchorRectY = startY + GAP * number + objectiveHeight
-      for (let index = 0; index < 28; index++) {
-        // 渲染选项框横向定位锚点
-          this.objectiveGroup.add(
-            snap.rect(
-              CONTENT_START_X + MARGIN_LEFT + NUMBER_ITEM_ML + optionGap * (index - 1),
-              startY + GAP * number + objectiveHeight,
-              NUMBER_ITEM_W,
-              NUMBER_ITEM_H
-            )
-          );
-      }
-      // 添加纵向定位锚点
-	  let anchorCount = this.objectiveItems.length > number ? number : this.objectiveItems.length
-	  this.blockList.forEach((blockItem,blockIndex) => {
-		  for (let index = 0; index < anchorCount; index++) {
-		    this.objectiveGroup.add(
-		      snap.rect(20, startY + GAP * index - 10 + (this.blockHeight * blockIndex), NUMBER_ITEM_W, NUMBER_ITEM_H)
-		    );
-		  }
-	  })
-      
+				let diff = this.leftItems.length - this.number
+				let refHeight = this.blockHeight * (blockList.length - 1)
+				let objectiveHeight = diff > 0 ? refHeight : refHeight - 26 * diff * -1
+				this.anchorRectY = startY + GAP * number + objectiveHeight
+				for (let index = 0; index < 28; index++) {
+					// 渲染选项框横向定位锚点
+					this.objectiveGroup.add(
+						snap.rect(
+							CONTENT_START_X + MARGIN_LEFT + NUMBER_ITEM_ML + optionGap * (index - 1),
+							startY + GAP * number + objectiveHeight,
+							NUMBER_ITEM_W,
+							NUMBER_ITEM_H
+						)
+					);
+				}
+				// 添加纵向定位锚点
+				let anchorCount = this.objectiveItems.length > number ? number : this.objectiveItems.length
+				this.blockList.forEach((blockItem, blockIndex) => {
+					for (let index = 0; index < anchorCount; index++) {
+						this.objectiveGroup.add(
+							snap.rect(20, startY + GAP * index - 10 + (this.blockHeight * blockIndex),
+								NUMBER_ITEM_W, NUMBER_ITEM_H)
+						);
+					}
+				})
 
-      // 渲染包围框
-      this.doRenderBorder(items, number, blockList.length);
-    },
 
-    // 获取每一列渲染的x坐标
-    getStartX(number, items,itemId) {
-      // 根据index求出当前列最多选项的题目从而获取当前列的宽度
-      let columnCount = Math.ceil(items.length / number); // 总共多少列
-      let curColumn = parseInt(items.map(i => i.id).indexOf(itemId) / number); // 当前index在第几列
-      let columnWidthArr = []; // 存放每一列的距前一列的宽度
-      let singleOptionW = NUMBER_ITEM_W + NUMBER_ITEM_ML;
-      let columnGap = 10 // 列与列之间的间隔
-      let orderWidth = 11 // 题号的最大宽度
-      for (var i = 0; i < columnCount; i++) {
-        if (i === 0) {
-          columnWidthArr.push(0); // 第一列左间距为0
-        } else {
-          // 后面每一列的取值为前一列最多选项宽度
-          let startIndex = number * (i - 1);
-          let maxOpitonCount = items
-            .slice(startIndex, startIndex + number)
-            .map((i) => i.option.length);
-          columnWidthArr.push(singleOptionW * Math.max(...maxOpitonCount) + orderWidth + columnGap);
-        }
-      }
-      // 第几列就取前几列的宽度总和 作为x值
-      return columnWidthArr.slice(0, curColumn + 1).length ? columnWidthArr.slice(0, curColumn + 1).reduce((a, b) => a + b) : 0;
-    },
-	
-	// 判断是否需要换行
-    needNewLine(index, number, items) {
-      let columnCount = Math.ceil(items.length / number); // 总共多少列
-      let curColumn = parseInt(index / number); // 当前index在第几列
-      let preColumnCells = [];
-      let columnCells = [];
-      let cellCountMax = 20; // 每行最多能放的选项数
-      for (var i = 0; i < columnCount; i++) {
-        if (i > 0) {
-          // 后面每一列的取值为前一列最多选项宽度
-          let startIndex = number * (i - 1);
-          let maxOpitonCount = items
-            .slice(startIndex, startIndex + number)
-            .map((i) => i.option.length);
-          preColumnCells.push(Math.max(...maxOpitonCount));
-        }
+				// 渲染包围框
+				this.doRenderBorder(items, number, blockList.length);
+			},
 
-        // 去所有列的最大选项数 方便得知自己当前列的最大值
-        let startIndex2 = number * i;
-        let maxOpitonCount2 = items
-          .slice(startIndex2, startIndex2 + number)
-          .map((i) => i.option.length);
-        columnCells.push(Math.max(...maxOpitonCount2));
-      }
-      let cellCount = preColumnCells.slice(0, curColumn).length
-        ? preColumnCells.slice(0, curColumn).reduce((a, b) => a + b)
-        : 0; // 目前已经有的选项数
-      // 如果前面所有列的最大选项数之和 加上 当前列的最大选项数  大于最大值 则需要换行
-      let totalCell = cellCount + columnCells[curColumn]
-      return {
-        need:totalCell > cellCountMax, // 是否需要换行
-        blockIndex:totalCell > cellCountMax ? parseInt(totalCell / cellCountMax) - 1 : -1 // 当前需要换到第几行
-      };
-    },
-  },
-  mounted: function () {
-    this.snap = Snap("#sheetObjectiveSvg");
-    this.objectiveGroup = this.snap.paper.g();
+			// 获取每一列渲染的x坐标
+			getStartX(number, items, itemId) {
+				// 根据index求出当前列最多选项的题目从而获取当前列的宽度
+				let columnCount = Math.ceil(items.length / number); // 总共多少列
+				let curColumn = parseInt(items.map(i => i.id).indexOf(itemId) / number); // 当前index在第几列
+				let columnWidthArr = []; // 存放每一列的距前一列的宽度
+				let singleOptionW = NUMBER_ITEM_W + NUMBER_ITEM_ML;
+				let columnGap = 10 // 列与列之间的间隔
+				let orderWidth = 11 // 题号的最大宽度
+				for (var i = 0; i < columnCount; i++) {
+					if (i === 0) {
+						columnWidthArr.push(0); // 第一列左间距为0
+					} else {
+						// 后面每一列的取值为前一列最多选项宽度
+						let startIndex = number * (i - 1);
+						let maxOpitonCount = items
+							.slice(startIndex, startIndex + number)
+							.map((i) => i.option.length);
+						columnWidthArr.push(singleOptionW * Math.max(...maxOpitonCount) + orderWidth + columnGap);
+					}
+				}
+				// 第几列就取前几列的宽度总和 作为x值
+				return columnWidthArr.slice(0, curColumn + 1).length ? columnWidthArr.slice(0, curColumn + 1).reduce((a,
+					b) => a + b) : 0;
+			},
 
-    // this.$nextTick(() => {
-    //   this.$emit("onRendered", this.$refs.baseInfoRef.clientHeight);
-    // });
-  },
-  computed:{
-    totalScore(){
-      return this.objectiveItems.length ? this.objectiveItems.map(i => i.score).reduce((a,b) => a + b) : 0
-    }
-  },
-  watch: {
-    items: {
-      // 数据变化时执行的逻辑代码
-      handler(n, old) {
-        if (n.length) {
-          let objectiveArr = ["single", "multiple", "judge"];
-          this.objectiveItems = n.filter((item) =>
-            objectiveArr.includes(item.type)
-          );
-		  
-          this.blockHeight = 26 * this.number
-          this.leftItems = JSON.parse(JSON.stringify(this.objectiveItems)) 
-		  this.$nextTick(() => {
-			  this.doRenderItems(this.objectiveItems, this.number);
-		  })
-        }
-      },
-	  immediate:true,
-      // 开启深度监听
-      deep: true,
-    },
-    anchorRectY: {
-      handler(n, o) {
-        this.$nextTick(() => {
-          this.$emit("onRendered", n);
-        });
-      },
-    },
-  },
-};
+			// 判断是否需要换行
+			needNewLine(index, number, items) {
+				let columnCount = Math.ceil(items.length / number); // 总共多少列
+				let curColumn = parseInt(index / number); // 当前index在第几列
+				let preColumnCells = [];
+				let columnCells = [];
+				let cellCountMax = 20; // 每行最多能放的选项数
+				for (var i = 0; i < columnCount; i++) {
+					if (i > 0) {
+						// 后面每一列的取值为前一列最多选项宽度
+						let startIndex = number * (i - 1);
+						let maxOpitonCount = items
+							.slice(startIndex, startIndex + number)
+							.map((i) => i.option.length);
+						preColumnCells.push(Math.max(...maxOpitonCount));
+					}
+
+					// 去所有列的最大选项数 方便得知自己当前列的最大值
+					let startIndex2 = number * i;
+					let maxOpitonCount2 = items
+						.slice(startIndex2, startIndex2 + number)
+						.map((i) => i.option.length);
+					columnCells.push(Math.max(...maxOpitonCount2));
+				}
+				let cellCount = preColumnCells.slice(0, curColumn).length ?
+					preColumnCells.slice(0, curColumn).reduce((a, b) => a + b) :
+					0; // 目前已经有的选项数
+				// 如果前面所有列的最大选项数之和 加上 当前列的最大选项数  大于最大值 则需要换行
+				let totalCell = cellCount + columnCells[curColumn]
+				return {
+					need: totalCell > cellCountMax, // 是否需要换行
+					blockIndex: totalCell > cellCountMax ? parseInt(totalCell / cellCountMax) - 1 : -1 // 当前需要换到第几行
+				};
+			},
+		},
+		mounted: function() {
+			this.snap = Snap("#sheetObjectiveSvg");
+			this.objectiveGroup = this.snap.paper.g();
+
+			// this.$nextTick(() => {
+			//   this.$emit("onRendered", this.$refs.baseInfoRef.clientHeight);
+			// });
+		},
+		computed: {
+			totalScore() {
+				return this.objectiveItems.length ? this.objectiveItems.map(i => i.score).reduce((a, b) => a + b) : 0
+			},
+			// 是否为根据试卷自动生成的答题卡
+			isAutoCreate(){
+				return this.$store.state.answerSheet.isAutoCreate
+			}
+		},
+		watch: {
+			items: {
+				// 数据变化时执行的逻辑代码
+				handler(n, old) {
+					if (n.length) {
+						let objectiveArr = ["single", "multiple", "judge"];
+						this.objectiveItems = n.filter((item) =>
+							objectiveArr.includes(item.type)
+						);
+
+						this.blockHeight = 26 * this.number
+						this.leftItems = JSON.parse(JSON.stringify(this.objectiveItems))
+						this.$nextTick(() => {
+							this.doRenderItems(this.objectiveItems, this.number);
+						})
+					}
+				},
+				immediate: true,
+				// 开启深度监听
+				deep: true,
+			},
+			anchorRectY: {
+				handler(n, o) {
+					this.$nextTick(() => {
+						this.$emit("onRendered", n);
+					});
+				},
+			},
+		},
+	};
 </script>
-<style scoped>
-.sheet-objective-container {
-  /* position: absolute; */
-  /* left: 0; */
-  /* top: 350px; */
-  width: 750px;
-}
+<style scoped lang="less">
+	.sheet-objective-container {
+		/* position: absolute; */
+		/* left: 0; */
+		/* top: 350px; */
+		width: 750px;
+	}
 
-/* .sheet-info-container:hover .info-edit{
+	/* .sheet-info-container:hover .info-edit{
     display: flex;
 } */
 
-.info-edit {
-  position: absolute;
-  top: 55px;
-  right: 110px;
-  width: 40px;
-  height: 25px;
-  background: #00a43a;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  color: #fff;
-  font-size: 12px;
-  cursor: pointer;
-  z-index: 0;
-}
+	.info-edit {
+		position: absolute;
+		top: 55px;
+		right: 110px;
+		width: 40px;
+		height: 25px;
+		/* background: #00a43a; */
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		color: #fff;
+		font-size: 12px;
+		z-index: 0;
+
+		span {
+			margin-right: 10px;
+			display: table;
+			background-color: #000000;
+			width: 40px;
+			padding: 2px 0;
+			text-align: center;
+			cursor: pointer;
+		}
+	}
 
-.edit-title {
-  margin: 10px 0;
-}
+	.edit-title {
+		margin: 10px 0;
+	}
 </style>
- 

+ 0 - 1
TEAMModelOS/ClientApp/src/view/answersheet/SheetSubjective.vue

@@ -12,7 +12,6 @@
         v-for="(item, index) in subjectiveItems"
         :key="index"
         :ids="'subjectiveEditor' + index"
-        :allItems="items"
         :items="[item]"
         type="1"
       ></BaseEditor>

+ 297 - 83
TEAMModelOS/ClientApp/src/view/answersheet/index.vue

@@ -7,33 +7,29 @@
 				<BaseSvgBg v-for="(page, pageIndex) in pages" :key="pageIndex" :ids="'svg' + pageIndex"
 					:total="pages.length"></BaseSvgBg>
 				<SheetBaseInfo></SheetBaseInfo>
-				
-				
-<!-- 				<SheetObjective :items="items" v-show="groupItems.objectiveItems.length" @onRendered="onRendered">
-				</SheetObjective>
-				<div class="sheet-subjective-wrap" :style="'top:' + subjectiveTop + 'px'">
-					<SheetComplete :items="items" v-if="groupItems.completeItems.length"></SheetComplete>
-					<SheetSubjective :items="groupItems.subjectiveItems" v-show="groupItems.subjectiveItems.length"></SheetSubjective>
-				</div> -->
-				
 				<!-- 绘制主区域 -->
 				<div class="sheet-groups">
 					<div v-for="(group,groupIndex) in groups" :key="groupIndex" class="sheet-group-item">
 						<div v-if="group.type === 'objective'">
-							<BaseTitleEditor :ids="'titleEditor' + groupIndex" :content="titleContent(groupIndex,group)"></BaseTitleEditor>
-							<SheetObjective :items="items" v-show="groupItems.objectiveItems.length" @onRendered="onRendered"></SheetObjective>
+							<BaseTitleEditor :ids="'titleEditor' + groupIndex"
+								:content="titleContent(groupIndex,group)"></BaseTitleEditor>
+							<SheetObjective :items="items" v-show="groupItems.objectiveItems.length"
+								@onRendered="onRendered"></SheetObjective>
 						</div>
 						<div v-else-if="group.type === 'complete'">
-							<BaseTitleEditor :ids="'titleEditor' + groupIndex" :content="titleContent(groupIndex,group)"></BaseTitleEditor>
+							<BaseTitleEditor :ids="'titleEditor' + groupIndex"
+								:content="titleContent(groupIndex,group)"></BaseTitleEditor>
 							<SheetComplete :items="items" v-if="groupItems.completeItems.length"></SheetComplete>
 						</div>
 						<div v-else>
-							<BaseTitleEditor :ids="'titleEditor' + groupIndex" :content="titleContent(groupIndex,group)"></BaseTitleEditor>
-							<SheetSubjective :items="groupItems.subjectiveItems" v-show="groupItems.subjectiveItems.length"></SheetSubjective>
+							<BaseTitleEditor :ids="'titleEditor' + groupIndex"
+								:content="titleContent(groupIndex,group)"></BaseTitleEditor>
+							<SheetSubjective :items="groupItems.subjectiveItems"
+								v-show="groupItems.subjectiveItems.length"></SheetSubjective>
 						</div>
 					</div>
 				</div>
-				
+
 			</div>
 		</div>
 		<div class="sheet-right">
@@ -43,20 +39,83 @@
 				<p class="sheet-right-title">基础设置</p>
 				<div>
 					<Checkbox v-model="isColumn">客观题竖向排列</Checkbox>
-					<Checkbox v-model="isColumn">自定义页眉</Checkbox>
-					<Checkbox v-model="isColumn">添加二维码</Checkbox>
-					<Checkbox v-model="isColumn">密封线</Checkbox>
+					<Checkbox v-model="isShowErCode">添加二维码</Checkbox>
+					<Checkbox v-model="isShowLines">密封线</Checkbox>
 				</div>
-				<p class="sheet-right-title">添加题型</p>
-				<div style="display: flex;flex-wrap: wrap;">
-					<span class="add-block-item"> + 客观题</span>
-					<span class="add-block-item"> + 填空题</span>
-					<span class="add-block-item"> + 简答题</span>
-					<span class="add-block-item"> + 作文(语)</span>
-					<span class="add-block-item"> + 作文(英)</span>
+				<p class="sheet-right-title" v-if="!isAutoCreate">添加题型</p>
+				<div style="display: flex;flex-wrap: wrap;" v-if="!isAutoCreate">
+					<span class="add-block-item" @click="onAddType('0')"> + 客观题</span>
+					<span class="add-block-item" @click="onAddType('1')"> + 填空题</span>
+					<span class="add-block-item" @click="onAddType('2')"> + 简答题</span>
+					<span class="add-block-item" @click="onAddType('3')"> + 作文(语)</span>
+					<span class="add-block-item" @click="onAddType('4')"> + 作文(英)</span>
 				</div>
 			</div>
 		</div>
+
+		<Modal v-model="isShowAdd" class-name="add-type-modal" width="650" title="添加题型">
+			<Tabs :value="activeTab" @on-click="onTabClick">
+				<TabPane label="客观题" name="0"></TabPane>
+				<TabPane label="填空题" name="1"></TabPane>
+				<TabPane label="简答题" name="2"></TabPane>
+				<TabPane label="作文(语)" name="3"></TabPane>
+				<TabPane label="作文(英)" name="4"></TabPane>
+			</Tabs>
+			<div>
+				<div class="add-type-section">
+					<p class="add-type-title">题号</p>
+					<div>
+						<span style="margin: 0 10px;">第</span>
+						<InputNumber :max="100" :min="1" v-model="addType.startIndex" @on-change="onStartChange">
+						</InputNumber>
+						<span style="margin: 0 10px;">题 到 第</span>
+						<InputNumber :max="100" :min="1" v-model="addType.endIndex" @on-change="onEndChange">
+						</InputNumber>
+						<span style="margin: 0 10px;">题,每题</span>
+						<InputNumber :max="100" :min="0" v-model="addType.everyScore" @on-change="renderAddItem">
+						</InputNumber>
+						<span style="margin: 0 10px;">分</span>
+						<span v-if="activeTab === '0' || activeTab === '1'" >
+							<span>每题 </span>
+							<InputNumber :max="8" :min="0" v-model="addType.everyOpts" @on-change="renderAddItem">
+							</InputNumber>
+							<span style="margin: 0 10px;">个{{ activeTab === '0' ? '选项' : '空格' }}</span>
+						</span>
+						<span v-if="activeTab === '3'">
+							<span>,共 </span>
+							<InputNumber :max="2000" :min="100" v-model="addType.maxWords"></InputNumber>
+							<span> 字 </span>
+						</span>
+						<span v-if="activeTab === '4'">
+							<span> 共 </span>
+							<InputNumber :max="30" :min="1" v-model="addType.maxLines"></InputNumber>
+							<span> 行</span>
+						</span>
+						
+					</div>
+				</div>
+				<p v-show="indexErr" style="color: red;">* 开始题号必须小于结束题号</p>
+				<div class="add-type-section" v-if="addItems.length && isAddInfoComplete">
+					<p class="add-type-title">配分</p>
+					<div class="score-box">
+						<div v-for="(item,index) in addItems" class="score-item">
+							<span>第 {{ item.order }} 题</span>
+							<div>
+								<InputNumber :max="100" :min="0" v-model="item.score"></InputNumber>
+								<span> 分 </span>
+								<span v-if="activeTab === '0' || activeTab === '1'" style="margin-left: 10px;">
+									<InputNumber :max="100" :min="0" v-model="item.opts"></InputNumber>
+									<span> 个{{ activeTab === '0' ? '选项' : '空格' }}</span>
+								</span>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+			<div slot="footer">
+				<Button type="primary" @click="doAddType">确定</Button>
+			</div>
+		</Modal>
 	</div>
 </template>
 
@@ -81,11 +140,6 @@
 				default: "",
 			},
 		},
-		provide: function() {
-			return {
-				reload: this.reload
-			}
-		},
 		components: {
 			SheetObjective,
 			SheetBaseInfo,
@@ -96,9 +150,23 @@
 		},
 		data() {
 			return {
-				groups:[],
-				isLoading:false,
-				isColumn:false,
+				indexErr: false,
+				addItems: [],
+				addType: {
+					startIndex: null,
+					endIndex: null,
+					everyScore: null,
+					everyOpts: null,
+					maxWords:800,
+					maxLines:10
+				},
+				isShowAdd: false,
+				isShowErCode:false,
+				isShowLines:false,
+				activeTab: '0',
+				groups: [],
+				isLoading: false,
+				isColumn: false,
 				isRouterAlive: true,
 				isRender: true,
 				pages: [],
@@ -109,35 +177,84 @@
 					subjectiveItems: [],
 				},
 				subjectiveTop: 0,
-				fromRouter:'',
-				typeList:{
-					objective:'选择题',
-					complete:'填空题',
-					subjective:'简答题'
+				fromRouter: '',
+				typeList: {
+					objective: '选择题',
+					complete: '填空题',
+					subjective: '简答题'
 				}
 			};
 		},
 		created() {
 			let routerPaper = this.$route.params.paper
-			if(routerPaper){
+			if (routerPaper) {
 				this.$store.commit('clearFixArr')
 				this.$store.commit('clearPage')
 				this.$store.commit('clearIsNewPage')
-				this.$store.commit('setPaper',routerPaper)
-				this.items = routerPaper.item
-			}else{
+				this.$store.commit('setPaper', routerPaper)
+				if (routerPaper.item === null) {
+					this.$store.commit('setCreateModal', 'diy')
+				} else {
+					this.items = routerPaper.item
+					this.$store.commit('setCreateModal', 'auto')
+				}
+				localStorage.setItem('scrollDis', 0)
+			} else {
 				this.goBack()
 			}
-			
+
 		},
 		methods: {
-			doDownload(){
+			onTabClick(type){
+				this.activeTab = type
+			},
+			onAddType(type) {
+				this.isShowAdd = true
+				this.activeTab = type
+				this.addType = {
+					startIndex: null,
+					endIndex: null,
+					everyScore: null,
+					everyOpts: (type === '0' || type === '1') ? null : 1,
+					maxWords:800,
+					maxLines:10
+				}
+			},
+
+			onStartChange(val) {
+				this.indexErr = val > this.addType.endIndex || (!val && !this.addType.endIndex)
+				this.renderAddItem()
+			},
+
+			onEndChange(val) {
+				this.indexErr = val < this.addType.startIndex || (!val && !this.addType.startIndex)
+				this.renderAddItem()
+			},
+			
+			/* 点击添加题型 */
+			doAddType() {
+				if (this.isAddInfoComplete) {
+					console.log(this.addItems)
+					this.addItems.forEach(i => {
+						i.option = new Array(i.opts).fill('0')
+						i.blankCount = i.opts
+						i.id = this.$tools.guid()
+					})
+					this.isShowAdd = false
+					this.items = this.items.concat(this.addItems)
+					this.$store.commit('setPaperItems', this.items)
+					this.doRender()
+				} else {
+					this.$Message.warning('添加信息不能为空!')
+				}
+			},
+			doDownload() {
 				this.isLoading = true
 				this.getPdf().then(res => {
 					this.isLoading = false
 				})
 			},
-			goBack(){
+			goBack() {
 				this.$router.push({
 					name: this.fromRouter || 'schoolBank',
 					params: {
@@ -153,7 +270,6 @@
 			},
 			// 客观题渲染完 来决定主观题的TOP值高度
 			onRendered(val) {
-				console.log('客观题渲染完',val)
 				this.subjectiveTop = val + INFO_H + 200;
 			},
 
@@ -163,6 +279,7 @@
 					completeItems: [],
 					subjectiveItems: [],
 				}
+				this.groups = []
 				let objectiveTypes = ["single", "multiple", "judge"];
 				this.items.forEach((i) => {
 					if (objectiveTypes.includes(i.type)) {
@@ -173,22 +290,22 @@
 						this.groupItems.subjectiveItems.push(i);
 					}
 				});
-				
-				if(this.groupItems.objectiveItems.length){
+
+				if (this.groupItems.objectiveItems.length) {
 					this.groups.push({
-						type:'objective',
+						type: 'objective',
 						items: this.groupItems.objectiveItems
 					})
 				}
-				if (this.groupItems.completeItems.length){
+				if (this.groupItems.completeItems.length) {
 					this.groups.push({
-						type:'complete',
+						type: 'complete',
 						items: this.groupItems.completeItems
 					})
 				}
-				if (this.groupItems.subjectiveItems.length){
+				if (this.groupItems.subjectiveItems.length) {
 					this.groups.push({
-						type:'subjective',
+						type: 'subjective',
 						items: this.groupItems.subjectiveItems
 					})
 				}
@@ -211,29 +328,79 @@
 					} else if (num > 10 && num < 20) {
 						return '十' + upperCaseNumber[String(num).charAt(1)]
 					} else {
-						return upperCaseNumber[String(num).charAt(0)] + '十' + upperCaseNumber[String(num).charAt(1)].replace('零', '')
+						return upperCaseNumber[String(num).charAt(0)] + '十' + upperCaseNumber[String(num).charAt(1)]
+							.replace('零', '')
 					}
 				}
 			},
+
+			renderAddItem() {
+				let addItems = []
+				let addInfo = this.addType
+				let len = addInfo.endIndex - addInfo.startIndex + 1
+				for (let i = 0; i < len; i++) {
+					addItems.push({
+						id: this.$tools.guid(),
+						order: addInfo.startIndex + i,
+						score: addInfo.everyScore,
+						opts: addInfo.everyOpts,
+						blankCount: 1,
+						maxWords:this.activeTab === '3' ? addInfo.maxWords : null,
+						maxLines:this.activeTab === '4' ? addInfo.maxLines : null,
+						type: this.activeTab === '0' ? 'single' : this.activeTab === '1' ? 'complete' : 'subjective'
+					})
+				}
+				this.addItems = addItems
+			}
 		},
 		mounted: function() {
 			this.doRender()
+			this.$EventBus.$off('deleteItem')
+			this.$EventBus.$on('deleteItem',val => {
+				console.log(val)
+				if(val === '0'){
+					this.groups = this.groups.filter(i => i.type !== 'complete')
+					this.items = this.items.filter(i => i.type !== 'complete')
+				}else if (val === 'objective'){
+					let objectiveTypes = ["single", "multiple", "judge"];
+					this.groups = this.groups.filter(i => i.type !== 'objective')
+					this.items = this.items.filter(i => !objectiveTypes.includes(i.type))
+				}else{
+					this.groups = this.groups.filter(i => i.items.length)
+				}
+				this.$EventBus.$emit('doRefresh')
+			})
 		},
-		beforeRouteEnter (to, from, next){
-		  next(vm => {
-			vm.fromRouter = from.name
-		  })
+		beforeRouteEnter(to, from, next) {
+			next(vm => {
+				vm.fromRouter = from.name
+			})
 		},
 		computed: {
 			getPage() {
 				return this.$store.state.answerSheet.pages;
 			},
-			
-			titleContent(){
-				return (groupIndex,group) => {
-					let totalScore = group.items.length ? group.items.map(i => i.score).reduce((a,b) => a + b) : 0
+
+			isAddInfoComplete() {
+				for (let key in this.addType) {
+					if (this.addType[key] === null) {
+						return false;
+					}
+				}
+				return true
+			},
+
+			// 是否为根据试卷自动生成的答题卡
+			isAutoCreate() {
+				return this.$store.state.answerSheet.isAutoCreate
+			},
+
+			titleContent() {
+				return (groupIndex, group) => {
+					let totalScore = group.items.length ? group.items.map(i => i.score).reduce((a, b) => a + b) : 0
 					let type = this.typeList[group.type]
-					return this.numberConvertToUppercase(groupIndex + 1) + '、' + type + '(共' + group.items.length +  '题,总计' + totalScore +  '分)' 
+					return this.numberConvertToUppercase(groupIndex + 1) + '、' + type + '(共' + group.items.length +
+						'题,总计' + totalScore + '分)'
 				}
 			}
 		},
@@ -242,8 +409,17 @@
 				handler(n, o) {
 					this.pages = new Array(n).fill(0);
 				},
-				immediate:true
+				immediate: true
 			},
+			isAddInfoComplete: {
+				handler(n, o) {
+					if (n) {
+						this.renderAddItem()
+					} else {
+						this.addItems = []
+					}
+				}
+			}
 		},
 	};
 </script>
@@ -253,13 +429,51 @@
 		justify-content: space-between;
 		position: relative;
 		width: 100%;
-		
-		.ivu-spin{
+
+		.ivu-spin {
 			background-color: #000000 !important;
 		}
 	}
-	
-	.sheet-groups{
+
+	.add-type-modal {
+		.add-type-section {
+			margin: 20px 10px;
+		}
+
+		.add-type-title {
+			margin: 10px 0;
+
+			&::before {
+				content: '';
+				display: inline-block;
+				border: 4px solid #267ce6;
+				border-radius: 50%;
+				margin-right: 10px;
+			}
+		}
+
+		.score-box {
+			padding: 5px 10px;
+			background-color: #0000000d;
+			border-radius: 5px;
+			max-height: 300px;
+			overflow-y: auto;
+
+			.score-item {
+				display: flex;
+				justify-content: space-between;
+				align-items: center;
+				padding: 8px 0;
+				border-bottom: 1px dashed #e4e4e4;
+			}
+		}
+
+		.ivu-input-number {
+			width: 50px;
+		}
+	}
+
+	.sheet-groups {
 		position: absolute;
 		top: 350px;
 		left: 0;
@@ -276,21 +490,21 @@
 		right: 10px;
 		height: 88vh;
 		padding: 20px;
-		
-		.ivu-btn{
+
+		.ivu-btn {
 			width: 100%;
 			height: 40px;
 			background-color: #00b29a;
 			color: #fff;
 			border: none;
 		}
-		
-		.btn-download{
+
+		.btn-download {
 			margin-top: 10px;
 			background-color: #00a7ee;
 		}
-		
-		.add-block-item{
+
+		.add-block-item {
 			display: inline-block;
 			margin: 5px;
 			background: #009de8;
@@ -299,13 +513,13 @@
 			border-radius: 4px;
 			cursor: pointer;
 		}
-		
-		&-title{
+
+		&-title {
 			font-size: 14px;
 			font-weight: bold;
 			margin: 15px 5px;
-			
-			&::before{
+
+			&::before {
 				content: '';
 				width: 5px;
 				height: 10px;
@@ -314,13 +528,13 @@
 				margin-right: 10px;
 			}
 		}
-		
-		.ivu-checkbox-wrapper{
+
+		.ivu-checkbox-wrapper {
 			margin: 10px;
 		}
-		
-		
-		
+
+
+
 	}
 
 	.sheet-left {

+ 16 - 13
TEAMModelOS/ClientApp/src/view/evaluation/bank/index.vue

@@ -13,23 +13,26 @@
 		</Tabs>
 		<div class="ev-list-operation">
 			<div class="import-exercise common-save-btn">
-				<div class="ev-list-paper-tools" style="display: flex;"  v-show="currentTab === 'paper' && ($access.can('admin.*||exercise-upd') || !isSchool)">
+				<div class="ev-list-paper-tools" style="display: flex;"  v-show="currentTab === 'paper' ">
 					<span @click="onShowPaperList" class="bank-tools-btn" v-if="isShowBackList">
 						<Icon type="md-arrow-back" size="16"/>
 						<span>{{ $t('evaluation.index.backList') }}</span>
 					</span>
-					<span @click="goCreatePaper('auto')" class="bank-tools-btn">
-						<Icon type="md-cube" size="16"/>
-						<span>{{ $t('evaluation.index.autoCreate') }}</span>
-					</span>
-					<span @click="goCreatePaper('manual')" class="bank-tools-btn">
-						<Icon type="md-hand" size="16"/>
-						<span>{{ $t('evaluation.index.manualCreate') }}</span>
-					</span>
-					<span @click="goCreatePaper('import')" class="bank-tools-btn">
-						<Icon type="md-folder" size="16"/>
-						<span>{{ $t('evaluation.index.importCreate') }}</span>
-					</span>
+					<div style="display: flex;" v-show="($access.can('admin.*||exercise-upd') || !isSchool)">
+						<span @click="goCreatePaper('auto')" class="bank-tools-btn">
+							<Icon type="md-cube" size="16"/>
+							<span>{{ $t('evaluation.index.autoCreate') }}</span>
+						</span>
+						<span @click="goCreatePaper('manual')" class="bank-tools-btn">
+							<Icon type="md-hand" size="16"/>
+							<span>{{ $t('evaluation.index.manualCreate') }}</span>
+						</span>
+						<span @click="goCreatePaper('import')" class="bank-tools-btn">
+							<Icon type="md-folder" size="16"/>
+							<span>{{ $t('evaluation.index.importCreate') }}</span>
+						</span>
+					</div>
+					
 				</div>
 				
 				<span @click="goCreateExercise" v-show="currentTab === 'exercise' && ($access.can('admin.*||exercise-upd') || !isSchool)" class="bank-tools-btn">

+ 7 - 7
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseExerciseList.vue

@@ -63,7 +63,7 @@
 					</div>
 					<div class="item-btn-toggle" @click.stop v-show="isShowTools && !isPreview">
 						<template v-if="!isExamPaper">
-							<InputNumber :max="item.score + surPlusScore" :min="0" v-model="item.score" style="display: inline-block ;width: 50px;margin-right: 10px;height: 30px;"
+							<InputNumber :max="item.score + surPlusScore" :min="0" :step="0.5" v-model="item.score" style="display: inline-block ;width: 50px;margin-right: 10px;height: 30px;"
 							 @click.stop></InputNumber>
 							<span style="margin-right: 10px;">{{$t('evaluation.paperList.score')}}</span>
 							<!-- <span class="item-score" title="设置题目分数" @click.stop="onSetSingleItem(item,index)" v-else>{{ item.score }} 分</span> -->
@@ -501,12 +501,12 @@
 			 * 配分变化时的剩余分数处理
 			 * @param val
 			 */
-			onScoreChange(val) {
-				this.surPlusScore = this.surPlusScore + this.lastScore - val
-				this.lastScore = val
-				this.$emit('scoreUpdate', this.surPlusScore)
+			// onScoreChange(val) {
+			// 	this.surPlusScore = this.surPlusScore + this.lastScore - val
+			// 	this.lastScore = val
+			// 	this.$emit('scoreUpdate', this.surPlusScore)
 
-			},
+			// },
 
 			/** 确认单个试题配分 */
 			onConfirmScore() {
@@ -714,7 +714,7 @@
 						this.totalNum = newPaper.item.length
 						
 						// 剩余可分配分数 更新
-						this.surPlusScore = newPaper.score - newPaper.item.reduce((p, e) => parseInt(p) + parseInt(e.score), 0);
+						this.surPlusScore = newPaper.score - newPaper.item.reduce((p, e) => Number(p) + Number(e.score), 0);
 						this.$emit('scoreUpdate', this.surPlusScore)
 						
 						this.pageScrollTo(0)

+ 9 - 0
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseImport.vue

@@ -6,6 +6,7 @@
                         :headers="headers"
                         :format="['docx','xlsx','xls']"
                         :on-format-error="handleFormatError"
+						:on-error="onUploadError"
                         :show-upload-list="isShowList"
                         :before-upload="beforeUpload"
                         :on-success="uploadSuccess">
@@ -287,6 +288,12 @@
 				this.errorList = []
 				this.importList = []
 			},
+			
+			/* 上传异常处理 */
+			onUploadError(e){
+				this.$Message.error(this.$t('evaluation.importFile.warningTips4'))
+				this.isBtnLoading = false
+			},
 
             /**
              * 上传文件成功回调
@@ -324,6 +331,8 @@
 						this.isBtnLoading = false
 					}
 					this.isSelectFinish = false
+				}).catch(e => {
+					console.log(e)
 				})
             },
         },

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

@@ -790,7 +790,7 @@
 					let guid = this.$tools.guid()
 					let paperItem = {
 						id: this.evaluationInfo.id || guid,
-						code: this.editPaper ? this.editPaper.code : (this.isSchool ? this.$store.state.userInfo.schoolCode : this.$store
+						code: this.editPaper ? this.editPaper.code.replace('Paper-','') : (this.isSchool ? this.$store.state.userInfo.schoolCode : this.$store
 							.state.userInfo.TEAMModelId),
 						scope: this.isSchool ? 'school' : 'private',
 						gradeIds: this.isSchool ? (this.evaluationInfo.paperGrade.length ? this.evaluationInfo.paperGrade : this.gradeList

+ 23 - 0
TEAMModelOS/ClientApp/src/view/homepage/HomePage.less

@@ -275,3 +275,26 @@
     text-align: center;
     margin-left: 10px;
 }
+.phone-tips{
+    color: white;
+    text-align: center;
+    margin-top: 30px;
+    font-size: 16px;
+    b{
+        color: #ed4014;
+    }
+}
+.tips-icon{
+    display: block;
+    margin: auto;
+    margin-top: 150px;
+    font-size: 80px;
+    margin-right: 5px;
+    color: #eeeeee;
+}
+.to-verify{
+    display: block;
+    margin: auto;
+    margin-top: 10px;
+    width: fit-content;
+}

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

@@ -1,5 +1,31 @@
 <template>
-    <div class="home-page-container dark-iview-split dark-iview-card">
+    <div v-if="!isComplete">
+        <!-- 如果是大陆站需要验证是否完成手机号认证 -->
+        <!-- <div v-if="!$store.state.userInfo.hasVerify && $store.state.config.srvAdr == 'China'">
+            <Icon custom="iconfont icon-phone-unverify" class="tips-icon" />
+            <p class="phone-tips">
+                <span>温馨提示:为了方便使用更加完整的系统功能,请先完成<b>手机号认证</b>!</span>
+                <router-link to="/regist" class="to-verify">前往认证>>></router-link>
+            </p>
+        </div> -->
+        <!-- <div v-else>
+            <Icon custom="iconfont icon-phone-verify" class="tips-icon" />
+            <p class="phone-tips">
+                <span>温馨提示:手机号注册已完成!</span>
+            </p>
+        </div> -->
+
+        <!-- 大陆和国际站都需要验证是否加入学校 -->
+        <div v-if="!$store.state.userInfo.hasSchool">
+            <Icon custom="iconfont icon-school" class="tips-icon" />
+            <p class="phone-tips">
+                <span>温馨提示:为了方便使用更加完整的系统功能,请先申请<b>加入学校</b>!</span>
+                <router-link to="/home/settings" class="to-verify">加入学校>>></router-link>
+            </p>
+        </div>
+    </div>
+
+    <div v-else class="home-page-container dark-iview-split dark-iview-card">
         <div class="prepare-area box-item">
             <p class="list-title">
                 {{$t('home.previewStudy')}}
@@ -32,10 +58,6 @@
                 <p class="chart-title">
                     {{$t('home.classData')}}
                 </p>
-                <!-- <i-circle :percent="80" style="margin:auto;display:block;" trail-color="#242328" :stroke-color="['#1E82E0','#1CC0F3','#1C9AE7']" :trail-width="9" :stroke-width="9" :size="180">
-                    <p class="demo-Circle-inner" style="font-size:50px;font-weight:bold;color:white;">80</p>
-                    <span class="demo-Circle-inner" style="font-size:14px;color:#1cc0f3;">平均互动指数</span>
-                </i-circle> -->
                 <TechScore></TechScore>
                 <TeachScore></TeachScore>
             </div>
@@ -51,7 +73,6 @@
                                 <p class="recorde-name">HiTeach-default-202009091212</p>
                                 <p class="record-time">
                                     <Time :time="((new Date()).getTime() - 60 * 3 * 1000)" />
-                                    <!-- <span>上传</span> -->
                                 </p>
                             </div>
                         </div>
@@ -203,7 +224,6 @@
                                 <div style="display:flex;justify-content:space-between;">
                                     <p>
                                         <span class="notice-title">李志轩</span>
-                                        <!--<span class="notice-dot"></span>-->
                                     </p>
                                     <span class="notice-time">2020-09-09 18:02</span>
                                 </div>
@@ -271,84 +291,90 @@
     </div>
 </template>
 <script>
-    import AcCountPie from "./AcCountPie.vue"
-    import TechScore from "./TechScore.vue"
-    import TeachScore from "./TeachScore.vue"
-    export default {
-        components: {
-            AcCountPie, TechScore, TeachScore
-        },
-        data() {
-            return {
-                split1: 0.5,
-                split2: 0.5,
-                split3: 0.5,
-                itemCount: 10
+import AcCountPie from "./AcCountPie.vue"
+import TechScore from "./TechScore.vue"
+import TeachScore from "./TeachScore.vue"
+export default {
+    components: {
+        AcCountPie, TechScore, TeachScore
+    },
+    data() {
+        return {
+            split1: 0.5,
+            split2: 0.5,
+            split3: 0.5,
+            itemCount: 10
+        }
+    },
+    methods: {
+        toAc(type) {
+            switch (type) {
+                case 'vote':
+                    this.$router.push({
+                        path: '/home/manageVote'
+                    })
+                    break
+                //case 'hw':
+                //    this.$router.push({
+                //        path: '/home/manageHomeWork'
+                //    })
+                //    break
+                case 'que':
+                    this.$router.push({
+                        path: '/home/manageQuestionnaire'
+                    })
+                    break
+                //case 'learn':
+                //    this.$router.push({
+                //        path: '/home/SelfLearn'
+                //    })
+                //    break
+                case 'test':
+                    this.$router.push({
+                        path: '/home/manageEvaluation'
+                    })
+                    break
+                default:
+                    break
             }
         },
-        methods: {
-            toAc(type) {
-                switch (type) {
-                    case 'vote':
-                        this.$router.push({
-                            path: '/home/manageVote'
-                        })
-                        break
-                    //case 'hw':
-                    //    this.$router.push({
-                    //        path: '/home/manageHomeWork'
-                    //    })
-                    //    break
-                    case 'que':
-                        this.$router.push({
-                            path: '/home/manageQuestionnaire'
-                        })
-                        break
-                    //case 'learn':
-                    //    this.$router.push({
-                    //        path: '/home/SelfLearn'
-                    //    })
-                    //    break
-                    case 'test':
-                        this.$router.push({
-                            path: '/home/manageEvaluation'
-                        })
-                        break
-                    default:
-                        break
-                }
-            },
-            toRecordPage() {
-                this.$router.push({
-                    path: '/home/classRecord'
-                })
-            },
-            toSelfLearn() {
-                //this.$router.push({
-                //    path: '/home/SelfLearn'
-                //})
-            },
-            toJoinSchool() {
-                this.$router.push({
-                    path: '/home/settings'
-                })
-            }
+        toRecordPage() {
+            this.$router.push({
+                path: '/home/classRecord'
+            })
+        },
+        toSelfLearn() {
+            //this.$router.push({
+            //    path: '/home/SelfLearn'
+            //})
         },
-        created() {
-            console.log(this.$store)
+        toJoinSchool() {
+            this.$router.push({
+                path: '/home/settings'
+            })
+        }
+    },
+    created() {
+        console.log(this.$store)
+    },
+    computed:{
+        //暂时只验证加入学校, 手机号需要对接API
+        isComplete(){
+            return this.$store.state.userInfo.hasSchool
         }
     }
+}
 </script>
 <style scoped lang="less">
-    @import "./HomePage.less";
+@import "./HomePage.less";
 </style>
 <style>
-    .home-page-container .ivu-card-body {
-        height: calc(100% - 52px);
-        padding: 0px;
-    }
+.home-page-container .ivu-card-body {
+    height: calc(100% - 52px);
+    padding: 0px;
+}
 
-    .home-page-container .__panel {
-        /* padding-right: 17px; */
-    }
+.home-page-container .__panel {
+    /* padding-right: 17px; */
+}
 </style>

+ 0 - 2
TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue

@@ -701,8 +701,6 @@ export default {
                         } else {
                             targetBlob = new BlobTool(privateSas.url, privateSas.name, privateSas.sas, 'private')
                         }
-                        console.log('scope', this.evaluationInfo.scope)
-                        console.log('target', targetBlob)
                         let privateBlob = new BlobTool(privateSas.url, privateSas.name, privateSas.sas, 'private')
                         let schoolBlob = undefined
                         let targetFolder = 'exam/' + examId + '/paper/'

+ 38 - 22
TEAMModelOS/ClientApp/src/view/learnactivity/ManualCreate.vue

@@ -56,7 +56,7 @@
         <vuescroll ref="manualScroll">
             <div class="manual-filter-wrap">
                 <Row style="width:100%;">
-                    <Col :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
+                    <Col :xs="24" :sm="24" :md="24" :lg="24" :xl="6">
                     <div class="manual-filter-item">
                         <span class="manual-filter-label">{{$t('evaluation.filter.origin')}}:</span>
                         <CheckboxGroup v-model="manualFilter.code" style="display:inline-block;"  @on-change="checkAll($event,'origin')">
@@ -66,7 +66,7 @@
                         </CheckboxGroup>
                     </div>
                     </Col>
-                    <Col :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
+                    <Col :xs="24" :sm="24" :md="24" :lg="24" :xl="18">
                     <div class="manual-filter-item evaluation-attr-form">
                         <span class="manual-filter-label">{{$t('evaluation.filter.period')}}:</span>
                         <Select v-model="manualFilter.periodCode[0]" :disabled="!isPeriod || isSchool"  size="small"  style="display: inline-block;width:100px"  @on-change="checkAll($event,'periodCode')">
@@ -76,10 +76,14 @@
 						<Select v-model="manualFilter.subjectCode[0]" :disabled="!isPeriod || isSchool"  size="small"  style="display: inline-block;width:100px"  @on-change="checkAll($event,'subjectCode')">
 						    <Option v-for="(item,index) in subjectList" :value="item.id" :key="index">{{ item.name }}</Option>
 						</Select>
-                        
+                        <span class="manual-filter-label" style="margin-left: 30px;">{{$t('evaluation.filter.level')}}:</span>
+                        <Select v-model="manualFilter.field"  size="small"  style="display: inline-block;width:100px"  @on-change="checkAll($event,'field')">
+                            <Option value="all">{{$t('evaluation.filter.all')}}</Option>
+                            <Option v-for="(item,index) in fieldList" :value="index" :key="index">{{ item }}</Option>
+                        </Select>
                     </div>
                     </Col>
-                    <Col :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
+                    <Col :xs="24" :sm="24" :md="24" :lg="24" :xl="16">
                     <div class="manual-filter-item">
                         <span class="manual-filter-label">{{$t('evaluation.filter.type')}}:</span>
                         <CheckboxGroup v-model="manualFilter.type" border style="display: inline-block;" @on-change="checkAll($event,'type')">
@@ -94,8 +98,8 @@
                             <Checkbox label="compose">{{$t('evaluation.compose')}}</Checkbox>
                         </CheckboxGroup>
                     </div>
-                    </Col>
-                    <Col :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
+                    </Col> 
+                    <Col :xs="24" :sm="24" :md="24" :lg="24" :xl="8">
                     <div class="manual-filter-item">
                         <span class="manual-filter-label">{{$t('evaluation.filter.diff')}}:</span>
                         <CheckboxGroup v-model="manualFilter.level" border style="display: inline-block;" @on-change="checkAll($event,'level')">
@@ -175,12 +179,15 @@
                     type: ['all'],
                     level: ['all'],
                     subjectCode: [],
-                    scoped: "school"
+                    scoped: "school",
+					field:'all'
                 },
                 schoolPeriod: [],
 				showQuestion:[],
 				subjectList:[],
-                groupList: {}
+                groupList: {},
+				fieldList: [this.$t('evaluation.level1'),this.$t('evaluation.level2'),this.$t('evaluation.level3'),
+				this.$t('evaluation.level4'),this.$t('evaluation.level5'),this.$t('evaluation.level6')],
             }
         },
 
@@ -199,36 +206,41 @@
             /**
              * 选择全部逻辑
              * @param data:选中数据
-             * @param field:字段名
+             * @param key:字段名
              */
-            checkAll(data, field) {
+            checkAll(data, key) {
 				console.log('点击了筛选区域')
 				// 切换学段
-				if(field === 'periodCode'){
+				if(key === 'periodCode'){
 					this.subjectList = this.schoolPeriod.filter(i => i.id === this.manualFilter.periodCode[0])[0].subjects
 					this.manualFilter.subjectCode = [this.subjectList[0].id]
 					this.queryQuestionByPage()
 					return
 				}
 				// 切换科目
-				if(field === 'subjectCode'){
+				if(key === 'subjectCode'){
+					this.queryQuestionByPage()
+					return
+				}
+				
+				if(key === 'origin'){
 					this.queryQuestionByPage()
 					return
 				}
 				
-				if(field === 'origin'){
+				if(key === 'field'){
 					this.queryQuestionByPage()
 					return
 				}
 				
 				// 切换其余筛选项
-                if (this.manualFilter[field].length !== 1 && this.manualFilter[field].indexOf('all') === 0) {
-                    this.manualFilter[field].splice(this.manualFilter[field].indexOf('all'), 1)
-                } else if (this.manualFilter[field].indexOf('all') > 0) {
-                    this.manualFilter[field].length = 0
-                    this.$set(this.manualFilter[field],0,'all')
-                }else if (this.manualFilter[field].length === 0){
-					this.$set(this.manualFilter[field],0,'all')
+                if (this.manualFilter[key].length !== 1 && this.manualFilter[key].indexOf('all') === 0) {
+                    this.manualFilter[key].splice(this.manualFilter[key].indexOf('all'), 1)
+                } else if (this.manualFilter[key].indexOf('all') > 0) {
+                    this.manualFilter[key].length = 0
+                    this.$set(this.manualFilter[key],0,'all')
+                }else if (this.manualFilter[key].length === 0){
+					this.$set(this.manualFilter[key],0,'all')
 				}
                 this.pageNum = 1
                 this.queryQuestionByPage()
@@ -270,7 +282,7 @@
                     "subjectId": scope === 'school' ? this.deleteAll(this.manualFilter.subjectCode) : [],
                     "level": this.deleteAll(this.manualFilter.level),
                     "type": this.deleteAll(this.manualFilter.type),
-                    "field": [],
+                    "field": this.manualFilter.field !== 'all' ? this.manualFilter.field + 1 : [],
                     "scope": scope,
                     "pid": null
                 }
@@ -369,7 +381,10 @@
 						this.subjectList = this.schoolPeriod.filter(i => i.id === this.periodCode)[0].subjects
 						this.manualFilter.subjectCode = [this.subjectCode]
 					}
-					this.queryQuestionByPage()
+					console.log(this.manualFilter)
+					if(!this.isSchool || this.manualFilter.periodCode.length){
+						this.queryQuestionByPage()
+					}
 				}
 			})
 			this.$EventBus.$off('onPaperItemChange')
@@ -410,6 +425,7 @@
 			subjectCode:{
 				handler(n){
 					this.manualFilter.subjectCode[0] = n
+					console.log(this.manualFilter.subjectCode)
 					this.queryQuestionByPage()
 				}
 			}

+ 7 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.less

@@ -69,7 +69,7 @@
             }
 
             .evaluation-type span {
-                margin-right: 10px;
+                margin-right: 5px;
             }
         }
     }
@@ -264,4 +264,10 @@
 }
 .mock-tea-scoring{
     margin-right: 40px;
+}
+.ev-info-tag{
+    color: #dadada;
+    border: 1px solid #a5a5a5;
+    border-radius: 2px;
+    padding: 1px 2px;
 }

+ 23 - 10
TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.vue

@@ -29,25 +29,30 @@
                             <p class="evaluation-type">
                                 <Icon type="md-time" style="margin-right:5px;" size="16" />
                                 <span>{{$t('learnActivity.mgtScEv.createTime')}}{{dateFormat(item.startTime)}}</span>
-                                <span class="evaluation-status-tag" :style="{ borderColor: item.progress == 'pending' ? '#0BADD4' : item.progress == 'going' ? '#1CC0F3' : '#949594', color: (item.progress == 'pending' ? '#0BADD4' : item.progress == 'going' ? '#1CC0F3' : '#949594')}">
-                                    {{ item.progress == 'pending' ? $t('learnActivity.mgtScEv.pending') : item.progress == 'going' ? $t('learnActivity.mgtScEv.going') : $t('learnActivity.mgtScEv.finish') }}
-                                </span>
                             </p>
                             <p class="evaluation-type">
                                 <Icon type="md-time" style="margin-right:5px;" size="16" />
                                 <span>{{$t('learnActivity.mgtScEv.endTime')}}{{dateFormat(item.endTime)}}</span>
-                                <span v-if="item.progress == 'going'" class="handle-end-tag" @click="handleEnd(index)">
-                                    {{$t('learnActivity.mgtScEv.stop')}}
-                                </span>
                             </p>
                             <div style="display:inline-flex">
                                 <p class="evaluation-type">
-                                    <Icon type="ios-cube" style="margin-right:5px;" size="14" />
-                                    <span>{{$t('learnActivity.mgtScEv.evType')}}{{getTypeLabel(item.type)}}</span>
+                                    <span class="ev-info-tag">{{getTypeLabel(item.type)}}</span>
                                 </p>
+                                <!-- 评测模式 -->
                                 <p class="evaluation-type">
-                                    <Icon type="ios-people" style="margin-right:5px;" size="16" />
-                                    <span>{{$t('learnActivity.mgtScEv.stuCount')}}{{item.stuCount}}</span>
+                                    <span class="ev-info-tag">{{getModeLabel(item.source)}}</span>
+                                </p>
+                                <!-- 活动状态 -->
+                                <p class="evaluation-type">
+                                    <span class="evaluation-status-tag" :style="{ borderColor: item.progress == 'pending' ? '#0BADD4' : item.progress == 'going' ? '#1CC0F3' : '#949594', color: (item.progress == 'pending' ? '#0BADD4' : item.progress == 'going' ? '#1CC0F3' : '#949594')}">
+                                        {{ item.progress == 'pending' ? $t('learnActivity.mgtScEv.pending') : item.progress == 'going' ? $t('learnActivity.mgtScEv.going') : $t('learnActivity.mgtScEv.finish') }}
+                                    </span>
+                                </p>
+                                <!-- 立即结束 -->
+                                <p class="evaluation-type">
+                                    <span v-if="item.progress == 'going'" class="handle-end-tag" @click="handleEnd(index)">
+                                        {{$t('learnActivity.mgtScEv.stop')}}
+                                    </span>
                                 </p>
                             </div>
                         </div>
@@ -129,6 +134,14 @@ export default {
         }
     },
     methods: {
+        /**获取mode对应的label */
+        getModeLabel(code) {
+            for (let item of this.$GLOBAL.EV_MODE()) {
+                if (item.value == code) {
+                    return item.label
+                }
+            }
+        },
         dropdownStates(flag) {
             if (!flag) this.filterByTag()
         },

+ 7 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.less

@@ -68,7 +68,7 @@
             }
 
             .evaluation-type span {
-                margin-right: 10px;
+                margin-right: 5px;
             }
         }
     }
@@ -236,4 +236,10 @@
 }
 .filter-item{
     margin: 10px 5px;
+}
+.ev-info-tag{
+    color: #dadada;
+    border: 1px solid #a5a5a5;
+    border-radius: 2px;
+    padding: 1px 2px;
 }

+ 32 - 26
TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue

@@ -20,7 +20,7 @@
                         <Icon type="md-trash" v-show="evaListShow.length" class="to-create-icon" :title="$t('learnActivity.mgtScEv.delete')" @click="deleteEvaluation" v-if="$access.can('admin.*|schoolAc-upd')" />
                         <Icon type="md-create" v-show="evaListShow.length && evaListShow[curEvaIndex] && evaListShow[curEvaIndex].progress == 'pending'" class="to-create-icon" @click="editEvaluation" :title="$t('learnActivity.mgtScEv.edit')" v-if="$access.can('admin.*|schoolAc-upd')" />
                         <!-- 筛选 -->
-                        <Poptip style="float:right" trigger="hover" :offset="-10" theme="light">
+                        <Poptip style="float:right" trigger="click" :offset="-10" theme="light">
                             <Icon type="ios-funnel" class="to-create-icon" :color="filter.status || filter.type || filter.mode ? '#2d8cf0':'#fff'" />
                             <div slot="content">
                                 <div class="filter-item">
@@ -60,30 +60,38 @@
                             <p class="evaluation-type">
                                 <Icon type="md-time" style="margin-right:5px;" size="16" />
                                 <span>{{$t('learnActivity.mgtScEv.createTime')}}{{dateFormat(item.startTime)}}</span>
-                                <span class="evaluation-status-tag" :style="{ borderColor: item.progress == 'pending' ? '#0BADD4' : item.progress == 'going' ? '#1CC0F3' : '#949594', color: (item.progress == 'pending' ? '#0BADD4' : item.progress == 'going' ? '#1CC0F3' : '#949594')}">
-                                    {{ item.progress == 'pending' ? $t('learnActivity.mgtScEv.pending') : item.progress == 'going' ? $t('learnActivity.mgtScEv.going') : $t('learnActivity.mgtScEv.finish') }}
-                                </span>
                             </p>
                             <p class="evaluation-type">
                                 <Icon type="md-time" style="margin-right:5px;" size="16" />
                                 <span>{{$t('learnActivity.mgtScEv.endTime')}}{{dateFormat(item.endTime)}}</span>
-                                <span v-if="item.progress == 'going'" class="handle-end-tag" @click="handleEnd(index)">
-                                    {{$t('learnActivity.mgtScEv.stop')}}
-                                </span>
+
                             </p>
+                            <!-- 学生人数 -->
+                            <!-- <p class="evaluation-type">
+                                <Icon type="ios-people" style="margin-right:5px;" size="16" />
+                                <span>{{$t('learnActivity.mgtScEv.stuCount')}}{{item.stuCount}}</span>
+                            </p> -->
                             <div style="display:inline-flex">
-                                <!-- <p class="evaluation-type">
-                                    <Icon type="ios-cube" style="margin-right:5px;" size="14" />
-                                    <span>{{$t('learnActivity.mgtScEv.evType')}}{{getTypeLabel(item.type)}}</span>
-                                </p> -->
                                 <p class="evaluation-type">
-                                    <Icon type="ios-cube" style="margin-right:5px;" size="14" />
-                                    <span>{{$t('learnActivity.mgtScEv.evType')}}{{getModeLabel(item.source)}}</span>
+                                    <span class="ev-info-tag">{{getTypeLabel(item.type)}}</span>
+                                </p>
+                                <!-- 评测模式 -->
+                                <p class="evaluation-type">
+                                    <span class="ev-info-tag">{{getModeLabel(item.source)}}</span>
+                                </p>
+                                <!-- 活动状态 -->
+                                <p class="evaluation-type">
+                                    <span class="evaluation-status-tag" :style="{ borderColor: item.progress == 'pending' ? '#0BADD4' : item.progress == 'going' ? '#1CC0F3' : '#949594', color: (item.progress == 'pending' ? '#0BADD4' : item.progress == 'going' ? '#1CC0F3' : '#949594')}">
+                                        {{ item.progress == 'pending' ? $t('learnActivity.mgtScEv.pending') : item.progress == 'going' ? $t('learnActivity.mgtScEv.going') : $t('learnActivity.mgtScEv.finish') }}
+                                    </span>
                                 </p>
+                                <!-- 立即结束 -->
                                 <p class="evaluation-type">
-                                    <Icon type="ios-people" style="margin-right:5px;" size="16" />
-                                    <span>{{$t('learnActivity.mgtScEv.stuCount')}}{{item.stuCount}}</span>
+                                    <span v-if="item.progress == 'going'" class="handle-end-tag" @click="handleEnd(index)">
+                                        {{$t('learnActivity.mgtScEv.stop')}}
+                                    </span>
                                 </p>
+
                             </div>
                         </div>
                         <EmptyData v-if="evaListShow.length == 0" style="margin-top:180px;" :textContent="`${scope == 'school' ? filterPeriodName:''}${$t('learnActivity.mgtScEv.nodata')}`"></EmptyData>
@@ -99,18 +107,15 @@
                     <span :class="curBarIndex == 1 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(1)">
                         {{$t('learnActivity.mgtScEv.tab2')}}
                     </span>
-                    <!-- <span v-show="evaListShow[curEvaIndex] && evaListShow[curEvaIndex].source == '2'" :class="curBarIndex == 2 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(2)">
-                        {{$t('learnActivity.mgtScEv.markSetting')}}
-                    </span>
-                    <span v-show="evaListShow[curEvaIndex] && evaListShow[curEvaIndex].source == '2'" :class="curBarIndex == 3 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(3)">
-                        {{$t('learnActivity.mgtScEv.markData')}}
-                    </span> -->
-                    <span :class="curBarIndex == 2 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(2)">
+
+                    <!-- 阅卷功能0531之前完成不了,暂时隐藏 -->
+                    <!-- <span :class="curBarIndex == 2 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(2)">
                         {{$t('learnActivity.mgtScEv.markSetting')}}
                     </span>
                     <span :class="curBarIndex == 3 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(3)">
                         {{$t('learnActivity.mgtScEv.markData')}}
-                    </span>
+                    </span> -->
+
                     <!--取消一键作答和一键评分功能-->
                     <!--<div style="float:right;" v-if="$access.ability('admin','mock-eva').validateAll" v-show="evaListShow[curEvaIndex] && evaListShow[curEvaIndex].progress == 'going'">
                         <Tooltip :content="$t('learnActivity.mgtScEv.autoTips1')" :max-width="240">
@@ -120,6 +125,7 @@
                             <Button type="warning" size="small" :loading="scoreLoading" class="mock-tea-scoring" @click="mockScoring">{{$t('learnActivity.mgtScEv.autoScore')}}</Button>
                         </Tooltip>
                     </div>-->
+
                     <!-- 保存阅卷配置 -->
                     <div style="float:right;" class="common-save-btn" v-show="curBarIndex == 2">
                         <Button class="mock-stu-answer" type="text" :loading="btnLoading" @click="saveMarkSetting" icon="ios-albums-outline">
@@ -183,7 +189,7 @@ export default {
     inject: ['reload'],
     data() {
         return {
-            btnLoading:false,
+            btnLoading: false,
             keyword: '',
             isSearch: false,
             answerLoading: false,
@@ -212,7 +218,7 @@ export default {
     },
     methods: {
         //保存阅卷配置
-        saveMarkSetting(){
+        saveMarkSetting() {
             console.log(this.$refs['markSetting'])
             this.$refs['markSetting'].saveSetting()
         },
@@ -248,7 +254,7 @@ export default {
             this.evaListShow = curPdEv.filter(item => {
                 let status = !this.filter.status || (this.filter.status == item.progress)
                 let type = !this.filter.type || (this.filter.type == item.type)
-                let mode = !this.filter.mode || (this.filter.type == item.source)
+                let mode = !this.filter.mode || (this.filter.mode == item.source)
                 return status && type && mode
             })
         },

+ 9 - 4
TEAMModelOS/ClientApp/src/view/learnactivity/PaperScore.vue

@@ -333,6 +333,12 @@ export default {
             default: '',
             required: true
         },
+        // 用于判断是个人还是校本评测
+        owner: {
+            type: String,
+            default: '',
+            required: true
+        },
         subjectId: {
             type: String,
             default: '',
@@ -394,7 +400,7 @@ export default {
                 "subjectId": this.subjectId,
                 "classId": this.studentAnswer.classId,
                 // "code": this.paperInfo.code,//这种方式paper code规则调整了,会多Paper-"
-                "code": this.examScope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,//暂时取代上面的方式
+                "code": this.owner == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,//暂时取代上面的方式
             }).then(
                 res => {
                     this.$Message.success(this.$t('learnActivity.score.markOk'))
@@ -506,12 +512,11 @@ export default {
         saveScore() {
             let requestData = {
                 "id": this.examId,
-                // "code": this.paperInfo.code,//这种方式paper code规则调整了,会多Paper-"
-                "code": this.examScope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,//暂时取代上面的方式
+                // "code": this.examScope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,//暂时取代上面的方式
+                "code": this.owner == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,//暂时取代上面的方式
                 "point": this.studentAnswer.scores,
                 "studentId": this.studentAnswer.id,
                 "classId": this.studentAnswer.classId,
-                // "school": this.paperInfo.code,//这种方式paper code规则调整了,会多Paper-"
                 "school": this.examScope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,//暂时取代上面的方式
                 "subjectId": this.subjectId
             }

+ 1 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/Scoring.vue

@@ -54,7 +54,7 @@
                     <Page show-total size="small" :current="currentPage" :total="studentScore.length" :page-size="pageSize" :page-size-opts="pageSizeOpts" @on-change="pageChange" @on-page-size-change="pageSizeChange" show-sizer />
                 </div>
                 <div class="dark-iview-table scoring-handle-box" v-show="showTest">
-                    <PaperScore ref="paperScore" :defaultIndex="defaultIndex" :examId="examInfo.id" :examScope="examInfo.scope" :paper="paperInfo" :studentAnswer="chooseStudent" :subjectId="chooseSubject" @nextStu="getNextStu" style="color:#515a6e;"></PaperScore>
+                    <PaperScore ref="paperScore" :defaultIndex="defaultIndex" :examId="examInfo.id" :owner="examInfo.owner" :examScope="examInfo.scope" :paper="paperInfo" :studentAnswer="chooseStudent" :subjectId="chooseSubject" @nextStu="getNextStu" style="color:#515a6e;"></PaperScore>
                     <Loading :top="200" type="1" style="text-align:center" v-show="dataLoading"></Loading>
                 </div>
             </div>

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

@@ -335,4 +335,9 @@
     right: 15px;
     top: 50%;
     margin-top: -10px;
+}
+.no-school-tips{
+    color: #ff9900;
+    text-align: center;
+    margin-top: 80px;
 }

+ 0 - 0
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue


部分文件因文件數量過多而無法顯示