Browse Source

Merge branch 'develop' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop

CrazyIter_Bin 2 năm trước cách đây
mục cha
commit
2102ae21fd
30 tập tin đã thay đổi với 3051 bổ sung538 xóa
  1. 1 178
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  2. 2 2
      TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs
  3. 89 0
      TEAMModelBI/Controllers/Census/SchoolController.cs
  4. 305 0
      TEAMModelBI/Controllers/RepairApi/SchoolRepController.cs
  5. 1 1
      TEAMModelBI/Models/RearEndMiddle.cs
  6. 3 3
      TEAMModelBI/TEAMModelBI.csproj
  7. 113 0
      TEAMModelOS.SDK/Models/Cosmos/BI/BISchool/BIRelation.cs
  8. 42 0
      TEAMModelOS.SDK/Models/Cosmos/BI/CurrencyModel.cs
  9. 55 9
      TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html
  10. 12 4
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css
  11. 1 1
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js
  12. 15 1
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json
  13. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf
  14. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff
  15. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2
  16. 323 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/AnswerBox.less
  17. 343 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/AnswerBox.vue
  18. 40 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/Index.vue
  19. 189 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/PreciseQues.vue
  20. 125 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/QuesContent.less
  21. 102 26
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/WrongQues.less
  22. 414 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/QuesList.vue
  23. 212 297
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/WrongQues.vue
  24. 10 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/iViewStyle.less
  25. 107 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/mobile/PreciseQues.vue
  26. 178 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/mobile/WrongQues.less
  27. 315 0
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/mobile/WrongQues.vue
  28. BIN
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/student-en-us.png
  29. 26 3
      TEAMModelOS/ClientApp/src/router/routes.js
  30. 28 13
      TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue

+ 1 - 178
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -2291,184 +2291,7 @@ namespace TEAMModelBI.Controllers.BISchool
 
             return Ok(new { state = RespondCode.Ok, scSimple });
         }
-
-
-        /// <summary>
-        /// 添加新学段的学校
-        /// </summary>
-        /// <param name="jsonElement"></param>
-        /// <returns></returns>
-        [ProducesDefaultResponseType]
-        [HttpPost("set-allscperiod")]
-        public async Task<IActionResult> SetAllScPeriod(JsonElement jsonElement)
-        {
-            jsonElement.TryGetProperty("Language", out JsonElement Language);
-            jsonElement.TryGetProperty("scId", out JsonElement scId);
-            jsonElement.TryGetProperty("periodName", out JsonElement periodName);
-            var cosmosClient = _azureCosmos.GetCosmosClient();
-            var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
-            StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
-            StringBuilder stringBuilder = new();
-            string text;
-            string scName = "默认学段";
-            while ((text = streamReader.ReadLine()) != null)
-            {
-                stringBuilder.Append(text.ToString());
-            }
-            streamReader.Close();
-            string input = stringBuilder.ToString();
-            List<SchoolConfig> schoolConfigs = input.ToObject<List<SchoolConfig>>();
-            SchoolConfig schoolConfig = null;
-            if (!string.IsNullOrEmpty($"{Language}"))
-                schoolConfig = schoolConfigs.Find(x => x.Lang.Contains($"{Language}"));
-
-            if (schoolConfig == null)
-            {
-                if ($"{Language}".Contains("en"))
-                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("en-US"));
-                else
-                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("zh-CN"));
-            }
-            string campusId = Guid.NewGuid().ToString();
-
-            StringBuilder noPeriodScSql = new("SELECT value(c) FROM c ");
-            List<School> allSc = new();
-
-            if (!string.IsNullOrEmpty($"{scId}"))
-                noPeriodScSql.Append($" where c.id='{scId}'");
-            else
-                noPeriodScSql.Append($" where c.code='Base' and c.period=[]");
-
-            if (!string.IsNullOrEmpty($"{periodName}"))
-                scName = $"{periodName}";
-
-            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(noPeriodScSql.ToString(),requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")}))
-            {
-                allSc.Add(item);
-            }
-            foreach (var school in allSc)
-            {
-                if (school.campuses.Count > 0)
-                    campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
-                
-                school.period.Add(new Period
-                {
-                    id = Guid.NewGuid().ToString(),
-                    name = scName,
-                    campusId = campusId,
-                    semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
-                        new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
-                    subjects = new List<Subject>() {
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
-                        },
-                    grades = schoolConfig.grades,
-                    analysis = new Analysis()
-                    {
-                        type = new List<ExamSimple>() { new ExamSimple { id = Guid.NewGuid().ToString(), name = schoolConfig.PresetExam[0].type[0].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[1].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[2].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[3].name } },
-                        income = schoolConfig.PresetExam[0].income,
-                        eugenics = schoolConfig.PresetExam[0].eugenics,
-                        touch = schoolConfig.PresetExam[0].touch
-                    }
-                });
-                if (!school.campuses.Select(x => x.id).Contains(campusId))
-                    school.campuses.Add(new Campus { name = school.name, id = campusId });
-
-                School rSchool = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey("Base"));
-            }
-
-            return Ok(new { state = RespondCode.Ok });
-        }
-
-        /// <summary>
-        /// 设置学校学段
-        /// </summary>
-        /// <param name="jsonElement"></param>
-        /// <returns></returns>
-        [ProducesDefaultResponseType]
-        [HttpPost("set-scperiod")]
-        public async Task<IActionResult> SetScPeriod(JsonElement jsonElement)
-        {
-            if (!jsonElement.TryGetProperty("scId", out JsonElement scId)) return BadRequest();
-            if (!jsonElement.TryGetProperty("periodName", out JsonElement periodName)) return BadRequest();
-
-            List<string> periodNames = $"{periodName}".ToObject<List<string>>();
-            jsonElement.TryGetProperty("Language", out JsonElement Language);
-
-            var cosmosClient = _azureCosmos.GetCosmosClient();
-            var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
-            StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
-            StringBuilder stringBuilder = new();
-            string text;
-            while ((text = streamReader.ReadLine()) != null)
-            {
-                stringBuilder.Append(text.ToString());
-            }
-            streamReader.Close();
-            string input = stringBuilder.ToString();
-            List<SchoolConfig> schoolConfigs = input.ToObject<List<SchoolConfig>>();
-            SchoolConfig schoolConfig = null;
-            if (!string.IsNullOrEmpty($"{Language}"))
-                schoolConfig = schoolConfigs.Find(x => x.Lang.Contains($"{Language}"));
-
-            if (schoolConfig == null)
-            {
-                if ($"{Language}".Contains("en"))
-                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("en-US"));
-                else
-                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("zh-CN"));
-            }
-            string campusId = Guid.NewGuid().ToString();
-            School school = null;
-
-            school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{scId}", new PartitionKey("Base"));
-            
-            if (school != null)
-            {
-                foreach (var item in periodNames)
-                {
-                    if (school.campuses.Count > 0)
-                        campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
-
-                    school.period.Add(new Period
-                    {
-                        id = Guid.NewGuid().ToString(),
-                        name = item,
-                        campusId = campusId,
-                        semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
-                        new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
-                        subjects = new List<Subject>() {
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
-                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
-                        },
-                        grades = schoolConfig.grades,
-                        analysis = new Analysis()
-                        {
-                            type = new List<ExamSimple>() { new ExamSimple { id = Guid.NewGuid().ToString(), name = schoolConfig.PresetExam[0].type[0].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[1].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[2].name },
-                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[3].name } },
-                            income = schoolConfig.PresetExam[0].income,
-                            eugenics = schoolConfig.PresetExam[0].eugenics,
-                            touch = schoolConfig.PresetExam[0].touch
-                        }
-                    });
-                }
-
-                if (!school.campuses.Select(x => x.id).Contains(campusId))
-                    school.campuses.Add(new Campus { name = school.name, id = campusId });
-            }
-
-            school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey("Base"));
-
-            return Ok(new { state = RespondCode.Ok, school });
-        }
-
+        
         #region 购买记录
 
         /// <summary>

+ 2 - 2
TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs

@@ -1470,7 +1470,7 @@ namespace TEAMModelBI.Controllers.BITable
                             isExitId = teacher.schools.Find(s => s.schoolId.Equals(scId));
                             if (isExitId == null)
                             {
-                                ScBaseInfo school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ScBaseInfo>(scId, new PartitionKey("Base"));
+                                ScEasyInfo school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ScEasyInfo>(scId, new PartitionKey("Base"));
                                 msg.Append($"{school.name}[{school.id}],");
                                 teacher.schools.Add(new Teacher.TeacherSchool() { schoolId = school.id, name = school.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = school.picture, areaId = school.areaId });
                             }
@@ -1486,7 +1486,7 @@ namespace TEAMModelBI.Controllers.BITable
                             isExitId = teacher.schools.Find(s => s.schoolId.Equals(scId));
                             if (isExitId == null)
                             {
-                                ScBaseInfo school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ScBaseInfo>(scId, new PartitionKey("Base"));
+                                ScEasyInfo school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ScEasyInfo>(scId, new PartitionKey("Base"));
                                 msg.Append($"{school.name}[{school.id}],");
                                 teacher.schools.Add(new Teacher.TeacherSchool() { schoolId = school.id, name = school.name, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), picture = school.picture, areaId = school.areaId });
                             }

+ 89 - 0
TEAMModelBI/Controllers/Census/SchoolController.cs

@@ -22,6 +22,7 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
 using TEAMModelOS.SDK.Models.Service.BI;
 using TEAMModelOS.SDK.Models.Service.BIStatsWay;
 
@@ -682,6 +683,94 @@ namespace TEAMModelBI.Controllers.Census
             return Ok(new { state = RespondCode.Ok ,area, statsInfo, scIds });
         }
 
