Browse Source

Merge branch 'develop3.0' of http://106.12.23.251:10080/TEAMMODEL/TEAMModelOS into develop3.0

zhouj1203@hotmail.com 5 năm trước cách đây
mục cha
commit
d8f34fdb29
71 tập tin đã thay đổi với 4698 bổ sung962 xóa
  1. 1 7
      TEAMModelGrpc/Models/ListPid.cs
  2. 33 0
      TEAMModelGrpc/Models/Response.cs
  3. 99 0
      TEAMModelGrpc/Models/SyllabusTreeDto.cs
  4. 89 0
      TEAMModelGrpc/Protos/CourseService.proto
  5. 5 9
      TEAMModelGrpc/Protos/KnowledgeService.proto
  6. 121 0
      TEAMModelGrpc/Protos/SyllabusService.proto
  7. 49 0
      TEAMModelGrpc/Services/CourseService.cs
  8. 24 5
      TEAMModelGrpc/Services/KnowledgeService.cs
  9. 117 0
      TEAMModelGrpc/Services/SyllabusService.cs
  10. 67 0
      TEAMModelGrpc/Services/VolumeService.cs
  11. 8 6
      TEAMModelGrpc/TEAMModelGrpc.csproj
  12. 1124 5
      TEAMModelGrpc/TEAMModelOS.GRPC.xml
  13. 5 5
      TEAMModelOS.SDK/Module/AzureCosmosDBV3/AzureCosmosDBV3Repository.cs
  14. 1 1
      TEAMModelOS.SDK/Module/AzureCosmosDBV3/IAzureCosmosDBV3Repository.cs
  15. 11 8
      TEAMModelOS.Service/Models/Core/ClassRoomStudent.cs
  16. 146 0
      TEAMModelOS.Service/Models/Learn/HomeWork.cs
  17. 216 0
      TEAMModelOS.Service/Models/Learn/HomeWorkStudent.cs
  18. 69 65
      TEAMModelOS.Service/Models/Learn/LeanProcess.cs
  19. 149 0
      TEAMModelOS.Service/Models/Learn/LearningAutonomous.cs
  20. 20 3
      TEAMModelOS.Service/Models/Syllabus/SyllabusNode.cs
  21. 2 4
      TEAMModelOS.Service/Models/Syllabus/SyllabusTree.cs
  22. 60 2
      TEAMModelOS.Service/Models/Syllabus/SyllabusVolume.cs
  23. 15 7
      TEAMModelOS.Service/Services/Syllabus/Implement/KnowledgeService.cs
  24. 269 0
      TEAMModelOS.Service/Services/Syllabus/Implement/SyllabusService.cs
  25. 119 0
      TEAMModelOS.Service/Services/Syllabus/Implement/VolumeService.cs
  26. 2 0
      TEAMModelOS.Service/Services/Syllabus/Interface/IKnowledgeService.cs
  27. 34 0
      TEAMModelOS.Service/Services/Syllabus/Interface/ISyllabusService.cs
  28. 16 0
      TEAMModelOS.Service/Services/Syllabus/Interface/IVolumeService.cs
  29. 374 23
      TEAMModelOS.Service/TEAMModelOS.Model.xml
  30. 12 0
      TEAMModelOS/ClientApp/src/api/learnActivity.js
  31. 6 0
      TEAMModelOS/ClientApp/src/common/CollapseMenuLayout.vue
  32. 34 11
      TEAMModelOS/ClientApp/src/components/learnactivity/BaseHwForm.vue
  33. 53 0
      TEAMModelOS/ClientApp/src/components/learnactivity/ContentFileList.less
  34. 71 0
      TEAMModelOS/ClientApp/src/components/learnactivity/ContentFileList.vue
  35. 0 1
      TEAMModelOS/ClientApp/src/components/learnactivity/QuestionList.vue
  36. 76 0
      TEAMModelOS/ClientApp/src/components/learnactivity/SelectLearnUnit.less
  37. 195 0
      TEAMModelOS/ClientApp/src/components/learnactivity/SelectLearnUnit.vue
  38. 47 0
      TEAMModelOS/ClientApp/src/css/custom-animate.less
  39. 3 0
      TEAMModelOS/ClientApp/src/css/disabled-form.less
  40. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/courseManage.js
  41. 4 4
      TEAMModelOS/ClientApp/src/router/routes.js
  42. 6 33
      TEAMModelOS/ClientApp/src/store/index.js
  43. 1 0
      TEAMModelOS/ClientApp/src/view/Home.vue
  44. 1 1
      TEAMModelOS/ClientApp/src/view/coursemgmt/CourseClassroom.vue
  45. 4 4
      TEAMModelOS/ClientApp/src/view/coursemgmt/CourseManage.vue
  46. 1 1
      TEAMModelOS/ClientApp/src/view/coursemgmt/CourseSyllabus.vue
  47. 3 3
      TEAMModelOS/ClientApp/src/view/learnactivity/ManageEvaluation.vue
  48. 1 1
      TEAMModelOS/ClientApp/src/view/school-mgmt/ClassroomSetting/ClassroomSetting.vue
  49. 2 11
      TEAMModelOS/ClientApp/src/view/school-mgmt/SystemSetting/SystemSetting.less
  50. 2 5
      TEAMModelOS/ClientApp/src/view/school-mgmt/SystemSetting/SystemSetting.vue
  51. 21 72
      TEAMModelOS/ClientApp/src/view/selflearning/CreateSelfLearn.less
  52. 49 162
      TEAMModelOS/ClientApp/src/view/selflearning/CreateSelfLearn.vue
  53. 63 0
      TEAMModelOS/ClientApp/src/view/selflearning/LearnProgress.less
  54. 95 0
      TEAMModelOS/ClientApp/src/view/selflearning/LearnProgress.vue
  55. 34 5
      TEAMModelOS/ClientApp/src/view/selflearning/ManageSelfLearn.less
  56. 17 3
      TEAMModelOS/ClientApp/src/view/selflearning/ManageSelfLearn.vue
  57. 0 47
      TEAMModelOS/ClientApp/src/view/selflearning/CreateLearnUnit.less
  58. 7 33
      TEAMModelOS/ClientApp/src/view/selflearning/CreateLearnUnit.vue
  59. 35 4
      TEAMModelOS/ClientApp/src/view/selflearning/CreateOrderLearn.less
  60. 149 35
      TEAMModelOS/ClientApp/src/view/selflearning/CreateOrderLearn.vue
  61. 0 0
      TEAMModelOS/ClientApp/src/view/teachcontent/ManageOrderLearn.less
  62. 0 0
      TEAMModelOS/ClientApp/src/view/teachcontent/ManageOrderLearn.vue
  63. 8 43
      TEAMModelOS/ClientApp/src/view/selflearning/ManageUnit.less
  64. 15 37
      TEAMModelOS/ClientApp/src/view/selflearning/ManageUnit.vue
  65. 275 0
      TEAMModelOS/Controllers/Learn/HomeWorkController.cs
  66. 63 2
      TEAMModelOS/Controllers/Learn/LearnController.cs
  67. 1 0
      TEAMModelOS/Controllers/Syllabus/KnowledgeController.cs
  68. 24 202
      TEAMModelOS/Controllers/Syllabus/SyllabusController.cs
  69. 13 91
      TEAMModelOS/Controllers/Syllabus/VolumeController.cs
  70. 41 0
      TEAMModelOS/Models/HomeWorkCommentDto.cs
  71. 20 0
      TEAMModelOS/Models/HomeWorkScoringDto.cs

+ 1 - 7
TEAMModelGrpc/Models/ListPid.cs

@@ -11,15 +11,9 @@ namespace TEAMModelGrpc.Models
     public class ListPid
     {
         /// <summary>
-        /// key 是pk ,value 是id
+        /// list IdPk
         /// </summary>
         [ProtoMember(1)]
-        public List<KeyValuePair<string, string>> ids { set; get; }
-
-        /// <summary>
-        /// 返回 删除结果
-        /// </summary>
-        [ProtoMember(2)]
         public List<IdPk> idPks { set; get; }
     }
 }

+ 33 - 0
TEAMModelGrpc/Models/Response.cs

@@ -0,0 +1,33 @@
+using ProtoBuf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace TEAMModelGrpc.Models
+{
+    [ProtoContract]
+    public class Response
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        [ProtoMember(1)]
+        public string message { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        [ProtoMember(2)]
+        public int code { get; set; }
+
+        public Response Success()
+        {
+            this.code = 200;
+            this.message = "Success";
+            return this;
+        }
+
+
+    }
+
+}

+ 99 - 0
TEAMModelGrpc/Models/SyllabusTreeDto.cs

@@ -0,0 +1,99 @@
+using ProtoBuf;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelOS.Service.Models.Syllabus;
+
+namespace TEAMModelGrpc.Models
+{
+    [ProtoContract]
+    public class SyllabusTreeDto
+    {
+        public SyllabusTreeDto()
+        {
+            children = new List<SyllabusTreeDto>();
+        }
+
+        [ProtoMember(16)]
+        public List<SyllabusTreeDto> children { get; set; }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        [ProtoMember(1)]
+        public string id { get; set; }
+        /// <summary>
+        /// 标题
+        /// </summary>
+        [ProtoMember(2)]
+        public string title { get; set; }
+        /// <summary>
+        /// 是否展开
+        /// </summary>
+        [ProtoMember(3)]
+        public bool expand { get; set; }
+        /// <summary>
+        /// 是否编辑
+        /// </summary>
+        [ProtoMember(4)]
+        public bool editable { get; set; } = true;
+        /// <summary>
+        /// 版本
+        /// </summary>
+        [ProtoMember(5)]
+        public string version { get; set; }
+        /// <summary>
+        /// 排序
+        /// </summary>
+        [ProtoMember(6)]
+        public int order { get; set; }
+        /// <summary>
+        /// 类型
+        /// </summary>
+        [ProtoMember(7)]
+        public int type { get; set; }
+        /// <summary>
+        /// 备注
+        /// </summary>
+        //public string remark { get; set; }
+        /// <summary>
+        /// 节点Key
+        /// </summary>
+        [ProtoMember(8)]
+        public string nodeKey { get; set; }
+        ///// <summary>
+        /////主键
+        ///// </summary>
+        //[Required(ErrorMessage = "{0} 必须填写")]
+        //public string Id { get; set; }
+        /// <summary>
+        /// 父级
+        /// </summary>
+        [ProtoMember(9)]
+        public string pid { get; set; }
+
+        /// <summary>
+        /// 册别编码
+        /// </summary>
+        [ProtoMember(10)]
+        public string volumeCode { get; set; }
+
+        /// <summary>
+        /// 数据状态
+        /// </summary>
+        [ProtoMember(11)]
+        public int status { get; set; } = 1;
+
+        [ProtoMember(12)]
+        public List<string> resources { get; set; }
+        [ProtoMember(13)]
+        public List<string> knowledges { get; set; }
+
+        [ProtoMember(14)]
+        public bool resource { get; set; }
+        [ProtoMember(15)]
+        public bool knowledge { get; set; }
+    }
+}

+ 89 - 0
TEAMModelGrpc/Protos/CourseService.proto

@@ -5,8 +5,15 @@ package math;
 
 
 service CourseService {
+   //查询课程
    rpc FindCourseByDict(Dict) returns(stream Course);
 
+   //保存课程
+   rpc SaveCourse(stream Course) returns(stream Course);
+
+   //删除课程
+   rpc DeleteCourse(ListPid) returns(ListPid);
+
 }
 
 
@@ -97,4 +104,86 @@ message CourseTime {
    string classroomCode = 4;
    //临时课程
    string frequencyName = 5;
+}
+
+enum HttpStatusCode {
+   option allow_alias = true;
+   ZERO = 0; // proto3 requires a zero value as the first item (it can be named anything)
+   Continue = 100;
+   SwitchingProtocols = 101;
+   Processing = 102;
+   EarlyHints = 103;
+   OK = 200;
+   Created = 201;
+   Accepted = 202;
+   NonAuthoritativeInformation = 203;
+   NoContent = 204;
+   ResetContent = 205;
+   PartialContent = 206;
+   MultiStatus = 207;
+   AlreadyReported = 208;
+   IMUsed = 226;
+   Ambiguous = 300;
+   MultipleChoices = 300;
+   MovedPermanently = 301;
+   Moved = 301;
+   Found = 302;
+   Redirect = 302;
+   SeeOther = 303;
+   RedirectMethod = 303;
+   NotModified = 304;
+   UseProxy = 305;
+   Unused = 306;
+   TemporaryRedirect = 307;
+   RedirectKeepVerb = 307;
+   PermanentRedirect = 308;
+   BadRequest = 400;
+   Unauthorized = 401;
+   PaymentRequired = 402;
+   Forbidden = 403;
+   NotFound = 404;
+   MethodNotAllowed = 405;
+   NotAcceptable = 406;
+   ProxyAuthenticationRequired = 407;
+   RequestTimeout = 408;
+   Conflict = 409;
+   Gone = 410;
+   LengthRequired = 411;
+   PreconditionFailed = 412;
+   RequestEntityTooLarge = 413;
+   RequestUriTooLong = 414;
+   UnsupportedMediaType = 415;
+   RequestedRangeNotSatisfiable = 416;
+   ExpectationFailed = 417;
+   MisdirectedRequest = 421;
+   UnprocessableEntity = 422;
+   Locked = 423;
+   FailedDependency = 424;
+   UpgradeRequired = 426;
+   PreconditionRequired = 428;
+   TooManyRequests = 429;
+   RequestHeaderFieldsTooLarge = 431;
+   UnavailableForLegalReasons = 451;
+   InternalServerError = 500;
+   NotImplemented = 501;
+   BadGateway = 502;
+   ServiceUnavailable = 503;
+   GatewayTimeout = 504;
+   HttpVersionNotSupported = 505;
+   VariantAlsoNegotiates = 506;
+   InsufficientStorage = 507;
+   LoopDetected = 508;
+   NotExtended = 510;
+   NetworkAuthenticationRequired = 511;
+}
+
+message IdPk {
+   string id = 1;
+   string pk = 2;
+   HttpStatusCode StatusCode = 3;
+}
+
+message ListPid {
+   //list IdPk
+   repeated IdPk idPks = 1;
 }

+ 5 - 9
TEAMModelGrpc/Protos/KnowledgeService.proto

@@ -5,10 +5,13 @@ package math;
 
 
 service KnowledgeService {
+   //查询知识点
    rpc FinKnowledge(Dict) returns(stream Knowledge);
 
+   //保存知识点
    rpc SaveKnowledge(stream Knowledge) returns(stream Knowledge);
 
+   //删除知识点
    rpc DeleteKnowledge(ListPid) returns(ListPid);
 
 }
@@ -158,14 +161,7 @@ message IdPk {
    HttpStatusCode StatusCode = 3;
 }
 
-message KeyValuePair_String_String {
-   string Key = 1;
-   string Value = 2;
-}
-
 message ListPid {
-   //key 是pk ,value 是id
-   repeated KeyValuePair_String_String ids = 1;
-   //返回 删除结果
-   repeated IdPk idPks = 2;
+   //list IdPk
+   repeated IdPk idPks = 1;
 }

+ 121 - 0
TEAMModelGrpc/Protos/SyllabusService.proto

@@ -0,0 +1,121 @@
+syntax = "proto3";
+option csharp_namespace = "TMDGrpc.SyllabusService";
+option java_package = "TMDGrpc.SyllabusService";
+package math;
+
+
+service SyllabusService {
+   //查找课纲
+   rpc FindSyllabusTree(Dict) returns(stream SyllabusTreeDto);
+
+   //按节点新增课纲
+   rpc SaveOrUpdateAsNodes(stream SyllabusNode) returns(Response);
+
+   //按树形新增课纲结构
+   rpc SaveOrUpdateAsTree(stream SyllabusTreeDto) returns(stream SyllabusTreeDto);
+
+}
+
+
+
+//请求参数Dict
+message Dict {
+   //数字Dict
+   map<string,double> NMap = 1;
+   //字符串Dict
+   map<string,string> SMap = 2;
+   //布尔Dict
+   map<string,bool> BMap = 3;
+   //字符串ListMap
+   repeated LSMap LSMap = 4;
+   //数字ListMap
+   repeated LNMap LNMap = 5;
+   //Byte ListMap
+   repeated LBMap LBMap = 6;
+}
+
+//Byte[] Map
+message LBMap {
+   //Key
+   string Key = 1;
+   //byte数组
+   bytes Value = 2;
+}
+
+//数字ListMap
+message LNMap {
+   //Key
+   string Key = 1;
+   //数字数组
+   repeated double Value = 2 [packed = false];
+}
+
+//字符串ListMap
+message LSMap {
+   //数字Dict
+   string Key = 1;
+   //字符串数组
+   repeated string Value = 2;
+}
+
+message SyllabusNode {
+   string id = 1;
+   //标题
+   string title = 2;
+   //是否展开
+   bool expand = 3;
+   //是否编辑
+   bool editable = 4;
+   //版本
+   string version = 5;
+   //排序
+   int32 order = 6;
+   //类型
+   int32 type = 7;
+   //节点Key
+   string nodeKey = 8;
+   //父级
+   string pid = 9;
+   //册别编码
+   string volumeCode = 10;
+   //数据状态
+   int32 status = 11;
+   repeated string resources = 12;
+   repeated string knowledges = 13;
+   bool resource = 14;
+   bool knowledge = 15;
+}
+
+message SyllabusTreeDto {
+   string id = 1;
+   //标题
+   string title = 2;
+   //是否展开
+   bool expand = 3;
+   //是否编辑
+   bool editable = 4;
+   //版本
+   string version = 5;
+   //排序
+   int32 order = 6;
+   //类型
+   int32 type = 7;
+   //节点Key
+   string nodeKey = 8;
+   //父级
+   string pid = 9;
+   //册别编码
+   string volumeCode = 10;
+   //数据状态
+   int32 status = 11;
+   repeated string resources = 12;
+   repeated string knowledges = 13;
+   bool resource = 14;
+   bool knowledge = 15;
+   repeated SyllabusTreeDto children = 16;
+}
+
+message Response {
+   string message = 1;
+   int32 code = 2;
+}

+ 49 - 0
TEAMModelGrpc/Services/CourseService.cs

@@ -20,6 +20,14 @@ namespace TEAMModelGrpc.Services
             this._cosmos = cosmosDBV3Repository;
         }
 
+
+        /// <summary>
+        /// 查询课程
+        /// </summary>
+        /// <param name="request"></param>
+        /// <param name="responseStream"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
         [Authorize]
         public async Task FindCourseByDict(Dict request, IServerStreamWriter<Course> responseStream, ServerCallContext context)
         {
@@ -35,5 +43,46 @@ namespace TEAMModelGrpc.Services
 
 
         }
+
+        /// <summary>
+        /// 保存课程
+        /// </summary>
+        /// <param name="requestStream"></param>
+        /// <param name="responseStream"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        [Authorize]
+        public async Task SaveCourse(IAsyncStreamReader<Course> requestStream, IServerStreamWriter<Course> responseStream, ServerCallContext context)
+        {
+            //Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
+            //keyValuePairs = request.ToDict();
+            List<Course> knowledges = new List<Course>();
+            await foreach (var message in requestStream.ReadAllAsync())
+            {
+                knowledges.Add(message);
+            }
+
+            await _cosmos.SaveOrUpdateAll(knowledges);
+
+            knowledges.ForEach(x =>
+            {
+                responseStream.WriteAsync(x);
+            });
+        }
+
+
+        /// <summary>
+        /// 删除课程
+        /// </summary>
+        /// <param name="listPid"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        [Authorize]
+        public async Task<ListPid> DeleteCourse(ListPid listPid, ServerCallContext context)
+        {
+            List<IdPk> idPks = await _cosmos.DeleteAll<Course>(listPid.idPks);
+            listPid.idPks = idPks;
+            return listPid;
+        }
     }
 }

+ 24 - 5
TEAMModelGrpc/Services/KnowledgeService.cs

@@ -15,9 +15,7 @@ using TEAMModelOS.Service.Services.Syllabus.Interface;
 
 namespace TEAMModelGrpc.Services
 {
-    /// <summary>
-    /// 
-    /// </summary>
+ 
     public class KnowledgeService : IGrpcService
     {
         private IAzureCosmosDBV3Repository cosmosDBV3Repository;
@@ -29,6 +27,14 @@ namespace TEAMModelGrpc.Services
             this.knowledgeService = knowledgeService;
         }
 
+
+        /// <summary>
+        /// 查询知识点
+        /// </summary>
+        /// <param name="request"></param>
+        /// <param name="responseStream"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
         [Authorize]
         public async Task FinKnowledge(Dict request, IServerStreamWriter<Knowledge> responseStream, ServerCallContext context)
         {
@@ -42,6 +48,13 @@ namespace TEAMModelGrpc.Services
         }
 
 
+        /// <summary>
+        /// 保存知识点
+        /// </summary>
+        /// <param name="requestStream"></param>
+        /// <param name="responseStream"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
         [Authorize]
         public async Task SaveKnowledge(IAsyncStreamReader<Knowledge> requestStream, IServerStreamWriter<Knowledge> responseStream, ServerCallContext context)
         {
@@ -62,10 +75,16 @@ namespace TEAMModelGrpc.Services
         }
 
 
+        /// <summary>
+        /// 删除知识点
+        /// </summary>
+        /// <param name="listPid"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        [Authorize]
         public async Task<ListPid> DeleteKnowledge(ListPid listPid, ServerCallContext context)
         {
-           List<IdPk> idPks = await cosmosDBV3Repository.DeleteAll<Knowledge>(listPid.ids);
-
+            List<IdPk> idPks = await knowledgeService.DeleteKnowledge(listPid.idPks);//await cosmosDBV3Repository.DeleteAll<Knowledge>(listPid.idPks);
             listPid.idPks = idPks;
             return listPid;
         }

+ 117 - 0
TEAMModelGrpc/Services/SyllabusService.cs

@@ -0,0 +1,117 @@
+using Grpc.Core;
+using Grpc.Extension.Abstract;
+using Microsoft.AspNetCore.Authorization;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelGrpc.Models;
+using TEAMModelOS.SDK.Helper.Common.JsonHelper;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Models.Syllabus;
+using TEAMModelOS.Service.Services.Syllabus.Interface;
+
+namespace TEAMModelGrpc.Services
+{
+    public class SyllabusService : IGrpcService
+    {
+        private ISyllabusService syllabusService;
+        private IAzureCosmosDBV3Repository cosmosDBV3Repository;
+
+        public SyllabusService(ISyllabusService syllabusService, IAzureCosmosDBV3Repository cosmosDBV3Repository)
+        {
+            this.syllabusService = syllabusService;
+            this.cosmosDBV3Repository = cosmosDBV3Repository;
+        }
+
+
+        /// <summary>
+        /// 查找课纲 
+        /// </summary>
+        /// <param name="request"></param>
+        /// <param name="responseStream"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        [Authorize]
+        public async Task FindSyllabusTree(Dict request, IServerStreamWriter<SyllabusTreeDto> responseStream, ServerCallContext context) 
+        {
+            Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
+            keyValuePairs = request.ToDict();
+            List<SyllabusTree> knowledges = await syllabusService.Find(keyValuePairs);
+            List<SyllabusTreeDto> list = knowledges.ToJson().FromJson<List<SyllabusTreeDto>>();
+
+            list.ForEach(x =>
+            {
+                responseStream.WriteAsync(x);
+            });
+        }
+
+        /// <summary>
+        /// 按节点新增课纲
+        /// </summary>
+        /// <param name="request"></param>
+        /// <param name="responseStream"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        public async Task<Response> SaveOrUpdateAsNodes(IAsyncStreamReader<SyllabusNode> requestStream,  ServerCallContext context) 
+        {
+
+            List<SyllabusNode> syllabusNodes = new List<SyllabusNode>();
+            await foreach (SyllabusNode syllabusNode in requestStream.ReadAllAsync()) 
+            {
+                syllabusNodes.Add(syllabusNode);
+            }
+
+            await syllabusService.SaveOrUpdateAsNodes(syllabusNodes);
+            Response response = new Response();
+            return response.Success();
+        }
+
+        /// <summary>
+        /// 按树形新增课纲结构
+        /// </summary>
+        /// <param name="request"></param>
+        /// <param name="responseStream"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        public async Task SaveOrUpdateAsTree(IAsyncStreamReader<SyllabusTreeDto> requestStream, IServerStreamWriter<SyllabusTreeDto> responseStream, ServerCallContext context)
+        {
+
+            List<SyllabusTree> syllabusTrees = new List<SyllabusTree>();
+            List<SyllabusTreeDto> syllabusTreeDtos = new List<SyllabusTreeDto>();
+            await foreach (SyllabusTreeDto syllabusNode in requestStream.ReadAllAsync())
+            {
+                syllabusTreeDtos.Add(syllabusNode);
+                SyllabusTree syllabusTree = syllabusNode.ToJson().FromJson<SyllabusTree>();
+                syllabusTrees.Add(syllabusTree);
+            }
+            await syllabusService.SaveOrUpdateAsTree(syllabusTrees);
+
+            syllabusTreeDtos.ForEach(x => {
+                responseStream.WriteAsync(x);
+            });
+        }
+
+
+        /// <summary>
+        /// 删除课纲
+        /// </summary>
+        /// <param name="request"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        [Authorize]
+        public async Task DeleteSyllabus(Dict request, IServerStreamWriter<SyllabusTreeDto> responseStream, ServerCallContext context)
+        {
+            Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
+            keyValuePairs = request.ToDict();
+            List<Syllabuses> syllabuses = await syllabusService.DeleteSyllabus(keyValuePairs);//await cosmosDBV3Repository.DeleteAll<Knowledge>(listPid.idPks);
+            List<SyllabusTreeDto> syllabusTreeDtos = syllabuses.ToJson().FromJson<List<SyllabusTreeDto>>();
+
+            syllabusTreeDtos.ForEach(x => { 
+                responseStream.WriteAsync(x);
+            });
+        }
+
+
+    }
+}

+ 67 - 0
TEAMModelGrpc/Services/VolumeService.cs

@@ -0,0 +1,67 @@
+using Grpc.Core;
+using Grpc.Extension.Abstract;
+using Microsoft.AspNetCore.Authorization;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelGrpc.Models;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Models.Syllabus;
+using TEAMModelOS.Service.Services.Syllabus.Interface;
+
+namespace TEAMModelGrpc.Services
+{
+    public class VolumeService :IGrpcService
+    {
+        private readonly IAzureCosmosDBV3Repository azureCosmosDBRepository;
+        private IVolumeService volumeService;
+
+        public VolumeService(IAzureCosmosDBV3Repository azureCosmosDBRepository, IVolumeService volumeService)
+        {
+            this.azureCosmosDBRepository = azureCosmosDBRepository;
+            this.volumeService = volumeService;
+        }
+
+        /// <summary>
+        /// 保存册别
+        /// </summary>
+        /// <param name="requestStream"></param>
+        /// <param name="responseStream"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        [Authorize]
+        public async Task SaveOrUpdateVolume(IAsyncStreamReader<SyllabusVolume> requestStream, IServerStreamWriter<SyllabusVolume> responseStream, ServerCallContext context) {
+
+            List<SyllabusVolume> volumes = new List<SyllabusVolume>();
+            await foreach (SyllabusVolume syllabusNode in requestStream.ReadAllAsync())
+            {
+                List<SyllabusVolume> volume = await volumeService.SaveOrUpdateVolume(syllabusNode);
+                volumes.AddRange(volume);
+            }
+            volumes.ForEach(x => {
+                responseStream.WriteAsync(x);
+            });
+        }
+
+        /// <summary>
+        /// 查询册别
+        /// </summary>
+        /// <param name="request"></param>
+        /// <param name="responseStream"></param>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        [Authorize]
+        public async Task FindVolume(Dict request, IServerStreamWriter<SyllabusVolume> responseStream, ServerCallContext context) {
+
+            Dictionary<string, object> dict = request.ToDict();
+
+            List<SyllabusVolume> syllabusVolumes = await azureCosmosDBRepository.FindByDict<SyllabusVolume>(dict);
+
+            syllabusVolumes.ForEach(x => { 
+                responseStream.WriteAsync(x);
+            });
+        }
+
+    }
+}

+ 8 - 6
TEAMModelGrpc/TEAMModelGrpc.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Web">
 
   <PropertyGroup>
     <TargetFramework>netcoreapp3.1</TargetFramework>
@@ -9,7 +9,13 @@
     <DocumentationFile>TEAMModelOS.GRPC.xml</DocumentationFile>
   </PropertyGroup>
   <ItemGroup>
-    <None Remove="Protos\greet.proto" />
+    <None Remove="Protos\SyllabusService.proto" />
+  </ItemGroup>
+  <ItemGroup>
+    <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
+    <Protobuf Include="Protos\CourseService.proto" GrpcServices="Server" />
+    <Protobuf Include="Protos\KnowledgeService.proto" GrpcServices="Server" />
+    <Protobuf Include="Protos\SyllabusService.proto" GrpcServices="Server" />
   </ItemGroup>
 
   <ItemGroup>
@@ -19,13 +25,9 @@
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
     <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.8" />
-    <PackageReference Include="ClouDASLibx" Version="1.1.4" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\TEAMModelOS.SDK\TEAMModelOS.SDK.csproj" />
     <ProjectReference Include="..\TEAMModelOS.Service\TEAMModelOS.Service.csproj" />
   </ItemGroup>
-  <ItemGroup>
-    <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
-  </ItemGroup>
 </Project>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1124 - 5
TEAMModelGrpc/TEAMModelOS.GRPC.xml


+ 5 - 5
TEAMModelOS.SDK/Module/AzureCosmosDBV3/AzureCosmosDBV3Repository.cs

@@ -254,7 +254,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
         }
 
 
-        public async Task<List<IdPk>> DeleteAll<T>(List<KeyValuePair<string, string>> ids) where T : ID
+        public async Task<List<IdPk>> DeleteAll<T>(List<IdPk> ids) where T : ID
         {
             CosmosModelInfo container = await InitializeCollection<T>();
             //string partitionKey = GetPartitionKey<T>();
@@ -268,16 +268,16 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
             Stopwatch stopwatch = Stopwatch.StartNew();
             for (int i = 0; i < pages; i++)
             {
-                List<KeyValuePair<string, string>> lists = ids.Skip((i) * pageSize).Take(pageSize).ToList();
+                List<IdPk> lists = ids.Skip((i) * pageSize).Take(pageSize).ToList();
                 List<Task> tasks = new List<Task>(lists.Count);
                 lists.ForEach(item =>
                 {
-                    tasks.Add(container.container.DeleteItemStreamAsync(item.Value, new PartitionKey(item.Key))
+                    tasks.Add(container.container.DeleteItemStreamAsync(item.id, new PartitionKey(item.pk))
                         .ContinueWith((Task<ResponseMessage> task) =>
                         {
                              using (ResponseMessage response = task.Result)
                            {
-                                idPks.Add(new IdPk { id = item.Value, pk = item.Key.ToString(), StatusCode = response.StatusCode });
+                                idPks.Add(new IdPk { id = item.id, pk = item.pk.ToString(), StatusCode = response.StatusCode });
                                 //    if (!response.IsSuccessStatusCode)
                                 //    {
                                 //    }
@@ -289,7 +289,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
                 if (container.cache && RedisHelper.Instance != null)
                 {
                     lists.ForEach(async x => {
-                        await RedisHelper.HDelAsync(CacheCosmosPrefix + container.container.Id,x.Value );
+                        await RedisHelper.HDelAsync(CacheCosmosPrefix + container.container.Id,x.id );
                     });
                 }
             }

+ 1 - 1
TEAMModelOS.SDK/Module/AzureCosmosDBV3/IAzureCosmosDBV3Repository.cs

@@ -31,7 +31,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
         Task<IdPk> DeleteAsync<T>(string id, string pk) where T : ID;
         Task<IdPk> DeleteAsync<T>(IdPk idPk) where T : ID;
         Task<List<IdPk>> DeleteAll<T>(List<T> entities) where T : ID;
-        Task<List<IdPk>> DeleteAll<T>(List<KeyValuePair<string, string>> ids) where T : ID;
+        Task<List<IdPk>> DeleteAll<T>(List<IdPk> ids) where T : ID;
         Task<List<IdPk>> DeleteAll<T>(Dictionary<string, object> dict) where T : ID;
         Task<T> Update<T>(T entity) where T : ID;
         Task<List<T>> UpdateAll<T>(List<T> entities) where T : ID;

+ 11 - 8
TEAMModelOS.Service/Models/Core/ClassRoomStudent.cs

@@ -10,6 +10,9 @@ namespace TEAMModelOS.Service.Models.Core
     [CosmosDB(RU = 400, Name = "CoreClassroomStudent",Cache = true)]
     public class ClassroomStudent:ID
     {
+        /// <summary>
+        /// classroomCode
+        /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
         public string id { get; set; } //classroomCode
 
@@ -19,16 +22,16 @@ namespace TEAMModelOS.Service.Models.Core
 
         public HashSet<string> studentId { get; set; }
 
-        public class Stu
-        {
-            public string studentId { get; set; }
+        //public class Stu
+        //{
+        //    public string studentId { get; set; }
 
-            /// <summary>
-            /// 座位
-            /// </summary>
-            public int seatNo { get; set; }
+        //    /// <summary>
+        //    /// 座位
+        //    /// </summary>
+        //    public int seatNo { get; set; }
 
-        }
+        //}
 
     }
 }

+ 146 - 0
TEAMModelOS.Service/Models/Learn/HomeWork.cs

@@ -0,0 +1,146 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Models.Exam.Models;
+
+namespace TEAMModelOS.Service.Models.Learn
+{
+    /// <summary>
+    /// 作业
+    /// </summary>
+    [CosmosDB(RU = 400, Name = "HomeWork")]
+    public class HomeWork:ID
+    {
+        public HomeWork()
+        {
+            target = new List<Target>();
+            resource = new List<ProcessRes>();
+        }
+
+        public string id { get; set; }
+
+        [PartitionKey]
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string scopeCode { get; set; }
+
+
+        /// <summary>
+        /// 作业名称
+        /// </summary>
+        public string name { get; set; }
+
+        /// <summary>
+        /// 作业发布对象
+        /// </summary>
+        public List<Target> target { get; set; }
+
+        /// <summary>
+        /// 发布模式 0 立即发布 1 定时
+        /// </summary>
+        public string publishModel { get; set; }
+
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        public long startTime { get; set; }
+
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        public long endTime { get; set; }
+
+        /// <summary>
+        /// 作业反馈类型
+        /// </summary>
+        //public string feedbackType { get; set; }
+
+        /// <summary>
+        /// 题目
+        /// </summary>
+        //public List<ExamItem> ExamItem { get; set; }
+
+
+
+        /// <summary>
+        /// 作业描述
+        /// </summary>
+        public string description { get; set; }
+
+  
+        /// <summary>
+        /// 作业附件
+        /// </summary>
+        public List<ProcessRes> resource { get; set; }
+
+
+        //public Subdto subdto { get; set; }
+
+        /// <summary>
+        /// 通知方式 0电子纸条 1 学生Email 2 家长Email
+        /// </summary>
+        //public string noticeMode { get; set; }
+
+        //public class Subdto {
+        //    /// <summary>
+        //    /// 提交人数
+        //    /// </summary>
+        //    public int submitted { get; set; }
+            
+        //    /// <summary>
+        //    /// 总人数
+        //    /// </summary>
+        //    public int sum { get; set; }
+
+        //}
+
+
+        /// <summary>
+        /// 发布对象
+        /// </summary>
+        public class Target {
+            [Required(ErrorMessage = "{0} 必须填写")]
+            public string classroomCode { get; set; }
+            [Required(ErrorMessage = "{0} 必须填写")]
+            public string scopeCode { get; set; }
+        }
+
+        /// <summary>
+        /// 作业附件
+        /// </summary>
+        public class ProcessRes
+        {
+            /// <summary>
+            /// 文件名字
+            /// </summary>
+            public string fileName { get; set; }
+            
+            /// <summary>
+            /// 
+            /// </summary>
+            public string blobUrl { get; set; }
+
+            /// <summary>
+            /// 文件大小
+            /// </summary>
+            public long size { get; set; }
+
+            /// <summary>
+            /// 缩略图链接  图片视频有 文件没有
+            /// </summary>
+            public string compressUrl { get; set; }
+
+            /// <summary>
+            /// 文件类型
+            /// </summary>
+            public string type { get; set; }
+
+            public int order { get; set; }
+
+        }
+
+
+    }
+}

+ 216 - 0
TEAMModelOS.Service/Models/Learn/HomeWorkStudent.cs

@@ -0,0 +1,216 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Models.Exam.Models;
+
+namespace TEAMModelOS.Service.Models.Learn
+{
+
+    /// <summary>
+    /// 作业数据
+    /// </summary>
+    [CosmosDB(RU = 400, Name = "HomeWorkStudent")]
+    public class HomeWorkStudent : ID
+    {
+        public HomeWorkStudent() {
+            content = new List<HomeWorkContent>();
+            comments = new List<HomeWorkComment>();
+        }
+        public string id { get; set; }
+
+        [PartitionKey]
+        public string homeWorkId { get; set; }
+
+
+        /// <summary>
+        /// 姓名
+        /// </summary>
+        public string name { get; set; }
+
+
+        /// <summary>
+        /// 醍摩豆id
+        /// </summary>
+        public string TEAMModelId { get; set; }
+
+        /// <summary>
+        /// 上课班级
+        /// </summary>
+        public string classroomCode { get; set; }
+
+        /// <summary>
+        /// 原生班级
+        /// </summary>
+        public string nativeroomCode { get; set; }
+
+
+        /// <summary>
+        /// 学号
+        /// </summary>
+        public string studentId { get; set; }
+
+        /// <summary>
+        /// 是否提交
+        /// </summary>
+        public bool submissionBool { get; set; } = false;
+
+        /// <summary>
+        /// 提交时间
+        /// </summary>
+        public string submissionTime { get; set; }
+
+        /// <summary>
+        /// 分数
+        /// </summary>
+        public double score { get; set; }
+
+        /// <summary>
+        /// 作业内容
+        /// </summary>
+        public List<HomeWorkContent> content { get; set; }
+
+
+        /// <summary>
+        /// 作业评论
+        /// </summary>
+        public List<HomeWorkComment> comments { get; set; }
+        //public Dictionary<string,HomeWorkComment> comments { get; set; }
+    }
+
+    /// <summary>
+    /// 作业内容
+    /// </summary>
+    public class HomeWorkContent {
+
+        /// <summary>
+        /// 作业反馈类型
+        /// </summary>
+        //public string feedbackType { get; set; }
+
+        /// <summary>
+        /// 在线编辑模式 作答记录
+        /// </summary>
+        //public List<ExamAnswer> examAnswers { get; set; }
+
+        /// <summary>
+        /// 作答记录
+        /// </summary>
+        public string answers { get; set; }
+
+        /// <summary>
+        ///  其他模式url 及name
+        /// </summary>
+        public List<ProcessRes> resource { get; set; }
+
+    }
+
+
+    public class ProcessRes
+    {
+        /// <summary>
+        /// 文件名字
+        /// </summary>
+        public string fileName { get; set; }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public string blobUrl { get; set; }
+
+        /// <summary>
+        /// 文件大小
+        /// </summary>
+        public long size { get; set; }
+
+        /// <summary>
+        /// 缩略图链接  图片视频有 文件没有
+        /// </summary>
+        public string compressUrl { get; set; }
+
+        /// <summary>
+        /// 文件类型
+        /// </summary>
+        public string type { get; set; }
+
+        public int order { get; set; }
+
+    }
+
+    /// <summary>
+    /// 作业评论
+    /// </summary>
+    public class HomeWorkComment {
+
+        public HomeWorkComment(){
+            reply = new List<Reply>();
+        }
+
+        /// <summary>
+        /// 评论id
+        /// </summary>
+        public string commentid { get; set; }
+
+        /// <summary>
+        /// 评论者id 醍摩豆或studenId
+        /// </summary>
+        public string fromId { get; set; }
+
+        /// <summary>
+        /// 被评论者id 醍摩豆或studenId
+        /// </summary>
+        public string toId { get; set; }
+
+        /// <summary>
+        /// 评论者身份 教师 学生
+        /// </summary>
+        public string identity { get; set; }
+
+        /// <summary>
+        /// 评语
+        /// </summary>
+        public string comment { get; set; }
+
+        /// <summary>
+        /// 评论时间
+        /// </summary>
+        public long createTime { get; set; }
+
+        /// <summary>
+        /// 评论回复
+        /// </summary>
+        public List<Reply>  reply { get; set; }
+
+    }
+
+    /// <summary>
+    /// 评论回复
+    /// </summary>
+    public class Reply
+    {
+        /// <summary>
+        /// 评论者id 醍摩豆或studenId
+        /// </summary>
+        public string fromId { get; set; }
+
+        /// <summary>
+        /// 被评论者id 醍摩豆或studenId
+        /// </summary>
+        public string toId { get; set; }
+
+        /// <summary>
+        /// 评论者身份 教师 学生
+        /// </summary>
+        public string identity { get; set; }
+
+        /// <summary>
+        /// 评语
+        /// </summary>
+        public string comment { get; set; }
+
+        public long createTime { get; set; }
+
+    }
+
+}

+ 69 - 65
TEAMModelOS.Service/Models/Learn/LeanProcess.cs

@@ -17,11 +17,11 @@ namespace TEAMModelOS.Service.Models.Learn
     {
 
         public LeanProcess() {
-            target = new List<string>();
-            steps = new List<ProcessStep>();
+            steps = new List<LearnUnit>();
         }
         
         public string id { get; set; }
+
         public string name { get; set; }
 
         [Required(ErrorMessage = "{0} 必须填写")]
@@ -32,92 +32,96 @@ namespace TEAMModelOS.Service.Models.Learn
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
         public string periodCode { get; set; }
+
+
         /// <summary>
         /// 活动介绍
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
         public string Introduce { get; set; }
+
+
         /// <summary>
         /// 学习对象
         /// </summary>
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public List<string> target { get; set; }
+        //public List<Target> target { get; set; }
+
+
         [Required(ErrorMessage = "{0} 必须填写")]
         [PartitionKey]
         public string scopeCode { get; set; }
-        /// <summary>
-        /// 步骤
-        /// </summary>
-        public List<ProcessStep> steps { get; set; }
-        /// <summary>
-        /// 是否闯关模式 0 或 1 vue组件不支持true false
-        /// </summary>
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public string isOrder { get; set; }
 
-        //创建时间 
-        public long createTime { get; set; }
-        //创建者
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public string creator { get; set; }
 
         /// <summary>
-        /// 编序式模板,课前预习,随堂练习,课后作业
+        /// 最小单元
         /// </summary>
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public string type { get; set; }
-        /// <summary>
-        /// 截至时间 时间戳
-        /// </summary>
-        public int expire { get; set; }
-    }
+        public List<LearnUnit> steps { get; set; }
+       
 
+        //创建时间 
+        //public long createTime { get; set; }
 
-    public class ProcessStep
-    {
-        public ProcessStep() {
-            resource = new List<ProcessRes>();
-            item = new List<ExamItem>();
-        }
-        /// <summary>
-        /// 资源内容
-        /// [{"name":"","url":"","order":""}]
-        /// </summary>
-        public List<ProcessRes> resource { get; set; }
-        /// <summary>
-        /// 题目
-        /// </summary>
-        public List<ExamItem> item { get; set; }
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public string name { get; set; }
-        public int order { get; set; }
-    }
-  
-    public class ProcessRes{
 
+        //创建者
         [Required(ErrorMessage = "{0} 必须填写")]
-        public string fileName { get; set; }
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public string blobUrl { get; set; }
-        public int order { get; set; }
-
-        /// <summary>
-        /// 文件大小
-        /// </summary>
-        public long size { get; set; }
+        public string creator { get; set; }
+        
+        public class Target
+        {
+            public string classroomCode { get; set; }
 
-        /// <summary>
-        /// 缩略图链接  图片视频有 文件没有
-        /// </summary>
-        public string compressUrl { get; set; }
+            public string scopeCode { get; set; }
+        }
 
-        /// <summary>
-        /// 文件类型
-        /// </summary>
-        public string type { get; set; }
 
+    }
 
 
-    }
+    //public class ProcessStep
+    //{
+    //    public ProcessStep() {
+    //        resource = new List<ProcessRes>();
+    //        item = new List<ExamItem>();
+    //    }
+    //    /// <summary>
+    //    /// 资源内容
+    //    /// [{"name":"","url":"","order":""}]
+    //    /// </summary>
+    //    public List<ProcessRes> resource { get; set; }
+    //    /// <summary>
+    //    /// 题目
+    //    /// </summary>
+    //    public List<ExamItem> item { get; set; }
+    //    [Required(ErrorMessage = "{0} 必须填写")]
+    //    public string name { get; set; }
+    //    public int order { get; set; }
+    //}
+
+    //public class ProcessRes{
+
+    //    [Required(ErrorMessage = "{0} 必须填写")]
+    //    public string fileName { get; set; }
+    //    [Required(ErrorMessage = "{0} 必须填写")]
+    //    public string blobUrl { get; set; }
+    //    public int order { get; set; }
+
+    //    /// <summary>
+    //    /// 文件大小
+    //    /// </summary>
+    //    public long size { get; set; }
+
+    //    /// <summary>
+    //    /// 缩略图链接  图片视频有 文件没有
+    //    /// </summary>
+    //    public string compressUrl { get; set; }
+
+    //    /// <summary>
+    //    /// 文件类型
+    //    /// </summary>
+    //    public string type { get; set; }
+
+
+
+    //}
 
 }

+ 149 - 0
TEAMModelOS.Service/Models/Learn/LearningAutonomous.cs

@@ -0,0 +1,149 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Models.Exam.Models;
+
+namespace TEAMModelOS.Service.Models.Learn
+{
+    /// <summary>
+    /// 自主学习
+    /// </summary>
+    [CosmosDB(RU = 400, Name = "LearningAutonomous")]
+    public class LearningAutonomous:ID
+    {
+
+        public LearningAutonomous()
+        {
+            target = new List<Target>();
+            steps = new List<ProcessStep>();
+        }
+
+        public string id { get; set; }
+
+        /// <summary>
+        /// 活动名称
+        /// </summary>
+        public string name { get; set; }
+
+        /// <summary>
+        /// 学科code
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string subjectCode { get; set; }
+
+        /// <summary>
+        /// 学段code
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string periodCode { get; set; }
+        /// <summary>
+        /// 活动介绍
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string Introduce { get; set; }
+        /// <summary>
+        /// 学习对象
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public List<Target> target { get; set; }
+
+        [Required(ErrorMessage = "{0} 必须填写")]
+        [PartitionKey]
+        public string scopeCode { get; set; }
+
+        /// <summary>
+        /// 步骤
+        /// </summary>
+        public List<ProcessStep> steps { get; set; }
+
+        /// <summary>
+        /// 是否闯关模式 0 或 1 vue组件不支持true false
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string isOrder { get; set; }
+
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public long createTime { get; set; }
+        
+        /// <summary>
+        /// 创建者
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string creator { get; set; }
+
+      
+        /// <summary>
+        /// 截至时间 时间戳
+        /// </summary>
+        public int expire { get; set; }
+
+        public class Target
+        {
+            public string classroomCode { get; set; }
+
+            public string scopeCode { get; set; }
+        }
+
+        public class ProcessStep
+        {
+            public ProcessStep()
+            {
+                resource = new List<ProcessRes>();
+                item = new List<ExamItem>();
+            }
+            /// <summary>
+            /// 资源内容
+            /// [{"name":"","url":"","order":""}]
+            /// </summary>
+            public List<ProcessRes> resource { get; set; }
+            /// <summary>
+            /// 题目
+            /// </summary>
+            public List<ExamItem> item { get; set; }
+
+            [Required(ErrorMessage = "{0} 必须填写")]
+            public string name { get; set; }
+        }
+
+        public class ProcessRes
+        {
+            /// <summary>
+            /// 文件名字
+            /// </summary>
+            [Required(ErrorMessage = "{0} 必须填写")]
+            public string fileName { get; set; }
+            
+            /// <summary>
+            /// 
+            /// </summary>
+            [Required(ErrorMessage = "{0} 必须填写")]
+            public string blobUrl { get; set; }
+            
+            
+            public int order { get; set; }
+
+            /// <summary>
+            /// 文件大小
+            /// </summary>
+            public long size { get; set; }
+
+            /// <summary>
+            /// 缩略图链接  图片视频有 文件没有
+            /// </summary>
+            public string compressUrl { get; set; }
+
+            /// <summary>
+            /// 文件类型
+            /// </summary>
+            public string type { get; set; }
+
+
+
+        }
+    }
+}

+ 20 - 3
TEAMModelOS.Service/Models/Syllabus/SyllabusNode.cs

@@ -1,10 +1,12 @@
-using System.Collections.Generic;
+using ProtoBuf;
+using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using TEAMModelOS.SDK.Context.Attributes.Azure;
 using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
 
 namespace TEAMModelOS.Service.Models.Syllabus
 {
+    [ProtoContract]
     public class SyllabusNode
     {
 
@@ -16,33 +18,40 @@ namespace TEAMModelOS.Service.Models.Syllabus
         /// 
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(1)]
         public string id { get; set; }
         /// <summary>
         /// 标题
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(2)]
         public string title { get; set; }
         /// <summary>
         /// 是否展开
         /// </summary>
+        [ProtoMember(3)]
         public bool expand { get; set; }
         /// <summary>
         /// 是否编辑
         /// </summary>
+        [ProtoMember(4)]
         public bool editable { get; set; } = true;
         /// <summary>
         /// 版本
         /// </summary>
+        [ProtoMember(5)]
         public string  version { get; set; } 
         /// <summary>
         /// 排序
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(6)]
         public int order { get; set; }
         /// <summary>
         /// 类型
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(7)]
         public int type { get; set; }
         /// <summary>
         /// 备注
@@ -52,6 +61,7 @@ namespace TEAMModelOS.Service.Models.Syllabus
         /// 节点Key
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(8)]
         public string nodeKey { get; set; }
         ///// <summary>
         /////主键
@@ -62,24 +72,31 @@ namespace TEAMModelOS.Service.Models.Syllabus
         /// 父级
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(9)]
         public string pid { get; set; }
 
         /// <summary>
         /// 册别编码
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(10)]
         public string volumeCode { get; set; }
 
         /// <summary>
         /// 数据状态
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(11)]
         public int status { get; set; } = 1;
 