+        /// <summary>
+        /// 学校信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-scinfos")]
+        public async Task<IActionResult> GetScInfos(JsonElement jsonElement)
+        {
+            try
+            {
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                List<string> scId = await CommonFind.FindScIds(cosmosClient, "select value(c.id) from c ", "Base");
+                List<BIRelation> scInfos = new();
+                foreach (var itemId in scId)
+                {
+                    BIRelation bIRelation = null;
+                    var resRel = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(itemId, new PartitionKey("BIRel"));
+                    if (resRel.Status == 200)
+                    {
+                        using var fileJson = await JsonDocument.ParseAsync(resRel.ContentStream);
+                        bIRelation = fileJson.ToObject<BIRelation>();
+                    }
+                    else
+                    {
+                        ScBaseInfo scBaseInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ScBaseInfo>(itemId, new PartitionKey("Base"));
+                        string areaName = null;
+                        if (!string.IsNullOrEmpty(scBaseInfo.areaId))
+                        {
+                            await foreach (var itemName in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<string>(queryText: $"select value(c.name) from c where c.pk='Area' and c.id='{scBaseInfo.areaId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base-Area") }))
+                            {
+                                areaName = itemName;
+                            }
+                        }
+
+                        bIRelation = new BIRelation()
+                        {
+                            id = scBaseInfo.id,
+                            name = scBaseInfo.name,
+                            picture = scBaseInfo.picture,
+                            size = scBaseInfo.size,
+                            createDate = scBaseInfo.createTime,
+                            region = scBaseInfo.region,
+                            province = scBaseInfo.province,
+                            city = scBaseInfo.city,
+                            dist = scBaseInfo.dist,
+                            address = scBaseInfo.address,
+                            areaId = scBaseInfo.areaId,
+                            scale = scBaseInfo.scale,
+                            areaName = areaName,
+                            upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
+                        };
+
+                        var response = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(itemId, new PartitionKey("ProductSum"));
+                        if (response.Status == 200)
+                        {
+                            using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                            if (json.RootElement.TryGetProperty("serial", out JsonElement serial) && !serial.ValueKind.Equals(JsonValueKind.Null))
+                            {
+                                List<string> serials = serial.ToObject<List<SchoolProductSumData>>().Select(x => x.prodCode).ToList();
+                                bIRelation.serial = serials;
+                            }
+                            if (json.RootElement.TryGetProperty("service", out JsonElement service) && !service.ValueKind.Equals(JsonValueKind.Null))
+                            {
+                                List<string> services = service.ToObject<List<SchoolProductSumData>>().Select(x => x.prodCode).ToList();
+                                bIRelation.service = services;
+                            }
+                            if (json.RootElement.TryGetProperty("hard", out JsonElement hard) && !hard.ValueKind.Equals(JsonValueKind.Null))
+                            {
+                                List<string> hards = hard.ToObject<List<SchoolProductSumDataHard>>().Select(x => x.prodCode).ToList();
+                                bIRelation.hard = hards;
+                            }
+                        }
+                        bIRelation = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<BIRelation>(bIRelation, new PartitionKey("BIRel"));
+                    }
+
+                    scInfos.Add(bIRelation);
+                }
+
+                return Ok(new { state = RespondCode.Ok, cnt = scId.Count, scInfos });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location},/school/get-scinfos \n{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
 
         /// <summary>
         /// 依据Id查询School容器  数据管理工具——查询工具

+ 305 - 0
TEAMModelBI/Controllers/RepairApi/SchoolRepController.cs

@@ -0,0 +1,305 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using System.Net.Http;
+using TEAMModelOS.SDK.DI.CoreAPI;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK;
+using TEAMModelOS.Models;
+using System.Threading.Tasks;
+using System.Text.Json;
+using System.IO;
+using TEAMModelBI.Models;
+using System.Collections.Generic;
+using System.Text;
+using TEAMModelOS.SDK.Extension;
+using System;
+using TEAMModelOS.SDK.Models;
+using Azure.Cosmos;
+using System.Linq;
+using TEAMModelOS.SDK.Context.Constant;
+using Pipelines.Sockets.Unofficial.Arenas;
+
+namespace TEAMModelBI.Controllers.RepairApi
+{
+    [Route("sccholrep")]
+    [ApiController]
+    public class SchoolRepController : ControllerBase
+    {
+
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly AzureRedisFactory _azureRedis;
+        private readonly IConfiguration _configuration;
+        private readonly NotificationService _notificationService;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly IWebHostEnvironment _environment; //读取文件
+        private readonly IHttpClientFactory _httpClient;
+
+        public SchoolRepController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, AzureRedisFactory azureRedis, IConfiguration configuration, NotificationService notificationService, CoreAPIHttpService coreAPIHttpService, IHttpClientFactory httpClient, IWebHostEnvironment hostingEnvironment)
+        {
+            _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _azureStorage = azureStorage;
+            _option = option?.Value;
+            _azureRedis = azureRedis;
+            _configuration = configuration;
+            _notificationService = notificationService;
+            _coreAPIHttpService = coreAPIHttpService;
+            _httpClient = httpClient;
+            _environment = hostingEnvironment;
+        }
+
+        /// <summary>
+        /// 添加新学段的学校
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-allscperiod")]
+        public async Task<IActionResult> SetAllScPeriod(JsonElement jsonElement)
+        {
+            jsonElement.TryGetProperty("Language", out JsonElement Language);
+            jsonElement.TryGetProperty("scId", out JsonElement scId);
+            jsonElement.TryGetProperty("periodName", out JsonElement periodName);
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
+            StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
+            StringBuilder stringBuilder = new();
+            string text;
+            string scName = "默认学段";
+            while ((text = streamReader.ReadLine()) != null)
+            {
+                stringBuilder.Append(text.ToString());
+            }
+            streamReader.Close();
+            string input = stringBuilder.ToString();
+            List<SchoolConfig> schoolConfigs = input.ToObject<List<SchoolConfig>>();
+            SchoolConfig schoolConfig = null;
+            if (!string.IsNullOrEmpty($"{Language}"))
+                schoolConfig = schoolConfigs.Find(x => x.Lang.Contains($"{Language}"));
+
+            if (schoolConfig == null)
+            {
+                if ($"{Language}".Contains("en"))
+                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("en-US"));
+                else
+                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("zh-CN"));
+            }
+            string campusId = Guid.NewGuid().ToString();
+
+            StringBuilder noPeriodScSql = new("SELECT value(c) FROM c ");
+            List<School> allSc = new();
+
+            if (!string.IsNullOrEmpty($"{scId}"))
+                noPeriodScSql.Append($" where c.id='{scId}'");
+            else
+                noPeriodScSql.Append($" join sp in c.period where c.code = 'Base' AND ARRAY_LENGTH(sp.grades) = 0 OR ARRAY_LENGTH(sp.subjects) = 0");
+
+            if (!string.IsNullOrEmpty($"{periodName}"))
+                scName = $"{periodName}";
+
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: "select value(c) from c where c.code='Base' and c.period=[]", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+            {
+                allSc.Add(item);
+            }
+
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText:noPeriodScSql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+            {
+                allSc.Add(item);
+            }
+
+            foreach (var school in allSc)
+            {
+                if (school.name.Contains("幼儿园"))
+                {
+                    string name = null;
+                    List<Subject> subjects = new();
+                    switch ($"{Language}")
+                    {
+                        case "zh-CN":
+                            name = "学前";
+                            subjects.Add(new Subject { id = Guid.NewGuid().ToString(), name = "语言", type = 1 });
+                            break;
+                        case "zh-TW":
+                            name = "學前";
+                            subjects.Add(new Subject { id = Guid.NewGuid().ToString(), name = "語言", type = 1 });
+                            break;
+                        case "en-US":
+                            name = "Pre-school";
+                            subjects.Add(new Subject { id = Guid.NewGuid().ToString(), name = "language", type = 1 });
+                            break;
+                    }
+                    if (school.period.Count > 0)
+                    {
+                        var grade = school.period.Find(sg => sg.grades.Count == 0);
+                        if (grade.grades.Count == 0)
+                            grade.grades = new List<string>() { name };
+
+                        var tempSub = school.period.Find(sg => sg.semesters.Count == 0);
+                        if (tempSub.semesters.Count == 0)
+                            tempSub.subjects = subjects;
+                    }
+                    else
+                    {
+                        if (school.campuses.Count > 0)
+                            campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
+
+                        school.period.Add(new Period
+                        {
+
+                        });
+
+                        if (!school.campuses.Select(x => x.id).Contains(campusId))
+                            school.campuses.Add(new Campus { name = school.name, id = campusId });
+                    }
+                }
+                else
+                {
+                    if (school.period.Count > 0)
+                    {
+                        var grade = school.period.Find(sg => sg.grades.Count == 0);
+                        if (grade.grades.Count == 0)
+                            grade.grades = schoolConfig.grades;
+
+                        var subject = school.period.Find(sg => sg.subjects.Count == 0);
+                        if (subject.subjects.Count == 0)
+                        {
+                            subject.subjects = new List<Subject>() {
+                            new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
+                            new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
+                            new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
+                            };
+                        }
+                    }
+                    else
+                    {
+                        if (school.campuses.Count > 0)
+                            campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
+
+                        school.period.Add(new Period
+                        {
+                            id = Guid.NewGuid().ToString(),
+                            name = scName,
+                            campusId = campusId,
+                            semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
+                        new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
+                            subjects = new List<Subject>() {
+                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
+                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
+                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
+                        },
+                            grades = schoolConfig.grades,
+                            analysis = new Analysis()
+                            {
+                                type = new List<ExamSimple>() { new ExamSimple { id = Guid.NewGuid().ToString(), name = schoolConfig.PresetExam[0].type[0].name },
+                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[1].name },
+                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[2].name },
+                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[3].name } },
+                                income = schoolConfig.PresetExam[0].income,
+                                eugenics = schoolConfig.PresetExam[0].eugenics,
+                                touch = schoolConfig.PresetExam[0].touch
+                            }
+                        });
+                        if (!school.campuses.Select(x => x.id).Contains(campusId))
+                            school.campuses.Add(new Campus { name = school.name, id = campusId });
+                    }
+                }
+
+                School rSchool = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey("Base"));
+            }
+
+            return Ok(new { state = RespondCode.Ok });
+        }
+
+        /// <summary>
+        /// 新增学校学段(多个)
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-scperiod")]
+        public async Task<IActionResult> SetScPeriod(JsonElement jsonElement)
+        {
+            if (!jsonElement.TryGetProperty("scId", out JsonElement scId)) return BadRequest();
+            if (!jsonElement.TryGetProperty("periodName", out JsonElement periodName)) return BadRequest();
+
+            List<string> periodNames = $"{periodName}".ToObject<List<string>>();
+            jsonElement.TryGetProperty("Language", out JsonElement Language);
+
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            var builder = $"{_environment.ContentRootPath}/JsonFile/Preset/LangSchoolConfig.json";
+            StreamReader streamReader = new(new FileStream(builder, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
+            StringBuilder stringBuilder = new();
+            string text;
+            while ((text = streamReader.ReadLine()) != null)
+            {
+                stringBuilder.Append(text.ToString());
+            }
+            streamReader.Close();
+            string input = stringBuilder.ToString();
+            List<SchoolConfig> schoolConfigs = input.ToObject<List<SchoolConfig>>();
+            SchoolConfig schoolConfig = null;
+            if (!string.IsNullOrEmpty($"{Language}"))
+                schoolConfig = schoolConfigs.Find(x => x.Lang.Contains($"{Language}"));
+
+            if (schoolConfig == null)
+            {
+                if ($"{Language}".Contains("en"))
+                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("en-US"));
+                else
+                    schoolConfig = schoolConfigs.Find(x => x.Lang.Contains("zh-CN"));
+            }
+            string campusId = Guid.NewGuid().ToString();
+            School school = null;
+
+            school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{scId}", new PartitionKey("Base"));
+
+            if (school != null)
+            {
+                foreach (var item in periodNames)
+                {
+                    if (school.campuses.Count > 0)
+                        campusId = school.campuses.Select(x => x.id).FirstOrDefault().ToString();
+
+                    school.period.Add(new Period
+                    {
+                        id = Guid.NewGuid().ToString(),
+                        name = item,
+                        campusId = campusId,
+                        semesters = new List<Semester>() { new Semester { name = schoolConfig.semester[0].term, start = schoolConfig.semester[0].start, month = schoolConfig.semester[0].month, day = schoolConfig.semester[0].day, id = Guid.NewGuid().ToString() },
+                        new Semester { name = schoolConfig.semester[1].term, start = schoolConfig.semester[1].start, month = schoolConfig.semester[1].month, day = schoolConfig.semester[1].day, id = Guid.NewGuid().ToString() } },
+                        subjects = new List<Subject>() {
+                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[0].name,type=schoolConfig.PresetSubject[0].type },
+                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[1].name,type=schoolConfig.PresetSubject[1].type },
+                        new Subject { id=Guid.NewGuid().ToString(),name=schoolConfig.PresetSubject[2].name,type=schoolConfig.PresetSubject[2].type }
+                        },
+                        grades = schoolConfig.grades,
+                        analysis = new Analysis()
+                        {
+                            type = new List<ExamSimple>() { new ExamSimple { id = Guid.NewGuid().ToString(), name = schoolConfig.PresetExam[0].type[0].name },
+                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[1].name },
+                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[2].name },
+                        new ExamSimple { id = Guid.NewGuid().ToString(), name =  schoolConfig.PresetExam[0].type[3].name } },
+                            income = schoolConfig.PresetExam[0].income,
+                            eugenics = schoolConfig.PresetExam[0].eugenics,
+                            touch = schoolConfig.PresetExam[0].touch
+                        }
+                    });
+                }
+
+                if (!school.campuses.Select(x => x.id).Contains(campusId))
+                    school.campuses.Add(new Campus { name = school.name, id = campusId });
+            }
+
+            school = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey("Base"));
+
+            return Ok(new { state = RespondCode.Ok, school });
+        }
+
+    }
+}

+ 1 - 1
TEAMModelBI/Models/RearEndMiddle.cs

@@ -7,7 +7,7 @@
     /// <summary>
     /// 学校基础
     /// </summary>