-         public List<string> resources { get; set; }
+        [ProtoMember(12)]
+        public List<string> resources { get; set; }
+        [ProtoMember(13)]
         public List<string> knowledges { get; set; }
 
-        public  bool resource { get; set; }
+        [ProtoMember(14)]
+        public bool resource { get; set; }
+        [ProtoMember(15)]
         public bool knowledge { get; set; }
         
     }

+ 2 - 4
TEAMModelOS.Service/Models/Syllabus/SyllabusTree.cs

@@ -1,10 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
+using System.Collections.Generic;
 
 namespace TEAMModelOS.Service.Models.Syllabus
 {
-     public class SyllabusTree :SyllabusNode
+    public class SyllabusTree :SyllabusNode
     {
         public SyllabusTree() {
             children = new List<SyllabusTree>();

+ 60 - 2
TEAMModelOS.Service/Models/Syllabus/SyllabusVolume.cs

@@ -6,37 +6,95 @@ using System.Text.Json.Serialization;
 using System.ComponentModel.DataAnnotations;
 using Newtonsoft.Json;
 using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using ProtoBuf;
 
 namespace TEAMModelOS.Service.Models.Syllabus
 {
     [CosmosDB(RU = 400, Name = "SyllabusVolume")]
+    [ProtoContract]
     public class SyllabusVolume :ID
-    { 
+    {
         /// <summary>
         /// id生成规则
         /// </summary>
+        [ProtoMember(1)]
         public string id { get; set; }
         /// <summary>
         /// 0默认教学课纲的册别 1个人或单独的专题课纲册别 2,系统课纲
         /// </summary>
+        [ProtoMember(2)]
         public int type { get; set; }
         /// <summary>
         /// Type 如果为0 则是学校编码  如果为1 则是seminar 专题/研讨/培训
         /// </summary>
         [PartitionKey]
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(3)]
         public string scopeCode { get; set; }
+        
+
+        /// <summary>
+        /// 学段
+        /// </summary>
+        [ProtoMember(4)]
         public string periodCode { get; set; }
+        
+
+        /// <summary>
+        /// 学科
+        /// </summary>
+        [ProtoMember(5)]
         public string subjectCode { get; set; }
+        
+
+        /// <summary>
+        /// 年级
+        /// </summary>
+        [ProtoMember(6)]
         public string gradeCode { get; set; }
+        
+
+        /// <summary>
+        /// 学期code
+        /// </summary>
+        [ProtoMember(7)]
         public string semesterCode { get; set; }
+        
+
+        /// <summary>
+        /// 状态
+        /// </summary>
+        [ProtoMember(8)]
         public int status { get; set; } = 1;
+        
+
+        /// <summary>
+        /// 册别name
+        /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
+        [ProtoMember(9)]
         public string volumeName { get; set; }
+        
+
+        /// <summary>
+        /// 册别code
+        /// </summary>
+        [ProtoMember(10)]
         public string volumeCode { get; set; }
+        
+
+        /// <summary>
+        /// 创建者醍摩豆id
+        /// </summary>
         [JsonPropertyName("TEAMModelId")]
         [JsonProperty("TEAMModelId")]
+        [ProtoMember(11)]
         public string TEAMModelId { get; set; }
-        public string[] editors { get; set; }
+        
+        /// <summary>
+        /// 共编使用者 的醍摩豆id
+        /// </summary>
+        [ProtoMember(12)]
+        public List<string> editors { get; set; }
     }
 }

+ 15 - 7
TEAMModelOS.Service/Services/Syllabus/Implement/KnowledgeService.cs

@@ -17,19 +17,27 @@ namespace TEAMModelOS.Service.Services.Syllabus.Implement
             _cosmos = cosmos;
         }
 
+        public async Task<List<IdPk>> DeleteKnowledge(List<IdPk> listPid)
+        {
+            List<IdPk> idPks = await _cosmos.DeleteAll<Knowledge>(listPid);
+            foreach (IdPk Knowledge in idPks)
+            {
+                List<Knowledge> knowledges = await _cosmos.FindSQL<Knowledge>($"select value(c) from c join A0  in c.points where 1=1  and  c.type = 0 and A0 =  '"+ Knowledge.id + "' ");
+                List<SyllabusResource> Resources = await _cosmos.FindSQL<SyllabusResource>($"select value(c) from c join A0  in c.points where 1=1  and  c.type = 0 and A0 =  '" + Knowledge.id + "' ");
+                foreach (Knowledge knowledge in knowledges) knowledge.points.Remove(Knowledge.id);
+                foreach (SyllabusResource Resource in Resources) Resource.points.Remove(Knowledge.id);
+                await _cosmos.SaveOrUpdateAll(Resources);
+                await _cosmos.SaveOrUpdateAll(knowledges);
+            }
+            return idPks;
+        }
+
         public async Task<List<Knowledge>> SaveOrUpdateKnowledge(List<Knowledge> request)
         {
             foreach (Knowledge item in request)
             {
                 if (item.id == null)
                 {
-                    //if (item.scope == "personal")
-                    //{
-                    //    item.id = item.partitionKey + "-" + item.TEAMModelId + "-" + item.knowledgeId.Replace("-", "");
-                    //}
-                    //else {
-                    //    item.id = item.partitionKey + "-" + item.subjectCode + "-" + item.knowledgeId.Replace("-", "");
-                    //}
                     item.id = Guid.NewGuid().ToString();
                 }
                 if (item.type == 1 && item.points.Count > 0)

+ 269 - 0
TEAMModelOS.Service/Services/Syllabus/Implement/SyllabusService.cs

@@ -0,0 +1,269 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Context.Exception;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+using TEAMModelOS.SDK.Helper.Common.JsonHelper;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Models.Syllabus;
+using TEAMModelOS.Service.Services.Syllabus.Interface;
+
+namespace TEAMModelOS.Service.Services.Syllabus.Implement
+{
+    public class SyllabusService: ISyllabusService
+    {
+        private readonly IAzureCosmosDBV3Repository azureCosmosDBRepository;
+
+        public SyllabusService(IAzureCosmosDBV3Repository azureCosmosDBRepository)
+        {
+            this.azureCosmosDBRepository = azureCosmosDBRepository;
+        }
+
+
+        /// <summary>
+        /// 查找课纲 
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        public async Task<List<SyllabusTree>> Find(Dictionary<string, object> request)
+        {
+            Dictionary<string, object> dict = new Dictionary<string, object>();
+            foreach (KeyValuePair<string, object> keyValuePair in request)
+            {
+                dict.Add("children[*]." + keyValuePair.Key, keyValuePair.Value);
+            }
+            List<Syllabuses> data = await azureCosmosDBRepository.FindByDict<Syllabuses>(dict);
+            List<SyllabusTree> treess = new List<SyllabusTree>();
+            if (data.IsNotEmpty())
+            {
+                Dictionary<string, Syllabuses> syllabuses = new Dictionary<string, Syllabuses>();
+                data.ForEach(x => syllabuses.TryAdd(x.id, x));
+                data = new List<Syllabuses>(syllabuses.Values);
+               
+                foreach (Syllabuses item in data)
+                {
+
+                    List<SyllabusNode> nodedata = item.children;
+                    if (request.TryGetValue("id", out object id))
+                    {
+                        foreach (SyllabusNode syllabus in nodedata)
+                        {
+                            if (syllabus.id == id.ToString())
+                            {
+                                List<SyllabusNode> nodes = new List<SyllabusNode>();
+                                nodes.Add(syllabus);
+                                await FindByPid(syllabus, nodes, nodedata);
+                                nodedata = nodes;
+                                break;
+                            }
+                        }
+                    }
+                    List<SyllabusTree> treess1 = ListToTree(nodedata);
+                    treess.AddRange(treess1);
+
+                    //treess.AddRange(treess1);
+                }
+
+               // return builder.Data(treess).build();
+            }
+            // else return builder.Data(data).build();
+            return treess;
+
+        }
+
+        public static async Task<List<SyllabusNode>> FindByPid(SyllabusNode data, List<SyllabusNode> nodes, List<SyllabusNode> nodedata)
+        {
+            foreach (SyllabusNode syllabus in nodedata)
+            {
+                if (syllabus.pid == data.id)
+                {
+                    nodes.Add(syllabus);
+                    await FindByPid(syllabus, nodes, nodedata);
+                }
+            }
+            return nodes;
+        }
+        
+
+        public async Task<List<Syllabuses>> SaveOrUpdateAsNodes(List<SyllabusNode> syllabusNodes)
+        {
+            List<Syllabuses> syllabuses = new List<Syllabuses>();
+
+            List<Syllabuses> data = await azureCosmosDBRepository.FindByDict<Syllabuses>(new Dictionary<string, object> { { "id", syllabusNodes[0].volumeCode } });
+            List<SyllabusNode> syllabusNodes1 = new List<SyllabusNode>();
+            if (data.IsNotEmpty())
+            {
+                syllabusNodes1.AddRange(data[0].children);
+                //replace
+                for (int i = 0; i < data[0].children.Count; i++)
+                {
+                    for (int j = 0; j < syllabusNodes.Count; j++)
+                    {
+                        if (data[0].children[i].id == syllabusNodes[j].id && data[0].children[i].volumeCode == syllabusNodes[j].volumeCode)
+                        {
+                            syllabusNodes1.Remove(data[0].children[i]);
+                            syllabusNodes1.Add(syllabusNodes[j]);
+                            syllabusNodes.Remove(syllabusNodes[j]);
+                        }
+                    }
+                }
+                data[0].children = syllabusNodes1;
+
+                //新增
+                data[0].children.AddRange(syllabusNodes);
+
+
+                syllabuses = await azureCosmosDBRepository.SaveOrUpdateAll<Syllabuses>(data);
+
+            }
+            else
+            {
+                throw new BizException("保存失败", ResponseCode.FAILED);
+                //return builder.Error(false, ResponseCode.FAILED, "保存失败").build();
+            }
+
+            return syllabuses;
+        }
+
+        public async Task<List<SyllabusTree>> SaveOrUpdateAsTree(List<SyllabusTree> request)
+        {
+            List<SyllabusNode> nodes = new List<SyllabusNode>();
+            Syllabuses syllabus = new Syllabuses();
+
+            TreeToList(request, nodes);
+            // List<SyllabusNode> nods = nodes.ToJson().FromJson<List<SyllabusNode>>() ;
+            syllabus.children = nodes;
+            syllabus.id = request[0].volumeCode;
+            syllabus.volumeCode = request[0].volumeCode;
+            await azureCosmosDBRepository.SaveOrUpdate<Syllabuses>(syllabus);
+            List<SyllabusTree> treess = ListToTree(nodes);
+            return treess;
+        }
+
+        public static List<SyllabusNode> TreeToList(List<SyllabusTree> trees, List<SyllabusNode> nodes)
+        {
+            trees = trees.OrderBy(x => x.order).ToList();
+            nodes.AddRange(trees.ToJson().FromJson<List<SyllabusNode>>());
+
+            foreach (SyllabusTree tree in trees)
+            {
+                if (null != tree.children && tree.children.Count > 0)
+                {
+                    TreeToList(tree.children, nodes);
+                }
+            }
+            return nodes;
+        }
+        private static List<SyllabusTree> ListToTree(List<SyllabusNode> noes)
+        {
+            List<SyllabusTree> list = noes.ToJson().FromJson<List<SyllabusTree>>();
+            //var lookup = list.ToDictionary(n => n.RowKey, n => n);
+
+            var res = from r in list group r by r.id into g select g;
+            Dictionary<string, SyllabusTree> blockDict = new Dictionary<string, SyllabusTree>();
+            foreach (var s in res)
+            {
+                blockDict.TryAdd(s.First().id, s.First());
+            }
+            return GetChild(list, blockDict);
+        }
+
+        public static List<SyllabusTree> GetChild(List<SyllabusTree> list, Dictionary<string, SyllabusTree> dict)
+        {
+            //  list = list.OrderBy(m => m.Order).ToList();
+            List<SyllabusTree> trees = new List<SyllabusTree>();
+            foreach (SyllabusTree node in list)
+            {
+                bool flag = dict.TryGetValue(node.pid, out SyllabusTree syllabus);
+                if (flag && syllabus != null)
+                {
+                    syllabus.children.Add(node);
+                }
+                else
+                {
+                    trees.Add(node);
+                }
+            }
+            return trees;
+        }
+
+        public async Task<List<Syllabuses>> DeleteSyllabus(Dictionary<string, object> request)
+        {
+            Dictionary<string, object> dict = new Dictionary<string, object>();
+            foreach (KeyValuePair<string, object> keyValuePair in request)
+            {
+                dict.Add("children[*]." + keyValuePair.Key, keyValuePair.Value);
+            }
+
+            List<Syllabuses> data = await azureCosmosDBRepository.FindByDict<Syllabuses>(dict);
+            Dictionary<string, Syllabuses> syllabuses = new Dictionary<string, Syllabuses>();
+            List<Syllabuses> data1 = new List<Syllabuses>();
+            if (data.Count > 0)
+            {
+                data.ForEach(x => syllabuses.TryAdd(x.id, x));
+                data = new List<Syllabuses>(syllabuses.Values);
+
+                //是否全删
+                bool flg = false;
+                foreach (Syllabuses item in data)
+                {
+                    List<SyllabusNode> nodedata = item.children;
+                    if (request.TryGetValue("id", out object id))
+                    {
+                        foreach (SyllabusNode syllabus in nodedata)
+                        {
+                            if (syllabus.id == id.ToString())
+                            {
+                                List<SyllabusNode> nodes = new List<SyllabusNode>();
+                                nodes.Add(syllabus);
+                                await FindByPid(syllabus, nodes, nodedata);
+                                nodedata = nodes;
+                                break;
+                            }
+                        }
+                    }
+                    List<SyllabusNode> syllabusNodes = new List<SyllabusNode>();
+                    syllabusNodes.AddRange(item.children);
+                    for (int i = 0; i < item.children.Count; i++)
+                    {
+                        for (int j = 0; j < nodedata.Count; j++)
+                        {
+                            if (item.children[i].id == nodedata[j].id)
+                            {
+                                syllabusNodes.Remove(item.children[i]);
+                            }
+                        }
+                    }
+                    item.children = syllabusNodes;
+                    if (item.children.Count == 0)
+                    {
+                        await azureCosmosDBRepository.DeleteAsync<Syllabuses>(item.id, item.volumeCode);
+                        flg = true;
+                    }
+                }
+                if (!flg)
+                {
+                    data1 = await azureCosmosDBRepository.SaveOrUpdateAll<Syllabuses>(data);
+
+                }
+
+
+                //if (flg)
+                //{
+
+                //    return builder.Data("全部删除成功").build();
+                //}
+                //else
+                //{
+                //    List<Syllabuses> data1 = await azureCosmosDBRepository.SaveOrUpdateAll<Syllabuses>(data);
+                //    return builder.Data(data1).build();
+                //}
+
+
+            }
+            return data1;
+        }
+    }
+}

+ 119 - 0
TEAMModelOS.Service/Services/Syllabus/Implement/VolumeService.cs

@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Context.Exception;
+using TEAMModelOS.SDK.Extension.SnowFlake;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Models.Syllabus;
+using TEAMModelOS.Service.Services.Syllabus.Interface;
+
+namespace TEAMModelOS.Service.Services.Syllabus.Implement
+{
+    public class VolumeService : IVolumeService
+    {
+
+        private readonly IAzureCosmosDBV3Repository azureCosmosDBRepository;
+
+        public VolumeService(IAzureCosmosDBV3Repository azureCosmosDBRepository)
+        {
+            this.azureCosmosDBRepository = azureCosmosDBRepository;
+        }
+
+        public async Task<List<SyllabusVolume>> SaveOrUpdateVolume(SyllabusVolume request)
+        {
+            if (request.editors != null && request.editors.Count > 5)
+            {
+                throw new BizException("共编人数大于5人!");
+            }
+            if (string.IsNullOrEmpty(request.id))
+            {
+                if (request.type == 0)
+                {
+                    List<SyllabusVolume> volumesFind = await azureCosmosDBRepository.FindByDict<SyllabusVolume>(new Dictionary<string, object>() {
+                        { "scopeCode",request.scopeCode},{ "periodCode", request.periodCode},
+                        { "subjectCode", request.subjectCode},{ "gradeCode", request.gradeCode},
+                        { "semesterCode",request.semesterCode},{ "volumeName",request.volumeName}  ,
+                        { "status",1} ,{ "type",0} });
+                    if (volumesFind.IsNotEmpty())
+                    {
+                        throw new BizException("已存在!", ResponseCode.DATA_EXIST);
+                    }
+                    ///校本课纲
+                    string key = request.scopeCode + IdWorker.getInstance().NextId();
+                    request.id = key;
+                    request.volumeCode = key;
+                }
+                else if (request.type == 1)
+                {
+                    List<SyllabusVolume> volumesFind = await azureCosmosDBRepository.FindByDict<SyllabusVolume>(new Dictionary<string, object>() {
+                        { "schoolCode",request.scopeCode},{ "periodCode", request.periodCode},
+                        { "subjectCode", request.subjectCode},{ "gradeCode", request.gradeCode},
+                        { "semesterCode",request.semesterCode},{ "volumeName",request.volumeName},
+                        { "TEAMModelId",request.TEAMModelId}, { "status",1} ,{ "type",1} });
+                    if (volumesFind.IsNotEmpty())
+                    {
+                        throw new BizException("已存在!", ResponseCode.DATA_EXIST);
+                    }
+                    ///个人课纲
+                    string key = "dynamic" + request.TEAMModelId.Replace("#", "") + IdWorker.getInstance().NextId();
+                    request.id = key;
+                    request.volumeCode = key;
+                }
+                else if (request.type == 2)
+                {
+                    ///系统课纲
+                    string key = "system" + IdWorker.getInstance().NextId();
+                    request.scopeCode = "system";
+                    request.id = key;
+                    request.volumeCode = key;
+                }
+            }
+            else
+            {
+                if (request.type == 0)
+                {
+                    List<SyllabusVolume> volumesFind = await azureCosmosDBRepository.FindByDict<SyllabusVolume>(new Dictionary<string, object>() {
+                    { "schoolCode",request.scopeCode},{ "periodCode", request.periodCode},
+                        { "subjectCode", request.subjectCode},{ "gradeCode", request.gradeCode},
+                        { "semesterCode",request.semesterCode},{ "volumeName",request.volumeName}  ,
+                        { "status",1} ,{ "type",0} });
+                    if (volumesFind.IsNotEmpty())
+                    {
+                        if (!volumesFind[0].id.Equals(request.id))
+                        {
+                            throw new BizException("已存在!", ResponseCode.DATA_EXIST);
+                        }
+                    }
+                }
+                else if (request.type == 1)
+                {
+                    List<SyllabusVolume> volumesFind = await azureCosmosDBRepository.FindByDict<SyllabusVolume>(new Dictionary<string, object>() {
+                        { "schoolCode",request.scopeCode},{ "periodCode", request.periodCode},
+                        { "subjectCode", request.subjectCode},{ "gradeCode", request.gradeCode},
+                        { "semesterCode",request.semesterCode},{ "volumeName",request.volumeName},
+                        { "TEAMModelId",request.TEAMModelId}, { "status",1} ,{ "type",1} });
+                    if (volumesFind.IsNotEmpty())
+                    {
+                        if (!volumesFind[0].id.Equals(request.id))
+                        {
+                            throw new BizException("已存在!", ResponseCode.DATA_EXIST);
+                        }
+                    }
+
+                }
+                else if (request.type == 2)
+                {
+                }
+
+            }
+            List<SyllabusVolume> volumes = new List<SyllabusVolume>
+            {
+                request
+            };
+            List<SyllabusVolume> volume = await azureCosmosDBRepository.SaveOrUpdateAll<SyllabusVolume>(volumes);
+            return volume;
+        }
+    }
+}

+ 2 - 0
TEAMModelOS.Service/Services/Syllabus/Interface/IKnowledgeService.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Text;
 using System.Threading.Tasks;
 using TEAMModelOS.SDK.Context.Configuration;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
 using TEAMModelOS.Service.Models.Syllabus;
 
 namespace TEAMModelOS.Service.Services.Syllabus.Interface
@@ -11,5 +12,6 @@ namespace TEAMModelOS.Service.Services.Syllabus.Interface
     {
         public Task<List<Knowledge>> SaveOrUpdateKnowledge(List<Knowledge> request);
 
+        public Task<List<IdPk>> DeleteKnowledge(List<IdPk> listPid);
     }
 }

+ 34 - 0
TEAMModelOS.Service/Services/Syllabus/Interface/ISyllabusService.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Context.Configuration;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Models.Syllabus;
+
+namespace TEAMModelOS.Service.Services.Syllabus.Interface
+{
+    public interface ISyllabusService : IBusinessService
+    {
+
+        /// <summary>
+        /// 查找课纲 
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        public Task<List<SyllabusTree>> Find(Dictionary<string, object> request);
+
+        /// <summary>
+        /// 保存或者修改课纲
+        /// </summary>
+        /// <param name="syllabusNodes"></param>
+        /// <returns></returns>
+        public Task<List<Syllabuses>> SaveOrUpdateAsNodes(List<SyllabusNode> syllabusNodes);
+
+        public Task<List<SyllabusTree>> SaveOrUpdateAsTree(List<SyllabusTree> request);
+
+        public Task<List<Syllabuses>> DeleteSyllabus(Dictionary<string, object> request);
+
+
+    }
+}

+ 16 - 0
TEAMModelOS.Service/Services/Syllabus/Interface/IVolumeService.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Context.Configuration;
+using TEAMModelOS.Service.Models.Syllabus;
+
+namespace TEAMModelOS.Service.Services.Syllabus.Interface
+{
+    public interface IVolumeService : IBusinessService
+    {
+
+        public  Task<List<SyllabusVolume>> SaveOrUpdateVolume(SyllabusVolume request);
+
+    }
+}

+ 374 - 23
TEAMModelOS.Service/TEAMModelOS.Model.xml

@@ -4,9 +4,9 @@
         <name>TEAMModelOS.Service</name>
     </assembly>
     <members>
-        <member name="P:TEAMModelOS.Service.Models.Core.ClassroomStudent.Stu.seatNo">
+        <member name="P:TEAMModelOS.Service.Models.Core.ClassroomStudent.id">
             <summary>
-            座位
+            classroomCode
             </summary>
         </member>
         <member name="T:TEAMModelOS.Service.Models.Core.LoginInfo">
@@ -274,55 +274,159 @@
             考试成绩信息
             </summary>
         </member>
-        <member name="T:TEAMModelOS.Service.Models.Learn.LeanProcess">
+        <member name="T:TEAMModelOS.Service.Models.Learn.HomeWork">
             <summary>
-            编序学习
+            作业
             </summary>
         </member>
-        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.periodCode">
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.name">
             <summary>
-            学段code
+            作业名称
             </summary>
         </member>
-        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.Introduce">
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.target">
             <summary>
-            活动介绍
+            作业发布对象
             </summary>
         </member>
-        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.target">
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.publishModel">
             <summary>
-            学习对象
+            发布模式 0 立即发布 1 定时
             </summary>
         </member>
-        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.steps">
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.startTime">
             <summary>
-            步骤
+            开始时间
             </summary>
         </member>
-        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.isOrder">
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.endTime">
             <summary>
-            是否闯关模式 0 或 1 vue组件不支持true false
+            结束时间
             </summary>
         </member>
-        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.type">
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.description">
             <summary>
-            编序式模板,课前预习,随堂练习,课后作业
+            作业描述
             </summary>
         </member>
-        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.expire">
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.resource">
             <summary>
-            截至时间 时间戳
+            作业附件
             </summary>
         </member>
-        <member name="P:TEAMModelOS.Service.Models.Learn.ProcessStep.resource">
+        <member name="T:TEAMModelOS.Service.Models.Learn.HomeWork.Target">
             <summary>
-            资源内容
-            [{"name":"","url":"","order":""}]
+            发布对象
             </summary>
         </member>
-        <member name="P:TEAMModelOS.Service.Models.Learn.ProcessStep.item">
+        <member name="T:TEAMModelOS.Service.Models.Learn.HomeWork.ProcessRes">
             <summary>
-            题目
+            作业附件
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.ProcessRes.fileName">
+            <summary>
+            文件名字
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.ProcessRes.blobUrl">
+            <summary>
+            
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.ProcessRes.size">
+            <summary>
+            文件大小
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.ProcessRes.compressUrl">
+            <summary>
+            缩略图链接  图片视频有 文件没有
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWork.ProcessRes.type">
+            <summary>
+            文件类型
+            </summary>
+        </member>
+        <member name="T:TEAMModelOS.Service.Models.Learn.HomeWorkStudent">
+            <summary>
+            作业数据
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.name">
+            <summary>
+            姓名
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.TEAMModelId">
+            <summary>
+            醍摩豆id
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.classroomCode">
+            <summary>
+            上课班级
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.nativeroomCode">
+            <summary>
+            原生班级
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.studentId">
+            <summary>
+            学号
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.submissionBool">
+            <summary>
+            是否提交
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.submissionTime">
+            <summary>
+            提交时间
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.score">
+            <summary>
+            分数
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.content">
+            <summary>
+            作业内容
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkStudent.comments">
+            <summary>
+            作业评论
+            </summary>
+        </member>
+        <member name="T:TEAMModelOS.Service.Models.Learn.HomeWorkContent">
+            <summary>
+            作业内容
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkContent.answers">
+            <summary>
+            作答记录
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkContent.resource">
+            <summary>
+             其他模式url 及name
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.ProcessRes.fileName">
+            <summary>
+            文件名字
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.ProcessRes.blobUrl">
+            <summary>
+            
             </summary>
         </member>
         <member name="P:TEAMModelOS.Service.Models.Learn.ProcessRes.size">
@@ -340,6 +444,96 @@
             文件类型
             </summary>
         </member>
+        <member name="T:TEAMModelOS.Service.Models.Learn.HomeWorkComment">
+            <summary>
+            作业评论
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkComment.commentid">
+            <summary>
+            评论id
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkComment.fromId">
+            <summary>
+            评论者id 醍摩豆或studenId
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkComment.toId">
+            <summary>
+            被评论者id 醍摩豆或studenId
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkComment.identity">
+            <summary>
+            评论者身份 教师 学生
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkComment.comment">
+            <summary>
+            评语
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkComment.createTime">
+            <summary>
+            评论时间
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.HomeWorkComment.reply">
+            <summary>
+            评论回复
+            </summary>
+        </member>
+        <member name="T:TEAMModelOS.Service.Models.Learn.Reply">
+            <summary>
+            评论回复
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.Reply.fromId">
+            <summary>
+            评论者id 醍摩豆或studenId
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.Reply.toId">
+            <summary>
+            被评论者id 醍摩豆或studenId
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.Reply.identity">
+            <summary>
+            评论者身份 教师 学生
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.Reply.comment">
+            <summary>
+            评语
+            </summary>
+        </member>
+        <member name="T:TEAMModelOS.Service.Models.Learn.LeanProcess">
+            <summary>
+            编序学习
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.periodCode">
+            <summary>
+            学段code
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.Introduce">
+            <summary>
+            活动介绍
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.scopeCode">
+            <summary>
+            学习对象
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LeanProcess.steps">
+            <summary>
+            最小单元
+            </summary>
+        </member>
         <member name="T:TEAMModelOS.Service.Models.Learn.LeanRecord">
             <summary>
             作答记录
@@ -365,6 +559,97 @@
             作答时长
             </summary>
         </member>
+        <member name="T:TEAMModelOS.Service.Models.Learn.LearningAutonomous">
+            <summary>
+            自主学习
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.name">
+            <summary>
+            活动名称
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.subjectCode">
+            <summary>
+            学科code
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.periodCode">
+            <summary>
+            学段code
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.Introduce">
+            <summary>
+            活动介绍
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.target">
+            <summary>
+            学习对象
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.steps">
+            <summary>
+            步骤
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.isOrder">
+            <summary>
+            是否闯关模式 0 或 1 vue组件不支持true false
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.createTime">
+            <summary>
+            创建时间
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.creator">
+            <summary>
+            创建者
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.expire">
+            <summary>
+            截至时间 时间戳
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.ProcessStep.resource">
+            <summary>
+            资源内容
+            [{"name":"","url":"","order":""}]
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.ProcessStep.item">
+            <summary>
+            题目
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.ProcessRes.fileName">
+            <summary>
+            文件名字
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.ProcessRes.blobUrl">
+            <summary>
+            
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.ProcessRes.size">
+            <summary>
+            文件大小
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.ProcessRes.compressUrl">
+            <summary>
+            缩略图链接  图片视频有 文件没有
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Learn.LearningAutonomous.ProcessRes.type">
+            <summary>
+            文件类型
+            </summary>
+        </member>
         <member name="T:TEAMModelOS.Service.Models.Learn.LearnUnit">
             <summary>
             考试基础信息
@@ -662,6 +947,51 @@
             Type 如果为0 则是学校编码  如果为1 则是seminar 专题/研讨/培训
             </summary>
         </member>
+        <member name="P:TEAMModelOS.Service.Models.Syllabus.SyllabusVolume.periodCode">
+            <summary>
+            学段
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Syllabus.SyllabusVolume.subjectCode">
+            <summary>
+            学科
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Syllabus.SyllabusVolume.gradeCode">
+            <summary>
+            年级
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Syllabus.SyllabusVolume.semesterCode">
+            <summary>
+            学期code
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Syllabus.SyllabusVolume.status">
+            <summary>
+            状态
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Syllabus.SyllabusVolume.volumeName">
+            <summary>
+            册别name
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Syllabus.SyllabusVolume.volumeCode">
+            <summary>
+            册别code
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Syllabus.SyllabusVolume.TEAMModelId">
+            <summary>
+            创建者醍摩豆id
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Syllabus.SyllabusVolume.editors">
+            <summary>
+            共编使用者 的醍摩豆id
+            </summary>
+        </member>
         <member name="T:TEAMModelOS.Service.Model.Exam.Models.SimpleExam">
             <summary>
             考试成绩信息
@@ -2726,5 +3056,26 @@
             <param name="border"></param>
             <returns></returns>
         </member>
+        <member name="M:TEAMModelOS.Service.Services.Syllabus.Implement.SyllabusService.Find(System.Collections.Generic.Dictionary{System.String,System.Object})">
+            <summary>
+            查找课纲 
+            </summary>
+            <param name="request"></param>
+            <returns></returns>
+        </member>
+        <member name="M:TEAMModelOS.Service.Services.Syllabus.Interface.ISyllabusService.Find(System.Collections.Generic.Dictionary{System.String,System.Object})">
+            <summary>
+            查找课纲 
+            </summary>
+            <param name="request"></param>
+            <returns></returns>
+        </member>
+        <member name="M:TEAMModelOS.Service.Services.Syllabus.Interface.ISyllabusService.SaveOrUpdateAsNodes(System.Collections.Generic.List{TEAMModelOS.Service.Models.Syllabus.SyllabusNode})">
+            <summary>
+            保存或者修改课纲
+            </summary>
+            <param name="syllabusNodes"></param>
+            <returns></returns>
+        </member>
     </members>
 </doc>

+ 12 - 0
TEAMModelOS/ClientApp/src/api/learnActivity.js

@@ -77,6 +77,18 @@ export default {
     */
     FindOrderLearn: function (data) {
         return post('/api/Learn/FindLeanProcess', data)
+    },
+    /*
+    *查询作业活动
+    */
+    SaveorUpdataHomeWork: function (data) {
+        return post('/api/HomeWork/SaveorUpdataHomeWork', data)
+    },
+    /*
+    *新增或者编辑作业活动
+    */
+    FindHomeWork: function (data) {
+        return post('/api/HomeWork/FindHomeWork', data)
     }
 
 

+ 6 - 0
TEAMModelOS/ClientApp/src/common/CollapseMenuLayout.vue

@@ -202,6 +202,12 @@
                                 name: '投票活动',
                                 router: '/home/manageVote',
                                 tag:'×'
+                            },
+                            {
+                                icon: '',
+                                name: '活动仪表盘',
+                                router: '/home/activityReport',
+                                tag:'T'
                             }
                         ]
                     }

+ 34 - 11
TEAMModelOS/ClientApp/src/components/learnactivity/BaseHwForm.vue

@@ -45,14 +45,6 @@
                 </Upload>
             </FormItem>
 
-            <FormItem label="通知方式" prop="noticeMode">
-                <RadioGroup v-model="hwForm.noticeMode">
-                    <Radio label="1">电子纸条</Radio>
-                    <Radio label="2">Email(学生)</Radio>
-                    <Radio label="3">Email(家长)</Radio>
-                </RadioGroup>
-            </FormItem>
-
             <FormItem label="其他" prop="other">
                 <CheckboxGroup v-model="hwForm.other">
                     <Checkbox label="view">开放观摩</Checkbox>
@@ -72,6 +64,7 @@
     export default {
         data() {
             return {
+                userInfo:this.$store.state.userInfo,
                 descriptionEditor: null,
                 defaultConfig: {
                   uploadImgServer: '/api/file/uploadWangEditor', // 图片上传地址
@@ -87,9 +80,17 @@
                     publishModel:'0',
                     startTime:'',
                     description: '',
-                    noticeMode: '1',
                     other: []
                 },
+                defaultParams: {
+                    scopeCode: "",
+                    name: "",
+                    target: [],
+                    publishModel: "0",
+                    startTime: 0,
+                    endTime: 0,
+                    resource: []
+                },
                 uploadList:[],
                 ruleValidate: {
                     name: [
@@ -119,8 +120,19 @@
             handleSubmit(name) {
                 this.$refs[name].validate((valid) => {
                     if (valid) {
-                        console.log(Math.round(this.hwForm.endTime.getTime()))
                         console.log(this.hwForm)
+                        let params = Object.assign({}, this.defaultParams)
+                        params.scopeCode = this.userInfo.TEAMModelId
+                        params.name = this.hwForm.name
+                        params.publishModel = this.hwForm.publishModel
+                        params.startTime = this.hwForm.publishModel === '1' ? Math.round(this.hwForm.startTime.getTime()) : null
+                        params.endTime = Math.round(this.hwForm.endTime.getTime())
+                        params.description = this.hwForm.description
+                        params.resource = []
+                        params.target = []
+
+                        console.log(params)
+                        console.log(this.defaultParams)
                         this.$Message.success('操作成功')
                     } else {
                         this.$Message.error('请将信息填写完整')
@@ -145,9 +157,20 @@
                     });
                 }
                 return check;
+            },
+
+            /**
+             * 新增作业或者编辑作业
+             * @param data
+             */
+            saveorUpdataHw(data) {
+                this.$api.learnActivity.SaveorUpdataHomeWork(data).then(res => {
+                    console.log(res)
+                })
             }
         },
-        mounted () {
+        mounted() {
+
             this.uploadList = this.$refs.upload.fileList;
 
             let descriptionEditor = new E(this.$refs.descriptionEditor)

+ 53 - 0
TEAMModelOS/ClientApp/src/components/learnactivity/ContentFileList.less

@@ -0,0 +1,53 @@
+@main-bgColor: rgb(40,40,40); //主背景颜色
+@borderColor: #424242;
+@primary-textColor: #fff; //文本主颜色
+@second-textColor: #a5a5a5; //文本副级颜色
+@primary-fontSize: 14px;
+@second-fontSize: 16px;
+
+.content-file-wrap {
+    height: fit-content;
+    padding: 10px 0px 20px 0px;
+    color: white;
+}
+.content-file-item {
+    width: ~"calc(100% - 10px)";
+
+    .action-icon {
+        cursor: pointer;
+        margin-right: 8px;
+        font-size: 18px;
+        line-height: 22px;
+
+        &:hover {
+            color: aqua;
+        }
+    }
+
+    .content-file-name-wrap {
+        font-size: 15px;
+        width: ~"calc(100% - 80px)";
+    }
+
+    .content-file-item-action {
+        display: none;
+    }
+
+    &:hover {
+        border-bottom: 1px solid @borderColor;
+        background: #606060;
+        padding-left: 4px;
+        border-radius: 4px;
+    }
+
+    &:hover .content-file-item-action {
+        display: inline-block;
+        float: right;
+    }
+}
+
+.file-icon {
+    display: inline-block;
+    vertical-align: sub;
+    margin-right: 5px;
+}

+ 71 - 0
TEAMModelOS/ClientApp/src/components/learnactivity/ContentFileList.vue

@@ -0,0 +1,71 @@
+<template>
+    <div class="content-file-wrap">
+        <div v-for="(item,index) in resources" class="content-file-item" :key="index">
+            <div class="file-icon">
+                <img v-if="item.extension == 'ppt' || item.extension == 'pptx'" src="../../assets/icon/ppt50.png" width="15" />
+                <img v-else-if="item.extension == 'doc' || item.extension == 'docx'" src="../../assets/icon/word50.png" width="15" />
+                <img v-else-if="item.extension == 'xls' || item.extension == 'xlsx'" src="../../assets/icon/xls50.png" width="15" />
+                <img v-else-if="item.extension == 'pdf'" src="../../assets/icon/pdf50.png" width="15" />
+                <img v-else-if="item.type == 'picture'" src="../../assets/icon/icon_img.png" width="15" />
+                <img v-else-if="item.type == 'video'" src="../../assets/icon/icon_video.png" width="15" />
+                <img v-else src="../../assets/icon/prelearn50.png" width="15" />
+            </div>
+            <span>
+                {{item.fileName}}
+            </span>
+            <span class="content-file-item-action">
+                <Icon type="md-download" class="action-icon" title="下载" @click="downloadFile(item)" />
+                <Icon v-if="item.type == 'video' || item.type == 'picture' || item.extension == 'pdf'" type="md-eye" class="action-icon" title="预览" @click="clickToPreview(item)" />
+            </span>
+        </div>
+        <NoData style="margin-top:30px;" v-if="resources.length == 0"></NoData>
+        <Modal v-model="previewStatus" :title="previewFile.fileName" width="800px" class="dark-iview-modal">
+            <video v-if="previewFile.type == 'video'" id="previewVideo" :src="previewFile.blobUrl+sasString" width="780" controls="controls">
+                {{$t('teachContent.tips8')}}
+            </video>
+            <img v-if="previewFile.type == 'picture'" :src="previewFile.blobUrl+sasString" width="780" style="border-radius:5px;" />
+            <embed v-if="previewFile.type == 'document'" :src="previewFile.blobUrl+sasString" width="780" height="600" />
+            <div slot="footer"></div>
+        </Modal>
+    </div>
+</template>
+<script>
+    import NoData from '@/common/NoData.vue'
+    export default {
+        props: {
+            resources: {
+                type: Array,
+                default: () => {
+                    return []
+                }
+            }
+        },
+        components: {
+            NoData
+        },
+        data() {
+            return {
+                previewStatus: false,
+                previewFile: [],
+                sasString: '',
+            }
+        },
+        methods: {
+            downloadFile(item) {
+                window.location.href = item.blobUrl + this.sasString
+            },
+            clickToPreview(file) {
+                this.previewStatus = true
+                this.previewFile = file
+            }
+        },
+        watch: {
+            
+        }
+    }
+</script>
+<style scoped lang="less">
+    @import "./ContentFileList.less";
+</style>
+<style>
+</style>

+ 0 - 1
TEAMModelOS/ClientApp/src/components/learnactivity/QuestionList.vue

@@ -5,7 +5,6 @@
 
                 <span class="question-order">{{index+1+'.'}}</span>
                 <span class="question-text" v-html='item.question' ></span>
-                <!--<slot name="score"></slot>-->
                 <Icon v-if="config.showSelect" type="ios-cart" title="选题" class="choose-question-btn" size="25" @click.stop="selectQuestion(item)" :color="selectedId.indexOf(item.id) == -1 ? 'white':'aqua'"/>
                 <Icon type="ios-arrow-dropdown" :color="index == openIndex? 'cyan':'white'" size="25" @click.stop="toglleQuestionDetail(index)" :class="index == openIndex ? 'toggle-detail-icon toggle-detail-icon-up':'toggle-detail-icon toggle-detail-icon-down'" :title="openIndex == index ? '收起':'查看详情'" />
             </div>

+ 76 - 0
TEAMModelOS/ClientApp/src/components/learnactivity/SelectLearnUnit.less

@@ -0,0 +1,76 @@
+.unit-filter-wrap {
+    background: #666666;
+    margin-bottom: 10px;
+    border-radius: 5px;
+    color: red;
+}
+
+.unit-list-wrap {
+    width: 100%;
+    height: 400px;
+    overflow: hidden;
+
+    &:before {
+        content: '';
+    }
+
+    .unit-list-item {
+        position: relative;
+        background: #484848;
+        margin-bottom: 2px;
+        margin-top: 6px;
+        border-radius: 2px;
+        padding: 10px 10px;
+        width: ~"calc(100% - 8px)";
+        height: fit-content;
+
+        &:hover {
+            background: #525252;
+            margin-bottom: 10px;
+            margin-top: 0px;
+            box-shadow: 1px 4px 5px #191919;
+        }
+
+        &:hover .unit-detail-action-icon {
+            display: inline-block !important;
+        }
+
+        .unit-name {
+            font-size: 16px;
+        }
+
+        .devid-line {
+            margin: 0 15px;
+            color: #AAAAAA;
+        }
+
+        .unit-detail-info {
+            font-size: 12px;
+            margin-top: 15px;
+            color: #AAAAAA;
+
+            .unit-detail-count {
+                color: white;
+            }
+        }
+
+        .unit-detail-action {
+            position: absolute;
+            right: 10px;
+            top: 0px;
+            line-height: 80px;
+
+            .unit-detail-action-icon {
+                color: white;
+                cursor: pointer;
+                font-size: 18px;
+                margin-right: 15px;
+                display: none;
+            }
+
+            .unit-detail-action-icon:hover {
+                color: aqua;
+            }
+        }
+    }
+}

+ 195 - 0
TEAMModelOS/ClientApp/src/components/learnactivity/SelectLearnUnit.vue

@@ -0,0 +1,195 @@
+<template>
+    <div style="width:100%;height:100%;">
+        <div class="unit-filter-wrap dark-iview-input">
+            <Input search clearable placeholder="关键字搜索..." style="width: 100%" />
+        </div>
+        <div class="unit-list-wrap">
+            <vuescroll>
+                <div class="unit-list-item" v-for="(item,index) in unitList" @click="selectUnit(item)">
+                    <p class="unit-name">
+                        {{item.name}}
+                    </p>
+                    <div class="unit-detail-info">
+                        <span class="unit-datail-label">
+                            资源数量:
+                        </span>
+                        <span class="unit-detail-count">
+                            {{item.resource.length}}
+                        </span>
+                        <span class="devid-line">|</span>
+                        <span class="unit-datail-label">
+                            题目数量:
+                        </span>
+                        <span class="unit-detail-count">
+                            {{item.item.length}}
+                        </span>
+                    </div>
+                    <div class="unit-detail-action">
+                        <Icon class="unit-detail-action-icon" type="ios-folder-open" />
+                        <Icon class="unit-detail-action-icon" type="md-checkmark" :style="{color:selectedUnitId.indexOf(item.id) == -1 ? 'white':'aqua','display':selectedUnitId.indexOf(item.id) == -1 ? 'none':'inline-block'}" size="20" @click.stop="selectUnit(item)" />
+                    </div>
+                </div>
+            </vuescroll>
+        </div>
+    </div>
+</template>
+<script>
+    export default {
+        props: {
+            config: {
+                type: Object,
+                default: () => {
+                    return {
+                        type: 'check' //check:多选模式 radio:单选模式
+                    }
+                }
+            }
+        },
+        data() {
+            return {
+                currentUnitIndex: 0,
+                unitList: [],
+                selectedUnitId: [],
+                selectedUnitItem: [],
+            }
+        },
+        methods: {
+            /**
+             * 通过id查询题目信息
+             * */
+            findQuestionById() {
+                if (this.unitList.length > 0) {
+                    this.isLoading = true
+                    if (!this.unitList[this.currentUnitIndex].requestedI) {
+                        this.$api.learnActivity.FindQuestionById(this.unitList[this.currentUnitIndex].item).then(
+                            res => {
+                                if (res.error == null) {
+                                    this.unitList[this.currentUnitIndex].item.length = 0
+                                    this.$set(this.unitList[this.currentUnitIndex], 'item', res.result.data)
+                                    this.unitList[this.currentUnitIndex].requestedI = true
+                                    console.log(this.unitList)
+                                } else {
+                                    this.$Message.error("API ERROR!")
+                                    setTimeout(() => {
+                                        this.isLoading = false
+                                    }, 500)
+                                }
+                            },
+                            err => {
+                                this.$Message.error("API ERROR!")
+                                setTimeout(() => {
+                                    this.isLoading = false
+                                }, 500)
+                            }
+                        )
+                    } else {
+                        setTimeout(() => {
+                            this.isLoading = false
+                        }, 200)
+                    }
+                }
+            },
+            /**
+             * 通过id查询内容信息
+             * */
+            findResourceById() {
+                if (this.unitList.length > 0) {
+                    this.isLoading = true
+                    if (!this.unitList[this.currentUnitIndex].requestedR) {
+
+                        this.$api.learnActivity.FindSyllabusResourceById(this.unitList[this.currentUnitIndex].resource).then(
+                            res => {
+                                if (res.error == null) {
+                                    this.unitList[this.currentUnitIndex].resource.length = 0
+                                    this.unitList[this.currentUnitIndex].resource = res.result.data
+                                    this.unitList[this.currentUnitIndex].requestedR = true
+                                } else {
+                                    this.$Message.error("API ERROR!")
+                                }
+                                setTimeout(() => {
+                                    this.isLoading = false
+                                }, 500)
+                            },
+                            err => {
+                                this.$Message.error("API ERROR!")
+                                setTimeout(() => {
+                                    this.isLoading = false
+                                }, 500)
+                            }
+                        )
+                    } else {
+                        setTimeout(() => {
+                            this.isLoading = false
+                        }, 200)
+                    }
+                }
+            },
+            /**
+             * 获取最小单元列表
+             * */
+            getUnit() {
+                //this.isLoading = true
+                let requestData = {
+                    scopeCode: this.$store.state.schoolBaseInfo.demoLoginInfo.TEAMModelId
+                }
+                this.$api.learnActivity.FindUnit(requestData).then(
+                    res => {
+                        if (res.error == null) {
+                            this.unitList = res.result.data
+                            if (this.unitList.length > 0) {
+                                this.findResourceById()
+                                this.findQuestionById()
+                            }
+                        } else {
+                            this.$Message.error('API ERROR!')
+                        }
+                    },
+                    err => {
+
+                    }
+                )
+            },
+            selectUnit(item) {
+                if (this.config.type == 'check') {
+                    let index = this.selectedUnitId.indexOf(item.id)
+                    if (index == -1) {
+                        this.selectedUnitId.push(item.id)
+                        this.selectedUnitItem.push(item)
+                    } else {
+                        this.selectedUnitId.splice(index, 1)
+                        this.selectedUnitItem.splice(index, 1)
+                    }
+                    
+                } else {
+                    if (this.selectedUnitId.length == 0) {
+                        this.selectedUnitId.push(item.id)
+                        this.selectedUnitItem.push(item)
+                    } else {
+                        let index = this.selectedUnitId.indexOf(item.id)
+                        if (index == -1) {
+                            this.selectedUnitId.length = 0
+                            this.selectedUnitItem.length = 0
+                            this.selectedUnitId.push(item.id)
+                            this.selectedUnitItem.push(item)
+                        } else {
+                            this.selectedUnitId.splice(index, 1)
+                            this.selectedUnitItem.splice(index, 1)
+                        }
+                    }
+                    
+                }
+                console.log(this.selectedUnitItem)
+                this.$emit('selectUnit', this.selectedUnitItem)
+            },
+        },
+        created() {
+            this.getUnit()
+        }
+    }
+</script>
+<style lang="less" scoped>
+@import "./SelectLearnUnit.less";
+</style>
+<style>
+
+</style>

+ 47 - 0
TEAMModelOS/ClientApp/src/css/custom-animate.less

@@ -0,0 +1,47 @@
+/*
+    块状选单active背景动画
+*/
+.block-bg{
+    position:relative;
+}
+.block-bg::before {
+    content: '';
+    z-index: 1;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    background-image: linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+    transform-origin: center right;
+    transform: scaleX(0);
+}
+
+.block-bg-active::before {
+    transform-origin: center left;
+    transform: scaleX(1);
+    transition: transform 0.3s ease-in-out;
+}
+
+/*
+    文字选单active line动画
+*/
+.line-bottom{
+    position:relative;
+}
+.line-bottom::before {
+    content: '';
+    position: absolute;
+    bottom: 0px;
+    width: 0px;
+    height: 2px;
+    background-color: white;
+}
+
+.line-bottom-active::before {
+    transition: width 0.3s ease;
+    width: 100%;
+}
+.line-bottom-active {
+    color: white !important;
+}

+ 3 - 0
TEAMModelOS/ClientApp/src/css/disabled-form.less

@@ -0,0 +1,3 @@
+.disabled-form{
+
+}

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

@@ -22,7 +22,7 @@ export default {
     addTeacher: '添加校外教师',
     searchHolder: 'ID或姓名搜索',
     courseTime: '课程时段设置',
-    courseClassroom: '授课教:',
+    courseClassroom: '授课教:',
     text: '至',
     courseTag: '平日课程',
     start: '开始',

+ 4 - 4
TEAMModelOS/ClientApp/src/router/routes.js

@@ -193,7 +193,7 @@ export const routes = [
             {
                 path: 'createLearnUnit',
                 name: 'createLearnUnit',
-                component: resolve => require(['@/view/selflearning/CreateLearnUnit.vue'], resolve)
+                component: resolve => require(['@/view/teachcontent/CreateLearnUnit.vue'], resolve)
             },
             {
                 path: 'createHomeWork',
@@ -203,7 +203,7 @@ export const routes = [
             {
                 path: 'createOrderLearn',
                 name: 'createOrderLearn',
-                component: resolve => require(['@/view/selflearning/CreateOrderLearn.vue'], resolve)
+                component: resolve => require(['@/view/teachcontent/CreateOrderLearn.vue'], resolve)
             },
             {
                 path: 'createSelfLearn',
@@ -218,12 +218,12 @@ export const routes = [
             {
                 path: 'manageUnit',
                 name: 'manageUnit',
-                component: resolve => require(['@/view/selflearning/ManageUnit.vue'], resolve)
+                component: resolve => require(['@/view/teachcontent/ManageUnit.vue'], resolve)
             },
             {
                 path: 'manageOrderLearn',
                 name: 'manageOrderLearn',
-                component: resolve => require(['@/view/selflearning/ManageOrderLearn.vue'], resolve)
+                component: resolve => require(['@/view/teachcontent/ManageOrderLearn.vue'], resolve)
             },
             {
                 path: 'manageSelfLearn',

+ 6 - 33
TEAMModelOS/ClientApp/src/store/index.js

@@ -34,39 +34,12 @@ export default new Vuex.Store({
   actions,
   getters,
   state: {
-    // 选择关注年级
-    selectgrade: [],
-    // 选择关注学期
-    selectterm: [],
-    // 选择某次考试
-    selectexam: {},
-    // 基础数据
-    basicsdata: {},
-    // 柱状图
-    zhuxhuang: {},
-    // 雷达图
-    leida: {},
-    // 饼图
-    pie: {},
-    // 折线图(大)
-    linechart: {},
-    // 考试类型选择
-    examtype: {},
-
-    // 文理科展现
-    wenli_show: true,
-
-    // 任教老师页面
-    // 选择数据对比
-    selectcontrast: [],
-    // 柱状图
-    barline: {},
-    // 大饼图
-    annulus: {},
-    // PR
-    accuracyPR: {},
-
-    periodList: []
+      userInfo: {
+          user: 'admin',
+          TEAMModelId: 'habook#0001',
+          school: '醍摩豆书院',
+          schoolCode: 'HBCN'
+      }
   },
   modules: {
     classMgmt,

+ 1 - 0
TEAMModelOS/ClientApp/src/view/Home.vue

@@ -153,4 +153,5 @@
     @import '../css/dark-iview-form.less';
     @import '../css/dark-iview-table.less';
     @import '../css/dark-iview-split.less';
+    @import '../css/custom-animate.less';
 </style>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/coursemgmt/CourseClassroom.vue

@@ -12,7 +12,7 @@
         </Poptip>
       </div>
       <div class="course-classroom-list-content">
-        <div v-if="courseInfo.classroom.length > 0" v-for="(item,index) in courseClassroomList" :key="index" @click="changeClassroom(index)" :class="currentClassroomIndex === index ? 'course-classroom-item course-classroom-item-active':'course-classroom-item'" >
+        <div v-if="courseInfo.classroom.length > 0" v-for="(item,index) in courseClassroomList" :key="index" @click="changeClassroom(index)" :class="currentClassroomIndex === index ? 'course-classroom-item block-bg block-bg-active':'course-classroom-item block-bg'" >
           <p class="classroom-code"><Icon :type="item.scope === 'school' ? 'ios-barcode-outline' : 'md-person'" color="white" size="18" style="margin-right:8px;" />{{item.classroomCode}}</p>
           <p class="classroom-name">{{item.classroomName}}</p>
           <p class="classroom-info ">

+ 4 - 4
TEAMModelOS/ClientApp/src/view/coursemgmt/CourseManage.vue

@@ -8,7 +8,7 @@
       </div>
       <div class="course-list-content">
         <span class="show-course-label">{{$t('courseManage.courseShow')}}<Icon type="ios-arrow-down" size="16" /></span>
-        <div v-if="$store.state.courseMgmt.courseList.length > 0" :class="index === $store.state.courseMgmt.currentCourseIndex ? 'course-list-item course-list-item-active':'course-list-item'" v-for="(item,index) in $store.state.courseMgmt.courseList" :key="index" @click="selectCourse(index)">
+        <div v-if="$store.state.courseMgmt.courseList.length > 0" :class="index === $store.state.courseMgmt.currentCourseIndex ? 'course-list-item block-bg block-bg-active':'course-list-item block-bg'" v-for="(item,index) in $store.state.courseMgmt.courseList" :key="index" @click="selectCourse(index)">
           <p class="course-code">
             <Icon :type="item.scope === 'school' ? 'ios-barcode-outline' : 'md-person'" color="#AAAAAA" />
             {{item.baseInfo.courseCode}}
@@ -30,9 +30,9 @@
     </div>
     <div class="course-detail">
       <div class="course-detail-header">
-        <span :class="currentSettingIndex === 0 ? 'setting-label setting-label-active':'setting-label'" @click="selectSetting(0)">{{$t('courseManage.baseSetting')}}</span>
-        <span :class="currentSettingIndex === 1 ? 'setting-label setting-label-active':'setting-label'" @click="selectSetting(1)">{{$t('courseManage.syllabusSetting')}}</span>
-        <span :class="currentSettingIndex === 2 ? 'setting-label setting-label-active':'setting-label'" @click="selectSetting(2)">{{$t('courseManage.classroomSetting')}}</span>
+        <span :class="currentSettingIndex === 0 ? 'setting-label line-bottom line-bottom-active':'setting-label line-bottom'" @click="selectSetting(0)">{{$t('courseManage.baseSetting')}}</span>
+        <span :class="currentSettingIndex === 1 ? 'setting-label line-bottom line-bottom-active':'setting-label line-bottom'" @click="selectSetting(1)">{{$t('courseManage.syllabusSetting')}}</span>
+        <span :class="currentSettingIndex === 2 ? 'setting-label line-bottom line-bottom-active':'setting-label line-bottom'" @click="selectSetting(2)">{{$t('courseManage.classroomSetting')}}</span>
       </div>
       <CourseBaseSetting ref="courseBaseSetting" v-if="currentSettingIndex === 0 && $store.state.courseMgmt.courseList.length > 0" :class="currentSettingIndex === 0 ? 'animated fadeIn':'animated fadeOut'"></CourseBaseSetting>
       <CourseSyllabus v-if="currentSettingIndex === 1 && $store.state.courseMgmt.courseList.length > 0" :class="currentSettingIndex === 1 ? 'animated fadeIn':'animated fadeOut'"></CourseSyllabus>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/coursemgmt/CourseSyllabus.vue

@@ -5,7 +5,7 @@
       <span :class="currentTabIndex == 1 ? 'tab-label tab-label-active':'tab-label'" @click="selectSyllabusTab(1)">{{$t('courseManage.syllabus.personalSyllabus')}}</span>
     </div>
     <div class="syllabus-filter-box">
-      <div>
+      <div class="dark-iview-select">
         <span>{{$t('courseManage.syllabus.period')}}</span>
         <Select v-model="filters.periodCode" filterable style="width:200px;" :placeholder="$t('courseManage.syllabus.placeHolder1')" :clearable="true" size="small">
           <Option v-for="(item,index) in $store.state.schoolBaseInfo.schoolBaseInfo.period" :value="item.periodCode" :key="index" @click.native="getCurrentGrade(index)">{{ item.periodName }}</Option>

+ 3 - 3
TEAMModelOS/ClientApp/src/view/learnactivity/ManageEvaluation.vue

@@ -7,7 +7,7 @@
             </div>
             <div class="evaluation-list-main">
                 <vuescroll>
-                    <div :class="index == avtiveEvaluationIndex ? 'evaluation-item evaluation-item-active':'evaluation-item'" v-for="(item,index) in evaluationList" @click="selectEvaluation(index)">
+                    <div :class="index == avtiveEvaluationIndex ? 'evaluation-item block-bg-active block-bg':'evaluation-item block-bg'" v-for="(item,index) in evaluationList" @click="selectEvaluation(index)">
                         <p class="evaluation-name">{{item.name}}</p>
                         <p class="evaluation-type">
                             <Icon type="ios-cube" color="#a5a5a5" style="margin-right:10px;" size="16" />
@@ -24,8 +24,8 @@
         </div>
         <div class="evaluation-detail-wrap">
             <div class="evaluation-detail-bar">
-                <span :class="currentBraIndex == 0 ? 'evalustion-bar-item evalustion-bar-item-active':'evalustion-bar-item'" @click="selectBar(0)">评测信息</span>
-                <span :class="currentBraIndex == 1 ? 'evalustion-bar-item evalustion-bar-item-active':'evalustion-bar-item'" @click="selectBar(1)">活动数据</span>
+                <span :class="currentBraIndex == 0 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(0)">评测信息</span>
+                <span :class="currentBraIndex == 1 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(1)">活动数据</span>
                 <span class="edit-evaluation" @click="editEvaluation"><Icon type="ios-create-outline" size="20" />编辑信息</span>
                 <span class="edit-evaluation"><Icon type="ios-send" size="20" />发布评测</span>
             </div>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/school-mgmt/ClassroomSetting/ClassroomSetting.vue

@@ -93,7 +93,7 @@
                     </p>
                     <div class="class-list">
                         <vuescroll>
-                            <div class="class-list-item" v-for="(item,index) in classroomListShow" @click="chooseClassroom(index)" :class="currentClassroomIndex == index ? 'active-item-bg':''">
+                            <div class="class-list-item" v-for="(item,index) in classroomListShow" @click="chooseClassroom(index)" :class="currentClassroomIndex == index ? 'block-bg block-bg-active':'block-bg'">
                                 <div class="class-list-item-left">
                                     <p class="class-name">{{item.classroomName}}</p>
                                     <p class="class-hiteach-code second-text-color">{{item.hiteach}}</p>

+ 2 - 11
TEAMModelOS/ClientApp/src/view/school-mgmt/SystemSetting/SystemSetting.less

@@ -115,10 +115,7 @@
             cursor: pointer;
 
             &:hover {
-                background-image: -webkit-linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);
-                background-image: -o-linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);
-                background-image: -moz-linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);
-                background-image: linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);
+                /*background-image: linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);*/
 
                 .period-btn-edit {
                     display: inline-block;
@@ -215,13 +212,7 @@
                 position: relative;
 
                 &:hover {
-                    background-image: -webkit-linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);
-                    background-image: -o-linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);
-                    background-image: -moz-linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);
-                    background-image: linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);
-                    /*.period-btn-edit {
-                        display: inline-block;
-                    }*/
+                    /*background-image: linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);*/
                     .term-item-tool {
                         display: inline-block;
                     }

+ 2 - 5
TEAMModelOS/ClientApp/src/view/school-mgmt/SystemSetting/SystemSetting.vue

@@ -47,7 +47,7 @@
           <span>{{$t('schoolBaseInfo.order')}}</span>
         </div>
         <div class="period-list">
-          <div class="period-item" v-for="(item,index) in schoolSetting.period" :key="index" @click="choosePeriod(index)" :class="index == currentSchoolSysIndex ? 'item-active-div':''">
+          <div class="period-item" v-for="(item,index) in schoolSetting.period" :key="index" @click="choosePeriod(index)" :class="index == currentSchoolSysIndex ? 'block-bg-active block-bg':'block-bg'">
             <p class="period-item-name">
               <EditableLabel ref="periodName" class="term-item-name" :content="item.periodName" @editComplete="handleEditPeriod($event,index)">
               </EditableLabel>
@@ -61,7 +61,6 @@
             <p class="period-item-num"><span></span>{{ $t('schoolBaseInfo.gradeNum') + item.grades.length}}</p>
             <p class="period-item-num"><span></span>{{ $t('schoolBaseInfo.periodNum') + item.subjects.length}}</p>
             <div class="period-item-tool">
-              <!--<Icon type="ios-copy" title="不知道" />-->
               <Icon type="md-trash" title="删除" @click.stop="delPeriod(index)" />
             </div>
           </div>
@@ -75,12 +74,11 @@
         <div class="col-body">
           <div class="no-data-text" v-if="!schoolSetting.period[currentSchoolSysIndex].semesters.length">{{$t('schoolBaseInfo.noSemester')}}</div>
           <div class="term-list" v-if="schoolSetting.period[currentSchoolSysIndex].semesters.length">
-            <div class="term-item editable" v-for="(item,index) in schoolSetting.period[currentSchoolSysIndex].semesters" :key="index" :class="index == currentSemesterIndex ? 'item-active-div':''" @click="chooseSemester(index)">
+            <div class="term-item editable" v-for="(item,index) in schoolSetting.period[currentSchoolSysIndex].semesters" :key="index" :class="index == currentSemesterIndex ? 'block-bg block-bg-active':'block-bg'" @click="chooseSemester(index)">
               <span class="term-item-name-line" :style="{backgroundColor: colorList[index]}"></span>
               <EditableLabel ref="semesterName" class="term-item-name" :content="item.semesterName" @editComplete="handleEditSemester($event,index)">
               </EditableLabel>
               <Icon type="md-create" class="edit-btn" :title="$t('schoolBaseInfo.editLabel')" @click="changeSemesterStatus(index)" />
-              <!--<p class="term-item-students-num">涉及学生数:0人</p>-->
               <div class="term-item-start">
                 <span>{{$t('schoolBaseInfo.startDate')}}</span>
                 <Select v-model="item.month" :placeholder="$t('schoolBaseInfo.monthHolder')">
@@ -108,7 +106,6 @@
                 </span>
                 <div>
                   <Icon class="first-arrow" size="22" type="ios-arrow-back" v-if="index + 1 == schoolSetting.period[currentSchoolSysIndex].semesters[currentSemesterIndex].month || index + 1 == endMonth" />
-                  <!--<Icon class="second-arrow" size="22" :class="index  < endMonth ? 'color-check':'color-uncheck'" type="ios-arrow-back" v-if="index + 1 == schoolSetting.period[currentSchoolSysIndex].semester[currentSemesterIndex].month || index + 1 == endMonth" />-->
                   <span v-if="auto">
                     <Icon class="second-arrow" size="22" :class="index  < endMonth ? 'color-check':'color-uncheck'" type="ios-arrow-back" v-if="index + 1 == schoolSetting.period[currentSchoolSysIndex].semesters[currentSemesterIndex].month || index + 1 == endMonth" />
                   </span>

+ 21 - 72
TEAMModelOS/ClientApp/src/view/selflearning/CreateSelfLearn.less

@@ -110,79 +110,28 @@
     margin-right:16px;
     color:white;
 }
-.unit-filter-wrap{
-    background:#666666;
-    margin-bottom:10px;
-    border-radius:5px;
-    color:red;
-}
-.unit-list-wrap {
-    width: 100%;
-    height: 400px;
-    overflow: hidden;
-
-    &:before {
-        content: '';
-    }
-
-    .unit-list-item {
-        position: relative;
-        background: #484848;
-        margin-bottom: 2px;
-        margin-top: 6px;
-        border-radius: 2px;
-        padding: 10px 10px;
-        width: ~"calc(100% - 8px)";
-        height: fit-content;
-
-        &:hover {
-            background: #525252;
-            margin-bottom: 10px;
-            margin-top: 0px;
-            box-shadow: 1px 4px 5px #191919;
-        }
-
-        &:hover .unit-detail-action-icon {
-            display: inline-block !important;
-        }
-
-        .unit-name {
-            font-size: 16px;
-        }
-
-        .devid-line {
-            margin: 0 15px;
-            color: #AAAAAA;
-        }
 
-        .unit-detail-info {
-            font-size: 12px;
-            margin-top: 15px;
-            color: #AAAAAA;
-
-            .unit-detail-count {
-                color: white;
-            }
-        }
-
-        .unit-detail-action {
-            position: absolute;
-            right: 10px;
-            top: 0px;
-            line-height: 80px;
-
-            .unit-detail-action-icon {
-                color: white;
-                cursor: pointer;
-                font-size: 18px;
-                margin-right: 15px;
-                display: none;
-            }
+.content-type-label {
+    color: white;
+    line-height: 13px;
+    margin: 10px 0px 5px 0px;
+    padding: 5px;
+    padding-left: 8px;
+    border-left: 2px solid white;
+    background: #333333;
+}
 
-            .unit-detail-action-icon:hover {
-                color: aqua;
-            }
-        }
+.content-file-wrap {
+    height: fit-content;
+    padding: 10px 0px 20px 0px;
+    color: white;
+    margin-bottom: 10px;
+}
 
-    }
+.content-question-wrap {
+    min-height: 200px;
+    padding: 10px 0px 20px 0px;
+}
+.content-file-item {
+    margin-bottom: 4px;
 }

+ 49 - 162
TEAMModelOS/ClientApp/src/view/selflearning/CreateSelfLearn.vue

@@ -85,9 +85,21 @@
                                 自学资源
                             </span>
                         </div>
-                        <div>
-
+                        <div style="height:calc(100% - 45px);" v-if="selfLearnInfo.steps.length !== 0">
+                            <vuescroll>
+                                <p class="content-type-label">内容:{{selfLearnInfo.steps[stepIndex].resource.length}}个</p>
+                                <div class="content-file-wrap">
+                                    <NoData style="margin-top:30px;" v-if="selfLearnInfo.steps[stepIndex].resource.length == 0"></NoData>
+                                    <p v-for="(item,index) in selfLearnInfo.steps[stepIndex].resource" class="content-file-item">{{item.fileName}}</p>
+                                </div>
+                                <p class="content-type-label">题目:{{selfLearnInfo.steps[stepIndex].item.length}}道</p>
+                                <div class="content-question-wrap">
+                                    <NoData v-if="selfLearnInfo.steps[stepIndex].item.length == 0" style="margin-top:30px;"></NoData>
+                                    <QuestionList v-else :questions="selfLearnInfo.steps[stepIndex].item"></QuestionList>
+                                </div>
+                            </vuescroll>
                         </div>
+                        <NoData style="margin-top:30px;" v-if="selfLearnInfo.steps.length == 0"></NoData>
                     </div>
                 </Split>
             </div>
@@ -97,37 +109,7 @@
                class="dark-iview-modal"
                width="960"
                @on-ok="confirmSelectUnit">
-            <div class="unit-filter-wrap dark-iview-input">
-                <Input search  clearable placeholder="关键字搜索..." style="width: 100%" />
-            </div>
-            <div class="unit-list-wrap">
-                <vuescroll>
-                    <div class="unit-list-item" v-for="(item,index) in unitList">
-                        <p class="unit-name">
-                            {{item.name}}
-                        </p>
-                        <div class="unit-detail-info">
-                            <span class="unit-datail-label">
-                                资源数量:
-                            </span>
-                            <span class="unit-detail-count">
-                                {{item.resource.length}}
-                            </span>
-                            <span class="devid-line">|</span>
-                            <span class="unit-datail-label">
-                                题目数量:
-                            </span>
-                            <span class="unit-detail-count">
-                                {{item.resource.length}}
-                            </span>
-                        </div>
-                        <div class="unit-detail-action">
-                            <Icon class="unit-detail-action-icon" type="ios-folder-open"/>
-                            <Icon class="unit-detail-action-icon" type="md-checkmark" :style="{color:selectedUnitId.indexOf(item.id) == -1 ? 'white':'aqua','display':selectedUnitId.indexOf(item.id) == -1 ? 'none':'inline-block'}" size="20" @click="selectUnit(item)"/>
-                        </div>
-                    </div>
-                </vuescroll>
-            </div>
+            <SelectLearnUnit></SelectLearnUnit>
         </Modal>
         <Modal v-model="selectOrderStatus"
                title="选择编序式教材"
@@ -153,7 +135,7 @@
                         </div>
                         <div class="unit-detail-action">
                             <Icon class="unit-detail-action-icon" type="ios-folder-open" />
-                            <Icon class="unit-detail-action-icon" type="md-checkmark" size="20" @click="selectOrder(item)" :style="{color:selectedOrderId.indexOf(item.id) == -1 ? 'white':'aqua','display':selectedOrderId.indexOf(item.id) == -1 ? 'none':'inline-block'}"/>
+                            <Icon class="unit-detail-action-icon" type="md-checkmark" size="20" @click="selectOrder(item)" :style="{color:selectedOrderId.indexOf(item.id) == -1 ? 'white':'aqua','display':selectedOrderId.indexOf(item.id) == -1 ? 'none':'inline-block'}" />
                         </div>
                         <div class="order-step-content">
 
@@ -184,16 +166,19 @@
 </template>
 <script>
     import ChooseContent from '@/components/learnactivity/ChooseContent.vue'
+    import QuestionList from '@/components/learnactivity/QuestionList.vue'
+    import SelectLearnUnit from '@/components/learnactivity/SelectLearnUnit.vue'
+    import NoData from '@/common/NoData.vue'
     export default {
         components: {
-            ChooseContent
+            ChooseContent,NoData,QuestionList,SelectLearnUnit
         },
         data() {
             return {
-                selectedUnitId:[],
-                selectedUnitItem:[],
-                selectedOrderId:[],
-                selectedOrderItem:[],
+                
+                
+                selectedOrderId: [],
+                selectedOrderItem: [],
                 editStepName: '',
                 stepIndex: 0,
                 demoLoginInfo: {
@@ -202,7 +187,7 @@
                     school: '醍摩豆书院',
                     schoolCode: 'HBCN'
                 },
-                newStepName:'',
+                newStepName: '',
                 ruleValidate: {
                     name: [
                         { required: true, message: '请完善活动名称', trigger: 'change' }
@@ -227,25 +212,25 @@
                 selectUnitStatus: false,
                 selectOrderStatus: false,
                 addCustomStatus: false,
-                split1:0.2,
+                split1: 0.2,
                 isLoading: false,
                 selfLearnInfo: {
                     name: '',
                     periodCode: '',
-                    subjectCode:'',
+                    subjectCode: '',
                     target: [],
                     isOrder: '',
-                    creator:'',
+                    creator: '',
                     introduce: '',
-                    endTime:'',
+                    endTime: '',
                     steps: []
                 },
                 addStepStatus: false,
                 classroomList: [],
-                unitList: [],
-                orderLearnList:[],
+                
+                orderLearnList: [],
                 isLoading: false,
-                currentUnitIndex:0,
+                
                 columns: [
                     {
                         title: '',
@@ -256,7 +241,7 @@
                         title: '',
                         slot: 'action',
                         width: 80,
-                        align:'right'
+                        align: 'right'
                     }
                 ],
             }
@@ -269,7 +254,7 @@
                     okText: '是',
                     cancelText: '否',
                     onOk: () => {
-                        this.selfLearnInfo.steps.splice(index,1)
+                        this.selfLearnInfo.steps.splice(index, 1)
                     }
                 })
             },
@@ -293,101 +278,9 @@
                     }
                 )
             },
-            /**
-             * 通过id查询题目信息
-             * */
-            findQuestionById() {
-                if (this.unitList.length > 0) {
-                    this.isLoading = true
-                    if (!this.unitList[this.currentUnitIndex].requestedI) {
-                        this.$api.learnActivity.FindQuestionById(this.unitList[this.currentUnitIndex].item).then(
-                            res => {
-                                if (res.error == null) {
-                                    this.unitList[this.currentUnitIndex].item.length = 0
-                                    this.$set(this.unitList[this.currentUnitIndex],'item',res.result.data)
-                                    this.unitList[this.currentUnitIndex].requestedI = true
-                                    console.log(this.unitList)
-                                } else {
-                                    this.$Message.error("API ERROR!")
-                                    setTimeout(() => {
-                                        this.isLoading = false
-                                    }, 500)
-                                }
-                            },
-                            err => {
-                                this.$Message.error("API ERROR!")
-                                setTimeout(() => {
-                                    this.isLoading = false
-                                },500)
-                            }
-                        )
-                    }else {
-                        setTimeout(() => {
-                            this.isLoading = false
-                        }, 200)
-                    }
-                }
-            },
-            /**
-             * 通过id查询内容信息
-             * */
-            findResourceById() {
-                if (this.unitList.length > 0) {
-                    this.isLoading = true
-                    if (!this.unitList[this.currentUnitIndex].requestedR) {
-
-                        this.$api.learnActivity.FindSyllabusResourceById(this.unitList[this.currentUnitIndex].resource).then(
-                            res => {
-                                if (res.error == null) {
-                                    this.unitList[this.currentUnitIndex].resource.length = 0
-                                    this.unitList[this.currentUnitIndex].resource = res.result.data
-                                    this.unitList[this.currentUnitIndex].requestedR = true
-                                } else {
-                                    this.$Message.error("API ERROR!")
-                                }
-                                setTimeout(() => {
-                                    this.isLoading = false
-                                }, 500)
-                            },
-                            err => {
-                                this.$Message.error("API ERROR!")
-                                setTimeout(() => {
-                                    this.isLoading = false
-                                }, 500)
-                            }
-                        )
-                    } else {
-                        setTimeout(() => {
-                            this.isLoading = false
-                        }, 200)
-                    }
-                }
-            },
-            /**
-             * 获取最小单元列表
-             * */
-            getUnit() {
-                //this.isLoading = true
-                let requestData = {
-                    scopeCode: this.$store.state.schoolBaseInfo.demoLoginInfo.TEAMModelId
-                }
-                this.$api.learnActivity.FindUnit(requestData).then(
-                    res => {
-                        if (res.error == null) {
-                            this.unitList = res.result.data
-                            if (this.unitList.length > 0) {
-                                this.findResourceById()
-                                this.findQuestionById()
-                            }
-                        } else {
-                            this.$Message.error('API ERROR!')
-                        }
-                    },
-                    err => {
-
-                    }
-                )
-            },
+            
+            
+            
             confirmEditStep() {
                 this.selfLearnInfo.steps[this.stepIndex].name = this.editStepName
             },
@@ -424,18 +317,7 @@
                 this.selectedUnitItem.length = 0
                 console.log(this.selfLearnInfo)
             },
-            selectUnit(item) {
-                let index = this.selectedUnitId.indexOf(item.id)
-                if (index == -1) {
-                    this.selectedUnitId.push(item.id)
-                    this.selectedUnitItem.push(item)
-                } else {
-                    this.selectedUnitId.splice(index, 1)
-                    this.selectedUnitItem.splice(index,1)
-                }
-                console.log(this.selectedUnitId)
-
-            },
+            
             selectOrder(item) {
                 let index = this.selectedOrderId.indexOf(item.id)
                 if (index == -1) {
@@ -443,7 +325,7 @@
                     this.selectedOrderItem.push(item)
                 } else {
                     this.selectedOrderId.splice(index, 1)
-                    this.selectedOrderItem.splice(index,1)
+                    this.selectedOrderItem.splice(index, 1)
                 }
                 console.log(this.selectedOrderId)
             },
@@ -452,13 +334,14 @@
                     this.selfLearnInfo.steps.push(...this.selectedOrderItem[i].steps)
                 }
                 this.selectedOrderItem.length = 0
+                console.log(this.selfLearnInfo)
             },
             confirmAddCustom() {
                 this.selfLearnInfo.steps.push(
                     {
                         name: this.newStepName,
                         resource: [],
-                        item:[]
+                        item: []
                     }
                 )
                 this.newStepName = ''
@@ -474,11 +357,11 @@
                 this.isLoading = true
                 setTimeout(() => {
                     this.isLoading = false
-                },2000)
+                }, 2000)
             }
         },
         created() {
-            this.getUnit()
+            
             this.findOrderLearn()
         }
     }
@@ -490,15 +373,19 @@
     .learn-step-header .ivu-tooltip-inner {
         background-color: rgba(70,76,91,1);
     }
+
     .base-info-form .ivu-form .ivu-form-item-label {
         color: #A5A5A5;
     }
+
     .learn-step-box .ivu-table-row-highlight {
         background-image: linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
     }
-    .learn-step-box .ivu-table-row-hover .edit-step-name-icon{
-        display:inline-block;
+
+    .learn-step-box .ivu-table-row-hover .edit-step-name-icon {
+        display: inline-block;
     }
+
     .learn-step-box .ivu-table-row-hover td {
         background: none !important;
     }

+ 63 - 0
TEAMModelOS/ClientApp/src/view/selflearning/LearnProgress.less

@@ -0,0 +1,63 @@
+@main-bgColor: rgb(40,40,40); //主背景颜色
+@borderColor: #424242;
+@primary-textColor: #fff; //文本主颜色
+@second-textColor: #a5a5a5; //文本副级颜色
+@primary-fontSize: 14px;
+@second-fontSize: 16px;
+
+.learn-progress-container {
+    width: 100%;
+    height: 100%;
+    .learn-progress-main{
+        width:100%;
+        height:~"calc(100% - 45px)";
+        padding-right:10px;
+    }
+}
+.learn-progress-filter {
+    width: 100%;
+    height: 45px;
+    line-height: 45px;
+    /*border-bottom:1px solid @borderColor;*/
+
+    .filter-label {
+        color: white;
+    }
+
+    .right-filter-wrap {
+        display: inline-block;
+        float: right;
+    }
+}
+.radio-box-wrap {
+    display: inline-block;
+    float: right;
+    margin-right: 55px;
+    margin-left: 30px;
+
+    .active-radio-box-item {
+        background: white;
+        color: black !important;
+    }
+
+    .radio-box-item {
+        color: white;
+
+        &:first-child {
+            border-top-left-radius: 5px;
+            border-bottom-left-radius: 5px;
+        }
+
+        &:last-child {
+            border-top-right-radius: 5px;
+            border-bottom-right-radius: 5px;
+            border-left: 0px;
+        }
+
+        line-height: 10px;
+        display: inline-block;
+        padding: 2px 10px;
+        border: 1px solid white;
+        cursor: pointer;
+    }
+}

+ 95 - 0
TEAMModelOS/ClientApp/src/view/selflearning/LearnProgress.vue

@@ -0,0 +1,95 @@
+<template>
+    <div class="learn-progress-container">
+        <div class="learn-progress-filter dark-iview-select">
+            <span class="filter-label">搜学生:</span>
+            <Select v-model="model11" filterable style="display:inline-block;width:200px;" size="small">
+                <Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option>
+            </Select>
+            <span  class="filter-label" style="margin-left:30px;">选班级:</span>
+            <Select v-model="model11" filterable style="display:inline-block;width:200px;" size="small">
+                <Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option>
+            </Select>
+            <div class="right-filter-wrap">
+                <div class="radio-box-wrap">
+                    <div :class="currentView == 0 ? 'radio-box-item active-radio-box-item':'radio-box-item'" @click="setCurrentView(0)">
+                        <Tooltip content="活动进度总览" placement="bottom" theme="light">
+                            <Icon type="md-list" size="15" />
+                        </Tooltip>
+                    </div>
+                    <div :class="currentView == 1 ? 'radio-box-item active-radio-box-item':'radio-box-item'" @click="setCurrentView(1)">
+                        <Tooltip content="学习自学概况" placement="bottom" theme="light">
+                            <Icon type="md-people" size="15" />
+                        </Tooltip>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="learn-progress-main dark-iview-table">
+            <Table :columns="columns" :data="data" :show-header="false">
+                <template slot-scope="{ row, index }" slot="progress">
+                    <Progress style="width:200px;" :percent="row.progress" :stroke-width="16" text-inside />
+                </template>
+                <template slot-scope="{ row, index }" slot="action">
+                    <Icon type="ios-people" size="22" style="cursor:pointer;"/>
+                </template>
+            </Table>
+        </div>
+    </div>
+</template>
+<script>
+    export default {
+        data() {
+            return {
+                currentView: 0,
+                columns: [
+                    {
+                        title: '学习阶段',
+                        key: 'name'
+                    },
+                    {
+                        title: '完成进度',
+                        slot: 'progress'
+                    },
+                    {
+                        title: '操作',
+                        slot: 'action',
+                        width:150
+                    }
+                ],
+                data: [
+                    {
+                        name: '一次函数基础',
+                        progress: 50,
+
+                    },
+                    {
+                        name: '一次函数基础',
+                        progress: 50,
+
+                    },
+                    {
+                        name: '一次函数基础',
+                        progress: 50,
+
+                    },
+                    {
+                        name: '一次函数基础',
+                        progress: 50,
+
+                    },
+                ]
+            }
+        },
+        methods: {
+            setCurrentView(index) {
+                this.currentView = index
+            }
+        }
+    }
+</script>
+<style scoped lang="less">
+@import "./LearnProgress.less";
+</style>
+<style>
+
+</style>

+ 34 - 5
TEAMModelOS/ClientApp/src/view/selflearning/ManageSelfLearn.less

@@ -10,11 +10,18 @@
     height: 100%;
     display: flex;
     flex-direction: row;
-    .self-learn-list-box{
-        width:350px;
+
+    .self-learn-list-box {
+        width: 350px;
+        height: 100%;
+        padding-left: 15px;
+        border-right: 1px solid @borderColor;
+    }
+
+    .self-learn-main {
+        width: ~"calc(100% - 350px)";
         height:100%;
         padding-left:15px;
-        border-right:1px solid @borderColor;
     }
 }
 .self-learn-list-box {
@@ -40,6 +47,8 @@
     padding: 10px 10px 10px 0px;
     border-bottom: 1px solid @borderColor;
     cursor: pointer;
+    position:relative;
+    
 
     .order-learn-name {
         color: white;
@@ -54,6 +63,26 @@
     }
 }
 
-.order-learn-item-active {
-    background-image: linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+.self-learn-main {
+    width: 100%;
+    height: 100%;
+    .self-learn-main-body{
+        width:100%;
+        height:~"calc(100% - 45px)";
+    } 
+    .self-learn-main-header {
+        height: 45px;
+        width: 100%;
+        line-height: 45px;
+        border-bottom: 1px solid @borderColor;
+
+        .main-header-tab {
+            color: @second-textColor;
+            margin-right: 35px;
+            cursor: pointer;
+            position: relative;
+            display: inline-block;
+            line-height: 25px;
+        }
+    }
 }

+ 17 - 3
TEAMModelOS/ClientApp/src/view/selflearning/ManageSelfLearn.vue

@@ -1,13 +1,12 @@
 <template>
     <div class="self-learn-container">
         <div class="self-learn-list-box">
-            
             <vuescroll>
                 <div class="list-box-header">
                     <span>自学活动列表</span>
                     <Icon type="md-add" class="to-create-icon" @click="goToCreate" />
                 </div>
-                <div :class="currentLearnIndex == index ? 'order-learn-item order-learn-item-active':'order-learn-item' " v-for="(item,index) in selfLearnList" @click="selectOrderLearn(index)">
+                <div :class="currentLearnIndex == index ? 'order-learn-item block-bg block-bg-active':'order-learn-item block-bg' " v-for="(item,index) in selfLearnList" @click="selectOrderLearn(index)">
                     <p class="order-learn-name">{{item.name}}</p>
                     <div class="order-learn-steps">
                         <span><Icon type="md-filing" style="margin-right:8px;" />闯关模式:</span>
@@ -21,16 +20,28 @@
                 <NoData v-if="selfLearnList.length == 0"></NoData>
             </vuescroll>
         </div>
+        <div class="self-learn-main">
+            <div class="self-learn-main-header">
+                <span :class="currentTabIndex == 0 ? 'main-header-tab line-bottom line-bottom-active':'main-header-tab line-bottom'" @click="selectTab(0)">基础信息</span>
+                <span :class="currentTabIndex == 1 ? 'main-header-tab line-bottom line-bottom-active':'main-header-tab line-bottom'" @click="selectTab(1)">学习进度</span>
+                <span :class="currentTabIndex == 2 ? 'main-header-tab line-bottom line-bottom-active':'main-header-tab line-bottom'" @click="selectTab(2)">学习数据</span>
+            </div>
+            <div class="self-learn-main-body">
+                <LearnProgress v-if="currentTabIndex == 1"></LearnProgress>
+            </div>
+        </div>
     </div>
 </template>
 <script>
     import NoData from '@/common/NoData.vue'
+    import LearnProgress from './LearnProgress.vue'
     export default {
         components: {
-            NoData
+            NoData,LearnProgress
         },
         data() {
             return {
+                currentTabIndex:0,
                 currentLearnIndex: 0,
                 selfLearnList: [
                     {
@@ -47,6 +58,9 @@
             }
         },
         methods: {
+            selectTab(index) {
+                this.currentTabIndex = index
+            },
             goToCreate() {
                 this.$router.push({
                     name: 'createSelfLearn'

+ 0 - 47
TEAMModelOS/ClientApp/src/view/selflearning/CreateLearnUnit.less

@@ -60,12 +60,6 @@
       margin-top: 15px;
     }
 
-    .content-file-wrap {
-      height: fit-content;
-      padding: 10px 0px 20px 0px;
-      color: white;
-    }
-
     .content-question-wrap {
       min-height: 200px;
       padding: 10px 0px 20px 0px;
@@ -140,48 +134,7 @@
 .file-content-wrap{
   padding-top:5px;
 }
-.content-file-item {
-    width: 100%;
-    display: flex;
-    flex-direction: row;
-    margin-bottom: 5px;
-
-    .action-icon {
-        cursor: pointer;
-        margin-right: 8px;
-        font-size: 18px;
-        line-height: 22px;
-
-        &:hover {
-            color: aqua;
-        }
-    }
-
-    .content-file-name-wrap {
-        font-size: 15px;
-        width: ~"calc(100% - 80px)";
-    }
 
-    .content-file-item-action {
-        display: none;
-    }
-
-    &:hover {
-        border-bottom: 1px solid @borderColor;
-        background: #606060;
-        padding-left: 4px;
-        border-radius: 4px;
-    }
-
-    &:hover .content-file-item-action {
-        display: inline-block;
-    }
-}
-.file-icon {
-    display: inline-block;
-    vertical-align: sub;
-    margin-right: 5px;
-}
 .btn-save {
     color: rgb(107, 223, 195);
     float: right;

+ 7 - 33
TEAMModelOS/ClientApp/src/view/selflearning/CreateLearnUnit.vue

@@ -19,28 +19,7 @@
                         <div style="height: calc(100% - 45px);">
                             <vuescroll>
                                 <p class="content-type-label">内容:{{learnUnit.resource.length}}个</p>
-                                <div class="content-file-wrap">
-                                    <NoData style="margin-top:30px;" v-if="learnUnit.resource.length == 0"></NoData>
-                                    <div class="content-file-item" v-for="(item,index) in learnUnit.resource">
-                                        <div class="content-file-name-wrap">
-                                            <div class="file-icon">
-                                                <img v-if="item.extension == 'ppt' || item.extension == 'pptx'" src="../../assets/icon/ppt50.png" width="15" />
-                                                <img v-else-if="item.extension == 'doc' || item.extension == 'docx'" src="../../assets/icon/word50.png" width="15" />
-                                                <img v-else-if="item.extension == 'xls' || item.extension == 'xlsx'" src="../../assets/icon/xls50.png" width="15" />
-                                                <img v-else-if="item.extension == 'pdf'" src="../../assets/icon/pdf50.png" width="15" />
-                                                <img v-else-if="item.type == 'picture'" src="../../assets/icon/icon_img.png" width="15" />
-                                                <img v-else-if="item.type == 'video'" src="../../assets/icon/icon_video.png" width="15" />
-                                                <img v-else src="../../assets/icon/prelearn50.png" width="15" />
-                                            </div>
-                                            <span>{{item.fileName}}</span>
-                                        </div>
-                                        <span class="content-file-item-action">
-                                            <Icon type="md-download" class="action-icon" title="下载" @click="downloadFile(item)"/>
-                                            <Icon v-if="item.type == 'video' || item.type == 'picture' || item.extension == 'pdf'" type="md-eye" class="action-icon" title="预览" @click="clickToPreview(item)" />
-                                            <!--<Icon type="md-close" class="action-icon" title="删除"/>-->
-                                        </span>
-                                    </div>
-                                </div>
+                                <ContentFileList :resources="learnUnit.resource"></ContentFileList>
                                 <p class="content-type-label">题目:{{learnUnit.item.length}}道</p>
                                 <div class="content-question-wrap">
                                     <NoData v-if="learnUnit.item.length == 0" style="margin-top:30px;"></NoData>
@@ -48,7 +27,6 @@
                                 </div>
                             </vuescroll>
                         </div>
-
                     </div>
                 </div>
             </Split>
@@ -60,14 +38,6 @@
                @on-ok="confirmToManage">
             <p>最小学习单元保存成功,是否跳转到管理页面查看?</p>
         </Modal>
-        <Modal v-model="previewStatus" :title="previewFile.fileName" width="800px" class="dark-iview-modal">
-            <video v-if="previewFile.type == 'video'" id="previewVideo" :src="previewFile.blobUrl+sasString" width="780" controls="controls">
-                {{$t('teachContent.tips8')}}
-            </video>
-            <img v-if="previewFile.type == 'picture'" :src="previewFile.blobUrl+sasString" width="780" style="border-radius:5px;" />
-            <embed v-if="previewFile.type == 'document'" :src="previewFile.blobUrl+sasString" width="780" height="600" />
-            <div slot="footer"></div>
-        </Modal>
     </div>
 </template>
 <script>
@@ -76,6 +46,7 @@
     import NoData from '@/common/NoData.vue'
     import QuestionList from '@/components/learnactivity/QuestionList.vue'
     import ChooseContent from '@/components/learnactivity/ChooseContent.vue'
+    import ContentFileList from '@/components/learnactivity/ContentFileList.vue'
     export default {
         data() {
             return {
@@ -103,7 +74,8 @@
             ChooseContent,
             NoData,
             EditableLabel,
-            QuestionList
+            QuestionList,
+            ContentFileList
         },
         methods: {
             /**
@@ -141,6 +113,7 @@
                         id: this.learnUnit.id,
                         name: this.learnUnit.name,
                         scopeCode: this.demoLoginInfo.TEAMModelId,
+                        creator: this.demoLoginInfo.TEAMModelId,
                         item: this.learnUnit.item.map(item => { return item.id }),
                         resource: this.learnUnit.resource.map(item => { return item.id })
                     }
@@ -170,7 +143,8 @@
             },
             getSelectFile(data) {
                 console.log(data)
-                this.learnUnit.resource.push(data.file)
+                //this.learnUnit.resource.push(data.file)
+                this.learnUnit.resource = data.files
             }
         },
         created() {

+ 35 - 4
TEAMModelOS/ClientApp/src/view/selflearning/CreateOrderLearn.less

@@ -159,8 +159,7 @@
 }
 
 .content-file-wrap {
-    height: fit-content;
-    padding: 10px 0px 20px 0px;
+    padding: 5px 0px 20px 0px;
     color: white;
     margin-bottom:10px;
 }
@@ -248,8 +247,19 @@
     border-left: 2px solid white;
     background: #333333;
 }
-.content-file-item{
-    margin-bottom:4px;
+.content-file-item {
+    margin-bottom: 4px;
+
+    &:hover {
+        border-bottom: 1px solid @borderColor;
+        background: #606060;
+        padding-left: 4px;
+        border-radius: 4px;
+    }
+
+    &:hover .content-file-item-action {
+        display: inline-block;
+    }
 }
 .btn-save {
     color: rgb(107, 223, 195);
@@ -257,4 +267,25 @@
     cursor: pointer;
     margin-top: 6px;
     margin-right: 40px;
+}
+
+.file-icon {
+    display: inline-block;
+    vertical-align: sub;
+    margin-right: 5px;
+}
+.action-icon {
+    cursor: pointer;
+    margin-right: 8px;
+    font-size: 18px;
+    line-height: 22px;
+
+    &:hover {
+        color: aqua;
+    }
+}
+.content-file-item-action {
+    display: none;
+    float:right;
+    margin-right:15px;
 }

+ 149 - 35
TEAMModelOS/ClientApp/src/view/selflearning/CreateOrderLearn.vue

@@ -26,12 +26,12 @@
                                 <Option v-for="(item,index) in $jsFn.getPeriod($store.state.schoolBaseInfo.schoolBaseInfo,orderLearnInfo.periodCode).subjects" :value="item.subjectCode" :key="index">{{ item.subjectName }}</Option>
                             </Select>
                         </FormItem>
-                        <FormItem label="学习对象" prop="target">
+                        <!--<FormItem label="学习对象" prop="target">
                             <Select v-model="orderLearnInfo.target">
                                 <Option v-for="(item,index) in classroomList" :value="item" :key="index">{{ item }}</Option>
                             </Select>
-                        </FormItem>
-                        <FormItem label="闯关模式" prop="isOrder">
+                        </FormItem>-->
+                        <!--<FormItem label="闯关模式" prop="isOrder">
                             <div slot="label" style="display:inline-block;">
                                 <span>闯关模式:</span>
                                 <Tooltip trigger="hover" content="是否必须通过阶段测试才能进入下一阶段学习" theme="light" placement="right" max-width="200">
@@ -42,9 +42,9 @@
                                 <Radio label="1">是</Radio>
                                 <Radio label="0" style="margin-left:30px;">否</Radio>
                             </RadioGroup>
-                        </FormItem>
+                        </FormItem>-->
                         <FormItem label="活动说明" prop="introduce">
-                            <Input v-model="orderLearnInfo.introduce" type="textarea" :rows="6"></Input>
+                            <Input v-model="orderLearnInfo.introduce" type="textarea" :rows="8"></Input>
                         </FormItem>
                     </Form>
                     <!--</vuescroll>-->
@@ -62,7 +62,7 @@
                                 <Icon class="add-learn-step-icon" type="md-add" size="20" />
                                 <div slot="content">
                                     <p class="add-step-type-label" @click="addStepStatus = true"><Icon type="ios-hand-outline" size="18" style="margin-right:5px;" />手动选择内容</p>
-                                    <p class="add-step-type-label"><Icon type="md-list" size="18" style="margin-right:5px;" @click="selectUnit" />选择最小单元</p>
+                                    <p class="add-step-type-label" @click="selectUnit"><Icon type="md-list" size="18" style="margin-right:5px;" />选择最小单元</p>
                                 </div>
                             </Tooltip>
 
@@ -83,12 +83,12 @@
                             学习资源
                             <div class="radio-box-wrap">
                                 <div :class="currentView == 0 ? 'radio-box-item active-radio-box-item':'radio-box-item'" @click="setCurrentView(0)">
-                                    <Tooltip content="查看学习资源" placement="bottom" theme="light">
+                                    <Tooltip content="查看学习资源" placement="bottom">
                                         <Icon type="md-list" size="15" />
                                     </Tooltip>
                                 </div>
                                 <div :class="currentView == 1 ? 'radio-box-item active-radio-box-item':'radio-box-item'" @click="setCurrentView(1)">
-                                    <Tooltip content="挑选学习资源" placement="bottom" theme="light">
+                                    <Tooltip content="挑选学习资源" placement="bottom">
                                         <Icon type="md-card" size="15" />
                                     </Tooltip>
                                 </div>
@@ -96,12 +96,7 @@
                         </div>
                         <!-- 选择学习资源 -->
                         <div v-if="orderLearnInfo.steps.length !== 0" :class="currentView == 1 ? 'animated faster fadeInLeft choose-learn-content-wrap':'animated fadeOutRight choose-learn-content-wrap'">
-                            <div class="create-learn-content">
-                                <span :class="currentCreateType == 0 ? 'active-span':''" @click="selectCreateType(0)">选择已建自学内容</span>
-                                <span :class="currentCreateType == 1 ? 'active-span':''" @click="selectCreateType(1)">临时创建自学内容</span>
-                            </div>
-                            <ChooseContent ref="chooseContent" v-show="currentCreateType == 1" :class="currentCreateType == 1 ? 'animated fadeIn':''" style="margin-top:10px;height:calc(100% - 50px);" @on-select-question="getSelectedQuestion" @on-cancel-file="cancelFile" @on-select-file="getSelectFile"></ChooseContent>
-                            <ManageUnit :type="0" v-show="currentCreateType == 0" :class="currentCreateType == 0 ? 'animated fadeIn':''" @chooseUnit="chooseUnit"></ManageUnit>
+                            <ChooseContent ref="chooseContent" style="margin-top:10px;height:calc(100% - 10px);" @on-select-question="getSelectedQuestion" @on-cancel-file="cancelFile" @on-select-file="getSelectFile"></ChooseContent>
                             <Poptip padding="0px 0px" offset="10" placement="top-end" width="300" trigger="hover" :class="shoppingCarClass">
                                 <Badge type="success" :count="getContentLength.total" show-zero :offset="[-3,-3]" style="margin-top:10px;cursor:pointer;" @mouseenter.native="changeActive($event)" @mouseleave.native="removeActive($event)">
                                     <img src="../../assets/shopping_car.svg" width="40" height="40" />
@@ -130,14 +125,15 @@
                         <div v-if="orderLearnInfo.steps.length !== 0" :class="currentView == 0 ? 'animated faster fadeInLeft preview-learn-content-wrap':'animated fadeOutRight preview-learn-content-wrap'">
                             <vuescroll>
                                 <p class="content-type-label">内容:{{orderLearnInfo.steps[stepIndex].resource.length}}个</p>
-                                <div class="content-file-wrap">
-                                    <NoData style="margin-top:30px;" v-if="orderLearnInfo.steps[stepIndex].resource.length == 0"></NoData>
-                                    <p v-for="(item,index) in orderLearnInfo.steps[stepIndex].resource" class="content-file-item">{{item.fileName}}</p>
+                                <div class="content-file-wrap" style="min-height:240px;">
+                                    <Loading v-show="listLoading"></Loading>
+                                    <ContentFileList v-show="!listLoading" :resources="orderLearnInfo.steps[stepIndex].resource"></ContentFileList>
                                 </div>
                                 <p class="content-type-label">题目:{{orderLearnInfo.steps[stepIndex].item.length}}道</p>
                                 <div class="content-question-wrap">
                                     <NoData v-if="orderLearnInfo.steps[stepIndex].item.length == 0" style="margin-top:30px;"></NoData>
-                                    <QuestionList v-else :questions="orderLearnInfo.steps[stepIndex].item"></QuestionList>
+                                    <Loading v-show="listLoading"></Loading>
+                                    <QuestionList v-show="!listLoading" :questions="orderLearnInfo.steps[stepIndex].item"></QuestionList>
                                 </div>
                             </vuescroll>
                         </div>
@@ -149,10 +145,18 @@
         <Modal v-model="addStepStatus"
                title="添加学习阶段"
                class="dark-iview-modal dark-iview-input"
+               width="660"
                @on-ok="confirmAddStep">
             <span>名称:</span>
             <Input v-model="newStepName" placeholder="请输入名称..." style="width: calc(100% - 50px);" />
         </Modal>
+        <Modal v-model="selectUnitStatus"
+               title="选择最小单元"
+               class="dark-iview-modal"
+               width="960"
+               @on-ok="confirmSelectUnit">
+            <SelectLearnUnit @selectUnit="getSelectedUnit"></SelectLearnUnit>
+        </Modal>
         <Modal v-model="editStepStatus"
                title="修改名称"
                class="dark-iview-modal dark-iview-input"
@@ -167,23 +171,32 @@
                @on-ok="confirmToManage">
             <p>编序式自主学习活动保存成功,是否跳转到管理页面查看?</p>
         </Modal>
+
     </div>
 </template>
 <script>
     import NoData from '@/common/NoData.vue'
     import QuestionList from '@/components/learnactivity/QuestionList.vue'
     import ChooseContent from '@/components/learnactivity/ChooseContent.vue'
-    import ManageUnit from "./ManageUnit.vue"
+    import SelectLearnUnit from '@/components/learnactivity/SelectLearnUnit.vue'
+    import ContentFileList from '@/components/learnactivity/ContentFileList.vue'
+    import Loading from '@/common/Loading.vue'
+    import { setTimeout } from 'core-js'
     export default {
         components: {
             NoData,
             QuestionList,
             ChooseContent,
-            ManageUnit
+            SelectLearnUnit,
+            ContentFileList,
+            Loading
         },
         data() {
             return {
+                selectedUnit: [],
+                selectUnitStatus: false,
                 isLoading: false,
+                listLoading: false,
                 goToManageStatus: false,
                 demoLoginInfo: {
                     user: 'admin',
@@ -211,19 +224,19 @@
                         title: '',
                         slot: 'action',
                         width: 50,
-                        align:'right'
+                        align: 'right'
                     }
                 ],
                 orderLearnInfo: {
                     name: '',
                     periodCode: '',
-                    subjectCode:'',
-                    target: [],
-                    isOrder: '',
-                    creator:'',
+                    subjectCode: '',
+                    creator: '',
                     introduce: '',
-                    type:'',
                     steps: []
+                    //target: [],
+                    //type: '',
+                    //isOrder: '',
                 },
                 ruleValidate: {
                     name: [
@@ -266,17 +279,87 @@
                         resourceL,
                         total: itemL + resourceL
                     }
-                    
+
                 }
             }
         },
         methods: {
+            /**
+             * 通过id查询题目信息
+             * */
+            findQuestionById() {
+                if (this.orderLearnInfo.steps.length > 0) {
+                    this.listLoading = true
+                    if (!this.orderLearnInfo.steps[this.stepIndex].requestedI) {
+                        this.$api.learnActivity.FindQuestionById(this.orderLearnInfo.steps[this.stepIndex].item).then(
+                            res => {
+                                if (res.error == null) {
+                                    this.orderLearnInfo.steps[this.stepIndex].item.length = 0
+                                    this.$set(this.orderLearnInfo.steps[this.stepIndex], 'item', res.result.data)
+                                    this.orderLearnInfo.steps[this.stepIndex].requestedI = true
+                                    console.log(this.orderLearnInfo)
+                                } else {
+                                    this.$Message.error("API ERROR!")
+                                }
+                                setTimeout(() => {
+                                    this.listLoading = false
+                                }, 500)
+                            },
+                            err => {
+                                this.$Message.error("API ERROR!")
+                                setTimeout(() => {
+                                    this.listLoading = false
+                                }, 1000)
+                            }
+                        )
+                    } else {
+                        setTimeout(() => {
+                            this.listLoading = false
+                        }, 300)
+                    }
+                }
+            },
+            /**
+             * 通过id查询内容信息
+             * */
+            findResourceById() {
+                if (this.orderLearnInfo.steps.length > 0) {
+                    this.listLoading = true
+                    if (!this.orderLearnInfo.steps[this.stepIndex].requestedR) {
+                        this.$api.learnActivity.FindSyllabusResourceById(this.orderLearnInfo.steps[this.stepIndex].resource).then(
+                            res => {
+                                if (res.error == null) {
+                                    this.orderLearnInfo.steps[this.stepIndex].resource.length = 0
+                                    this.orderLearnInfo.steps[this.stepIndex].resource = res.result.data
+                                    this.orderLearnInfo.steps[this.stepIndex].requestedR = true
+                                } else {
+                                    this.$Message.error("API ERROR!")
+                                }
+                                setTimeout(() => {
+                                    this.listLoading = false
+                                }, 500)
+                            },
+                            err => {
+                                this.$Message.error("API ERROR!")
+                                setTimeout(() => {
+                                    this.listLoading = false
+                                }, 500)
+                            }
+                        )
+                    } else {
+                        setTimeout(() => {
+                            this.listLoading = false
+                        }, 300)
+                    }
+                }
+            },
             /**
              * 确认修改学习阶段名称
              * @param index
              */
             confirmEditStep() {
                 this.orderLearnInfo.steps[this.stepIndex].name = this.editStepName
+                console.log(this.orderLearnInfo)
             },
             /**
              * 编辑学习阶段名称
@@ -295,7 +378,20 @@
                 this.currentView = 0
             },
             selectUnit() {
-
+                this.selectUnitStatus = true
+            },
+            /**
+             * 处理SelectLearnUnit组件选择事件
+             * @param data
+             */
+            getSelectedUnit(data) {
+                console.log(data)
+                this.selectedUnit = data
+            },
+            confirmSelectUnit() {
+                this.orderLearnInfo.steps.push(...this.selectedUnit)
+                this.selectedUnit.length = 0
+                console.log(this.orderLearnInfo)
             },
             changeActive(e) {
                 this.shoppingCarClass = 'question-shopping-car animated pulse'
@@ -311,7 +407,7 @@
                     {
                         name: this.newStepName,
                         resource: [],
-                        item:[]
+                        item: []
                     }
                 )
                 this.newStepName = ''
@@ -331,9 +427,18 @@
                     this.isLoading = true
                     this.orderLearnInfo.creator = this.demoLoginInfo.TEAMModelId
                     this.orderLearnInfo.scopeCode = this.demoLoginInfo.TEAMModelId
-                    this.orderLearnInfo.type = '1'//教学情境
-                    this.orderLearnInfo.target = ['三年级五班']//学习对象
-                    this.$api.learnActivity.SaveOrderLearn(this.orderLearnInfo).then(
+                    let str = JSON.stringify(this.orderLearnInfo)
+                    let requestData = JSON.parse(str)
+                    for (let i = 0; i < requestData.steps.length; i++) {
+                        if (requestData.steps[i].requestedI) {
+                            requestData.steps[i].item = requestData.steps[i].item.map(item => { return item.id })
+                        } 
+                        if (requestData.steps[i].requestedR) {
+                            requestData.steps[i].resource = requestData.steps[i].resource.map(item => { return item.id })
+                        }                        
+                    }
+                    
+                    this.$api.learnActivity.SaveOrderLearn(requestData).then(
                         res => {
                             if (res.error == null) {
                                 this.orderLearnInfo.id = res.result.data.id
@@ -385,6 +490,8 @@
             getCurrentItem(row, index) {
                 this.stepIndex = index
                 this.currentView = 0
+                this.findResourceById()
+                this.findQuestionById()
                 this.$refs.chooseContent.refreshData()
             },
             dragOrder(index1, index2) {
@@ -405,6 +512,13 @@
     @import "./CreateOrderLearn.less";
 </style>
 <style lang="less">
+    .content-file-wrap #loadingBox {
+        margin-top: 88px !important;
+    }
+    .base-info-label .ivu-tooltip-inner {
+        background-color: rgba(70,76,91,1);
+    }
+
     .base-info-form .ivu-input, .base-info-form .ivu-select-selection {
         background: none;
         color: white;
@@ -488,8 +602,8 @@
     .learn-step-wrap .ivu-table-row-highlight {
         background-image: linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
     }
-    .learn-step-wrap .ivu-table-row-hover .edit-step-name-icon{
-        display:inline-block;
+
+    .learn-step-wrap .ivu-table-row-hover .edit-step-name-icon {
+        display: inline-block;
     }
-    
 </style>

TEAMModelOS/ClientApp/src/view/selflearning/ManageOrderLearn.less → TEAMModelOS/ClientApp/src/view/teachcontent/ManageOrderLearn.less


TEAMModelOS/ClientApp/src/view/selflearning/ManageOrderLearn.vue → TEAMModelOS/ClientApp/src/view/teachcontent/ManageOrderLearn.vue


+ 8 - 43
TEAMModelOS/ClientApp/src/view/selflearning/ManageUnit.less

@@ -85,7 +85,7 @@
             .unit-content-label {
                 color: white;
                 line-height: 13px;
-                margin: 15px 0px;
+                margin-top: 15px;
                 padding: 5px;
                 padding-left: 8px;
                 border-left: 2px solid white;
@@ -99,47 +99,12 @@
         }
     }
 }
-.content-file-item {
-    width: 100%;
-    display: flex;
-    flex-direction: row;
-    margin-bottom: 5px;
-
-    .action-icon {
-        cursor: pointer;
-        margin-right: 8px;
-        font-size: 18px;
-        line-height: 22px;
-        color:white;
-        &:hover {
-            color: aqua;
-        }
-    }
-
-    .content-file-name-wrap {
-        font-size: 15px;
-        width: ~"calc(100% - 100px)";
-        color:white;
-    }
-
-    .content-file-item-action {
-        display: none;
-    }
-
-    &:hover {
-        border-bottom: 1px solid @borderColor;
-        background: #606060;
-        padding-left: 4px;
-        border-radius: 4px;
-    }
-
-    &:hover .content-file-item-action {
-        display: inline-block;
-    }
-}
 
-.file-icon {
-    display: inline-block;
-    vertical-align: text-top;
-    margin-right: 5px;
+.to-create-icon {
+    float: right;
+    margin-right: 20px;
+    margin-top: 12px;
+    cursor: pointer;
+    color: white;
+    font-size: 18px;
 }

+ 15 - 37
TEAMModelOS/ClientApp/src/view/selflearning/ManageUnit.vue

@@ -1,7 +1,12 @@
 <template>
     <div class="manage-unit-container">
         <div class="unit-list-wrap" :style="{'padding-left':type==1 ? '15px':'0px' }">
-            <p class="unit-list-label">最小单元列表</p>
+            <div class="unit-list-label">
+                <span>
+                    最小单元列表
+                </span>
+            <Icon type="md-add" class="to-create-icon" @click="goToCreate" />        
+            </div>
             <div :class="index == currentUnitIndex ? 'unit-list-item unit-list-item-active':'unit-list-item'" v-for="(item,index) in unitList" @click="selectUnit(index)">
                 <p class="unit-item-name">{{item.name}}</p>
                 <p class="unit-item-resource"><Icon type="ios-folder" style="margin-right:10px;" />资源数:{{item.resource.length}}</p>
@@ -20,37 +25,17 @@
                 <vuescroll>
                     <p class="unit-content-label">自学内容</p>
                     <div class="unit-content-detail">
-                        <NoData v-if="unitList[currentUnitIndex].length == 0" style="margin-top:120px;"></NoData>
                         <Loading v-show="isLoading"></Loading>
-                        <div v-show="!isLoading" :class="isLoading ? 'content-file-item':'content-file-item animated fadeIn'" v-for="(item,index) in unitList[currentUnitIndex].resource">
-                            <div class="content-file-name-wrap">
-                                <div class="file-icon">
-                                    <img v-if="item.extension == 'ppt' || item.extension == 'pptx'" src="../../assets/icon/ppt50.png" width="15" />
-                                    <img v-else-if="item.extension == 'doc' || item.extension == 'docx'" src="../../assets/icon/word50.png" width="15" />
-                                    <img v-else-if="item.extension == 'xls' || item.extension == 'xlsx'" src="../../assets/icon/xls50.png" width="15" />
-                                    <img v-else-if="item.extension == 'pdf'" src="../../assets/icon/pdf50.png" width="15" />
-                                    <img v-else-if="item.type == 'picture'" src="../../assets/icon/icon_img.png" width="15" />
-                                    <img v-else-if="item.type == 'video'" src="../../assets/icon/icon_video.png" width="15" />
-                                    <img v-else src="../../assets/icon/prelearn50.png" width="15" />
-                                </div>
-                                <span>{{item.fileName}}</span>
-                            </div>
-                            <span class="content-file-item-action">
-                                <Icon type="md-download" class="action-icon" title="下载" @click="downloadFile(item)" />
-                                <Icon v-if="item.type == 'video' || item.type == 'picture' || item.extension == 'pdf'" type="md-eye" class="action-icon" title="预览" @click="clickToPreview(item)" />
-                                <Icon type="md-close" class="action-icon" title="删除" />
-                            </span>
-                        </div>
+                        <ContentFileList v-show="!isLoading" :resources="unitList[currentUnitIndex].resource"></ContentFileList>
                     </div>
 
                     <p class="unit-content-label">检测题目</p>
                     <div class="unit-content-detail">
                         <NoData v-if="unitList[currentUnitIndex].length == 0" style="margin-top:120px;"></NoData>
                         <Loading v-show="isLoading"></Loading>
-                        <QuestionList v-show="!isLoading" :class="isLoading ? '':'animated fadeIn'" :questions="unitList[currentUnitIndex].item"></QuestionList>
+                        <QuestionList v-show="!isLoading" :class="isLoading ? '':'animated fadeIn'" :questions="unitList[currentUnitIndex].item" style="margin-top:12px;"></QuestionList>
 
                     </div>
-
                 </vuescroll>
             </div>
         </div>
@@ -59,20 +44,13 @@
                @on-ok="confirmEdit">
             <p>确认跳转到最小单元编辑页面?</p>
         </Modal>
-        <Modal v-model="previewStatus" :title="previewFile.fileName" width="800px" class="dark-iview-modal">
-            <video v-if="previewFile.type == 'video'" id="previewVideo" :src="previewFile.blobUrl+sasString" width="780" controls="controls">
-                {{$t('teachContent.tips8')}}
-            </video>
-            <img v-if="previewFile.type == 'picture'" :src="previewFile.blobUrl+sasString" width="780" style="border-radius:5px;" />
-            <embed v-if="previewFile.type == 'document'" :src="previewFile.blobUrl+sasString" width="780" height="600" />
-            <div slot="footer"></div>
-        </Modal>
     </div>
 </template>
 <script>
     import NoData from '@/common/NoData.vue'
     import Loading from '@/common/Loading.vue'
     import QuestionList from '@/components/learnactivity/QuestionList.vue'
+    import ContentFileList from '@/components/learnactivity/ContentFileList.vue'
     export default {
         props: {
             type: {
@@ -82,12 +60,11 @@
         components: {
             NoData,
             QuestionList,
-            Loading
+            Loading,
+            ContentFileList
         },
         data() {
             return {
-                previewStatus: false,
-                previewFile: {},
                 sasString:'',
                 editUnitStatus: false,
                 isLoading: false,
@@ -96,9 +73,10 @@
             }
         },
         methods: {
-            clickToPreview(file) {
-                this.previewStatus = true
-                this.previewFile = file
+            goToCreate() {
+                this.$router.push({
+                    name: 'createLearnUnit'
+                })
             },
             downloadFile(item) {
                 window.location.href = item.blobUrl + this.sasString

+ 275 - 0
TEAMModelOS/Controllers/Learn/HomeWorkController.cs

@@ -0,0 +1,275 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using OpenXmlPowerTools;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.Context.Exception;
+using TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest;
+using TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Models.Core;
+using TEAMModelOS.Service.Models.Courses;
+using TEAMModelOS.Service.Models.Learn;
+using static TEAMModelOS.Service.Models.Learn.HomeWork;
+
+namespace TEAMModelOS.Controllers.Learn
+{
+    [Route("api/[controller]")]
+    [ApiController]
+    public class HomeWorkController : ControllerBase
+    {
+        private readonly IAzureCosmosDBV3Repository _cosmos;
+
+        public HomeWorkController(IAzureCosmosDBV3Repository cosmos)
+        {
+            _cosmos = cosmos;
+        }
+
+
+        /// <summary>
+        /// 新增或修改 作业活动 同时创建关联关系表
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("SaveorUpdataHomeWork")]
+        public async Task<BaseJosnRPCResponse> SaveorUpdataHomeWork(JosnRPCRequest<HomeWork> request)
+        {
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+
+            if (request.@params.publishModel.Equals("0"))
+            {
+                request.@params.startTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
+
+            }
+            bool flg = false; 
+
+            if (string.IsNullOrEmpty(request.@params.id)) {
+
+                request.@params.id = Guid.NewGuid().ToString();
+
+                flg = true;
+            }
+
+
+            HomeWork homeWork = await _cosmos.SaveOrUpdate<HomeWork>(request.@params);
+
+            if (flg) {
+                //根据作业发布对象查找到每一个具体学生生成关联关系表 HomeWorkStudent
+                List<Target> targets = request.@params.target;
+                List<ClassroomStudent> Classrooms = new List<ClassroomStudent>();
+                List<HomeWorkStudent> homeWorkStudents = new List<HomeWorkStudent>();
+                foreach (Target target in targets)
+                {
+                    List<ClassroomStudent> classroom = await _cosmos.FindByDict<ClassroomStudent>(new Dictionary<string, object> { { "id", target.classroomCode }, { "scopeCode", target.scopeCode } });
+
+                    if (classroom.IsNotEmpty()) {
+                        foreach (string studentid in classroom[0].studentId)
+                        {
+                            HomeWorkStudent homeWorkStudent = new HomeWorkStudent();
+                            homeWorkStudent.id = Guid.NewGuid().ToString();
+                            homeWorkStudent.homeWorkId = request.@params.id;
+                            homeWorkStudent.studentId = studentid;
+                            homeWorkStudent.classroomCode = target.classroomCode;
+                            homeWorkStudents.Add(homeWorkStudent);
+                        }
+                    }
+                    
+                }
+                if (homeWorkStudents.IsNotEmpty())
+                {
+                    foreach (HomeWorkStudent homeWorkStudents1 in homeWorkStudents)
+                    {
+                        Student student = await _cosmos.FindById<Student>(homeWorkStudents1.studentId);//FindByDict<Student>(new Dictionary<string, object> { { "id", homeWorkStudents1.studentId } });
+                        if (student != null)
+                        {
+                            homeWorkStudents1.name = student.name;
+                            homeWorkStudents1.TEAMModelId = student.TEAMModelId;
+                            homeWorkStudents1.nativeroomCode = student.classroomCode;
+                        }
+                    }
+                    await _cosmos.SaveOrUpdateAll<HomeWorkStudent>(homeWorkStudents);
+                }
+
+
+
+            }
+           
+
+            return builder.Data(homeWork).build();
+        }
+
+
+        /// <summary>
+        /// 保存或修改学生作业关联表
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("SaveorUpdataWorkStudents")]
+        public async Task<BaseJosnRPCResponse> SaveorUpdataWorkStudents(JosnRPCRequest<List<HomeWorkStudent>> request) 
+        {
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+            await _cosmos.SaveOrUpdateAll<HomeWorkStudent>(request.@params);
+            return builder.Data(request.@params).build();
+        }
+
+        /// <summary>
+        /// 查询作业活动
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("FindHomeWork")]
+        public async Task<BaseJosnRPCResponse> FindHomeWork(JosnRPCRequest<Dictionary<string,object>> request) {
+
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+            List<HomeWork> data = new List<HomeWork>();
+            if (request.@params.IsNotEmpty())
+            {
+                data = await _cosmos.FindByDict<HomeWork>(request.@params);
+            }
+            else
+            {
+                throw new BizException("参数异常", ResponseCode.PARAMS_ERROR);
+                //builder.Error(false,ResponseCode.PARAMS_ERROR,"参数异常");
+            }
+            return builder.Data(data).Extend(new Dictionary<string, object> { { "count", data.Count } }).build();
+        }
+
+        /// <summary>
+        /// 查询作业学生关联
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("FindStudent")]
+        public async Task<BaseJosnRPCResponse> FindStudent(JosnRPCRequest<Dictionary<string, object>> request)
+        {
+
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+            List<HomeWorkStudent> data = new List<HomeWorkStudent>();
+            if (request.@params.IsNotEmpty())
+            {
+                data = await _cosmos.FindByDict<HomeWorkStudent>(request.@params);
+            }
+            else
+            {
+                throw new BizException("参数异常", ResponseCode.PARAMS_ERROR);
+                //builder.Error(false,ResponseCode.PARAMS_ERROR,"参数异常");
+            }
+            return builder.Data(data).Extend(new Dictionary<string, object> { { "count", data.Count } }).build();
+        }
+
+
+        /// <summary>
+        /// 查询教师教的课程的教室的详细信息
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("FindClassroom")]
+        public async Task<BaseJosnRPCResponse> FindClassroom(JosnRPCRequest<string> request) 
+        {
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+            List<Course> courses = await _cosmos.FindByDict<Course>(dict:new Dictionary<string, object> { { "assistTeacher[*]", request.@params },{ "scopeCode.|", request.@params } }, propertys: new List<string> { "classroom" });
+            //List<Course> courses2 = await _cosmos.FindByDict<Course>(dict:new Dictionary<string, object> { { "scopeCode", request.@params } }, propertys: new List<string> { "classroom" });
+            //List<Course> courses = new List<Course>();
+            //courses.AddRange(courses1);
+            //courses.AddRange(courses2);
+            if (courses.IsNotEmpty())
+            {
+
+                List<string> classroom = new List<string>();
+                foreach (Course course in courses)
+                {
+                    classroom.AddRange(course.classroom);
+                }
+                List<Classroom> classroom1 = await _cosmos.FindByDict<Classroom>(dict: new Dictionary<string, object> { { "classroomCode", classroom } }, propertys: new List<string> { "classroomCode", "classroomName", "headMaster", "periodCode", "gradeCode", "scopeCode", "id", "studentCount", "status" });
+
+                if (classroom1.IsNotEmpty())
+                {
+
+                    builder.Data(classroom1);
+                }
+            }
+            else {
+
+                throw new BizException("没有找到该老师协同课程", ResponseCode.NOT_FOUND);
+            }
+            
+           
+
+            return builder.build();
+        }
+
+
+
+        /// <summary>
+        /// 作业打分
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("Scoring")]
+        public async Task<BaseJosnRPCResponse> HomeWorkScoring(JosnRPCRequest<HomeWorkScoringDto> request) 
+        {
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+            List<HomeWorkStudent> homeWorkStudents = await _cosmos.FindByDict<HomeWorkStudent>(new Dictionary<string, object> { { "id", request.@params.id }, { "homeWorkId", request.@params.homeWorkId } });
+            HomeWorkStudent data = new HomeWorkStudent();
+            if (homeWorkStudents.IsNotEmpty()) {
+
+                homeWorkStudents[0].score = request.@params.score;
+                data = await _cosmos.Update(homeWorkStudents[0]);
+            }
+            return builder.Data(data).build() ;
+        }
+
+
+        /// <summary>
+        /// 作业评论
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("Comment")]
+        public async Task<BaseJosnRPCResponse> HomeWorkComment(JosnRPCRequest<HomeWorkCommentDto> request)
+        {
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+            List<HomeWorkStudent> homeWorkStudents = await _cosmos.FindByDict<HomeWorkStudent>(new Dictionary<string, object> { { "id", request.@params.id }, { "homeWorkId", request.@params.homeWorkId } });
+            HomeWorkStudent data = new HomeWorkStudent();
+            if (homeWorkStudents.IsNotEmpty())
+            {
+                if (string.IsNullOrEmpty(request.@params.commentid))
+                {
+                    //评论
+                    HomeWorkComment comment = new HomeWorkComment();
+                    comment.commentid = Guid.NewGuid().ToString();
+                    comment.fromId = request.@params.fromId;
+                    comment.toId = request.@params.toId;
+                    comment.identity = request.@params.identity;
+                    comment.comment = request.@params.comment;
+                    comment.createTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
+                    homeWorkStudents[0].comments.Add(comment);
+                }
+                else 
+                {
+                    //回复评论
+                    foreach (HomeWorkComment comment in homeWorkStudents[0].comments ) {
+                        if (comment.commentid == request.@params.commentid) {
+                            Reply reply = new Reply();
+                            reply.fromId = request.@params.fromId;
+                            reply.toId = request.@params.toId;
+                            reply.identity = request.@params.identity;
+                            reply.comment = request.@params.comment;
+                            reply.createTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
+                            comment.reply.Add(reply);
+                        }
+                    }
+                }
+
+                //homeWorkStudents[0].comments[request.@params.TEAMModelId] = request.@params.comment;
+                data = await _cosmos.Update(homeWorkStudents[0]);
+            }
+            return builder.Data(data).build();
+        }
+
+    }
+}

+ 63 - 2
TEAMModelOS/Controllers/Learn/LearnController.cs

@@ -24,7 +24,7 @@ namespace TEAMModelOS.Controllers.Learn
         }
 
         /// <summary>
-        /// 保存考试信息
+        /// 保存最小单元
         /// </summary>
         /// <param name="request"></param>
         /// <returns></returns>
@@ -84,7 +84,6 @@ namespace TEAMModelOS.Controllers.Learn
                     if (string.IsNullOrEmpty(request.@params.id))
                     {
                         request.@params.id = Guid.NewGuid().ToString();
-                        request.@params.createTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
                     }
                 LeanProcess leanProcesses =  await cosmosDBV3Repository.SaveOrUpdate<LeanProcess>(request.@params);
                 builder.Data(leanProcesses);
@@ -183,5 +182,67 @@ namespace TEAMModelOS.Controllers.Learn
             }
             return builder.build();
         }
+
+
+        /// <summary>
+        /// 新增或修改自主学习
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("SaveorUpdataLearningAutonomous")]
+        public async Task<BaseJosnRPCResponse> SaveorUpdataLearningAutonomous(JosnRPCRequest<List<LearningAutonomous>> request)
+        {
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+            if (ValidateHelper.IsValid(request.@params))
+            {
+                request.@params.ForEach(x =>
+                {
+                    if (string.IsNullOrEmpty(x.id))
+                    {
+                        x.id = new Guid().ToString();
+                        x.createTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
+                    }
+                });
+                List<LearningAutonomous> learningAutonomous = await cosmosDBV3Repository.SaveOrUpdateAll<LearningAutonomous>(request.@params);
+                builder.Data(learningAutonomous);
+            }
+            return builder.build();
+        }
+
+
+
+        /// <summary>
+        /// 查询自主学习
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("FindLearningAutonomous")]
+        public async Task<BaseJosnRPCResponse> FindLearningAutonomous(JosnRPCRequest<Dictionary<string, object>> request)
+        {
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+            if (request.@params != null)
+            {
+                builder.Data(await cosmosDBV3Repository.FindByDict<LearningAutonomous>(request.@params));
+            }
+            return builder.build();
+        }
+
+
+        /// <summary>
+        /// 删除自主学习
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [HttpPost("DeleteLearningAutonomous")]
+        public async Task<BaseJosnRPCResponse> DeleteLearningAutonomous(JosnRPCRequest<IdPk> request)
+        {
+            JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
+            if (request.@params != null)
+            {
+                builder.Data(await cosmosDBV3Repository.DeleteAsync<LearningAutonomous>(request.@params));
+            }
+            return builder.build();
+        }
+
     }
 }

+ 1 - 0
TEAMModelOS/Controllers/Syllabus/KnowledgeController.cs

@@ -302,6 +302,7 @@ namespace TEAMModelOS.Controllers.Syllabus
                 if (Knowledge.type == 1) {
                     List<Knowledge> knowledges = await  _cosmos.FindSQL<Knowledge>("SELECT value(c) FROM c join a in c.points where Contains(a, '"+ Knowledge.id + "') = true ");
                     List<SyllabusResource> Resources = await _cosmos.FindSQL<SyllabusResource>("SELECT value(c) FROM c join a in c.points where Contains(a, '" + Knowledge.id + "') = true ");
+                    //select value(c) from c join A0  in c.points where 1=1  and A0 =  @points0
                     foreach (Knowledge knowledge in knowledges) knowledge.points.Remove(Knowledge.id);
                     foreach (SyllabusResource Resource in Resources) Resource.points.Remove(Knowledge.id);
                     await _cosmos.SaveOrUpdateAll(Resources);

+ 24 - 202
TEAMModelOS/Controllers/Syllabus/SyllabusController.cs

@@ -14,6 +14,7 @@ using System.Linq;
 using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
+using TEAMModelOS.Service.Services.Syllabus.Interface;
 
 namespace TEAMModelOS.Controllers.Syllabus
 {
@@ -22,7 +23,9 @@ namespace TEAMModelOS.Controllers.Syllabus
     //[Authorize]
     public class SyllabusController : BaseController
     {
-        private readonly IAzureCosmosDBV3Repository azureCosmosDBRepository;
+        private IAzureCosmosDBV3Repository azureCosmosDBRepository;
+        private ISyllabusService syllabusService;
+
         public SyllabusController(IAzureCosmosDBV3Repository _azureCosmosDBRepository)
         {
             azureCosmosDBRepository = _azureCosmosDBRepository;
@@ -36,35 +39,13 @@ namespace TEAMModelOS.Controllers.Syllabus
         public async Task<BaseJosnRPCResponse> SaveOrUpdateAsTree(JosnRPCRequest<List<SyllabusTree>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            List<SyllabusNode> nodes = new List<SyllabusNode>();
-            Syllabuses syllabus = new Syllabuses();
-           
-            TreeToList(request.@params, nodes);
-            // List<SyllabusNode> nods = nodes.ToJson().FromJson<List<SyllabusNode>>() ;
-            syllabus.children = nodes;
-            syllabus.id = request.@params[0].volumeCode;
-            syllabus.volumeCode = request.@params[0].volumeCode;
-            await azureCosmosDBRepository.SaveOrUpdate<Syllabuses>(syllabus);
-            List<SyllabusTree> treess = ListToTree(nodes);
+            List<SyllabusTree> treess = await syllabusService.SaveOrUpdateAsTree(request.@params);
             return builder.Data(treess).build();
         }
-        public static List<SyllabusNode> TreeToList(List<SyllabusTree> trees, List<SyllabusNode> nodes)
-        {
-            trees = trees.OrderBy(x => x.order).ToList();
-            nodes.AddRange(trees.ToJson().FromJson<List<SyllabusNode>>());
 
-            foreach (SyllabusTree tree in trees)
-            {
-                if (null != tree.children && tree.children.Count > 0)
-                {
-                    TreeToList(tree.children, nodes);
-                }
-            }
-            return nodes;
-        }
 
         /// <summary>
-        /// 批量保存或更新课纲
+        /// 按节点新增课纲
         /// </summary>
         /// <param name="request"></param>
         /// <returns></returns>
@@ -72,76 +53,11 @@ namespace TEAMModelOS.Controllers.Syllabus
         public async Task<BaseJosnRPCResponse> SaveOrUpdateAsNodes(JosnRPCRequest<List<SyllabusNode>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            List<SyllabusNode> syllabusNodes = request.@params;
-            List<Syllabuses> data = await azureCosmosDBRepository.FindByDict<Syllabuses>(new Dictionary<string, object> { { "id", syllabusNodes[0].volumeCode } });
-            List<SyllabusNode> syllabusNodes1 = new List<SyllabusNode>();
-            if (data.Count > 0) {
-
-                syllabusNodes1.AddRange(data[0].children); 
-                //replace
-                for (int i = 0; i < data[0].children.Count; i++)
-                {
-                    for (int j = 0; j < syllabusNodes.Count; j++)
-                    {
-                        if (data[0].children[i].id == syllabusNodes[j].id && data[0].children[i].volumeCode == syllabusNodes[j].volumeCode)
-                        {
-                            syllabusNodes1.Remove(data[0].children[i]);
-                            syllabusNodes1.Add(syllabusNodes[j]);
-                            syllabusNodes.Remove(syllabusNodes[j]);
-                        }
-                    }
-                }
-                data[0].children = syllabusNodes1;
-                
-                //新增
-                data[0].children.AddRange(syllabusNodes);
-
-
-                List<Syllabuses> syllabuses = await azureCosmosDBRepository.SaveOrUpdateAll<Syllabuses>(data);
-                if (syllabuses != null) return builder.Data(request.@params).build();
-                else  return builder.Data(syllabuses).build();
-            }
-            else
-            {
-                throw new BizException("保存失败", ResponseCode.FAILED); 
-                //return builder.Error(false, ResponseCode.FAILED, "保存失败").build();
-            }
-           
-        }
-
-        private static List<SyllabusTree> ListToTree(List<SyllabusNode> noes)
-        {
-            List<SyllabusTree> list = noes.ToJson().FromJson<List<SyllabusTree>>();
-            //var lookup = list.ToDictionary(n => n.RowKey, n => n);
-
-            var res = from r in list group r by r.id into g select g;
-            Dictionary<string, SyllabusTree> blockDict = new Dictionary<string, SyllabusTree>();
-            foreach (var s in res)
-            {
-                blockDict.TryAdd(s.First().id, s.First());
-            }
-            return GetChild(list, blockDict);
+            List<Syllabuses> syllabuses = await syllabusService.SaveOrUpdateAsNodes(request.@params);
+            if (syllabuses.IsNotEmpty()) return builder.Data(request.@params).build();
+            else return builder.Data(syllabuses).build();
         }
 
-        public static List<SyllabusTree> GetChild(List<SyllabusTree> list, Dictionary<string, SyllabusTree> dict)
-        {
-            //  list = list.OrderBy(m => m.Order).ToList();
-            List<SyllabusTree> trees = new List<SyllabusTree>();
-            foreach (SyllabusTree node in list)
-            {
-
-                bool flag = dict.TryGetValue(node.pid, out SyllabusTree syllabus);
-                if (flag && syllabus != null)
-                {
-                    syllabus.children.Add(node);
-                }
-                else
-                {
-                    trees.Add(node);
-                }
-            }
-            return trees;
-        }
         /// <summary>
         /// 删除课纲
         /// </summary>
@@ -151,79 +67,26 @@ namespace TEAMModelOS.Controllers.Syllabus
         public async Task<BaseJosnRPCResponse> Delete(JosnRPCRequest<Dictionary<string, object>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            Dictionary<string, object> dict = new Dictionary<string, object>();
-            foreach (KeyValuePair<string, object> keyValuePair in request.@params)
-            {
-                dict.Add("children[*]." + keyValuePair.Key, keyValuePair.Value);
-            }
+            List<Syllabuses> syllabuses = await syllabusService.DeleteSyllabus(request.@params);
 
-            List<Syllabuses> data = await azureCosmosDBRepository.FindByDict<Syllabuses>(dict);
-            Dictionary<string, Syllabuses> syllabuses = new Dictionary<string, Syllabuses>();
-
-            if (data.Count > 0)
+            if (syllabuses.IsNotEmpty())
             {
-                data.ForEach(x => syllabuses.TryAdd(x.id, x));
-                data = new List<Syllabuses>(syllabuses.Values);
-
-                //是否全删
-                bool flg = false;
-                foreach (Syllabuses item in data)
-                {
-                    List<SyllabusNode> nodedata = item.children;
-                    if (request.@params.TryGetValue("id", out object id))
-                    {
-                        foreach (SyllabusNode syllabus in nodedata)
-                        {
-                            if (syllabus.id == id.ToString())
-                            {
-                                List<SyllabusNode> nodes = new List<SyllabusNode>();
-                                nodes.Add(syllabus);
-                                await FindByPid(syllabus, nodes, nodedata);
-                                nodedata = nodes;
-                                break;
-                            }
-                        }
-                    }
-                    List<SyllabusNode> syllabusNodes = new List<SyllabusNode>();
-                    syllabusNodes.AddRange(item.children);
-                    for (int i = 0; i < item.children.Count; i++)
-                    {
-                        for (int j = 0; j < nodedata.Count; j++)
-                        {
-                            if (item.children[i].id == nodedata[j].id)
-                            {
-                                syllabusNodes.Remove(item.children[i]);
-                            }
-                        }
-                    }
-                    item.children = syllabusNodes;
-                    if (item.children.Count == 0)
-                    {
-                        await azureCosmosDBRepository.DeleteAsync<Syllabuses>(item.id, item.volumeCode);
-                        flg = true;
-                    }
-                }
-                if (flg)
-                {
-
-                    return builder.Data("全部删除成功").build();
-                }
-                else
-                {
-                    List<Syllabuses> data1 = await azureCosmosDBRepository.SaveOrUpdateAll<Syllabuses>(data);
-                    return builder.Data(data1).build();
-                }
+                return builder.Data(syllabuses).build();
             }
-            else
-            {
-                return builder.Data(null).build();
-                //throw new BizException("数据不存在", ResponseCode.DATA_EMPTY_NULL);
+            else { 
+                return builder.Data("全部删除成功").build();
+
             }
+            //else
+            //{
+            //    return builder.Data(null).build();
+            //    //throw new BizException("数据不存在", ResponseCode.DATA_EMPTY_NULL);
+            //}
 
             //return builder.Data(flag).Extend(new Dictionary<string, object>() { { "deleteData", nodes } }).build();
         }
 
-
+       
 
         public static async Task<List<SyllabusNode>> FindByPid(SyllabusNode data, List<SyllabusNode> nodes, List<SyllabusNode> nodedata)
         {
@@ -249,50 +112,9 @@ namespace TEAMModelOS.Controllers.Syllabus
         public async Task<BaseJosnRPCResponse> Find(JosnRPCRequest<Dictionary<string, object>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            Dictionary<string, object> dict = new Dictionary<string, object>();
-            foreach (KeyValuePair<string, object> keyValuePair in request.@params)
-            {
-                dict.Add("children[*]." + keyValuePair.Key, keyValuePair.Value);
-            }
-
-            List<Syllabuses> data = await azureCosmosDBRepository.FindByDict<Syllabuses>(dict);
-            if (data.IsNotEmpty())
-            {
-                Dictionary<string, Syllabuses> syllabuses = new Dictionary<string, Syllabuses>();
-                data.ForEach(x => syllabuses.TryAdd(x.id, x));
-                data = new List<Syllabuses>(syllabuses.Values);
-                List <SyllabusTree> treess = new List<SyllabusTree> ();
-                foreach (Syllabuses item in data)
-                {
-
-                    List<SyllabusNode> nodedata = item.children;
-                    if (request.@params.TryGetValue("id", out object id))
-                    {
-                        foreach (SyllabusNode syllabus in nodedata)
-                        {
-                            if (syllabus.id == id.ToString())
-                            {
-                                List<SyllabusNode> nodes = new List<SyllabusNode>();
-                                nodes.Add(syllabus);
-                                await FindByPid(syllabus, nodes, nodedata);
-                                nodedata = nodes;
-                                break;
-                            }
-                        }
-                    }
-                    List<SyllabusTree> treess1 = ListToTree(nodedata);
-                    treess.AddRange(treess1); 
-
-                    //treess.AddRange(treess1);
-                }
-
-                return builder.Data(treess).build();
-            }
-            else return builder.Data(data).build();
-            //throw new BizException("资源未找到", ResponseCode.NOT_FOUND);
-
-            //return builder.Error(false, ResponseCode.NOT_FOUND, "资源未找到").build();
-            //throw new BizException("sss");
+            List<SyllabusTree> treess = await syllabusService.Find(request.@params);
+            return builder.Data(treess).build();
         }
+
     }
 }

+ 13 - 91
TEAMModelOS/Controllers/Syllabus/VolumeController.cs

@@ -16,6 +16,7 @@ using TEAMModelOS.SDK.Module.AzureCosmosDB.Interfaces;
 using TEAMModelOS.Controllers;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.Service.Services.Syllabus.Interface;
 
 namespace TEAMModelOS.Controllers.Syllabus
 {
@@ -23,12 +24,16 @@ namespace TEAMModelOS.Controllers.Syllabus
     [ApiController]
     public class VolumeController : BaseController
     {
-        private readonly IAzureCosmosDBV3Repository azureCosmosDBRepository;
-        public VolumeController(IAzureCosmosDBV3Repository _azureCosmosDBRepository)
+        private IAzureCosmosDBV3Repository azureCosmosDBRepository;
+        private IVolumeService volumeService;
+
+        public VolumeController(IAzureCosmosDBV3Repository azureCosmosDBRepository, IVolumeService volumeService)
         {
-            azureCosmosDBRepository = _azureCosmosDBRepository;
+            this.azureCosmosDBRepository = azureCosmosDBRepository;
+            this.volumeService = volumeService;
         }
 
+
         /// <summary>
         /// 新增册别
         /// </summary>
@@ -38,96 +43,11 @@ namespace TEAMModelOS.Controllers.Syllabus
         public async Task<BaseJosnRPCResponse> SaveOrUpdate(JosnRPCRequest<SyllabusVolume> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            if (request.@params.editors != null && request.@params.editors.Length > 5)
-            {
-                throw new BizException("共编人数大于5人!");
-            }
-            if (string.IsNullOrEmpty(request.@params.id))
-            {
-                if (request.@params.type == 0)
-                {
-                    List<SyllabusVolume> volumesFind = await azureCosmosDBRepository.FindByDict<SyllabusVolume>(new Dictionary<string, object>() {
-                        { "scopeCode",request.@params.scopeCode},{ "periodCode", request.@params.periodCode},
-                        { "subjectCode", request.@params.subjectCode},{ "gradeCode", request.@params.gradeCode},
-                        { "semesterCode",request.@params.semesterCode},{ "volumeName",request.@params.volumeName}  ,
-                        { "status",1} ,{ "type",0} });
-                    if (volumesFind.IsNotEmpty())
-                    {
-                        throw new BizException("已存在!", ResponseCode.DATA_EXIST);
-                    }
-                    ///校本课纲
-                    string key = request.@params.scopeCode + IdWorker.getInstance().NextId();
-                    request.@params.id = key;
-                    request.@params.volumeCode = key;
-                }
-                else if (request.@params.type == 1)
-                {
-                    List<SyllabusVolume> volumesFind = await azureCosmosDBRepository.FindByDict<SyllabusVolume>(new Dictionary<string, object>() {
-                        { "schoolCode",request.@params.scopeCode},{ "periodCode", request.@params.periodCode},
-                        { "subjectCode", request.@params.subjectCode},{ "gradeCode", request.@params.gradeCode},
-                        { "semesterCode",request.@params.semesterCode},{ "volumeName",request.@params.volumeName},
-                        { "TEAMModelId",request.@params.TEAMModelId}, { "status",1} ,{ "type",1} });
-                    if (volumesFind.IsNotEmpty())
-                    {
-                        throw new BizException("已存在!", ResponseCode.DATA_EXIST);
-                    }
-                    ///个人课纲
-                    string key = "dynamic" + request.@params.TEAMModelId.Replace("#", "") + IdWorker.getInstance().NextId();
-                    request.@params.id = key;
-                    request.@params.volumeCode = key;
-                }
-                else if (request.@params.type == 2)
-                {
-                    ///系统课纲
-                    string key = "system" + IdWorker.getInstance().NextId();
-                    request.@params.scopeCode = "system";
-                    request.@params.id = key;
-                    request.@params.volumeCode = key;
-                }
-            }
-            else {
-                if (request.@params.type == 0)
-                {
-                    List<SyllabusVolume> volumesFind = await azureCosmosDBRepository.FindByDict<SyllabusVolume>(new Dictionary<string, object>() {
-                    { "schoolCode",request.@params.scopeCode},{ "periodCode", request.@params.periodCode},
-                        { "subjectCode", request.@params.subjectCode},{ "gradeCode", request.@params.gradeCode},
-                        { "semesterCode",request.@params.semesterCode},{ "volumeName",request.@params.volumeName}  ,
-                        { "status",1} ,{ "type",0} });
-                    if (volumesFind.IsNotEmpty())
-                    {
-                        if (!volumesFind[0].id.Equals(request.@params.id)) {
-                            throw new BizException("已存在!", ResponseCode.DATA_EXIST);
-                        }
-                    }
-                }
-                else if (request.@params.type == 1)
-                {
-                    List<SyllabusVolume> volumesFind = await azureCosmosDBRepository.FindByDict<SyllabusVolume>(new Dictionary<string, object>() {
-                        { "schoolCode",request.@params.scopeCode},{ "periodCode", request.@params.periodCode},
-                        { "subjectCode", request.@params.subjectCode},{ "gradeCode", request.@params.gradeCode},
-                        { "semesterCode",request.@params.semesterCode},{ "volumeName",request.@params.volumeName},
-                        { "TEAMModelId",request.@params.TEAMModelId}, { "status",1} ,{ "type",1} });
-                    if (volumesFind.IsNotEmpty())
-                    {
-                        if (!volumesFind[0].id.Equals(request.@params.id))
-                        {
-                            throw new BizException("已存在!", ResponseCode.DATA_EXIST);
-                        }
-                    }
-                   
-                }
-                else if (request.@params.type == 2)
-                {
-                }
-
-            }
-            List<SyllabusVolume> volumes = new List<SyllabusVolume>
-            {
-                request.@params
-            };
-            List<SyllabusVolume> volume = await azureCosmosDBRepository.SaveOrUpdateAll<SyllabusVolume>(volumes);
+            List<SyllabusVolume> volume = await volumeService.SaveOrUpdateVolume(request.@params);
             return builder.Data(volume.IsEmpty() ? null : volume[0]).build();
         }
+
+       
         /// <summary>
         /// 删除册别
         /// </summary>
@@ -159,6 +79,8 @@ namespace TEAMModelOS.Controllers.Syllabus
             }
             return builder.Data(flag).build();
         }
+
+
         /// <summary>
         /// 查找册别
         /// </summary>

+ 41 - 0
TEAMModelOS/Models/HomeWorkCommentDto.cs

@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.Models
+{
+    public class HomeWorkCommentDto
+    {
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string id { get; set; }
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string homeWorkId { get; set; }
+
+        /// <summary>
+        /// 评论id 不带是评论 带是评论的回复
+        /// </summary>
+        public string commentid { get; set; }
+
+        /// <summary>
+        /// 评论者id
+        /// </summary>
+        public string fromId { get; set; }
+        
+        /// <summary>
+        /// 被评论者id 醍摩豆或studenId
+        /// </summary>
+        public string toId { get; set; }
+
+        /// <summary>
+        /// 评论者身份 教师 学生
+        /// </summary>
+        public string identity { get; set; }
+
+        /// <summary>
+        /// 评语
+        /// </summary>
+        public string comment { get; set; }
+    }
+}

+ 20 - 0
TEAMModelOS/Models/HomeWorkScoringDto.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelOS.Service.Models.Learn;
+
+namespace TEAMModelOS.Models
+{
+    public class HomeWorkScoringDto
+    {
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string id { get; set; }
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string homeWorkId { get; set; }
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public double score { get; set; }
+
+    }
+}