-    public record ScBaseInfo
+    public record ScEasyInfo
     {
         public string id { get; set; }
         public string code { get; set; }

+ 3 - 3
TEAMModelBI/TEAMModelBI.csproj

@@ -65,9 +65,9 @@
 		<SpaRoot>ClientApp\</SpaRoot>
 		<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
 		<UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-		<Version>1.2211.16</Version>
-		<AssemblyVersion>1.2211.11.16</AssemblyVersion>
-		<FileVersion>1.2211.11.16</FileVersion>
+		<Version>1.2211.18</Version>
+		<AssemblyVersion>1.2211.11.18</AssemblyVersion>
+		<FileVersion>1.2211.11.18</FileVersion>
 		<Description>TEAMModelBI(BI)</Description>
 		<PackageReleaseNotes>BI版本说明版本切换标记2022000908</PackageReleaseNotes>
 		<PackageId>TEAMModelBI</PackageId>

+ 113 - 0
TEAMModelOS.SDK/Models/Cosmos/BI/BISchool/BIRelation.cs

@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.BI.BISchool
+{
+    /// <summary>
+    /// BI学校列表中间件
+    /// </summary>
+    public class BIRelation : CosmosEntity
+    {
+        //id   学校列表
+        //code BIRel
+        //pk  state
+        public BIRelation()
+        {
+            code = "BIRel";
+            pk = "Stats";
+        }
+        /// <summary>
+        /// 学校名称
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 学校log
+        /// </summary>
+        public string picture { get; set; }
+        /// <summary>
+        /// 国家
+        /// </summary>
+        public string region { get; set; }
+        /// <summary>
+        /// 省份
+        /// </summary>
+        public string province { get; set; }
+        /// <summary>
+        /// 城市
+        /// </summary>
+        public string city { get; set; }
+        /// <summary>
+        /// 区/县/郡
+        /// </summary>
+        public string dist { get; set; }
+        /// <summary>
+        /// 详细地址
+        /// </summary>
+        public string address { get; set; }
+        /// <summary>
+        /// 所在区级Id
+        /// </summary>
+        public string areaId { get; set; }
+        /// <summary>
+        /// 所在区级名称
+        /// </summary>
+        public string areaName { get; set; }
+        /// <summary>
+        /// 空间大小
+        /// </summary>
+        public int size { get; set; }
+        /// <summary>
+        /// 规模大小
+        /// </summary>
+        public int scale { get; set; }
+        /// <summary>
+        /// 学校顾问信息
+        /// </summary>
+        public List<IdInfo> assists { get; set; }
+        /// <summary>
+        /// 学校销售
+        /// </summary>
+        public List<IdInfo> sales { get; set; }
+        /// <summary>
+        /// 学校软体id
+        /// </summary>
+        public List<string> serial { get; set; }
+        /// <summary>
+        /// 学校服务id
+        /// </summary>
+        public List<string> service { get; set; }
+        /// <summary>
+        /// 学校硬体
+        /// </summary>
+        public List<string> hard { get; set; }
+        /// <summary>
+        /// 本条数据更新时间
+        /// </summary>
+        public long upDate { get; set; }
+        /// <summary>
+        /// 学校创建时间
+        /// </summary>
+        public long createDate { get; set; }
+    }
+    /// <summary>
+    /// 账户简易信息
+    /// </summary>
+    public class IdInfo
+    {
+        /// <summary>
+        /// 账号id
+        /// </summary>
+        public string id { get; set; }
+        /// <summary>
+        /// 账号名称
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 账号头像
+        /// </summary>
+        public string picture { get; set; }
+    }
+}

+ 42 - 0
TEAMModelOS.SDK/Models/Cosmos/BI/CurrencyModel.cs

@@ -17,12 +17,54 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
     {
         public string id { get; set; }
         public string code { get; set; }
+
+        /// <summary>
+        /// 学校名称
+        /// </summary>
         public string name { get; set; }
+        /// <summary>
+        /// 学校log
+        /// </summary>
         public string picture { get; set; }
         public int size { get; set; }
         public long createTime { get; set; }
     }
 
+    /// <summary>
+    /// 学校基础信息信息
+    /// </summary>
+    public class ScBaseInfo : ScBase 
+    {
+        /// <summary>
+        /// 国家
+        /// </summary>
+        public string region { get; set; }
+        /// <summary>
+        /// 省份
+        /// </summary>
+        public string province { get; set; }
+        /// <summary>
+        /// 城市
+        /// </summary>
+        public string city { get; set; }
+        /// <summary>
+        /// 区/县/郡
+        /// </summary>
+        public string dist { get; set; }
+        /// <summary>
+        /// 详细地址
+        /// </summary>
+        public string address { get; set; }
+        /// <summary>
+        /// 所在区级Id
+        /// </summary>
+        public string areaId { get; set; }
+        /// <summary>
+        /// 规模大小
+        /// </summary>
+        public int scale { get; set; }
+    }
+
     /// <summary>
     /// 
     /// </summary>

+ 55 - 9
TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html

@@ -3,8 +3,8 @@
 <head>
   <meta charset="utf-8"/>
   <title>iconfont Demo</title>
-  <link rel="shortcut icon" href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico" type="image/x-icon"/>
-  <link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg"/>
+  <link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
+  <link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
   <link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
   <link rel="stylesheet" href="demo.css">
   <link rel="stylesheet" href="iconfont.css">
@@ -54,6 +54,18 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xfa96;</span>
+                <div class="name">咖啡</div>
+                <div class="code-name">&amp;#xfa96;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe716;</span>
+                <div class="name">问号-无圈</div>
+                <div class="code-name">&amp;#xe716;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe67f;</span>
                 <div class="name">员工管理  证件  学生证   工作证</div>
@@ -1254,9 +1266,9 @@
 <pre><code class="language-css"
 >@font-face {
   font-family: 'iconfont';
-  src: url('iconfont.woff2?t=1655720468210') format('woff2'),
-       url('iconfont.woff?t=1655720468210') format('woff'),
-       url('iconfont.ttf?t=1655720468210') format('truetype');
+  src: url('iconfont.woff2?t=1669086215029') format('woff2'),
+       url('iconfont.woff?t=1669086215029') format('woff'),
+       url('iconfont.ttf?t=1669086215029') format('truetype');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -1283,11 +1295,29 @@
         <ul class="icon_lists dib-box">
           
           <li class="dib">
-            <span class="icon iconfont icon-id-card"></span>
+            <span class="icon iconfont icon-kafei"></span>
+            <div class="name">
+              咖啡
+            </div>
+            <div class="code-name">.icon-kafei
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-wenhao"></span>
+            <div class="name">
+              问号-无圈
+            </div>
+            <div class="code-name">.icon-wenhao
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-yuangongguanlizhengjianxueshengzhenggongzuozheng"></span>
             <div class="name">
               员工管理  证件  学生证   工作证
             </div>
-            <div class="code-name">.icon-id-card
+            <div class="code-name">.icon-yuangongguanlizhengjianxueshengzhenggongzuozheng
             </div>
           </li>
           
@@ -3084,10 +3114,26 @@
           
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
-                  <use xlink:href="#icon-id-card"></use>
+                  <use xlink:href="#icon-kafei"></use>
+                </svg>
+                <div class="name">咖啡</div>
+                <div class="code-name">#icon-kafei</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-wenhao"></use>
+                </svg>
+                <div class="name">问号-无圈</div>
+                <div class="code-name">#icon-wenhao</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-yuangongguanlizhengjianxueshengzhenggongzuozheng"></use>
                 </svg>
                 <div class="name">员工管理  证件  学生证   工作证</div>
-                <div class="code-name">#icon-id-card</div>
+                <div class="code-name">#icon-yuangongguanlizhengjianxueshengzhenggongzuozheng</div>
             </li>
           
             <li class="dib">

+ 12 - 4
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 2000444 */
-  src: url('iconfont.woff2?t=1655720468210') format('woff2'),
-       url('iconfont.woff?t=1655720468210') format('woff'),
-       url('iconfont.ttf?t=1655720468210') format('truetype');
+  src: url('iconfont.woff2?t=1669086215029') format('woff2'),
+       url('iconfont.woff?t=1669086215029') format('woff'),
+       url('iconfont.ttf?t=1669086215029') format('truetype');
 }
 
 .iconfont {
@@ -13,7 +13,15 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
-.icon-id-card:before {
+.icon-kafei:before {
+  content: "\fa96";
+}
+
+.icon-wenhao:before {
+  content: "\e716";
+}
+
+.icon-yuangongguanlizhengjianxueshengzhenggongzuozheng:before {
   content: "\e67f";
 }
 

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js


+ 15 - 1
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json

@@ -5,10 +5,24 @@
   "css_prefix_text": "icon-",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "24103836",
+      "name": "咖啡",
+      "font_class": "kafei",
+      "unicode": "fa96",
+      "unicode_decimal": 64150
+    },
+    {
+      "icon_id": "9974774",
+      "name": "问号-无圈",
+      "font_class": "wenhao",
+      "unicode": "e716",
+      "unicode_decimal": 59158
+    },
     {
       "icon_id": "14719218",
       "name": "员工管理  证件  学生证   工作证",
-      "font_class": "id-card",
+      "font_class": "yuangongguanlizhengjianxueshengzhenggongzuozheng",
       "unicode": "e67f",
       "unicode_decimal": 59007
     },

BIN
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf


BIN
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff


BIN
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2


+ 323 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/AnswerBox.less

@@ -0,0 +1,323 @@
+.answer-box {
+    width: 100%;
+    height: 100%;
+    padding: 25px;
+    padding-bottom: 50px;
+
+    .title-box {
+        width: 100%;
+        height: 45px;
+        background-color: #FFFFFF;
+        position: absolute;
+        top: 0;
+        left: 0;
+        z-index: 6;
+        border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+        color: #24b880;
+        font-size: 20px;
+        padding: 5px 15px;
+
+        .logout-icon {
+            cursor: pointer;
+        }
+
+        .test-title {
+            margin-left: 10px;
+            font-weight: bold;
+        }
+    }
+
+    .size {
+        &-A {
+            font-size: 25px;
+        }
+
+        &-B {
+            font-size: 20px;
+        }
+
+        &-C {
+            font-size: 18px;
+        }
+    }
+
+    .quertion-area {
+        background: #F3F9F3;
+        padding: 15px;
+        font-weight: bold;
+        margin-bottom: 25px;
+        border-radius: 5px;
+
+        .header {
+            font-size: 17px;
+            display: flex;
+            justify-content: space-between;
+
+            &>p {
+
+                cursor: pointer;
+            }
+
+            .ivu-icon {
+                position: relative;
+                top: -0.13rem;
+                margin-right: 5px;
+            }
+        }
+    }
+
+    .answer-content {
+        width: 100%;
+        height: 100%;
+
+        .answer-area {
+            display: flex;
+            font-size: 17px;
+            margin-bottom: 15px;
+
+
+            .answer-tip {
+                color: #68A129;
+                margin-right: 10px;
+                min-width: 80px;
+            }
+        }
+
+        .code-box {
+            width: 100%;
+            display: flex;
+            flex-wrap: wrap;
+            justify-content: center;
+
+            &>div {
+                width: 45%;
+                font-size: 17px;
+                margin-bottom: 25px;
+
+                &:nth-child(odd) {
+                    margin-right: 30px;
+                }
+
+                &:nth-child(even) {
+                    margin-left: 30px;
+                }
+
+                .code-block {
+                    padding: 15px 20px;
+                    padding-right: 30px;
+                    border-radius: 5px;
+                    height: auto;
+                    background-color: #F2F2F2;
+                    display: flex;
+                    cursor: pointer;
+                    position: relative;
+
+                    .code-label {
+                        font-weight: bold;
+                        margin-right: 10px;
+                    }
+
+                    .code-icon {
+                        font-size: 20px;
+                        font-weight: bold;
+                        position: absolute;
+                        right: 0px;
+                        top: 50%;
+                        transform: translate(-50%, -50%);
+                    }
+                }
+
+                .code-block-active {
+                    background: #98C468;
+                    color: #fff;
+                }
+            }
+
+        }
+
+        .compose-content {
+            width: 100%;
+            padding: 0 2%;
+            margin-bottom: 25px;
+        }
+    }
+
+    .question-content {
+        width: 100%;
+        height: 100%;
+        height: calc(100% - 30px);
+
+        div {
+            z-index: 2;
+        }
+
+        .quertion-icon {
+            // z-index: -1;
+            font-size: 40rem;
+            font-weight: bold;
+            position: absolute;
+            right: calc(50% - 40rem);
+            top: 50%;
+            transform: translate(-50%, -50%);
+            color: #e0e0e0;
+        }
+    }
+
+    .rest-box {
+        font-size: 3rem;
+        text-align: center;
+        padding-top: 7%;
+
+        p {
+            margin-bottom: 10px;
+        }
+
+        .ivu-icon {
+            font-size: 15rem;
+        }
+    }
+
+    .function-button {
+        position: absolute;
+        bottom: 40px;
+        width: calc(100% - 100px);
+        display: flex;
+        justify-content: space-between;
+        flex-direction: row-reverse;
+
+        .common-button {
+            width: 15%;
+            height: 35px;
+            border: none;
+            font-size: 18px;
+            font-weight: bold;
+            color: #fff;
+        }
+    }
+}
+
+@media screen and (max-width: 520px) {
+    .answer-box {
+        height: calc(100% - 50px);
+        padding: 0;
+        // padding-bottom: 50px;
+        background-color: #fff;
+
+        .title-box{
+            background-color: #f2f2f2;
+            height: 50px;
+            border-bottom: none;
+            font-size: 16px;
+            color: #686868;
+            padding-top: 10px;
+        }
+
+        .size {
+            &-A {
+                font-size: 20px;
+            }
+
+            &-B {
+                font-size: 18px;
+            }
+
+            &-C {
+                font-size: 16px;
+            }
+        }
+
+        .answer-content {
+
+            .compose-content {
+                padding: 0 5%;
+            }
+
+            .answer-area {
+                display: block;
+                font-size: 14px;
+                padding: 0 5%;
+            }
+
+            .code-box {
+                width: 100%;
+                display: block;
+
+                &>div {
+                    width: 90%;
+                    margin: 0 5%;
+                    font-size: 14px;
+                    margin-bottom: 25px;
+
+                    &:nth-child(odd) {
+                        margin-right: 0;
+                    }
+
+                    &:nth-child(even) {
+                        margin-left: 5%;
+                    }
+                }
+            }
+        }
+
+        .quertion-area {
+            background: #fff;
+            position: relative;
+            overflow: hidden;
+            margin-bottom: 0;
+
+            .header {
+                font-size: 14px;
+            }
+        }
+
+        .question-know {
+            border-bottom: 1px dashed #ccc;
+            border-radius: 0;
+            margin-bottom: 15px;
+        }
+
+        .question-content {
+            height: 100%;
+
+            .quertion-icon {
+                font-size: 30rem;
+                right: calc(50% - 30rem);
+            }
+        }
+
+        .rest-box {
+            font-size: 2rem;
+            padding-top: 40%;
+        }
+
+        .function-button {
+            bottom: 15px;
+            width: calc(100% - 20px);
+
+            .common-button {
+                width: 22%;
+                height: 30px;
+                font-size: 15px;
+            }
+
+            .rest-button {
+                width: 40%;
+            }
+
+            .only-button {
+                width: 100%;
+            }
+        }
+
+        .analysis {
+            width: auto;
+            padding: 1px 5px;
+            background: #ccc;
+            display: block;
+            position: absolute;
+            bottom: 50px;
+            left: 50%;
+            transform: translate(-50%, -50%);
+        }
+    }
+}

+ 343 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/AnswerBox.vue

@@ -0,0 +1,343 @@
+<template>
+    <div class="answer-box">
+        <Loading v-show="isLoading" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
+        <div class="title-box">
+            <span class="logout-icon" @click="openWarmMessage(1)">
+                <svg-icon icon-class="logout" />
+            </span>
+            <span class="test-title">课程名称:罗老师小课堂</span>
+        </div>
+        <div class="answer-content" v-if="practiceType != 2 && practiceType != 5">
+            <vuescroll>
+                <!-- <div :class="['quertion-area', `size-${queNum}`, 'question-know']"> -->
+                <div :class="['quertion-area', `size-${queNum}`]">
+                    <div class="header" v-show="practiceType != 1">
+                        <span>【多选题】</span>
+                        <p @click="onCollection">
+                            <Icon custom="iconfont icon-shoucang1" size="21" color="#3B660C" v-show="!iscollection"></Icon>
+                            <Icon custom="iconfont icon-shoucang2" size="21" color="#EA8F3E" v-show="iscollection"></Icon>
+                            <span>收藏</span>
+                        </p>
+                    </div>
+                    <div v-html="question"></div>
+                </div>
+                <template v-if="practiceType === 3 || practiceType === 4">
+                    <div class="code-box" v-if="false">
+                        <div v-for="(item, index) in codeList" :key="index">
+                            <div :class="['code-block', isChecked(item.code) ? 'code-block-active' : '']" :tabIndex="index"
+                                @click="onAnswerCheck(item, index)" :style="{'cursor': practiceType === 3 ? 'pointer' : 'no-drop'}"
+                            >
+                                <span class="code-label">{{ item.code }}</span>
+                                <span v-html="item.value"></span>
+                                <template v-if="practiceType === 4">
+                                    <Icon custom="iconfont icon-choose" class="code-icon" color="#3B660C"></Icon>
+                                    <Icon custom="iconfont icon-cuowu" class="code-icon" color="#DB5248"></Icon>
+                                </template>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="compose-content" v-if="practiceType === 3">
+                        <Compose ref="compose" :itemInfo="itemInfo" :close="false" :textData="checkedAnswerList"
+                            :index="1" @dataGet="getComposeAns"
+                        ></Compose>
+                    </div>
+                    <div class="answer-area" v-else>
+                        <span class="answer-tip">我的答案:</span>
+                        <p v-html="checkedAnswerList[0]"></p>
+                    </div>
+                </template>
+                <div v-if="practiceType === 1 || practiceType === 4">
+                    <div class="answer-area">
+                        <span class="answer-tip">【答案】</span>
+                        <p>
+                            这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟,如“安得广厦千万间,大庇天下寒士俱欢颜"这样的诗句,表现出作者在自己生活极度艰难的情景下,依然不忘忧国忧民,情真意切.感人至深。
+                        </p>
+                    </div>
+                    <div class="answer-area">
+                        <span class="answer-tip">【解析】</span>
+                        <p>
+                            这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。
+                        </p>
+                    </div>
+                </div>
+            </vuescroll>
+        </div>
+        <div class="question-content quertion-area" v-if="practiceType === 2">
+            <Icon custom="iconfont icon-wenhao" class="quertion-icon"></Icon>
+            <vuescroll>
+                <div :class="[`size-${queNum}`]" v-html="question"></div>
+            </vuescroll>
+        </div>
+        <div class="rest-box" v-if="practiceType === 5">
+            <p>让脑袋冷静一下</p>
+            <p>休息一下再继续</p>
+            <Icon custom="iconfont icon-kafei"></Icon>
+        </div>
+        <div class="function-button">
+            <Button class="common-button only-button" style="background: #84ba48" v-if="practiceType === 1" @click="goTo(2)">了解了</Button>
+            <template v-if="practiceType === 2">
+                <Button class="common-button" style="background: #84ba48" @click="goTo(3)">肯定会</Button>
+                <Button class="common-button" style="background: #b9c746" @click="goTo(3)">应该会</Button>
+                <Button class="common-button" style="background: #da933b" @click="goTo(3)">不太会</Button>
+                <Button class="common-button" style="background: #c2543f" @click="goTo(3)">不会</Button>
+            </template>
+            <Button class="common-button only-button" style="background: #c0c0c0" v-if="practiceType === 3" @click="goTo(4)">提交</Button>
+            <Button class="common-button only-button" style="background: #84ba48" v-if="practiceType === 4" @click="goTo(0)">继续</Button>
+            <template v-if="practiceType === 5">
+                <Button class="common-button rest-button" style="background: #84ba48" @click="goTo(1)">活力满满,继续</Button>
+                <Button class="common-button rest-button" style="background: #c0c0c0" @click="openWarmMessage(1)">改天再练,先离开</Button>
+            </template>
+        </div>
+        <!-- <div class="analysis">解析</div> -->
+    </div>
+</template>
+
+<script>
+import Loading from "@/common/Loading.vue"
+import Compose from '../EventView/EventContentTypeTemplate/composePaper.vue'
+import { mapState } from 'vuex'
+export default {
+    components: {
+        Loading,
+        Compose,
+    },
+    data() {
+        return {
+            isLoading: false,
+            question: `
+            这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。
+            这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。
+            这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。
+            这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。
+            <img src="./student-en-us.png" alt="">`,
+            /* question: `I heard the echo, from the valleys and the heart
+                Open to the lonely soul of sickle harvesting I heard the echo, from the valleys and the heart
+                Repeat outrightly, but also repea also repeat the well-being of Eventualy soul of sickle harvesting I heard the echo, from the valleys and the heart
+                Repeat outrightly, but also repeat the well- 
+                Open to the lonely soul of sickle harvesting I heard the echo, from the valleys and the heart
+                Eventua<img src="./student-en-us.png" alt="">`, */
+            codeList: [
+                {code: "A", value: `这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟,如“安得广厦千万间,大庇天下寒士俱欢颜"这样的诗句,
+                    表现出作者在自己生活极度艰难的情景下,依然不忘忧国忧民,情真意切.感人至深。`},
+                {code: "B", value: "表达了作者渴望⼀展抱负,杀敌报国,建功⽴业的雄⼼壮志。"},
+                {code: "C", value: "从表达⽅式上看,词的上阕重在叙事(描写);下阕重在抒情。"},
+                {code: "D", value: "《茅屋为秋风所破歌》"},
+                {code: "E", value: `这是以抒写官军全体将⼠⼼愿的⽅式,表现了诗⼈坚定的政治⽴场,这⾥所说的“报君”、
+                    “为君死”跟封建时代⾂⼦的“愚忠”有着本质的区别,“君”这是中央集权的象征,“为君死”即为维护中央集权战死。
+                    从这个意义上说,这两句也可算得是诗⼈那个时代的最强⾳了。`},
+                {code: "F", value: "《茅屋为秋风所破歌》"},
+            ],
+            checkedAnswerList: [],
+            iscollection: false,
+            itemInfo: {},
+            quesList: [],
+            qsAll: [],
+            nowIndex: 0,
+            practiceType: 1, //1:学习,2:询问,3:作答,4:答案,5:休息
+        }
+    },
+    computed: {
+        ...mapState({
+            userInfo: state => state.userInfo,
+        }),
+        queNum() {
+            // 计算字节数
+            let len = 0
+            for (var i = 0; i < this.question.length; i++) {
+                var c = this.question.charCodeAt(i)
+                //单字节加1
+                if (
+                    (c >= 0x0001 && c <= 0x007e) ||
+                    (0xff60 <= c && c <= 0xff9f)
+                ) {
+                    len++
+                } else {
+                    len += 2
+                }
+            }
+            return len < 500 ? "A" : len < 1200 ? "B" : "C"
+            // 字节长度
+            // 同一段中文,字节数比长度更符合样式要求
+            console.log(this.question.length)
+            return this.question.length < 500 ? "A" : this.question.length < 1200 ? "B" : "C"
+        },
+        isChecked() {
+            return item => {
+                return this.checkedAnswerList.map(item => item).indexOf(item) > -1
+            }
+        },
+    },
+    mounted () {
+        this.qsAll = this.$route.params.qsList
+        this.quesList = [
+            {
+                "q_id":"f5adefef-44fc-43a1-7de6-fa1f8afa5f2b",
+                "index":0,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":null,
+                "correctness":1,
+                "end_time":1665651561,
+                "confidence_level":2
+            },{
+                "q_id":"baff9b62-7978-1ebb-8f36-af2bb78cd853",
+                "index":1,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":6,
+                "correctness":0,
+                "end_time":1665651561,
+                "confidence_level":4
+            },{
+                "q_id":"6df25a81-41ac-1e1a-78bd-5377c8d2ce4f",
+                "index":2,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":7,
+                "correctness":0,
+                "end_time":1665651561,
+                "confidence_level":1
+            },{
+                "q_id":"1d62b867-2923-3700-ca72-ed9bad257303",
+                "index":3,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":null,
+                "correctness":1,
+                "end_time":1665651561,
+                "confidence_level":3
+            },{
+                "q_id":"d8e382a5-b713-0657-d197-4d7935ddf386",
+                "index":4,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":null,
+                "correctness":0,
+                "end_time":1665651561,
+                "confidence_level":3
+            },{
+                "q_id":"b67bd57a-d19e-b6d0-5e03-b1c184362b2d",
+                "index":5,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":1,
+                "correctness":1,
+                "end_time":1665651561,
+                "confidence_level":4
+            },{
+                "q_id":"c13d70a5-0952-bc4e-d7bf-a9bda829afe2",
+                "index":6,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":null,
+                "correctness":1,
+                "end_time":1665651561,
+                "confidence_level":1
+            },{
+                "q_id":"b0dcda93-a191-ad1f-a3c7-58c373131c49",
+                "index":7,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":2,
+                "correctness":0,
+                "end_time":1665651561,
+                "confidence_level":2
+            },{
+                "q_id":"5de46f22-cce9-f4b0-aeb8-b3e648671bbf",
+                "index":8,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":null,
+                "correctness":1,
+                "end_time":1665651561,
+                "confidence_level":1
+            },{
+                "q_id":"a9cd68d1-7148-1bb4-9d91-5b63db7da1f3",
+                "index":9,
+                "unit_id":10,
+                "skill_id":6101,
+                "start_time":1665651534,
+                "difficulty":5,
+                "correctness":1,
+                "end_time":1665651561,
+                "confidence_level":4
+            },
+        ]
+    },
+    methods: {
+        // 选项点击事件
+        onAnswerCheck(item, index) {
+            if(this.practiceType === 4) {
+                return
+            }
+            let list = this.checkedAnswerList
+            let isExistIndex = list.indexOf(item.code)
+            if (isExistIndex > -1) {
+                this.checkedAnswerList.splice(isExistIndex, 1)
+            } else {
+                if(true) { //单选
+                    this.checkedAnswerList.length = 0
+                }
+                this.checkedAnswerList.push(item.code)
+            }
+        },
+        // 收藏题目
+        onCollection() {
+            this.iscollection = !this.iscollection
+        },
+        // 獲取富文本返回數據
+        getComposeAns(data, index) {
+            // index可能为0
+            if (index !== undefined) {
+                this.checkedAnswerList.splice(0)
+                if (data) {
+                    this.checkedAnswerList.push(data)
+                }
+            }
+        },
+        // 下一步该做什么
+        goTo(type) {
+            if(type) {
+                // 没有作答点击提交
+                if(type === 4 && !this.checkedAnswerList.length) {
+                    this.$Message.warning("请先作答!")
+                } else {
+                    this.practiceType = type
+                }
+            } else {
+                this.checkedAnswerList = []
+                // 根据做题进度进入(学习/休息)界面
+                this.practiceType = 5
+            }
+        },
+        //打开提示信息
+        openWarmMessage(showMessageNum) {
+            if(showMessageNum === 1) {
+                this.quitTest()
+            }
+        },
+        //退出测试
+        quitTest() {
+            let param = {
+                sid: this.userInfo.sub,
+                record: this.quesList
+            }
+            this.isLoading = true
+            this.$router.go(-1)
+        },
+    }
+}
+</script>
+
+<style lang="less" scoped>
+@import "./AnswerBox.less";
+</style>

+ 40 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/Index.vue

@@ -0,0 +1,40 @@
+<template>
+    <div class="wrong-index">
+        <div>
+            <router-view></router-view>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    components: {},
+}
+</script>
+
+<style lang="less" scoped>
+.wrong-index {
+    width: 100%;
+    height: 100%;
+    background-color: #f2f2f2;
+    padding: 25px;
+    
+    & > div {
+        // padding: 25px;
+        width: 100%;
+        height: 100%;
+        background-color: #fff;
+        border-radius: 5px;
+    }
+}
+
+@media screen and (max-width: 576px) {
+    .wrong-index {
+        padding: 10px;
+
+        & > div {
+            background-color: #f2f2f2;
+        }
+    }
+}
+</style>

+ 189 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/PreciseQues.vue

@@ -0,0 +1,189 @@
+<template>
+    <div class="count-box">
+        <div class="count-header">
+            <div>
+                <p class="count-text">
+                    已练习
+                </p>
+                <p class="count-num count-num-1">11</p>
+            </div>
+            <div>
+                <p class="count-text">
+                    已熟练
+                </p>
+                <p class="count-num count-num-2">34</p>
+            </div>
+            <div>
+                <p class="count-text">
+                    总题数
+                </p>
+                <p class="count-num count-num-3">215</p>
+            </div>
+            <div>
+                <p class="count-text">最近一次练习</p>
+                <p class="count-text-foot">
+                    <span class="count-num count-num-4">1</span>
+                    日前
+                </p>
+            </div>
+            <div>
+                <p class="count-text">建议练习时间</p>
+                <p class="count-text-foot">
+                    <span class="count-num count-num-4">3</span>
+                    日后
+                    <span>(2022-11-1)</span>
+                </p>
+            </div>
+            <div class="count-btn">
+                <Button type="success" @click="openModal">开始练习</Button>
+            </div>
+        </div>
+        <div class="charts-box">
+            <div id="Difficulty"></div>
+        </div>
+        <Modal v-model="isReview" class="student-check no-ok" title="练习列表">
+            <div v-for="(item, index) in quesList" :key="index" class="ques-list">
+                <img src="./student-en-us.png" alt="">
+                <div class="ques-content">
+                    <p>{{ item.name }}</p>
+                    <Progress :percent="90" :hide-info="true" :stroke-width="5" stroke-color="#52c46c" />
+                    <div class="tip-foot">
+                        <span>
+                            练习:{{ item.prc }}
+                        </span>
+                        <span>
+                            熟练:{{ item.know }}
+                        </span>
+                    </div>
+                </div>
+                <Button @click="startReview">开始练习</Button>
+            </div>
+        </Modal>
+    </div>
+</template>
+
+<script>
+export default {
+    data () {
+        return {
+            isReview: false,
+            filtType: {
+                term: 0,
+                num: 0
+            },
+            quesList: [
+                {
+                    name: "语文古诗词",
+                    prc: "24",
+                    know: "12",
+                },
+                {
+                    name: "语文古诗词",
+                    prc: "24",
+                    know: "12",
+                },
+                {
+                    name: "语文古诗词",
+                    prc: "24",
+                    know: "12",
+                },
+                {
+                    name: "语文古诗词",
+                    prc: "24",
+                    know: "12",
+                },
+            ]
+        }
+    },
+    mounted () {
+        this.setMap()
+    },
+    methods: {
+        openModal() {
+            this.isReview = true
+        },
+        startReview() {
+            this.$router.push({
+                name: "answer",
+            })
+        },
+        setMap() {
+            let myChart = this.$echarts.init(document.getElementById("Difficulty"))
+            let option = {
+                // backgroundColor: '#2c343c',
+                title: {
+                    text: '学习难度分布',
+                    left: 'center',
+                    bottom: 20,
+                    textStyle: {
+                        color: '#868686'
+                    }
+                },
+                tooltip: {
+                    trigger: 'item'
+                },
+                visualMap: {
+                    show: false,
+                    min: 80,
+                    max: 600,
+                    inRange: {
+                        colorLightness: [0, 1]
+                    }
+                },
+                series: [
+                    {
+                        name: 'Access From',
+                        type: 'pie',
+                        radius: '55%',
+                        center: ['50%', '50%'],
+                        data: [
+                            { value: 335, name: '中等' },
+                            { value: 274, name: '困难' },
+                            { value: 235, name: '艰深' },
+                            { value: 400, name: '简单' }
+                        ].sort(function (a, b) {
+                            return a.value - b.value;
+                        }),
+                        roseType: 'radius',
+                        label: {
+                            color: '#000'
+                        },
+                        labelLine: {
+                            lineStyle: {
+                                color: 'rgba(255, 255, 255, 0.3)'
+                            },
+                            smooth: 0.2,
+                            length: 10,
+                            length2: 20
+                        },
+                        itemStyle: {
+                            color: '#c23531',
+                            shadowBlur: 100,
+                            shadowColor: 'rgba(0, 0, 0, 0.4)'
+                        },
+                        animationType: 'scale',
+                        animationEasing: 'elasticOut',
+                        animationDelay: function (idx) {
+                            return Math.random() * 200;
+                        }
+                    }
+                ]
+            }
+            myChart.setOption(option)
+        },
+    },
+}
+</script>
+
+<style lang="less" scoped>
+@import "./QuesContent.less";
+</style>
+
+<style lang="less">
+@import "./iViewStyle.less";
+.no-ok {
+    .ivu-btn-primary {
+        display: none;
+    }
+}
+</style>

+ 125 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/QuesContent.less

@@ -0,0 +1,125 @@
+.count-box {
+    width: 100%;
+    // padding: 25px;
+    padding-top: 2%;
+
+    .count-header {
+        display: flex;
+        flex-wrap: wrap;
+        align-items: center;
+        width: 100%;
+
+        &>div {
+            width: 33%;
+            margin-bottom: 30px;
+            margin-top: 10px;
+            text-align: center;
+        }
+
+        .count-text {
+            font-size: 1.5rem;
+            font-weight: bold;
+            margin-bottom: 5px;
+        }
+
+        .count-text-foot {
+            font-size: 1.2rem;
+            font-weight: bold;
+        }
+
+        .count-num {
+            font-size: 3rem;
+            font-weight: bold;
+
+            &-1 {
+                color: #278ED1;
+            }
+
+            &-2 {
+                color: #38a106;
+            }
+
+            &-3 {
+                color: #828282;
+            }
+
+            &-4 {
+                color: #828282;
+            }
+        }
+
+        .count-btn {
+            display: flex;
+            align-items: center;
+            flex-direction: column;
+
+            .ivu-btn {
+                margin-bottom: 10px;
+                font-size: 1.2rem;
+                font-weight: bold;
+                height: 40px;
+                width: 70%;
+            }
+        }
+    }
+
+    .charts-box {
+        width: 90%;
+        height: 23rem;
+        text-align: center;
+        margin: 0 5%;
+
+        #Difficulty,
+        #Study {
+            width: 100%;
+            height: 100%;
+        }
+    }
+}
+
+.ques-list {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 25px;
+
+    &>img {
+        width: 90px;
+    }
+
+    .ques-content {
+        width: 60%;
+        font-size: 12px;
+
+        .tip-foot {
+            &>span:first-child {
+                padding-right: 15px;
+                margin-right: 15px;
+                position: relative;
+
+                &::after {
+                    content: "";
+                    width: 1px;
+                    height: 13px;
+                    position: absolute;
+                    right: 0px;
+                    top: 50%;
+                    transform: translate(-50%, -50%);
+                    background: #a3a3a3;
+                }
+            }
+        }
+    }
+
+    .ivu-btn {
+        background-color: #24B880;
+        color: #fff;
+        border: none;
+    }
+}
+
+@media screen and (max-height: 1024px) {
+    .count-box .charts-box {
+        height: 30rem;
+    }
+}

+ 102 - 26
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/WrongQues.less

@@ -1,18 +1,21 @@
 @import '~@/assets/student-web/component_styles/color.less';
 
-.wrong-ques{
-    padding: 2%;
-    background: #F9F9F9;
-
-    & > div {
-        background-color: #FFFFFF;
-    }
-
-    .filter-type{
-        padding: 1%;
-        margin-bottom: 20px;
+.wrong-ques {
+    width: 100%;
+    height: 100%;
+    position: relative;
+
+    .filter-type {
+        padding: 25px 30px;
+        // padding-bottom: 20px;
+        border-bottom: 1px dashed #ccc;
+        width: 100%;
+
+        .ivu-icon {
+            display: none;
+        }
 
-        & > div{
+        &>div {
             margin-bottom: 12px;
 
             &:last-child {
@@ -25,7 +28,7 @@
             margin-right: 10px;
             font-weight: bold;
         }
-        
+
         .point-box {
             border: 1px solid #24B880;
             background-color: @primary;
@@ -35,7 +38,7 @@
             margin-right: 10px;
             display: inline-block;
 
-            .ivu-icon{
+            .ivu-icon {
                 cursor: pointer;
                 margin-left: 5px;
             }
@@ -50,7 +53,7 @@
             display: inline-block;
             float: right;
 
-            & > span{
+            &>span {
                 font-size: 18px;
                 font-weight: bold;
                 color: #de0000;
@@ -58,12 +61,66 @@
             }
         }
     }
-    
-    .topic-list{
+
+    .no-filter {
+        position: absolute;
+        top: 0;
+        left: 0;
+        background: #fff;
+        z-index: 4;
+
+        &>div {
+            display: none;
+        }
+
+        .search {
+            display: block;
+        }
+
+        .ivu-icon {
+            display: block;
+            font-size: 30px;
+            position: absolute;
+            bottom: -34px;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            cursor: pointer;
+        }
+
+    }
+
+    .show-filter {
+        &>div {
+            display: block;
+        }
+
+        .ivu-icon {
+            bottom: -27px;
+        }
+    }
+
+    .frames1 {
+        // transform: translateY(-70%);
+        animation: hidetip 3s linear infinite;
+
+        @keyframes hidetip {
+            0% {}
+
+            100% {
+                transform: translateY(-69%);
+            }
+        }
+    }
+
+    .topic-list {
+        width: 100%;
+        // height: calc(100% - 260px);
+        height: 100%;
+        padding: 25px;
         padding-bottom: 20px;
 
-        & > div:first-child {
-            border-bottom: 1px solid #e0e0e0;
+        &>div:first-child {
+            // border-bottom: 1px solid #e0e0e0;
             padding: 10px 1%;
         }
 
@@ -75,18 +132,17 @@
             cursor: pointer;
         }
 
-        .start-btn{
+        .start-btn {
             border-color: @primary;
             background-color: @primary;
             color: #fff;
         }
 
-        .ivu-checkbox-group-item{
+        .ivu-checkbox-group-item {
             display: flex;
             margin-right: 0;
 
-            & > div{
-            }
+            &>div {}
         }
 
         .topic-box {
@@ -98,13 +154,15 @@
                 border-top: 1px dashed #ccc;
                 padding-top: 5px;
                 margin-top: 15px;
+                display: flex;
+                justify-content: space-between;
 
-                & > span {
+                &>span {
                     // margin-right: 8%;
 
                     // vertical-align: sub;
                     color: #868686;
-                    border-right: 2px solid #d2d2d2;
+                    // border-right: 2px solid #d2d2d2;
                     font-size: 12px;
                     padding: 0 15px;
 
@@ -117,7 +175,25 @@
                     }
                 }
             }
+
+            .answer-area {
+                display: flex;
+                // font-size: 17px;
+                margin-top: 10px;
+
+
+                .answer-tip {
+                    color: #68A129;
+                    margin-right: 10px;
+                    min-width: 60px;
+                }
+            }
         }
+
     }
 
-}
+    .list-scroll {
+        width: 100%;
+        height: ~"calc(100% - 50px)";
+    }
+}

+ 414 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/QuesList.vue

@@ -0,0 +1,414 @@
+<template>
+    <div class="wrong-ques student-check">
+        <Scroll class="list-scroll">
+        <!-- 筛选 -->
+        <div :class="['filter-type', {'show-filter': isOpen, 'no-filter': winHeight}]">
+            <div>
+                <span class="type-name">{{ $t('studentWeb.wrongTopic.subject') }}:</span>
+                <RadioGroup v-model="filtSubject" type="button" button-style="solid" @on-change="subjChange">
+                    <Radio v-for="(item, index) in subjectList" :key="index" :label="index">{{ item.name }}</Radio>
+                </RadioGroup>
+            </div>
+            <div>
+                <span class="type-name">{{ $t('studentWeb.wrongTopic.type') }}:</span>
+                <RadioGroup v-model="filtType" type="button" button-style="solid" @on-change="typeChange">
+                    <Radio v-for="(item, index) in typeList" :key="index" :label="index">{{ item }}</Radio>
+                </RadioGroup>
+            </div>
+            <!-- <div>
+                <span class="type-name">{{ $t('studentWeb.wrongTopic.diff') }}:</span>
+                <RadioGroup v-model="filtDiff" type="button" button-style="solid" @on-change="diffChange">
+                    <Radio :label="0">{{ $t("studentWeb.type.all") }}</Radio>
+                    <Radio v-for="(item, index) in diffList" :key="index + 1" :label="index + 1">{{ item }}</Radio>
+                </RadioGroup>
+            </div>
+            <div>
+                <span class="type-name">{{ $t('studentWeb.wrongTopic.level') }}:</span>
+                <RadioGroup v-model="filtLevel" type="button" button-style="solid" @on-change="levelChange">
+                    <Radio v-for="(item, index) in levelList" :key="index" :label="index">{{ item }}</Radio>
+                </RadioGroup>
+            </div> -->
+            <div>
+                <span class="type-name">收藏:</span>
+                <RadioGroup v-model="filtLevel" type="button" button-style="solid" @on-change="levelChange">
+                    <Radio :label="0">全部</Radio>
+                    <Radio :label="1">已收藏</Radio>
+                    <Radio :label="2">未收藏</Radio>
+                </RadioGroup>
+            </div>
+            <div>
+                <span class="type-name">排序:</span>
+                <Select v-model="filtLevel" style="width:250px">
+                    <Option :value="0">首次答错时间排序</Option>
+                    <Option :value="1">最近练习时间排序</Option>
+                </Select>
+            </div>
+            <!-- <div>
+                <span class="type-name">{{ $t('studentWeb.wrongTopic.point') }}:</span>
+                <template v-if="showPoint.length">
+                    <span v-for="(item, index) in showPoint" :key="index" class="point-box">
+                        {{ item.name }}
+                        <Icon type="md-close" @click="removePoint(index)" />
+                    </span>
+                </template>
+                <Icon type="md-add-circle" size="18" color="#24B880" @click="pointShow = true" />
+            </div> -->
+            <div class="search">
+                <Input v-model="subTitle" :placeholder="$t('studentWeb.wrongTopic.search')" style="width: 302px" class="light-iview-input"
+                        @on-change="searchChange" clearable />
+                <!-- <DatePicker type="date" :placeholder="$t('studentWeb.wrongTopic.date')" :options="options" @on-change="dateChange"
+                            style="width: 200px" class="light-iview-input"
+                /> -->
+                <span class="have-total">
+                    {{ $t('studentWeb.wrongTopic.word1') }}
+                    <span>{{ topicTotal }}</span>
+                    {{ $t('studentWeb.wrongTopic.topic') }}
+                </span>
+            </div>
+            <Icon type="md-arrow-dropdown" @click="isOpen = !isOpen" v-show="!isOpen" />
+            <Icon type="md-arrow-dropup" @click="isOpen = !isOpen" v-show="isOpen" />
+        </div>
+        <!-- 题目列表 -->
+        <div class="topic-list">
+            <!-- <div style="overflow: hidden;">
+                <Checkbox v-model="checkAll">{{ $t('studentWeb.wrongTopic.allTopic') }}</Checkbox>
+                <span style="float: right">
+                    {{ $t('studentWeb.wrongTopic.check') }}:
+                    <span style="font-size: 18px; font-weight: bold;">{{ checkNum }}</span>
+                    <span :class="['start-btn-primary', {'start-btn': checkNum}]" @click="startPra">{{ $t('studentWeb.wrongTopic.startPractice') }}</span>
+                </span>
+            </div> -->
+            <template v-if="exerciseList.length">
+                <!-- <Scroll class="list-scroll"> -->
+                    <!-- <CheckboxGroup v-model="checkTopicArr"> -->
+                        <!-- <Checkbox :label="index" v-for="(item, index) in exerciseList" :key="index" class="topic-box"> -->
+                        <div v-for="(item, index) in exerciseList" :key="index" class="topic-box">
+                            <div style="width: 100%;">
+                                <span style="vertical-align: top; margin-right: 5px; cursor: pointer;" @click="onCollection">
+                                    <Icon custom="iconfont icon-shoucang1" size="19" color="#3B660C" v-show="!iscollection"></Icon>
+                                    <Icon custom="iconfont icon-shoucang2" size="19" color="#EA8F3E" v-show="iscollection"></Icon>
+                                </span>
+                                <span style="vertical-align: top;">{{ pageSize * (pageNum - 1) + index + 1 }}. </span>
+                                <div v-html="item.question" style="width: calc(99% - 40px); display: inline-block;"></div>
+                                <div class="answer-area">
+                                    <span class="answer-tip">【答案】</span>
+                                    <p>
+                                        这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟,如“安得广厦千万间,大庇天下寒士俱欢颜"这样的诗句,表现出作者在自己生活极度艰难的情景下,依然不忘忧国忧民,情真意切.感人至深。
+                                    </p>
+                                </div>
+                                <div class="answer-area">
+                                    <span class="answer-tip">【解析】</span>
+                                    <p>
+                                        这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。
+                                    </p>
+                                </div>
+                                <!-- <div class="topic-type">
+                                    <span>
+                                        {{ $t('studentWeb.wrongTopic.type') }}:{{ typeObj[item.type] }}
+                                    </span>
+                                    <span>
+                                        {{ $t('studentWeb.wrongTopic.diff') }}:{{ diffList[item.level - 1] }}
+                                    </span>
+                                    <span>
+                                        {{ $t('studentWeb.wrongTopic.level') }}:{{ levelList[item.field] }}
+                                    </span>
+                                    <span>
+                                        {{ $t('studentWeb.wrongTopic.wrong') }}:15%
+                                    </span>
+                                    <span>
+                                        {{ $t('studentWeb.wrongTopic.wrongNum') }}:2
+                                    </span>
+                                </div> -->
+                                <div class="topic-type">
+                                    <span>
+                                        建议下次练习时间:2022-11-5
+                                    </span>
+                                    <span>
+                                        最近练习:2022-10-7
+                                    </span>
+                                    <span>
+                                        加入时间:2022-9-17
+                                    </span>
+                                </div>
+                            </div>
+                        </div>
+                    <!-- </CheckboxGroup> -->
+                <!-- </Scroll> -->
+            </template>
+            <Page :total="topicTotal" show-sizer show-total :page-size="pageSize" @on-page-size-change="pageSizeChange"
+		            :current="pageNum" @on-change="pageChange" :page-size-opts="[5, 10, 15, 20]"
+                    style="text-align: center; margin-top: 20px;" />
+        </div>
+    </Scroll>
+        <Modal v-model="pointShow" :title="$t('studentWeb.wrongTopic.checkPoint')" @on-ok="okPoint" class="wrong-ques-modal">
+            <p>
+                <!-- <span style="margin-left: 50px;">学段:初中</span> -->
+                <span>{{ $t('studentWeb.wrongTopic.subject') }}:{{ subjectList[filtSubject].name }}</span>
+            </p>
+            <div class="check-point">
+                <Input v-model="pointField" :placeholder="$t('studentWeb.wrongTopic.searchPoint')" class="light-iview-input" />
+                <template v-if="allPoint.length">
+                    <CheckboxGroup v-model="checkPointArr">
+                        <Checkbox :label="index" border v-for="(item, index) in allPoint" :key="index">
+                            {{ item.name }}
+                        </Checkbox>
+                    </CheckboxGroup>
+                </template>
+            </div>
+        </Modal>
+    </div>
+</template>
+
+<script>
+export default {
+    name: "",
+    data () {
+        return {
+            MyNo: "8",
+            MyName: "",
+            animal: "",
+            filtSubject: 0,
+            filtType: 0,
+            filtDiff: 0,
+            filtLevel: 0,
+            subjectList: [], //学科
+            typeList: [ //题型
+                this.$t("studentWeb.type.all"),
+                this.$t("studentWeb.exam.queType.single"),
+                this.$t("studentWeb.exam.queType.multiply"),
+                this.$t("studentWeb.exam.queType.judge"),
+                this.$t("studentWeb.exam.queType.complete"),
+                this.$t("studentWeb.exam.queType.subjective"),
+                this.$t("studentWeb.exam.queType.compose"),
+                this.$t("studentWeb.exam.queType.correct"),
+                this.$t("studentWeb.exam.queType.connector")
+            ],
+            typeObj: {
+                all: this.$t("studentWeb.type.all"),
+                complete: this.$t("studentWeb.exam.queType.complete"),
+                compose: this.$t("studentWeb.exam.queType.compose"),
+                connector: this.$t("studentWeb.exam.queType.connector"),
+                correct: this.$t("studentWeb.exam.queType.correct"),
+                judge: this.$t("studentWeb.exam.queType.judge"),
+                multiple: this.$t("studentWeb.exam.queType.multiply"),
+                single: this.$t("studentWeb.exam.queType.single"),
+                subjective: this.$t("studentWeb.exam.queType.subjective"),
+            },
+            diffList: this.$GLOBAL.EXERCISE_DIFFS(), //难度
+            levelList: [ //层次
+                this.$t("studentWeb.type.all"),
+                this.$t("evaluation.level1"),
+                this.$t("evaluation.level2"),
+                this.$t("evaluation.level3"),
+                this.$t("evaluation.level4"),
+                this.$t("evaluation.level5"),
+                this.$t("evaluation.level6")
+            ],
+            subTitle: "",
+            options: {
+                disabledDate (date) {
+                    return date && date.valueOf() > Date.now() - 86400000;
+                }
+            },
+            topicTotal: 0,
+            checkAll: false,
+            allPoint: [], //所有知识点
+            checkPointArr: [], //选择知识点
+            showPoint: [],
+            topicRes: [], //初始题
+            topicList: [], //所有题
+            exerciseList: [], //页面展示的题
+            checkTopicArr: [],
+            pointShow: false, //知识点弹框
+            pointField: "",
+            pageSize: 10,
+			pageNum: 1, //当前页码
+            iscollection: false,
+            isOpen: false,
+            winHeight: 0,
+        }
+    },
+    async created () {
+        this.MyName = this.$t("studentWeb.type.wrongTopic");
+        this.$emit("onNavNo", this.MyNo);
+        this.$emit("onNavName", this.MyName);
+        this.subjectList = [
+            { name: "语文"},
+            { name: "数学"},
+            { name: "英语"}
+        ]
+        this.allPoint = [
+            { name: "字音"},
+            { name: "字形"},
+            { name: "文言文释义"},
+            { name: "拟人"}
+        ]
+        this.getTopicList()
+    },
+    mounted () {
+        window.addEventListener('scroll', this.handlerScroll, true)
+    },
+    methods: {
+        dateChange(date) {
+            console.log(date);
+        },
+        checkPoint() {
+
+        },
+        // 获取题目
+        getTopicList() {
+            var queryData = {
+                "@DESC": "createTime",
+                "code": "hbcn",
+                "periodId": [],
+                "gradeIds[*]": [],
+                "subjectId": ["8b94c6b6-2572-41e5-89b9-a82fcf13891e"],
+                "level": [],
+                "type": [],
+                "field": [],
+                "scope": "school",
+                "knowledge[*]": [],
+                "pid": null
+            }
+            this.$api.newEvaluation.FindExerciseList(queryData).then(res => {
+                if(res.items){
+                    this.topicRes = res.items
+                    this.topicList = this.topicRes
+                    this.topicTotal = this.topicList.length
+                    this.pageChange(1)
+                }
+            }).catch((e) => {
+            });
+        },
+        okPoint() {
+            this.showPoint = []
+            this.checkPointArr.forEach(item => {
+                this.showPoint.push(this.allPoint[item])
+            })
+            // 重新获取题目
+        },
+        removePoint(index) {
+            this.showPoint.splice(index, 1)
+            // 重新获取题目
+        },
+        /**
+         * 切换每页显示数量
+         * @param val
+         */
+        pageSizeChange(val) {
+            this.pageSize = val;
+            this.pageChange(1);
+        },
+        /**
+         * 切换页码操作
+         * @param page
+         */
+        async pageChange(page) {
+            this.pageNum = page;
+            let start = this.pageSize * (page - 1);
+            let end = this.pageSize * page;
+            // 拿到当前页码需要展示的数据
+            let simpleList = this.topicList.slice(start, end);
+            try {
+                // 执行试题换取完整JSON数据
+                this.exerciseList = simpleList;
+                // this.exerciseList = await this.$evTools.getFullItem(simpleList);
+                // this.currentPage = page;
+                // this.totalNum = this.exerciseList.length
+                /* this.pageScrollTo(0);
+                this.onHandleToggle(false)
+                this.$refs.childRef && this.$refs.childRef[0] && (this.$refs.childRef[0].collapseList = []) */
+            } catch (e) {
+                this.$Message.error('Blob Error : ' + e)
+            }
+        },
+        // 选择学科
+        subjChange(val) {
+            console.log(val);
+            // 选择学科后要重新获取题目
+        },
+        // 选择题型
+        typeChange(val) {
+            console.log(val);
+            // 一样重新获取题目
+        },
+        // 选择难度
+        diffChange(val) {
+            console.log(val);
+            // 一样重新获取题目
+        },
+        // 选择层次
+        levelChange(val) {
+            console.log(val);
+            // 一样重新获取题目
+        },
+        // 搜索词
+        searchChange() {
+            let val = this.subTitle
+            console.log(val);
+            this.topicList = this.topicRes.filter(i => i.question.indexOf(val) > -1)
+            this.topicTotal = this.topicList.length
+            this.pageChange(1)
+        },
+        startPra() {
+            // this.$router.push({
+            //     name: "eventView/evaluation",
+                /* params: {
+                    papers: this.paperInfo
+                } */
+            // })
+        },
+        // 收藏题目
+        onCollection() {
+            this.iscollection = !this.iscollection
+        },
+        handlerScroll(e) {
+            this.winHeight = e.target.scrollTop || document.documentElement.scrollTop
+            this.isOpen = false
+        },
+    },
+    computed: {
+        checkNum() {
+            var num = 0
+            if(this.topicList.length) {
+                num = this.checkTopicArr.length
+            }
+            return num
+        },
+    },
+    watch: {
+        checkAll: {
+            handler(n, o) {
+                if(this.topicList.length) {
+                    if(n) {
+                        this.checkTopicArr = []
+                        this.topicList.forEach((item, index) => {
+                            this.checkTopicArr.push(index)
+                        });
+                    } else {
+                        this.checkTopicArr = []
+                    }
+                }
+            }
+        },
+    },
+    destroyed () {
+        document.removeEventListener('scroll', this.handlerScroll)
+    }
+}
+</script>
+
+<style lang="less" scoped>
+@import "./QuesList.less";
+</style>
+
+<style lang="less">
+@import "./iViewStyle.less";
+.list-scroll {
+
+    .ivu-scroll-container {
+        width: 100%;
+        height: 100% !important;
+    }
+}
+</style>

+ 212 - 297
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/WrongQues.vue

@@ -1,341 +1,256 @@
 <template>
-    <div class="wrong-ques student-check">
-        <!-- 筛选 -->
-        <div class="filter-type">
+    <div class="count-box">
+        <div class="count-header">
             <div>
-                <span class="type-name">{{ $t('studentWeb.wrongTopic.subject') }}:</span>
-                <RadioGroup v-model="filtSubject" type="button" button-style="solid" @on-change="subjChange">
-                    <Radio v-for="(item, index) in subjectList" :key="index" :label="index">{{ item.name }}</Radio>
-                </RadioGroup>
+                <p class="count-text">
+                    今日新增
+                </p>
+                <p class="count-num count-num-1">11</p>
             </div>
             <div>
-                <span class="type-name">{{ $t('studentWeb.wrongTopic.type') }}:</span>
-                <RadioGroup v-model="filtType" type="button" button-style="solid" @on-change="typeChange">
-                    <Radio v-for="(item, index) in typeList" :key="index" :label="index">{{ item }}</Radio>
-                </RadioGroup>
+                <p class="count-text">
+                    已熟练
+                </p>
+                <p class="count-num count-num-2">34</p>
             </div>
             <div>
-                <span class="type-name">{{ $t('studentWeb.wrongTopic.diff') }}:</span>
-                <RadioGroup v-model="filtDiff" type="button" button-style="solid" @on-change="diffChange">
-                    <Radio :label="0">{{ $t("studentWeb.type.all") }}</Radio>
-                    <Radio v-for="(item, index) in diffList" :key="index + 1" :label="index + 1">{{ item }}</Radio>
-                </RadioGroup>
+                <p class="count-text">
+                    总题数
+                </p>
+                <p class="count-num count-num-3">215</p>
             </div>
             <div>
-                <span class="type-name">{{ $t('studentWeb.wrongTopic.level') }}:</span>
-                <RadioGroup v-model="filtLevel" type="button" button-style="solid" @on-change="levelChange">
-                    <Radio v-for="(item, index) in levelList" :key="index" :label="index">{{ item }}</Radio>
-                </RadioGroup>
+                <p class="count-text">最近一次复习</p>
+                <p class="count-text-foot">
+                    <span class="count-num count-num-4">1</span>
+                    日前
+                </p>
             </div>
             <div>
-                <span class="type-name">{{ $t('studentWeb.wrongTopic.point') }}:</span>
-                <template v-if="showPoint.length">
-                    <span v-for="(item, index) in showPoint" :key="index" class="point-box">
-                        {{ item.name }}
-                        <Icon type="md-close" @click="removePoint(index)" />
-                    </span>
-                </template>
-                <Icon type="md-add-circle" size="18" color="#24B880" @click="pointShow = true" />
+                <p class="count-text">建议复习时间</p>
+                <p class="count-text-foot">
+                    <span class="count-num count-num-4">3</span>
+                    日后
+                    <span>(2022-11-1)</span>
+                </p>
             </div>
-            <div>
-                <Input v-model="subTitle" :placeholder="$t('studentWeb.wrongTopic.search')" style="width: 300px" class="light-iview-input"
-                        @on-change="searchChange" clearable />
-                <DatePicker type="date" :placeholder="$t('studentWeb.wrongTopic.date')" :options="options" @on-change="dateChange"
-                            style="width: 200px" class="light-iview-input"
-                />
-                <span class="have-total">
-                    {{ $t('studentWeb.wrongTopic.word1') }}
-                    <span>{{ topicTotal }}</span>
-                    {{ $t('studentWeb.wrongTopic.topic') }}
-                </span>
+            <div class="count-btn">
+                <Button type="success" @click="findQues">查找所有错题</Button>
+                <Button type="success" @click="openModal">马上复习</Button>
             </div>
         </div>
-        <!-- 题目列表 -->
-        <div class="topic-list">
-            <div style="overflow: hidden;">
-                <Checkbox v-model="checkAll">{{ $t('studentWeb.wrongTopic.allTopic') }}</Checkbox>
-                <span style="float: right">
-                    {{ $t('studentWeb.wrongTopic.check') }}:
-                    <span style="font-size: 18px; font-weight: bold;">{{ checkNum }}</span>
-                    <span :class="['start-btn-primary', {'start-btn': checkNum}]" @click="startPra">{{ $t('studentWeb.wrongTopic.startPractice') }}</span>
-                </span>
-            </div>
-            <template v-if="exerciseList.length">
-                <vuescroll>
-                    <CheckboxGroup v-model="checkTopicArr">
-                        <Checkbox :label="index" v-for="(item, index) in exerciseList" :key="index" class="topic-box">
-                            <div style="width: 100%;">
-                                <span style="vertical-align: top;">{{ pageSize * (pageNum - 1) + index + 1 }}. </span>
-                                <div v-html="item.question" style="width: calc(99% - 40px); display: inline-block;"></div>
-                                <div class="topic-type">
-                                    <span>
-                                        {{ $t('studentWeb.wrongTopic.type') }}:{{ typeObj[item.type] }}
-                                    </span>
-                                    <span>
-                                        {{ $t('studentWeb.wrongTopic.diff') }}:{{ diffList[item.level - 1] }}
-                                    </span>
-                                    <span>
-                                        {{ $t('studentWeb.wrongTopic.level') }}:{{ levelList[item.field] }}
-                                    </span>
-                                    <span>
-                                        {{ $t('studentWeb.wrongTopic.wrong') }}:15%
-                                    </span>
-                                    <span>
-                                        {{ $t('studentWeb.wrongTopic.wrongNum') }}:2
-                                    </span>
-                                </div>
-                            </div>
-                        </Checkbox>
-                    </CheckboxGroup>
-                </vuescroll>
-            </template>
-            <Page :total="topicTotal" show-sizer show-total :page-size="pageSize" @on-page-size-change="pageSizeChange"
-		            :current="pageNum" @on-change="pageChange" :page-size-opts="[5, 10, 15, 20]"
-                    style="text-align: center; margin-top: 20px;" />
+        <div class="charts-box">
+            <div id="Study"></div>
         </div>
-        <Modal v-model="pointShow" :title="$t('studentWeb.wrongTopic.checkPoint')" @on-ok="okPoint" class="wrong-ques-modal">
-            <p>
-                <!-- <span style="margin-left: 50px;">学段:初中</span> -->
-                <span>{{ $t('studentWeb.wrongTopic.subject') }}:{{ subjectList[filtSubject].name }}</span>
-            </p>
-            <div class="check-point">
-                <Input v-model="pointField" :placeholder="$t('studentWeb.wrongTopic.searchPoint')" class="light-iview-input" />
-                <template v-if="allPoint.length">
-                    <CheckboxGroup v-model="checkPointArr">
-                        <Checkbox :label="index" border v-for="(item, index) in allPoint" :key="index">
-                            {{ item.name }}
-                        </Checkbox>
-                    </CheckboxGroup>
-                </template>
+        <Modal v-model="isReview" @on-ok="startReview" ok-text="开始" class="student-check">
+            <div style="margin-bottom: 20px;">
+                <span class="type-name">{{ $t('studentWeb.wrongTopic.subject') }}:</span>
+                <RadioGroup v-model="filtType.term" type="button" button-style="solid">
+                    <Radio v-for="(item, index) in termList" :key="index" :label="index">{{ item.value }}</Radio>
+                </RadioGroup>
+            </div>
+            <div>
+                <span class="type-name">数量:</span>
+                <RadioGroup v-model="filtType.num" type="button" button-style="solid">
+                    <Radio v-for="(item, index) in numList" :key="index" :label="index">{{ item.value }}</Radio>
+                </RadioGroup>
             </div>
         </Modal>
     </div>
 </template>
 
 <script>
+import { mapState } from 'vuex'
 export default {
-    name: "",
     data () {
         return {
-            MyNo: "8",
-            MyName: "",
-            animal: "",
-            filtSubject: 0,
-            filtType: 0,
-            filtDiff: 0,
-            filtLevel: 0,
-            subjectList: [], //学科
-            typeList: [ //题型
-                this.$t("studentWeb.type.all"),
-                this.$t("studentWeb.exam.queType.single"),
-                this.$t("studentWeb.exam.queType.multiply"),
-                this.$t("studentWeb.exam.queType.judge"),
-                this.$t("studentWeb.exam.queType.complete"),
-                this.$t("studentWeb.exam.queType.subjective"),
-                this.$t("studentWeb.exam.queType.compose"),
-                this.$t("studentWeb.exam.queType.correct"),
-                this.$t("studentWeb.exam.queType.connector")
-            ],
-            typeObj: {
-                all: this.$t("studentWeb.type.all"),
-                complete: this.$t("studentWeb.exam.queType.complete"),
-                compose: this.$t("studentWeb.exam.queType.compose"),
-                connector: this.$t("studentWeb.exam.queType.connector"),
-                correct: this.$t("studentWeb.exam.queType.correct"),
-                judge: this.$t("studentWeb.exam.queType.judge"),
-                multiple: this.$t("studentWeb.exam.queType.multiply"),
-                single: this.$t("studentWeb.exam.queType.single"),
-                subjective: this.$t("studentWeb.exam.queType.subjective"),
+            isReview: false,
+            filtType: {
+                term: 0,
+                num: 0
             },
-            diffList: this.$GLOBAL.EXERCISE_DIFFS(), //难度
-            levelList: [ //层次
-                this.$t("studentWeb.type.all"),
-                this.$t("evaluation.level1"),
-                this.$t("evaluation.level2"),
-                this.$t("evaluation.level3"),
-                this.$t("evaluation.level4"),
-                this.$t("evaluation.level5"),
-                this.$t("evaluation.level6")
+            termList: [
+                {
+                    value: "上学期",
+                    code: 0,
+                },
+                {
+                    value: "下学期",
+                    code: 1,
+                },
+            ],
+            numList: [
+                {
+                    value: "10",
+                    code: 0,
+                },
+                {
+                    value: "20",
+                    code: 1,
+                },
+                {
+                    value: "30",
+                    code: 2,
+                },
+                {
+                    value: "40",
+                    code: 3,
+                },
+                {
+                    value: "50",
+                    code: 4,
+                },
             ],
-            subTitle: "",
-            options: {
-                disabledDate (date) {
-                    return date && date.valueOf() > Date.now() - 86400000;
-                }
-            },
-            topicTotal: 0,
-            checkAll: false,
-            allPoint: [], //所有知识点
-            checkPointArr: [], //选择知识点
-            showPoint: [],
-            topicRes: [], //初始题
-            topicList: [], //所有题
-            exerciseList: [], //页面展示的题
-            checkTopicArr: [],
-            pointShow: false, //知识点弹框
-            pointField: "",
-            pageSize: 5,
-			pageNum: 1, //当前页码
         }
     },
-    async created () {
-        this.MyName = this.$t("studentWeb.type.wrongTopic");
-        this.$emit("onNavNo", this.MyNo);
-        this.$emit("onNavName", this.MyName);
-        this.subjectList = [
-            { name: "语文"},
-            { name: "数学"},
-            { name: "英语"}
-        ]
-        this.allPoint = [
-            { name: "字音"},
-            { name: "字形"},
-            { name: "文言文释义"},
-            { name: "拟人"}
-        ]
-        this.getTopicList()
+    computed: {
+        ...mapState({
+            userInfo: state => state.userInfo,
+        })
+    },
+    mounted () {
+        this.setMap()
     },
     methods: {
-        dateChange(date) {
-            console.log(date);
-        },
-        checkPoint() {
-
-        },
-        // 获取题目
-        getTopicList() {
-            var queryData = {
-                "@DESC": "createTime",
-                "code": "hbcn",
-                "periodId": [],
-                "gradeIds[*]": [],
-                "subjectId": ["8b94c6b6-2572-41e5-89b9-a82fcf13891e"],
-                "level": [],
-                "type": [],
-                "field": [],
-                "scope": "school",
-                "knowledge[*]": [],
-                "pid": null
-            }
-            this.$api.newEvaluation.FindExerciseList(queryData).then(res => {
-                if(res.items){
-                    this.topicRes = res.items
-                    this.topicList = this.topicRes
-                    this.topicTotal = this.topicList.length
-                    this.pageChange(1)
-                }
-            }).catch((e) => {
-            });
-        },
-        okPoint() {
-            this.showPoint = []
-            this.checkPointArr.forEach(item => {
-                this.showPoint.push(this.allPoint[item])
+        findQues() {
+            this.$router.push({
+                name: "AllQues",
             })
-            // 重新获取题目
-        },
-        removePoint(index) {
-            this.showPoint.splice(index, 1)
-            // 重新获取题目
         },
-        /**
-         * 切换每页显示数量
-         * @param val
-         */
-        pageSizeChange(val) {
-            this.pageSize = val;
-            this.pageChange(1);
+        openModal() {
+            this.isReview = true
         },
-        /**
-         * 切换页码操作
-         * @param page
-         */
-        async pageChange(page) {
-            this.pageNum = page;
-            let start = this.pageSize * (page - 1);
-            let end = this.pageSize * page;
-            // 拿到当前页码需要展示的数据
-            let simpleList = this.topicList.slice(start, end);
-            try {
-                // 执行试题换取完整JSON数据
-                this.exerciseList = simpleList;
-                // this.exerciseList = await this.$evTools.getFullItem(simpleList);
-                // this.currentPage = page;
-                // this.totalNum = this.exerciseList.length
-                /* this.pageScrollTo(0);
-                this.onHandleToggle(false)
-                this.$refs.childRef && this.$refs.childRef[0] && (this.$refs.childRef[0].collapseList = []) */
-            } catch (e) {
-                this.$Message.error('Blob Error : ' + e)
+        startReview() {
+            let param = {
+                sid: this.userInfo.sub,
+                unit_id: null, //单元id
+                mode: 0, //0:错题复习,1:学习+复习
+                t: Date.now()
             }
+            // "Q_s":题目状态,可以此数值排序,数值越小应越早练习
+            let record = [
+                {
+                    "q_id": "f5adefef-44fc-43a1-7de6-fa1f8afa5f2b",
+                    "Q_s": 0.2388560312
+                },
+                {
+                    "q_id": "baff9b62-7978-1ebb-8f36-af2bb78cd853",
+                    "Q_s": 0.1244064826
+                },
+                {
+                    "q_id": "6df25a81-41ac-1e1a-78bd-5377c8d2ce4f",
+                    "Q_s": 0.243247358
+                },
+                {
+                    "q_id": "1d62b867-2923-3700-ca72-ed9bad257303",
+                    "Q_s": 0.0
+                },
+                {
+                    "q_id": "d8e382a5-b713-0657-d197-4d7935ddf386",
+                    "Q_s": 0.9004817513
+                },
+                {
+                    "q_id": "b67bd57a-d19e-b6d0-5e03-b1c184362b2d",
+                    "Q_s": 0.106642678
+                },
+                {
+                    "q_id": "c13d70a5-0952-bc4e-d7bf-a9bda829afe2",
+                    "Q_s": 0.1379331019
+                },
+                {
+                    "q_id": "b0dcda93-a191-ad1f-a3c7-58c373131c49",
+                    "Q_s": 0.1419861052
+                },
+                {
+                    "q_id": "5de46f22-cce9-f4b0-aeb8-b3e648671bbf",
+                    "Q_s": 0.0
+                },
+                {
+                    "q_id": "a9cd68d1-7148-1bb4-9d91-5b63db7da1f3",
+                    "Q_s": 0.0
+                },
+            ]
+            record.sort((a, b) => {
+                return a.Q_s - b.Q_s
+            })
+
+            this.$router.push({
+                name: "answer",
+                param: {
+                    qsList: record
+                },
+            })
         },
-        // 选择学科
-        subjChange(val) {
-            console.log(val);
-            // 选择学科后要重新获取题目
-        },
-        // 选择题型
-        typeChange(val) {
-            console.log(val);
-            // 一样重新获取题目
-        },
-        // 选择难度
-        diffChange(val) {
-            console.log(val);
-            // 一样重新获取题目
-        },
-        // 选择层次
-        levelChange(val) {
-            console.log(val);
-            // 一样重新获取题目
-        },
-        // 搜索词
-        searchChange() {
-            let val = this.subTitle
-            console.log(val);
-            this.topicList = this.topicRes.filter(i => i.question.indexOf(val) > -1)
-            this.topicTotal = this.topicList.length
-            this.pageChange(1)
-        },
-        startPra() {
-            // this.$router.push({
-            //     name: "eventView/evaluation",
-                /* params: {
-                    papers: this.paperInfo
-                } */
-            // })
-        },
-    },
-    computed: {
-        checkNum() {
-            var num = 0
-            if(this.topicList.length) {
-                num = this.checkTopicArr.length
+        setMap() {
+            let myChart = this.$echarts.init(document.getElementById("Study"))
+            let option = {
+                // backgroundColor: '#2c343c',
+                title: {
+                    text: '错题难度分布',
+                    left: 'center',
+                    bottom: 20,
+                    textStyle: {
+                        color: '#000'
+                    }
+                },
+                tooltip: {
+                    trigger: 'item'
+                },
+                visualMap: {
+                    show: false,
+                    min: 80,
+                    max: 600,
+                    inRange: {
+                        colorLightness: [0, 1]
+                    }
+                },
+                series: [
+                    {
+                        name: 'Access From',
+                        type: 'pie',
+                        radius: '55%',
+                        center: ['50%', '50%'],
+                        data: [
+                            { value: 335, name: '中等' },
+                            { value: 274, name: '困难' },
+                            { value: 235, name: '艰深' },
+                            { value: 400, name: '简单' }
+                        ].sort(function (a, b) {
+                            return a.value - b.value;
+                        }),
+                        roseType: 'radius',
+                        label: {
+                            color: '#000'
+                        },
+                        labelLine: {
+                            lineStyle: {
+                                color: 'rgba(255, 255, 255, 0.3)'
+                            },
+                            smooth: 0.2,
+                            length: 10,
+                            length2: 20
+                        },
+                        itemStyle: {
+                            color: '#c23531',
+                            shadowBlur: 100,
+                            shadowColor: 'rgba(0, 0, 0, 0.4)'
+                        },
+                        animationType: 'scale',
+                        animationEasing: 'elasticOut',
+                        animationDelay: function (idx) {
+                            return Math.random() * 200;
+                        }
+                    }
+                ]
             }
-            return num
+            myChart.setOption(option)
         },
     },
-    watch: {
-        checkAll: {
-            handler(n, o) {
-                if(this.topicList.length) {
-                    if(n) {
-                        this.checkTopicArr = []
-                        this.topicList.forEach((item, index) => {
-                            this.checkTopicArr.push(index)
-                        });
-                    } else {
-                        this.checkTopicArr = []
-                    }
-                }
-            }
-        }
-    }
 }
 </script>
 
 <style lang="less" scoped>
-@import "./WrongQues.less";
+@import "./QuesContent.less";
 </style>
 
 <style lang="less">

+ 10 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/iViewStyle.less

@@ -71,6 +71,16 @@
         background: @primary;
     }
 
+    .ivu-modal .ivu-btn-primary {
+        background-color: #24B880;
+        border: none;
+        cursor: pointer;
+    }
+
+    .ivu-modal .ivu-btn-text {
+        display: none;
+    }
+
     .topic-list {
         .ivu-checkbox{
             margin-right: 8px;

+ 107 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/mobile/PreciseQues.vue

@@ -0,0 +1,107 @@
+<template>
+    <div>
+        <div class="home-view">
+            <div class="home-head">
+                <div>
+                    <p>已练习</p>
+                    <p class="num left" style="color: #278ED1;">37</p>
+                </div>
+                <div>
+                    <p>已熟练</p>
+                    <p class="num left" style="color: #538E12;">21</p>
+                </div>
+                <div>
+                    <p>总题数</p>
+                    <p class="num" style="color: #828282;">154</p>
+                </div>
+            </div>
+            <div class="home-top">
+                <span>最近一次复习</span>
+                <span class="time">2022-10-29</span>
+            </div>
+            <div class="home-top">
+                <span>建议复习时间</span>
+                <span class="time">3日后(2022-11-4)</span>
+            </div>
+        </div>
+        <div class="home-view have-img">
+            <img src="" alt="">
+            <span>学习难度分布</span>
+        </div>
+        <div class="home-view">
+            <div v-for="(item, index) in quesList" :key="index" class="ques-list">
+                <img src="../student-en-us.png" alt="">
+                <div class="ques-content">
+                    <p>{{ item.name }}</p>
+                    <Progress :percent="90" :hide-info="true" :stroke-width="5" stroke-color="#52c46c" />
+                    <div class="tip-foot">
+                        <span>
+                            练习:{{ item.prc }}
+                        </span>
+                        <span>
+                            熟练:{{ item.know }}
+                        </span>
+                    </div>
+                </div>
+                <Button @click="startReview" size="small">开始练习</Button>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    data () {
+        return {
+            quesList: [
+                {
+                    name: "语文古诗词",
+                    prc: "24",
+                    know: "12",
+                },
+                {
+                    name: "语文古诗词",
+                    prc: "24",
+                    know: "12",
+                },
+                {
+                    name: "语文古诗词",
+                    prc: "24",
+                    know: "12",
+                },
+                {
+                    name: "语文古诗词",
+                    prc: "24",
+                    know: "12",
+                },
+            ]
+        }
+    },
+    async created () {
+        this.MyName = this.$t("studentWeb.type.wrongTopic");
+        this.$emit("onNavNo", this.MyNo);
+        this.$emit("onNavName", this.MyName);
+    },
+    mounted () {
+    },
+    methods: {
+        startReview() {
+            this.$router.push({
+                name: "answer",
+            })
+        },
+    }
+}
+</script>
+
+
+<style lang="less" scoped>
+@import "./WrongQues.less";
+</style>
+
+<style lang="less">
+@import "../iViewStyle.less";
+.student-check .ivu-input-wrapper {
+    margin-right: 0;
+}
+</style>

+ 178 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/mobile/WrongQues.less

@@ -0,0 +1,178 @@
+.home-view {
+    background-color: #fff;
+    padding: 10px;
+    padding-bottom: 20px;
+    border-radius: 5px;
+    margin-bottom: 20px;
+
+    &>img {
+        width: 100%;
+        height: 200px;
+    }
+
+    &>.ivu-btn {
+        width: 100%;
+        border: none;
+        background: #9AC46D;
+        color: #fff;
+    }
+
+    .home-top {
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 15px;
+
+        .num {
+            font-size: 20px;
+            font-weight: bold;
+        }
+
+        .time {
+            font-size: 17px;
+            font-weight: bold;
+        }
+    }
+
+    .home-head {
+        display: flex;
+        justify-content: space-evenly;
+        text-align: center;
+        margin: 30px 0;
+
+        &>div {
+            width: 33%;
+        }
+
+        .num {
+            font-size: 35px;
+            font-weight: bold;
+            position: relative;
+        }
+
+        .left:last-child::after {
+            content: "";
+            width: 1px;
+            height: 13px;
+            position: absolute;
+            right: 0px;
+            top: 50%;
+            transform: translate(-50%, -50%);
+            background: #a3a3a3;
+        }
+    }
+
+    .ques-list {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 25px;
+
+        &>img {
+            width: 90px;
+        }
+
+        .ques-content {
+            width: 45%;
+            font-size: 12px;
+
+            .tip-foot {
+                &>span:first-child {
+                    padding-right: 15px;
+                    margin-right: 15px;
+                    position: relative;
+
+                    &::after {
+                        content: "";
+                        width: 1px;
+                        height: 13px;
+                        position: absolute;
+                        right: 0px;
+                        top: 50%;
+                        transform: translate(-50%, -50%);
+                        background: #a3a3a3;
+                    }
+                }
+            }
+        }
+
+        .ivu-btn {
+            background-color: #24B880;
+            color: #fff;
+            border: none;
+        }
+    }
+}
+
+.ques-list {
+    padding: 10px 0;
+
+    .filter-type {
+        padding: 10px;
+        margin-bottom: 12px;
+        border-bottom: 1px dashed #ccc;
+
+        &>div {
+            margin-bottom: 12px;
+
+            &:last-child {
+                margin-bottom: 0;
+                // margin-top: 10px;
+            }
+        }
+
+        .have-total {
+            display: block;
+            text-align: right;
+
+            &>span {
+                font-size: 18px;
+                font-weight: bold;
+                color: #de0000;
+                margin: 0 5px;
+            }
+        }
+    }
+
+    .topic-list {
+        padding: 0 10px;
+
+        .answer-area {
+            display: flex;
+            // font-size: 17px;
+            margin-top: 5px;
+
+
+            .answer-tip {
+                color: #68A129;
+                margin-right: 10px;
+                min-width: 60px;
+            }
+        }
+
+        .topic-box {
+            // border-bottom: 1px solid #e0e0e0;
+            margin-bottom: 20px;
+            // padding: 10px 1%;
+
+            .topic-type {
+                border-top: 1px dashed #ccc;
+                padding-top: 5px;
+                margin-top: 5px;
+
+                &>p {
+                    // margin-right: 8%;
+
+                    // vertical-align: sub;
+                    color: #868686;
+                    // border-right: 2px solid #d2d2d2;
+                    font-size: 12px;
+                    padding: 0 15px;
+                }
+            }
+        }
+    }
+}
+
+.have-img {
+    text-align: center;
+}

+ 315 - 0
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/mobile/WrongQues.vue

@@ -0,0 +1,315 @@
+<template>
+    <div>
+        <div class="home-view">
+            <div class="home-top">
+                <div>
+                    今日新增
+                    <span class="num">15</span>
+                </div>
+                <div>
+                    已熟练
+                    <span class="num">26</span>
+                </div>
+            </div>
+            <div>
+                <Progress :percent="90" :hide-info="true" stroke-color="#9AC46D" :stroke-width="5" />
+                <div class="home-top">
+                    <span>已掌握 51%</span>
+                    <span>111/214</span>
+                </div>
+            </div>
+            <div class="home-top">
+                <span>最近一次复习</span>
+                <span class="time">2022-10-29</span>
+            </div>
+            <div class="home-top">
+                <span>建议复习时间</span>
+                <span class="time">3日后(2022-11-4)</span>
+            </div>
+            <Button>马上复习</Button>
+        </div>
+        <div class="home-view have-img">
+            <img src="" alt="">
+            <span>错题难度分布</span>
+        </div>
+        <div class="home-view ques-list student-check">
+            <div class="filter-type">
+                <div>
+                    <span class="type-name">{{ $t('studentWeb.wrongTopic.subject') }}:</span>
+                    <RadioGroup v-model="filtSubject" type="button" button-style="solid" @on-change="subjChange">
+                        <Radio v-for="(item, index) in subjectList" :key="index" :label="index">{{ item.name }}</Radio>
+                    </RadioGroup>
+                </div>
+                <div>
+                    <span class="type-name">{{ $t('studentWeb.wrongTopic.type') }}:</span>
+                    <RadioGroup v-model="filtType" type="button" button-style="solid" @on-change="typeChange">
+                        <Radio v-for="(item, index) in typeList" :key="index" :label="index">{{ item }}</Radio>
+                    </RadioGroup>
+                </div>
+                <div>
+                    <span class="type-name">收藏:</span>
+                    <RadioGroup v-model="filtLevel" type="button" button-style="solid" @on-change="levelChange">
+                        <Radio :label="0">全部</Radio>
+                        <Radio :label="1">已收藏</Radio>
+                        <Radio :label="2">未收藏</Radio>
+                    </RadioGroup>
+                </div>
+                <div>
+                    <span class="type-name">排序:</span>
+                    <Select v-model="filtLevel" style="width: 87%">
+                        <Option :value="0">首次答错时间排序</Option>
+                        <Option :value="1">最近练习时间排序</Option>
+                    </Select>
+                </div>
+                <div>
+                    <Input v-model="subTitle" :placeholder="$t('studentWeb.wrongTopic.search')" style="width: 100%" class="light-iview-input"
+                            @on-change="searchChange" clearable />
+                    <span class="have-total">
+                        {{ $t('studentWeb.wrongTopic.word1') }}
+                        <span>{{ topicTotal }}</span>
+                        {{ $t('studentWeb.wrongTopic.topic') }}
+                    </span>
+                </div>
+            </div>
+            <!-- 题目列表 -->
+            <div class="topic-list">
+                <!-- <div style="overflow: hidden;">
+                    <Checkbox v-model="checkAll">{{ $t('studentWeb.wrongTopic.allTopic') }}</Checkbox>
+                    <span style="float: right">
+                        {{ $t('studentWeb.wrongTopic.check') }}:
+                        <span style="font-size: 18px; font-weight: bold;">{{ checkNum }}</span>
+                        <span :class="['start-btn-primary', {'start-btn': checkNum}]" @click="startPra">{{ $t('studentWeb.wrongTopic.startPractice') }}</span>
+                    </span>
+                </div> -->
+                <template v-if="exerciseList.length">
+                    <!-- <Scroll class="list-scroll"> -->
+                        <!-- <CheckboxGroup v-model="checkTopicArr"> -->
+                            <!-- <Checkbox :label="index" v-for="(item, index) in exerciseList" :key="index" class="topic-box"> -->
+                            <div v-for="(item, index) in exerciseList" :key="index" class="topic-box">
+                                <div style="width: 100%;">
+                                    <span style="vertical-align: top; margin-right: 5px; cursor: pointer;" @click="onCollection">
+                                        <Icon custom="iconfont icon-shoucang1" size="19" color="#3B660C" v-show="!iscollection"></Icon>
+                                        <Icon custom="iconfont icon-shoucang2" size="19" color="#EA8F3E" v-show="iscollection"></Icon>
+                                    </span>
+                                    <span style="vertical-align: top;">{{ pageSize * (pageNum - 1) + index + 1 }}. </span>
+                                    <div v-html="item.question" style="width: calc(99% - 40px); display: inline-block;"></div>
+                                    <div class="answer-area">
+                                        <span class="answer-tip">【答案】</span>
+                                        <p>
+                                            这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟,如“安得广厦千万间,大庇天下寒士俱欢颜"这样的诗句,表现出作者在自己生活极度艰难的情景下,依然不忘忧国忧民,情真意切.感人至深。
+                                        </p>
+                                    </div>
+                                    <div class="answer-area">
+                                        <span class="answer-tip">【解析】</span>
+                                        <p>
+                                            这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。这首诗之所以震撼人心,最重要的原因是诗人忘我的精神、博大的胸襟。
+                                        </p>
+                                    </div>
+                                    <!-- <div class="topic-type">
+                                        <span>
+                                            {{ $t('studentWeb.wrongTopic.type') }}:{{ typeObj[item.type] }}
+                                        </span>
+                                        <span>
+                                            {{ $t('studentWeb.wrongTopic.diff') }}:{{ diffList[item.level - 1] }}
+                                        </span>
+                                        <span>
+                                            {{ $t('studentWeb.wrongTopic.level') }}:{{ levelList[item.field] }}
+                                        </span>
+                                        <span>
+                                            {{ $t('studentWeb.wrongTopic.wrong') }}:15%
+                                        </span>
+                                        <span>
+                                            {{ $t('studentWeb.wrongTopic.wrongNum') }}:2
+                                        </span>
+                                    </div> -->
+                                    <div class="topic-type">
+                                        <p>
+                                            建议下次练习时间:2022-11-5
+                                        </p>
+                                        <p>
+                                            最近练习:2022-10-7
+                                        </p>
+                                        <p>
+                                            加入时间:2022-9-17
+                                        </p>
+                                    </div>
+                                </div>
+                            </div>
+                        <!-- </CheckboxGroup> -->
+                    <!-- </Scroll> -->
+                </template>
+                <!-- <Page :total="topicTotal" show-sizer show-total :page-size="pageSize" @on-page-size-change="pageSizeChange"
+                        :current="pageNum" @on-change="pageChange" :page-size-opts="[5, 10, 15, 20]"
+                        style="text-align: center; margin-top: 20px;" /> -->
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    data () {
+        return {
+            topicTotal: 0,
+            topicRes: [], //初始题
+            topicList: [], //所有题
+            subTitle: "",
+            subjectList: [], //学科
+            typeList: [ //题型
+                this.$t("studentWeb.type.all"),
+                this.$t("studentWeb.exam.queType.single"),
+                this.$t("studentWeb.exam.queType.multiply"),
+                this.$t("studentWeb.exam.queType.judge"),
+                this.$t("studentWeb.exam.queType.complete"),
+                this.$t("studentWeb.exam.queType.subjective"),
+                this.$t("studentWeb.exam.queType.compose"),
+                this.$t("studentWeb.exam.queType.correct"),
+                this.$t("studentWeb.exam.queType.connector")
+            ],
+            typeObj: {
+                all: this.$t("studentWeb.type.all"),
+                complete: this.$t("studentWeb.exam.queType.complete"),
+                compose: this.$t("studentWeb.exam.queType.compose"),
+                connector: this.$t("studentWeb.exam.queType.connector"),
+                correct: this.$t("studentWeb.exam.queType.correct"),
+                judge: this.$t("studentWeb.exam.queType.judge"),
+                multiple: this.$t("studentWeb.exam.queType.multiply"),
+                single: this.$t("studentWeb.exam.queType.single"),
+                subjective: this.$t("studentWeb.exam.queType.subjective"),
+            },
+            diffList: this.$GLOBAL.EXERCISE_DIFFS(), //难度
+            levelList: [ //层次
+                this.$t("studentWeb.type.all"),
+                this.$t("evaluation.level1"),
+                this.$t("evaluation.level2"),
+                this.$t("evaluation.level3"),
+                this.$t("evaluation.level4"),
+                this.$t("evaluation.level5"),
+                this.$t("evaluation.level6")
+            ],
+            exerciseList: [], //页面展示的题
+            filtLevel: 0,
+            filtType: 0,
+            filtSubject: 0,
+            pageSize: 5,
+			pageNum: 1, //当前页码
+            iscollection: false,
+        }
+    },
+    async created () {
+        this.MyName = this.$t("studentWeb.type.wrongTopic");
+        this.$emit("onNavNo", this.MyNo);
+        this.$emit("onNavName", this.MyName);
+        this.subjectList = [
+            { name: "语文"},
+            { name: "数学"},
+            { name: "英语"}
+        ]
+        this.getTopicList()
+    },
+    mounted () {
+    },
+    methods: {
+        // 获取题目
+        getTopicList() {
+            var queryData = {
+                "@DESC": "createTime",
+                "code": "hbcn",
+                "periodId": [],
+                "gradeIds[*]": [],
+                "subjectId": ["8b94c6b6-2572-41e5-89b9-a82fcf13891e"],
+                "level": [],
+                "type": [],
+                "field": [],
+                "scope": "school",
+                "knowledge[*]": [],
+                "pid": null
+            }
+            this.$api.newEvaluation.FindExerciseList(queryData).then(res => {
+                if(res.items){
+                    this.topicRes = res.items
+                    this.topicList = this.topicRes
+                    this.topicTotal = this.topicList.length
+                    this.pageChange(1)
+                }
+            }).catch((e) => {
+            });
+        },
+        /**
+         * 切换每页显示数量
+         * @param val
+         */
+        pageSizeChange(val) {
+            this.pageSize = val;
+            this.pageChange(1);
+        },
+        /**
+         * 切换页码操作
+         * @param page
+         */
+        async pageChange(page) {
+            this.pageNum = page;
+            let start = this.pageSize * (page - 1);
+            let end = this.pageSize * page;
+            // 拿到当前页码需要展示的数据
+            let simpleList = this.topicList.slice(start, end);
+            try {
+                // 执行试题换取完整JSON数据
+                this.exerciseList = simpleList;
+                // this.exerciseList = await this.$evTools.getFullItem(simpleList);
+                // this.currentPage = page;
+                // this.totalNum = this.exerciseList.length
+                /* this.pageScrollTo(0);
+                this.onHandleToggle(false)
+                this.$refs.childRef && this.$refs.childRef[0] && (this.$refs.childRef[0].collapseList = []) */
+            } catch (e) {
+                this.$Message.error('Blob Error : ' + e)
+            }
+        },
+        // 选择学科
+        subjChange(val) {
+            console.log(val);
+            // 选择学科后要重新获取题目
+        },
+        // 选择题型
+        typeChange(val) {
+            console.log(val);
+            // 一样重新获取题目
+        },
+        // 选择难度
+        diffChange(val) {
+            console.log(val);
+            // 一样重新获取题目
+        },
+        // 选择层次
+        levelChange(val) {
+            console.log(val);
+            // 一样重新获取题目
+        },
+        // 搜索词
+        searchChange() {
+            let val = this.subTitle
+            console.log(val);
+            this.topicList = this.topicRes.filter(i => i.question.indexOf(val) > -1)
+            this.topicTotal = this.topicList.length
+            this.pageChange(1)
+        },
+        // 收藏题目
+        onCollection() {
+            this.iscollection = !this.iscollection
+        },
+    }
+}
+</script>
+
+
+<style lang="less" scoped>
+@import "./WrongQues.less";
+</style>
+
+<style lang="less">
+@import "../iViewStyle.less";
+.student-check .ivu-input-wrapper {
+    margin-right: 0;
+}
+</style>

BIN
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/student-en-us.png


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

@@ -1473,9 +1473,32 @@ export const routes = [{
         },
         {
             // 错题本
-            name: "wrongQues",
-            path: "wrongQues",
-            component: () => import('@/components/student-web/WrongQusetion/WrongQues'),
+            name: "practice",
+            path: "practice",
+            // redirect: '/studentWeb/practice',
+            component: () => import('@/components/student-web/WrongQusetion/Index'),
+            children: [
+                {
+                    name: "WrongQues",
+                    path: "wrongQues",
+                    component: () => import('@/components/student-web/WrongQusetion/WrongQues'),
+                },
+                {
+                    name: "PreciseQues",
+                    path: "preciseQues",
+                    component: () => import('@/components/student-web/WrongQusetion/PreciseQues'),
+                },
+                {
+                    name: "AllQues",
+                    path: "allQues",
+                    component: () => import('@/components/student-web/WrongQusetion/QuesList'),
+                },
+                {
+                    name: "answer",
+                    path: "answer",
+                    component: () => import('@/components/student-web/WrongQusetion/AnswerBox'),
+                }
+            ],
         },
         {
             // 课堂记录

+ 28 - 13
TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue

@@ -65,7 +65,7 @@
                     </MenuItem> -->
                     <!-- 课堂记录 -->
                     <MenuItem name="10" to="/studentWeb/classRecord" :title="$t('studentWeb.courseContent.classRecord')"
-                            v-show="selectClass && !onlySystem && !courseList[selectClass - 1].isSystem"
+                            v-show="selectClass && !onlySystem"
                     >
                         <svg-icon icon-class="course" class="tabIcon1" />
                         <span class="no-show" v-show="MyNo != 10">{{ $t('studentWeb.courseContent.classRecord') }}</span>
@@ -90,10 +90,15 @@
                         <span class="no-show" v-show="MyNo != 3">{{ $t('studentWeb.type.activity') }}</span>
                     </MenuItem>
                     <!-- 错题本 -->
-                    <!-- <MenuItem name="8" to="/studentWeb/wrongQues" :title="$t('studentWeb.type.wrongTopic')">
+                    <!-- <MenuItem name="8" to="/studentWeb/practice/wrongQues" :title="$t('studentWeb.type.wrongTopic')">
                         <Icon custom="iconfont icon-cuotiji" size="17" class="tabIcon1" />
                         <span class="no-show" v-show="MyNo != 8">{{ $t('studentWeb.type.wrongTopic') }}</span>
                     </MenuItem> -->
+                    <!-- 精准练习 -->
+                    <!-- <MenuItem name="12" to="/studentWeb/practice/preciseQues" title="精准练习">
+                        <Icon custom="iconfont icon-cuotiji" size="17" class="tabIcon1" />
+                        <span class="no-show" v-show="MyNo != 12">精准练习</span>
+                    </MenuItem> -->
                     <!-- 成绩 -->
                     <MenuItem name="7" to="/studentWeb/achievement" :title="$t('studentWeb.type.achievement')" v-show="selectClass">
                         <Icon custom="iconfont icon-chengjitongji" size="18" style="font-weight: bold" />
@@ -137,6 +142,14 @@
                                 <svg-icon icon-class="course" class="profile-pop-icon profile-pop-icon-1" />
                                 {{ $t('studentWeb.course') }}
                             </div> -->
+                            <!-- <div class="profile-pop-item" @click="goto('/studentWeb/practice/wrongQues')" v-show="selectClass">
+                                <Icon custom="iconfont icon-cuotiji" size="16" class="profile-pop-icon" />
+                                {{ $t('studentWeb.type.wrongTopic') }}
+                            </div>
+                            <div class="profile-pop-item" @click="goto('/studentWeb/practice/preciseQues')" v-show="selectClass && !onlySystem">
+                                <Icon custom="iconfont icon-cuotiji" size="16" class="profile-pop-icon" />
+                                {{ $t('studentWeb.type.wrongTopic1') }}
+                            </div> -->
                             <div class="profile-pop-item" @click="goto('/studentWeb/homeworkView')" v-show="selectClass">
                                 <svg-icon icon-class="doc" class="profile-pop-icon profile-pop-icon-1" />
                                 {{ $t('studentWeb.type.homework') }}
@@ -145,7 +158,7 @@
                                 <svg-icon icon-class="test" style="margin-left: 2px; margin-right: -2px;" class="profile-pop-icon profile-pop-icon-1" />
                                 {{ $t('studentWeb.type.exam') }}
                             </div>
-                            <div class="profile-pop-item" @click="goto('/studentWeb/classRecord')" v-show="selectClass && !onlySystem && !courseList[selectClass - 1].isSystem">
+                            <div class="profile-pop-item" @click="goto('/studentWeb/classRecord')" v-show="selectClass && !onlySystem">
                                 <svg-icon icon-class="course" style="margin-left: 2px; margin-right: -2px;" class="profile-pop-icon profile-pop-icon-1" />
                                 {{ $t('studentWeb.courseContent.classRecord') }}
                             </div>
@@ -557,6 +570,7 @@ export default {
             }
             param.userType = this.$store.state.userInfo.scope === "tmduser" ? "tmdid" : "schoolid"
             this.$api.studentWeb.getClassList(param).then(res => {
+                let cousList = []
                 if(res.courses.length) {
                     var schclassIds = []
                     res.courses.forEach(item => {
@@ -587,7 +601,7 @@ export default {
                                 })
                                 sch.listName = listName ? listName.name : ""
                                 if(haveClassId && (allClassId.length && allClassId.includes(haveClassId))) {
-                                    this.courseList.push({
+                                    cousList.push({
                                         id: item.course.id,
                                         no: item.course.no,
                                         name: item.course.name,
@@ -603,6 +617,7 @@ export default {
                                         showName: `${item.course.name}(${sch.teacherName}-${listName ? listName.name : ""})`,
                                         courseAddDate,
                                         createTime: item.stuCourse.createTime,
+                                        isSystem: false,
                                     })
                                 }
                             })
@@ -610,7 +625,7 @@ export default {
                     })
                     if(this.$store.state.userInfo.scope === "student") {
                         // 校内学生行政班未加入课程,需要有一个基本课程,来支持评测跳转
-                        let admClass = this.courseList.find(item => {
+                        let admClass = cousList.find(item => {
                             return item.list === this.user.studentProfile.classinfo.id
                         })
                         if(!admClass) {
@@ -632,14 +647,9 @@ export default {
                                 createTime: 0,
                                 isSystem: true,
                             }
-                            this.courseList.unshift(admClass)
+                            cousList.unshift(admClass)
                         }
                     }
-                    if(this.selectClass && this.selectClass <= this.courseList.length) {
-                        this.classChange(this.selectClass)
-                    } else {
-                        this.selectClass = 0
-                    }
                 } else if(this.$store.state.userInfo.scope === "student") {
                     this.onlySystem = true
                     this.$store.commit("setOnlySystem", true)
@@ -661,11 +671,16 @@ export default {
                         createTime: 0,
                         isSystem: true,
                     }
-                    this.courseList.push(admClass)
+                    cousList.push(admClass)
                 }
-                this.courseList.sort(function (a, b) {
+                this.courseList = cousList.sort(function (a, b) {
                     return b.createTime - a.createTime //时间正序
                 })
+                if(this.selectClass && this.selectClass <= cousList.length) {
+                    this.classChange(this.selectClass)
+                } else {
+                    this.selectClass = 0
+                }
                 this.$store.commit("setAllCourse", this.courseList)
             })
         },