Parcourir la source

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

liqk il y a 5 ans
Parent
commit
2ff5f861de
51 fichiers modifiés avec 11630 ajouts et 828 suppressions
  1. 1 1
      TEAMModelOS.SDK/Extension/JwtAuth/Models/JwtBlackRecord.cs
  2. 1 1
      TEAMModelOS.SDK/Extension/Language/LanguageExtension.cs
  3. 1 1
      TEAMModelOS.SDK/Extension/MessagePush/MessagePushExtension.cs
  4. 1 1
      TEAMModelOS.SDK/Extension/MessagePush/Model/SmsConfig.cs
  5. 2 2
      TEAMModelOS.SDK/Helper/Common/JsonHelper/JsonApiHelper.cs
  6. 1 1
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobClientSingleton.cs
  7. 1 1
      TEAMModelOS.SDK/Module/AzureBlob/Container/AzureBlobModel.cs
  8. 0 3
      TEAMModelOS.SDK/Module/AzureBlob/Implements/AzureBlobDBRepository.cs
  9. 62 19
      TEAMModelOS.SDK/Module/AzureCosmosDB/Implements/AzureCosmosDBRepository.cs
  10. 1 1
      TEAMModelOS.SDK/Module/AzureCosmosDB/Interfaces/IAzureCosmosDBRepository.cs
  11. 0 12
      TEAMModelOS.SDK/Module/AzureTable/Configuration/AzureTableConfig.cs
  12. 0 2
      TEAMModelOS.SDK/Module/AzureTable/Configuration/AzureTableOptions.cs
  13. 0 22
      TEAMModelOS.SDK/Module/AzureTable/Configuration/AzureTableServiceBuilder.cs
  14. 0 50
      TEAMModelOS.SDK/Module/AzureTable/Configuration/AzureTableServiceCollectionExtensions.cs
  15. 1 2
      TEAMModelOS.SDK/Module/AzureTable/Configuration/HaBookTableContinuationToken.cs
  16. 0 36
      TEAMModelOS.SDK/Module/AzureTable/Configuration/TableClientSingleton.cs
  17. 120 84
      TEAMModelOS.SDK/Module/AzureTable/Implements/AzureTableDBRepository.cs
  18. 1 1
      TEAMModelOS.SDK/Module/AzureTable/Interfaces/IAzureTableDBRepository.cs
  19. 5 2
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  20. 1 1
      TEAMModelOS.Service/Models/Core/LoginInfo.cs
  21. 1 1
      TEAMModelOS.Service/Models/Core/ResourceReference.cs
  22. 1 1
      TEAMModelOS.Service/Models/PowerPoint/Border.cs
  23. 1 1
      TEAMModelOS.Service/Models/Syllabus/KnowledgeBlock.cs
  24. 1 1
      TEAMModelOS.Service/Models/Syllabus/KnowledgeBlockPoint.cs
  25. 1 1
      TEAMModelOS.Service/Models/Syllabus/KnowledgePoint.cs
  26. 8 0
      TEAMModelOS.Service/Models/Syllabus/SyllabusNode.cs
  27. 7 0
      TEAMModelOS.Service/Models/Syllabus/SyllabusResource.cs
  28. 1 0
      TEAMModelOS.Service/Services/PowerPoint/Implement/PowerPointHelper.cs
  29. 1059 143
      TEAMModelOS.Service/Services/PowerPoint/Implement/ShapeGenerator.cs
  30. 222 173
      TEAMModelOS.Service/Services/PowerPoint/Implement/ShapeHelper.cs
  31. 8985 0
      TEAMModelOS.Service/Services/PowerPoint/Implement/ShapeSvg.cs
  32. 1 1
      TEAMModelOS/ClientApp/src/api/knowledge.js
  33. 6 0
      TEAMModelOS/ClientApp/src/api/syllabus.js
  34. 90 24
      TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue
  35. 5 0
      TEAMModelOS/ClientApp/src/router/routes.js
  36. 22 4
      TEAMModelOS/ClientApp/src/view/knowledge-point/index/Index.less
  37. 286 133
      TEAMModelOS/ClientApp/src/view/knowledge-point/index/index.vue
  38. 48 37
      TEAMModelOS/ClientApp/src/view/knowledge-point/index/operation/addBlock.vue
  39. 230 0
      TEAMModelOS/ClientApp/src/view/knowledge-point/index/operation/addPoint.vue
  40. 47 50
      TEAMModelOS/ClientApp/src/view/syllabus/newSyllabus/index.vue
  41. 336 0
      TEAMModelOS/ClientApp/src/view/syllabus/newSyllabus/operation/BaseKnowledge.vue
  42. 38 0
      TEAMModelOS/ClientApp/src/view/syllabus/newSyllabus/operation/BaseResource.vue
  43. 19 5
      TEAMModelOS/ClientApp/src/view/syllabus/newSyllabus/operation/addVolume.vue
  44. 2 1
      TEAMModelOS/ClientApp/vue.config.js
  45. 1 1
      TEAMModelOS/Controllers/Core/StudentController.cs
  46. 2 2
      TEAMModelOS/Controllers/Syllabus/KnowledgeController.cs
  47. 2 2
      TEAMModelOS/Controllers/Syllabus/ResourceController.cs
  48. 1 1
      TEAMModelOS/Controllers/Syllabus/SyllabusController.cs
  49. 1 1
      TEAMModelOS/Controllers/Syllabus/VolumeController.cs
  50. 1 0
      TEAMModelOS/Models/CommonQuery.cs
  51. 6 2
      TEAMModelOS/Startup.cs

+ 1 - 1
TEAMModelOS.SDK/Extension/JwtAuth/Models/JwtBlackRecord.cs

@@ -1,4 +1,4 @@
-using Microsoft.WindowsAzure.Storage.Table;
+using Microsoft.Azure.Cosmos.Table;
 using System;
 using System.Collections.Generic;
 using System.Text;

+ 1 - 1
TEAMModelOS.SDK/Extension/Language/LanguageExtension.cs

@@ -12,7 +12,7 @@ namespace TEAMModelOS.SDK.Extension.Language
         public static void AddLanguage(this IServiceCollection services, IConfigurationSection LangConfiguration)
         {
             services.Configure<List<SmsCountryCode>>(LangConfiguration);
-            services.AddSingleton<ILanguageService, LanguageService>();
+            services.AddScoped<ILanguageService, LanguageService>();
         }
     }
 }

+ 1 - 1
TEAMModelOS.SDK/Extension/MessagePush/MessagePushExtension.cs

@@ -14,7 +14,7 @@ namespace TEAMModelOS.SDK.Extension.MessagePush
         public static void SendCloud(this IServiceCollection services, IConfigurationSection configuration)
         {
             services.Configure<SmsSendCloud>(configuration);
-            services.AddSingleton<ISendCloudService, SendCloudService>();
+            services.AddScoped<ISendCloudService, SendCloudService>();
         }
     }
 }

+ 1 - 1
TEAMModelOS.SDK/Extension/MessagePush/Model/SmsConfig.cs

@@ -1,5 +1,5 @@
 
-using Microsoft.WindowsAzure.Storage.Table;
+using Microsoft.Azure.Cosmos.Table;
 
 namespace TEAMModelOS.SDK.Extension.MessagePush.Model
 {

+ 2 - 2
TEAMModelOS.SDK/Helper/Common/JsonHelper/JsonApiHelper.cs

@@ -16,12 +16,12 @@ namespace TEAMModelOS.SDK.Helper.Common.JsonHelper
             PropertyNameCaseInsensitive = true,                     //忽略大小写
             //PropertyNamingPolicy = JsonNamingPolicy.CamelCase     //命名方式是默认还是CamelCase
         };
-        public static string ToJson(this object input)
+        public static string ToApiJson(this object input)
         {
             return JsonSerializer.Serialize(input, options);
         }
 
-        public static T FromJson<T>(this string input)
+        public static T FromApiJson<T>(this string input)
         {
             return JsonSerializer.Deserialize<T>(input, options);
         }

+ 1 - 1
TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobClientSingleton.cs

@@ -1,4 +1,4 @@
-using Microsoft.WindowsAzure.Storage;
+
 using Microsoft.WindowsAzure.Storage.Blob;
 using System;
 

+ 1 - 1
TEAMModelOS.SDK/Module/AzureBlob/Container/AzureBlobModel.cs

@@ -1,6 +1,6 @@
 
 using Microsoft.AspNetCore.Http;
-using Microsoft.WindowsAzure.Storage.Table;
+using Microsoft.Azure.Cosmos.Table;
 using System;
 using System.ComponentModel.DataAnnotations;
 using System.IO;

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 3
TEAMModelOS.SDK/Module/AzureBlob/Implements/AzureBlobDBRepository.cs


+ 62 - 19
TEAMModelOS.SDK/Module/AzureCosmosDB/Implements/AzureCosmosDBRepository.cs

@@ -24,6 +24,10 @@ using System.Text;
 using TEAMModelOS.SDK.Helper.Common.ReflectorExtensions;
 using Microsoft.AspNetCore.Hosting;
 using System.Collections.Concurrent;
+using DataType = Microsoft.Azure.Documents.DataType;
+using RequestOptions = Microsoft.Azure.Documents.Client.RequestOptions;
+using PartitionKey = Microsoft.Azure.Documents.PartitionKey;
+using Newtonsoft.Json.Linq;
 
 namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Implements
 { /// <summary>
@@ -61,12 +65,12 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Implements
                 }
                 Database = options.Database;
                 CollectionThroughput = options.CollectionThroughput;
-                CosmosClient.CreateDatabaseIfNotExistsAsync(new Database { Id = Database });
+                CosmosClient.CreateDatabaseIfNotExistsAsync(new Microsoft.Azure.Documents.Database { Id = Database });
                 // _connectionString = options.ConnectionString;
-               // CosmosSerializer
+                // CosmosSerializer
 
                 //获取数据库所有的表
-                FeedResponse<DocumentCollection> collections = CosmosClient.ReadDocumentCollectionFeedAsync(UriFactory.CreateDatabaseUri(Database)).GetAwaiter().GetResult();
+                Microsoft.Azure.Documents.Client.FeedResponse<DocumentCollection> collections = CosmosClient.ReadDocumentCollectionFeedAsync(UriFactory.CreateDatabaseUri(Database)).GetAwaiter().GetResult();
                 foreach (IGrouping<string, DocumentCollection> group in collections.GroupBy(c => c.Id))
                 {
                     DocumentCollectionDict.TryAdd(group.Key, group.First());
@@ -109,7 +113,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Implements
                     else
                     {
                         DocumentCollection collectionDefinition = new DocumentCollection { Id = CollectionName };
-                        collectionDefinition.IndexingPolicy = new IndexingPolicy(new RangeIndex(DataType.String) { Precision = -1 });
+                        collectionDefinition.IndexingPolicy = new Microsoft.Azure.Documents.IndexingPolicy(new RangeIndex(DataType.String) { Precision = -1 });
 
                         // collectionDefinition.PartitionKey = new PartitionKeyDefinition {  Paths = new System.Collections.ObjectModel.Collection<string>() };
                         if (!string.IsNullOrEmpty(PartitionKey))
@@ -122,7 +126,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Implements
                             CollectionThroughput = RU;
                         }
                         DocumentCollection DocumentCollection = CosmosClient.CreateDocumentCollectionIfNotExistsAsync(
-                            UriFactory.CreateDatabaseUri(Database), collectionDefinition, new RequestOptions { OfferThroughput = CollectionThroughput }).GetAwaiter().GetResult();
+                            UriFactory.CreateDatabaseUri(Database), collectionDefinition, new Microsoft.Azure.Documents.Client.RequestOptions { OfferThroughput = CollectionThroughput }).GetAwaiter().GetResult();
                         DocumentCollectionDict.TryAdd(CollectionName, DocumentCollection);
                     }
                 }
@@ -171,7 +175,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Implements
             else
             {
                 DocumentCollection documentCollection = new DocumentCollection { Id = CollectionName };
-                documentCollection.IndexingPolicy = new IndexingPolicy(new RangeIndex(DataType.String) { Precision = -1 });
+                documentCollection.IndexingPolicy = new Microsoft.Azure.Documents.IndexingPolicy(new RangeIndex(DataType.String) { Precision = -1 });
 
                 // collectionDefinition.PartitionKey = new PartitionKeyDefinition {  Paths = new System.Collections.ObjectModel.Collection<string>() };
                 if (!string.IsNullOrEmpty(PartitionKey))
@@ -640,7 +644,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Implements
             };
         }
 
-        public async Task<List<T>> FindByDict<T>(Dictionary<string, object> dict, bool IsPk)
+        public async Task<List<T>> FindByDict<T>(Dictionary<string, object> dict, bool IsPk=true)
         {
             Type t = typeof(T);
             // List<T> objs = new List<T>();
@@ -665,19 +669,58 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Implements
 
         private static string GenSql(object obj, string key)
         {
-            Type s = obj.GetType();
-            TypeCode typeCode = Type.GetTypeCode(s);
-            return typeCode switch
+
+            if (obj is JArray array)
             {
-                TypeCode.String => " and c." + key + "=" + "'" + obj.ToString() + "'",
-                TypeCode.Int32 => " and c." + key + "=" + int.Parse(obj.ToString()),
-                TypeCode.Double => " and c." + key + "=" + double.Parse(obj.ToString()),
-                //case TypeCode.Byte: return "and c." + key + "=" + (Byte)obj ;   
-                TypeCode.Boolean => " and c." + key + "=" + bool.Parse(obj.ToString()),
-                TypeCode.DateTime => " and c." + key + "=" + (DateTime)obj,
-                TypeCode.Int64 => " and c." + key + "=" + long.Parse(obj.ToString()),
-                _ => null,
-            };
+                StringBuilder sql = new StringBuilder(" and  c." + key + " in (");
+                foreach (JValue obja in array) {
+                    if (obja.Value is string a) {
+                        sql.Append("'" + a + "',");
+                    }
+                    if (obja.Value is int b)
+                    {
+                        sql.Append(b + ",");
+
+                    }
+                    if (obja.Value is double c)
+                    {
+                        sql.Append(c + ",");
+                    }
+                    if (obja.Value is bool d)
+                    {
+                        sql.Append(d + ",");
+
+                    }
+                    if (obja.Value is long e)
+                    {
+                        sql.Append(e + ",");
+                    }
+                    if (obja.Value is DateTime f)
+                    {
+                        sql.Append(f + ",");
+                    }
+                }
+                string sqls=  sql.ToString().Substring(0, sql.Length - 1);
+                sqls += ") ";
+                return sqls;
+            }
+            else {
+                Type s = obj.GetType();
+                TypeCode typeCode = Type.GetTypeCode(s);
+
+                return typeCode switch
+                {
+                    TypeCode.String => " and c." + key + "=" + "'" + obj.ToString() + "'",
+                    TypeCode.Int32 => " and c." + key + "=" + int.Parse(obj.ToString()),
+                    TypeCode.Double => " and c." + key + "=" + double.Parse(obj.ToString()),
+                    //case TypeCode.Byte: return "and c." + key + "=" + (Byte)obj ;   
+                    TypeCode.Boolean => " and c." + key + "=" + bool.Parse(obj.ToString()),
+                    TypeCode.DateTime => " and c." + key + "=" + (DateTime)obj,
+                    TypeCode.Int64 => " and c." + key + "=" + long.Parse(obj.ToString()),
+                    _ => null,
+                };
+            }
+            
         }
 
         public  IQueryable<dynamic> FindByDict(string CollectionName,  Dictionary<string, object> dict)

+ 1 - 1
TEAMModelOS.SDK/Module/AzureCosmosDB/Interfaces/IAzureCosmosDBRepository.cs

@@ -20,7 +20,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Interfaces
         Task<List<T>> FindSQL<T>(string sql, bool isPK);
         Task<List<T>> FindLinq<T>(Func<IQueryable<object>, object> singleOrDefault);
         Task<List<T>> FindByParams<T>(Dictionary<string, object> dict);
-        Task<List<T>> FindByDict<T>(Dictionary<string, object> dict, bool isPK);
+        Task<List<T>> FindByDict<T>(Dictionary<string, object> dict, bool isPK=true);
         Task<List<T>> SaveAll<T>(List<T> enyites);
         Task<List<T>> UpdateAll<T>(Dictionary<string, object> dict, Dictionary<string, object> updateFilters, List<string> deleteKeys = null);
         Task<List<T>> DeleteAll<T>(Dictionary<string, object> dict);

+ 0 - 12
TEAMModelOS.SDK/Module/AzureTable/Configuration/AzureTableConfig.cs

@@ -1,12 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Module.AzureTable.Configuration
-{
-    public class AzureTableConfig
-    {
-        public readonly static string AZURE_CHINA = "AzureChina";
-        public readonly static string AZURE_GLOBAL = "AzureGlobal";
-    }
-}

+ 0 - 2
TEAMModelOS.SDK/Module/AzureTable/Configuration/AzureTableOptions.cs

@@ -7,8 +7,6 @@ namespace TEAMModelOS.SDK.Module.AzureTable.Configuration
     public class AzureTableOptions
     {
         public string ConnectionString { get; set; } 
-        public string AzureTableDialect { get; set; } 
-        public string DialectKey { get; set; } 
         /// <summary>
         /// 
         /// </summary>

+ 0 - 22
TEAMModelOS.SDK/Module/AzureTable/Configuration/AzureTableServiceBuilder.cs

@@ -1,22 +0,0 @@
-using Microsoft.Extensions.DependencyInjection;
-using System;
-
-namespace TEAMModelOS.SDK.Module.AzureTable.Configuration
-{
-    public class AzureTableServiceBuilder : ServiceCollection
-    {
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="services"></param>
-        public AzureTableServiceBuilder(IServiceCollection services)
-        {
-            Services = services ?? throw new ArgumentNullException(nameof(services));
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        public IServiceCollection Services { get; }
-    }
-}

+ 0 - 50
TEAMModelOS.SDK/Module/AzureTable/Configuration/AzureTableServiceCollectionExtensions.cs

@@ -1,50 +0,0 @@
-using TEAMModelOS.SDK.Module.AzureTable.Implements;
-using TEAMModelOS.SDK.Module.AzureTable.Interfaces;
-using Microsoft.Extensions.DependencyInjection;
-using System;
-
-namespace TEAMModelOS.SDK.Module.AzureTable.Configuration
-{
-    public static class AzureTableServiceCollectionExtensions
-    {
-        public static AzureTableServiceBuilder Builder { get; set; }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="services"></param>
-        /// <returns></returns>
-        private static AzureTableServiceBuilder AddServerBuilder(this IServiceCollection services)
-        {
-            return new AzureTableServiceBuilder(services);
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="services"></param>
-        /// <returns></returns>
-        public static AzureTableServiceBuilder AddAzureTableStorage(this IServiceCollection services)
-        {
-            if (Builder == null)
-            {
-                Builder = services.AddServerBuilder();
-            }
-            services.AddSingleton<IAzureTableDBRepository, AzureTableDBRepository>();
-            return Builder;
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="builder"></param>
-        /// <param name="_connectionString"></param>
-        /// <returns></returns>
-        public static AzureTableServiceBuilder AddConnection(this AzureTableServiceBuilder builder, AzureTableOptions databaseOptions)
-        {
-            builder.Services.AddSingleton(databaseOptions);
-            return builder;
-        }
-        
-    }
-}

+ 1 - 2
TEAMModelOS.SDK/Module/AzureTable/Configuration/HaBookTableContinuationToken.cs

@@ -1,6 +1,5 @@
 
-using Microsoft.WindowsAzure.Storage;
-using Microsoft.WindowsAzure.Storage.Table;
+using Microsoft.Azure.Cosmos.Table;
 using System;
 using System.ComponentModel.DataAnnotations;
 using TEAMModelOS.SDK.Extension.DataResult.PageToken;

+ 0 - 36
TEAMModelOS.SDK/Module/AzureTable/Configuration/TableClientSingleton.cs

@@ -1,36 +0,0 @@
-using Microsoft.WindowsAzure.Storage;
-using Microsoft.WindowsAzure.Storage.Table;
-
-namespace TEAMModelOS.SDK.Module.AzureTable.Configuration
-{
-    public sealed class TableClientSingleton
-    {
-        private static string _connectionString;
-        private CloudTableClient TableClient;
-        private TableClientSingleton() { }
-        public CloudTableClient GetTableClient()
-        {
-            if (TableClient != null)
-            {
-                return TableClient;
-            }
-            else
-            {
-                getInstance(_connectionString);
-                return TableClient;
-            }
-        }
-        public static TableClientSingleton getInstance(string connectionString)
-        {
-            _connectionString = connectionString;
-            return SingletonInstance.instance;
-        }
-        private static class SingletonInstance
-        {
-            public static TableClientSingleton instance = new TableClientSingleton()
-            {
-                TableClient = CloudStorageAccount.Parse(_connectionString).CreateCloudTableClient()
-            };
-        }
-    }
-}

Fichier diff supprimé car celui-ci est trop grand
+ 120 - 84
TEAMModelOS.SDK/Module/AzureTable/Implements/AzureTableDBRepository.cs


+ 1 - 1
TEAMModelOS.SDK/Module/AzureTable/Interfaces/IAzureTableDBRepository.cs

@@ -1,8 +1,8 @@
 using TEAMModelOS.SDK.Module.AzureTable.Configuration;
 using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-using Microsoft.WindowsAzure.Storage.Table;
 using System.Collections.Generic;
 using System.Threading.Tasks;
+using Microsoft.Azure.Cosmos.Table;
 
 namespace TEAMModelOS.SDK.Module.AzureTable.Interfaces
 {

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

@@ -2,7 +2,10 @@
 
   <PropertyGroup>
     <TargetFramework>netcoreapp3.1</TargetFramework>
-    <Version>2.0.0</Version>
+    <Version>2.0.3</Version>
+    <AssemblyVersion>2.0.0.3</AssemblyVersion>
+    <FileVersion>2.0.0.3</FileVersion>
+    <PackageReleaseNotes>jsonapi</PackageReleaseNotes>
   </PropertyGroup>
 
   <ItemGroup>
@@ -25,6 +28,6 @@
     <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.6.0" />
     <PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
     <PackageReference Include="XC.Framework.Security.RSAUtil" Version="1.0.1" />
+    <PackageReference Include="Microsoft.Azure.Cosmos.Table" Version="2.0.0-preview" />
   </ItemGroup>
-
 </Project>

+ 1 - 1
TEAMModelOS.Service/Models/Core/LoginInfo.cs

@@ -1,4 +1,4 @@
-using Microsoft.WindowsAzure.Storage.Table;
+using Microsoft.Azure.Cosmos.Table;
 using TEAMModelOS.SDK.Context.Attributes.Azure;
 
 namespace TEAMModelOS.Service.Models.Core

+ 1 - 1
TEAMModelOS.Service/Models/Core/ResourceReference.cs

@@ -1,4 +1,4 @@
-using Microsoft.WindowsAzure.Storage.Table;
+using Microsoft.Azure.Cosmos.Table;
 using System;
 using System.Collections.Generic;
 using System.Text;

+ 1 - 1
TEAMModelOS.Service/Models/PowerPoint/Border.cs

@@ -7,7 +7,7 @@ namespace HiTeachCC.Model.PowerPoint
     public  class Border
     {
 
-        public int Width { get; set; }
+        public double Width { get; set; }
         public string Color { get; set; }
         public string Type { get; set; }
         /// <summary>

+ 1 - 1
TEAMModelOS.Service/Models/Syllabus/KnowledgeBlock.cs

@@ -1,4 +1,4 @@
-using Microsoft.WindowsAzure.Storage.Table;
+using Microsoft.Azure.Cosmos.Table;
 using System.ComponentModel.DataAnnotations;
 using TEAMModelOS.SDK.Context.Attributes.Azure;
 

+ 1 - 1
TEAMModelOS.Service/Models/Syllabus/KnowledgeBlockPoint.cs

@@ -1,4 +1,4 @@
-using Microsoft.WindowsAzure.Storage.Table;
+using Microsoft.Azure.Cosmos.Table;
 using System.ComponentModel.DataAnnotations;
 using TEAMModelOS.SDK.Context.Attributes.Azure;
 

+ 1 - 1
TEAMModelOS.Service/Models/Syllabus/KnowledgePoint.cs

@@ -1,4 +1,4 @@
-using Microsoft.WindowsAzure.Storage.Table;
+using Microsoft.Azure.Cosmos.Table;
 using System.ComponentModel.DataAnnotations;
 using TEAMModelOS.SDK.Context.Attributes.Azure;
 

+ 8 - 0
TEAMModelOS.Service/Models/Syllabus/SyllabusNode.cs

@@ -7,6 +7,11 @@ namespace TEAMModelOS.Service.Models.Syllabus
     [CosmosDB(RU = 400, Name = "SyllabusNode")]
     public class SyllabusNode
     {
+
+        public SyllabusNode() {
+            resources = new List<string>();
+            knowledges = new List<string>();
+        }
         /// <summary>
         /// 
         /// </summary>
@@ -70,5 +75,8 @@ namespace TEAMModelOS.Service.Models.Syllabus
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
         public int status { get; set; } = 1;
+        public List<string> resources { get; set; }
+        public List<string> knowledges { get; set; }
+        
     }
 }

+ 7 - 0
TEAMModelOS.Service/Models/Syllabus/SyllabusResource.cs

@@ -77,5 +77,12 @@ namespace TEAMModelOS.Service.Models.Syllabus
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
         public string sha1Code { get; set; }
+
+        /// <summary>
+        /// 学校编码
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string schoolCode { get; set; }
+        
     }
 }

+ 1 - 0
TEAMModelOS.Service/Services/PowerPoint/Implement/PowerPointHelper.cs

@@ -833,6 +833,7 @@ namespace HiTeachCC.Service.PowerPoint.Implement
         /// <returns></returns>
         public static string ColorToning(string nodeXml, string colorHex)
         {
+            if (string.IsNullOrEmpty(colorHex)) { return null; }
             TEAMModelOS.SDK.Helper.Common.ColorHelper.ColorConverter converter = new TEAMModelOS.SDK.Helper.Common.ColorHelper.ColorConverter();
             XmlDocument doc = new XmlDocument();
             doc.LoadXml(nodeXml);

Fichier diff supprimé car celui-ci est trop grand
+ 1059 - 143
TEAMModelOS.Service/Services/PowerPoint/Implement/ShapeGenerator.cs


+ 222 - 173
TEAMModelOS.Service/Services/PowerPoint/Implement/ShapeHelper.cs

@@ -4,7 +4,6 @@ using System;
 using System.Collections.Generic;
 using System.Drawing;
 using System.Linq;
-using System.Text;
 using System.Xml;
 using TEAMModelOS.SDK.Helper.Common.ColorHelper;
 using TEAMModelOS.Service.Models.PowerPoint.Inner;
@@ -15,166 +14,216 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
     {
         private const double px96 = 96.00, px72 = 72.00, px914400 = 914400.00, px12700 = 12700.00;
         private const double rot60000 = 60000.00;
-        public static Border GetBorder(XmlNode node, bool isSvgMode, string bType, Dictionary<string, string> slideLayoutClrOvride, XmlNode themeContent)
+        public static Border GetBorder(XmlNode node, bool isSvgMode, string bType, Dictionary<string, string> slideLayoutClrOvride, XmlNode slideMasterContent ,  XmlNode themeContent)
         {
-
-            Border border = new Border();
+            var borderWidth = 0.0;
+            if (node.Name.Equals("p:cxnSp"))
+            {
+                borderWidth = 0.75;
+            }
+            Border border = new Border() { Width = borderWidth };
            
-                string cssText = "";
-                XmlNode lineNode = null;
-                if (bType == "shape")
-                {
-                    cssText = "border: ";
-                    lineNode = node.GetTextByPath( "p:spPr/a:ln");// node["p:spPr"]["a:ln"];
-                }
-                else if (bType == "text")
-                {
-                    cssText = "";
-                    lineNode = PowerPointHelper.GetTextByPath(node, "a:rPr/a:ln");// node["a:rPr"]["a:ln"];
+            XmlNode lineNode = null;
+            if (bType == "shape")
+            {
+               // cssText = "border: ";
+                lineNode = node.GetTextByPath("p:spPr/a:ln");// node["p:spPr"]["a:ln"];
+            }
+            else if (bType == "text")
+            {
+              //  cssText = "";
+                lineNode = PowerPointHelper.GetTextByPath(node, "a:rPr/a:ln");// node["a:rPr"]["a:ln"];
 
-                }
-                if (lineNode == null)
-                {
-                    return null;
-                }
-                var borderWidth = 0.0;
+            }
+            if (lineNode != null)
+            {
                 XmlNode wnode = lineNode.GetTextByPath("@w");
                 if (wnode != null)
                 {
-                    borderWidth = double.Parse(wnode.Value) / px12700;
+                    border.Width = double.Parse(wnode.Value) / px12700;
                 }
                 // Border width: 1pt = 12700, default = 0.75pt
                 //  borderWidth = double.Parse(PowerPointHelper.GetTextByPath(lineNode, "@w").Value) / px12700;
-                if (wnode != null || borderWidth < 1)
-                {
-                    cssText += "0pt ";
-                }
-                else
-                {
-                    cssText += borderWidth + "pt ";
-                }
-                // Border type
-                var borderType = PowerPointHelper.GetTextByPath(lineNode, "a:prstDash/@val").Value;
-                var strokeDasharray = "0";
-                switch (borderType)
-                {
-                    case "solid":
-                        cssText += "solid";
-                        strokeDasharray = "0";
-                        break;
-                    case "dash":
-                        cssText += "dashed";
-                        strokeDasharray = "5";
-                        break;
-                    case "dashDot":
-                        cssText += "dashed";
-                        strokeDasharray = "5, 5, 1, 5";
-                        break;
-                    case "dot":
-                        cssText += "dotted";
-                        strokeDasharray = "1, 5";
-                        break;
-                    case "lgDash":
-                        cssText += "dashed";
-                        strokeDasharray = "10, 5";
-                        break;
-                    case "lgDashDotDot":
-                        cssText += "dashed";
-                        strokeDasharray = "10, 5, 1, 5, 1, 5";
-                        break;
-                    case "sysDash":
-                        cssText += "dashed";
-                        strokeDasharray = "5, 2";
-                        break;
-                    case "sysDashDot":
-                        cssText += "dashed";
-                        strokeDasharray = "5, 2, 1, 5";
-                        break;
-                    case "sysDashDotDot":
-                        cssText += "dashed";
-                        strokeDasharray = "5, 2, 1, 5, 1, 5";
-                        break;
-                    case "sysDot":
-                        cssText += "dotted";
-                        strokeDasharray = "2, 5";
-                        break;
-                    case null:
-                    //console.log(borderType);
-                    default:
-                        cssText += "solid";
-                        strokeDasharray = "0";
-                        break;
-                }
-                // Border color
-                var borderColor = PowerPointHelper.GetTextByPath(lineNode, "a:solidFill/:srgbClr/@val").Value;
-                if (borderColor == null)
+                //if (wnode != null || borderWidth < 1)
+                //{
+                //    cssText += "0pt ";
+                //}
+                //else
+                //{
+                //    borderWidth=
+                //    cssText += borderWidth + "pt ";
+                //}
+            }
+
+            // Border type
+            if (lineNode != null)
+            {
+                var borderType = PowerPointHelper.GetTextByPath(lineNode, "a:prstDash/@val");
+                if (borderType != null)
                 {
-                    var schemeClrNode = PowerPointHelper.GetTextByPathList(lineNode, "a:solidFill/a:schemeClr");
-                    if (schemeClrNode != null)
+                    switch (borderType.Value)
                     {
-                        var schemeClr = PowerPointHelper.GetTextByPath(lineNode, "a:solidFill/a:schemeClr/@val");
-                        borderColor = GetSchemeColorFromTheme(schemeClr.Value, null ,slideLayoutClrOvride,themeContent);
+                        case "solid":
+                            border.Type = "solid";
+                            border.Stroke = "0";
+                            break;
+                        case "dash":
+                            border.Type += "dashed";
+                            border.Stroke = "5";
+                            break;
+                        case "dashDot":
+                            border.Type = "dashed";
+                            border.Stroke = "5, 5, 1, 5";
+                            break;
+                        case "dot":
+                            border.Type = "dotted";
+                            border.Stroke = "1, 5";
+                            break;
+                        case "lgDash":
+                            border.Type = "dashed";
+                            border.Stroke = "10, 5";
+                            break;
+                        case "lgDashDotDot":
+                            border.Type = "dashed";
+                            border.Stroke = "10, 5, 1, 5, 1, 5";
+                            break;
+                        case "sysDash":
+                            border.Type = "dashed";
+                            border.Stroke = "5, 2";
+                            break;
+                        case "sysDashDot":
+                            border.Type = "dashed";
+                            border.Stroke = "5, 2, 1, 5";
+                            break;
+                        case "sysDashDotDot":
+                            border.Type = "dashed";
+                            border.Stroke = "5, 2, 1, 5, 1, 5";
+                            break;
+                        case "sysDot":
+                            border.Type = "dotted";
+                            border.Stroke = "2, 5";
+                            break;
+                        case null:
+                        //console.log(borderType);
+                        default:
+                            border.Type = "solid";
+                            border.Stroke = "0";
+                            break;
                     }
                 }
+            }
+            else {
+                border.Type = "solid";
+                border.Stroke = "0";
+            }
+            // Border color
+            string borderColorstr = "";
+            if (lineNode != null) {
+                //var borderColor = PowerPointHelper.GetTextByPath(lineNode, "a:solidFill/a:srgbClr/@val");
+                //if (borderColor == null)
+                //{
+                //    var schemeClrNode = PowerPointHelper.GetTextByPathList(lineNode, "a:solidFill/a:schemeClr");
+                //    if (schemeClrNode != null)
+                //    {
+                //        var schemeClr = PowerPointHelper.GetTextByPath(lineNode, "a:solidFill/a:schemeClr/@val");
+                //        borderColorstr = GetSchemeColorFromTheme(schemeClr.Value, null, slideLayoutClrOvride, themeContent);
+                //        borderColorstr = PowerPointHelper.ColorToning(lineNode.OuterXml, borderColorstr);
+                //    }
+                //}
 
-                // 2. drawingML namespace
-                if (borderColor == null)
-                {
-                    var schemeClrNode = PowerPointHelper.GetTextByPathList(node, "p:style/a:lnRef/a:schemeClr");
-                    if (schemeClrNode != null)
-                    {
-                        var schemeClr = PowerPointHelper.GetTextByPath(node, "p:style/a:lnRef/a:schemeClr/@val");
-                        borderColor = GetSchemeColorFromTheme(schemeClr.Value, null, slideLayoutClrOvride, themeContent);
-                    }
-                    if (borderColor != null)
-                    {
-                        var shade = PowerPointHelper.GetTextByPath(node, "p:style/a:lnRef/a:schemeClr/a:shade/@val");
-                        if (shade != null)
-                        {
-                            double shaded = double.Parse(shade.Value) / 100000.0;
-                            var color = ColorTranslator.FromHtml("#" + borderColor);
-                            ColorHSL colorHSL = ColorHelper.RgbToHsl(new ColorRGB(color.R, color.G, color.B));
-                            colorHSL.L = colorHSL.L * shaded;
-                            ColorRGB colorRGB = colorHSL.HslToRgb();
-                            borderColor = ColorTranslator.ToHtml(Color.FromArgb(colorRGB.R, colorRGB.G, colorRGB.B));
-                            // borderColor = color.hex.replace("#", "");
-                        }
-                    }
+                borderColorstr= GetSolidFill(lineNode, slideLayoutClrOvride, slideMasterContent, themeContent);
+                borderColorstr = PowerPointHelper.ColorToning(lineNode.OuterXml, borderColorstr);
+            }
+            
 
+            // 2. drawingML namespace
+            if (string.IsNullOrEmpty(borderColorstr))
+            {
+               XmlNode lnRefNode =  PowerPointHelper.GetTextByPath(node, "p:style/a:lnRef");
+                if (lnRefNode != null) {
+                    borderColorstr = GetSolidFill(lnRefNode, slideLayoutClrOvride, slideMasterContent, themeContent);
+                    borderColorstr = PowerPointHelper.ColorToning(lnRefNode.OuterXml, borderColorstr);
                 }
+                //var schemeClrNode = PowerPointHelper.GetTextByPathList(node, "p:style/a:lnRef/a:schemeClr");
+                //if (schemeClrNode != null)
+                //{
+                //    var schemeClr = PowerPointHelper.GetTextByPath(node, "p:style/a:lnRef/a:schemeClr/@val");
+                //    if (schemeClr != null)
+                //    {
+                //        borderColorstr = GetSchemeColorFromTheme(schemeClr.Value, null, slideLayoutClrOvride, themeContent);
+                //    }
+                //}
+                //if (borderColor != null)
+                //{
+                //    var shade = PowerPointHelper.GetTextByPath(node, "p:style/a:lnRef/a:schemeClr/a:shade/@val");
+                //    if (shade != null)
+                //    {
+                //        double shaded = double.Parse(shade.Value) / 100000.0;
+                //        var color = ColorTranslator.FromHtml("#" + borderColor);
+                //        ColorHSL colorHSL = ColorHelper.RgbToHsl(new ColorRGB(color.R, color.G, color.B));
+                //        colorHSL.L = colorHSL.L * shaded;
+                //        ColorRGB colorRGB = colorHSL.HslToRgb();
+                //        borderColorstr = ColorTranslator.ToHtml(Color.FromArgb(colorRGB.R, colorRGB.G, colorRGB.B));
+                //        // borderColor = color.hex.replace("#", "");
+                //    }
+                //}
 
-                if (borderColor == null)
-                {
-                    if (isSvgMode)
-                    {
-                        borderColor = "none";
-                    }
-                    else
-                    {
-                        borderColor = "#000";
-                    }
-                }
-                else
-                {
-                    borderColor = "#" + borderColor;
+            }
+            if (!string.IsNullOrEmpty(borderColorstr)) {
+                border.Color = borderColorstr;
+                if (border.Width == 0) {
+                    border.Width = 1;
+                }
+            }
+            return border;
+
+            //if (borderColor == null)
+            //{
+            //    if (isSvgMode)
+            //    {
+            //        borderColorstr = "none";
+            //    }
+            //    else
+            //    {
+            //        borderColorstr = "#000";
+            //    }
+            //}
+            //else
+            //{
+            //    borderColorstr = "#" + borderColorstr;
+
+            //}
+            //cssText += " " + borderColor + " ";
+            //if (borderType != null)
+            //{
+            //    if (isSvgMode)
+            //    {
+            //        return new Border { Color = borderColorstr, Width = (int)borderWidth, Type = borderType.Value, Stroke = strokeDasharray };
+            //    }
+            //    else
+            //    {
+            //        return border;
+            //    }
+            //}
+            //else
+            //{
+
+            //    if (isSvgMode)
+            //    {
+            //        return new Border { Color = borderColorstr, Width = (int)borderWidth, Type = "", Stroke = strokeDasharray };
+            //    }
+            //    else
+            //    {
+            //        return border;
+            //    }
+            //}
 
-                }
-                cssText += " " + borderColor + " ";
 
 
-                if (isSvgMode)
-                {
-                    return new Border { Color = borderColor, Width = (int)borderWidth, Type = borderType, Stroke = strokeDasharray };
-                }
-                else
-                {
-                    return border;
-                }
-          
 
         }
 
-        public static string GetSchemeColorFromTheme(string schemeClr, XmlNode sldMasterNode ,  Dictionary<string ,string > slideLayoutClrOvride ,XmlNode themeContent)
+        public static string GetSchemeColorFromTheme(string schemeClr, XmlNode sldMasterNode, Dictionary<string, string> slideLayoutClrOvride, XmlNode themeContent)
         {
             //<p:clrMap ...> in slide master
             // e.g. tx2="dk2" bg2="lt2" tx1="dk1" bg1="lt1" slideLayoutClrOvride
@@ -264,7 +313,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
             ptrn += "</pattern>";// '';
             return ptrn;
         }
-        public static string GetSvgGradient(double w, double h, double angl, List<string> color_arry, int  shpId, Dictionary<string, string> slideLayoutClrOvride, XmlNode themeContent)
+        public static string GetSvgGradient(double w, double h, double angl, List<string> color_arry, int shpId, Dictionary<string, string> slideLayoutClrOvride, XmlNode themeContent)
         {
 
             var stopsArray = GetMiddleStops(color_arry.Count - 2);
@@ -273,7 +322,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
             double svgHeight = h;
             double svgWidth = w;
             string svg = "";
-            List<double> xy_ary = SVGangle(angl, svgHeight, svgWidth,  slideLayoutClrOvride,   themeContent);
+            List<double> xy_ary = SVGangle(angl, svgHeight, svgWidth, slideLayoutClrOvride, themeContent);
             double x1 = xy_ary[0];
             double y1 = xy_ary[1];
             double x2 = xy_ary[2];
@@ -287,7 +336,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
 
             for (var i = 0; i < sal; i++)
             {
-                svg += "<stop offset=\"" + (System.Math.Round(double.Parse(stopsArray[i])) / 100 * sr) / sr + "\" stop-color=\"" + color_arry[i] + "\"";
+                svg += "<stop offset=\"" + (System.Math.Round(double.Parse(stopsArray[i].Replace("%", ""))) / 100 * sr) / sr + "\" stop-color=\"" + color_arry[i] + "\"";
                 svg += "/>\n";
             }
 
@@ -321,7 +370,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
             sArry.Add("100%");
             return sArry;
         }
-        public static List<double> SVGangle(double deg, double svgHeight, double svgWidth , Dictionary<string, string> slideLayoutClrOvride, XmlNode themeContent)
+        public static List<double> SVGangle(double deg, double svgHeight, double svgWidth, Dictionary<string, string> slideLayoutClrOvride, XmlNode themeContent)
         {
             double w = svgWidth;
             double h = svgHeight;
@@ -399,42 +448,43 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
             double y2 = System.Math.Round(ty1 / h * 100 * 100) / 100;
             return new List<double> { x1, y1, x2, y2 };
         }
-        public static Fill GetPatternFill(XmlNode node ,Dictionary<string, string> slideLayoutClrOvride,  XmlNode slideMasterContent, XmlNode themeContent)
+        public static Fill GetPatternFill(XmlNode node, Dictionary<string, string> slideLayoutClrOvride, XmlNode slideMasterContent, XmlNode themeContent)
         {
             Fill fill = new Fill { Type = 4 };
             //处理前景色 
-            var fgClr = node.GetTextByPath( "a:fgClr");
-            string fgclr = GetSolidFill(fgClr, slideLayoutClrOvride,  slideMasterContent, themeContent);
-            fgclr =PowerPointHelper.ColorToning(fgClr.OuterXml, fgclr);
+            var fgClr = node.GetTextByPath("a:fgClr");
+            string fgclr = GetSolidFill(fgClr, slideLayoutClrOvride, slideMasterContent, themeContent);
+            fgclr = PowerPointHelper.ColorToning(fgClr.OuterXml, fgclr);
             fill.gradColor.Add(fgclr);
             // 处理背景色
-            var bgClr = node.GetTextByPath( "a:bgClr");
+            var bgClr = node.GetTextByPath("a:bgClr");
             string bgclr = GetSolidFill(bgClr, slideLayoutClrOvride, slideMasterContent, themeContent);
             bgclr = PowerPointHelper.ColorToning(bgClr.OuterXml, bgclr);
             //处理内置图案属性
             var prst = node.GetTextByPath("@prst");
-            if (prst != null) {
+            if (prst != null)
+            {
                 fill.pattPrst = prst.Value;
             }
             fill.gradColor.Add(bgclr);
             return fill;
         }
 
-        public static  dynamic GetSlideSize(XmlDocument xdoc)
+        public static dynamic GetSlideSize(XmlDocument xdoc)
         {
             var sldSzNode = xdoc.GetTextByPath("//pkg:part[@pkg:name='/ppt/presentation.xml']/pkg:xmlData/p:presentation/p:sldSz");
             double width = double.Parse(sldSzNode.GetTextByPath("@cx").Value) * px96 / px914400;
             double height = double.Parse(sldSzNode.GetTextByPath("@cy").Value) * px96 / px914400;
             return new { width, height };
         }
-        public static Fill GetGradientFill(XmlNode node, Dictionary<string, string> slideLayoutClrOvride,XmlNode slideMasterContent, XmlNode themeContent)
+        public static Fill GetGradientFill(XmlNode node, Dictionary<string, string> slideLayoutClrOvride, XmlNode slideMasterContent, XmlNode themeContent)
         {
             XmlNodeList gsLst = PowerPointHelper.GetTextByPathList(node, "a:gsLst/a:gs");// node["a:gsLst"]["a:gs"];
             //get start color
             var color_ary = new List<string>();
             for (int i = 0; i < gsLst.Count; i++)
             {
-                var lo_color = GetSolidFill(gsLst[i] , slideLayoutClrOvride, slideMasterContent,  themeContent);
+                var lo_color = GetSolidFill(gsLst[i], slideLayoutClrOvride, slideMasterContent, themeContent);
                 lo_color = PowerPointHelper.ColorToning(gsLst[i].OuterXml, lo_color);
                 color_ary.Add(lo_color);
             }
@@ -452,15 +502,15 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
                 Rot = rot
             };
         }
-      
+
         public static Position GetPosition(XmlNode slideXfrmNode, XmlNode slideLayoutXfrmNode, XmlNode slideMasterXfrmNode)
         {
 
             XmlNode off = null;
             XmlNode ext = null;
-            double x, y,w,h;
+            double x, y, w, h;
             //ext
-            if(slideXfrmNode != null)
+            if (slideXfrmNode != null)
             {
                 ext = PowerPointHelper.GetTextByPath(slideXfrmNode, "a:ext");
             }
@@ -477,7 +527,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
             {
                 off = PowerPointHelper.GetTextByPath(slideXfrmNode, "a:off");
             }
-            else if (slideLayoutXfrmNode != null && off==null)
+            else if (slideLayoutXfrmNode != null && off == null)
             {
                 off = PowerPointHelper.GetTextByPath(slideLayoutXfrmNode, "a:off");
             }
@@ -485,20 +535,20 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
             {
                 off = PowerPointHelper.GetTextByPath(slideMasterXfrmNode, "a:off");
             }
-            x = double.Parse(off.GetTextByPath( "@x").Value) * px96 / px914400;
-            y = double.Parse(off.GetTextByPath( "@y").Value) * px96 / px914400;
+            x = double.Parse(off.GetTextByPath("@x").Value) * px96 / px914400;
+            y = double.Parse(off.GetTextByPath("@y").Value) * px96 / px914400;
             w = double.Parse(ext.GetTextByPath("@cx").Value) * px96 / px914400;
             h = double.Parse(ext.GetTextByPath("@cy").Value) * px96 / px914400;
             return new Position()
             {
-                Cx=w,
-                Cy=h,
+                Cx = w,
+                Cy = h,
                 X = x,
                 Y = y
             };
         }
 
-        public static  NodesTable IndexNodes(XmlNode content)
+        public static NodesTable IndexNodes(XmlNode content)
         {
             var idTable = new Dictionary<string, XmlNode>();
             var idxTable = new Dictionary<string, XmlNode>();
@@ -558,7 +608,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
             return double.Parse(angle.Value) / 60000.00;
         }
 
-        public  static XmlNode GetNodesTable(XmlNode id, XmlNode idx, XmlNode type, WarpObj warpObj, string LayoutOrMaster)
+        public static XmlNode GetNodesTable(XmlNode id, XmlNode idx, XmlNode type, WarpObj warpObj, string LayoutOrMaster)
         {
             XmlNode resNode = null;
             if (resNode == null)
@@ -703,45 +753,44 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
             }
             return opcity;
         }
-        public static  Fill GetBgGradientFill(XmlNode bgPr, XmlNode phClr, Dictionary<string ,string > slideLayoutClrOvride, XmlNode slideMasterContent,  XmlNode themeContent)
+        public static Fill GetBgGradientFill(XmlNode bgPr, string phClr, Dictionary<string, string> slideLayoutClrOvride, XmlNode slideMasterContent, XmlNode themeContent)
         {
-            ;
             if (bgPr != null)
             {
                 var grdFill = bgPr.GetTextByPath("a:gradFill");
-                return ShapeHelper.GetGradientFill(grdFill, slideLayoutClrOvride, slideMasterContent, themeContent);
+                return GetGradientFill(grdFill, slideLayoutClrOvride, slideMasterContent, themeContent);
             }
             else
             {
                 if (phClr == null)
                 {
-                    return new Fill { Type = 1, Color = phClr.Value };
+                    return new Fill { Type = 1, Color = phClr };
                 }
             }
             return null;
         }
 
-        public  static string GetSolidFill(XmlNode node, Dictionary<string, string> slideLayoutClrOvride,   XmlNode slideMasterContent, XmlNode themeContent)
+        public static string GetSolidFill(XmlNode node, Dictionary<string, string> slideLayoutClrOvride, XmlNode slideMasterContent, XmlNode themeContent)
         {
 
             if (node == null)
             {
                 return null;
             }
-            string Color = "FFF";
+            string Color =null;
             // Fill fill = new Fill() { Color = "FFF", Type = 1 };
             var srgbClrval = node.GetTextByPath("a:srgbClr/@val");
             var schemeClrval = node.GetTextByPath("a:schemeClr/@val");
             if (srgbClrval != null)
             {
-                 Color = srgbClrval.Value; //#...
+                Color = srgbClrval.Value; //#...
             }
             else if (schemeClrval != null)//node["a:schemeClr"] != null)
             {
                 //a:schemeClr
                 // var schemeClr = PowerPointHelper.GetTextByPath(node, "a:schemeClr/@val");
                 //console.log(schemeClr)
-                 Color = ShapeHelper.GetSchemeColorFromTheme(schemeClrval.Value, slideMasterContent, slideLayoutClrOvride, themeContent); //#...
+                Color = ShapeHelper.GetSchemeColorFromTheme(schemeClrval.Value, slideMasterContent, slideLayoutClrOvride, themeContent); //#...
 
             }
             else if (PowerPointHelper.GetTextByPath(node, "a:scrgbClr") != null)
@@ -755,7 +804,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
                 var green = (defBultColorValsG.Value.IndexOf("%") != -1) ? defBultColorValsG.Value.Split("%").First() : defBultColorValsG.Value;
                 var blue = (defBultColorValsB.Value.IndexOf("%") != -1) ? defBultColorValsB.Value.Split("%").First() : defBultColorValsB.Value;
                 var scrgbClr = red + "," + green + "," + blue;
-                 Color = ToHex(255 * (double.Parse(red) / 100)) + ToHex(255 * (double.Parse(green) / 100)) + ToHex(255 * (double.Parse(blue) / 100));
+                Color = ToHex(255 * (double.Parse(red) / 100)) + ToHex(255 * (double.Parse(green) / 100)) + ToHex(255 * (double.Parse(blue) / 100));
                 //console.log("scrgbClr: " + scrgbClr);
 
             }
@@ -763,7 +812,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
             {
                 //<a:prstClr val="black"/>  //Need to test/////////////////////////////////////////////
                 var prstClr = PowerPointHelper.GetTextByPath(node, "a:prstClr/@val");// node["a:prstClr"]["attrs"]["val"];
-               Color = GetColorName2Hex(prstClr.Value);
+                Color = GetColorName2Hex(prstClr.Value);
                 //console.log("prstClr: " + prstClr+" => hexClr: "+color);
             }
             else if (PowerPointHelper.GetTextByPath(node, "a:hslClr") != null)
@@ -778,7 +827,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
                 var lum = double.Parse((defBultColorVals_lum.Value.IndexOf("%") != -1) ? defBultColorVals_lum.Value.Split("%").First() : defBultColorVals_lum.Value) / 100;
                 var hslClr = defBultColorVals_hue.Value.ToString() + "," + defBultColorVals_sat.Value.ToString() + "," + defBultColorVals_lum.Value.ToString();
                 var hsl2rgb = HslToRgb(hue, sat, lum);
-                 Color = ToHex(hsl2rgb.r) + ToHex(hsl2rgb.g) + ToHex(hsl2rgb.b);
+                Color = ToHex(hsl2rgb.r) + ToHex(hsl2rgb.g) + ToHex(hsl2rgb.b);
                 //defBultColor = cnvrtHslColor2Hex(hslClr); //TODO
                 // console.log("hslClr: " + hslClr);
             }
@@ -788,7 +837,7 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
                 var sysClr = PowerPointHelper.GetTextByPath(node, "a:sysClr/@lastClr").Value;
                 if (sysClr != null)
                 {
-                  Color = sysClr;
+                    Color = sysClr;
                 }
             }
             return Color;

Fichier diff supprimé car celui-ci est trop grand
+ 8985 - 0
TEAMModelOS.Service/Services/PowerPoint/Implement/ShapeSvg.cs


+ 1 - 1
TEAMModelOS/ClientApp/src/api/knowledge.js

@@ -28,7 +28,7 @@ export default {
     DeleteSchoolPoint: function (data) {
         return post('/api/Knowledge/DeleteSchoolPoint', data)
     },
-    // 手动添加学校的私有知识点
+    // 删除学校知识块
     DeleteSchoolBlock: function (data) {
         return post('/api/Knowledge/DeleteSchoolBlock', data)
     },

+ 6 - 0
TEAMModelOS/ClientApp/src/api/syllabus.js

@@ -16,11 +16,17 @@ export default {
     DeleteVolume: function (data) {
         return post('/api/Volume/Delete', data)
     },
+    // 根据册别查找课纲数据
     GetTreeByVolume: function (data) {
         return post('/api/Syllabus/Find', data)
     },
+    // 按照树形保存整个课纲
     SaveOrUpdateAsTree: function (data) {
         return post('/api/Syllabus/SaveOrUpdateAsTree', data)
     },
+    // 保存或者新增单个节点
+    SaveOrUpdateAsNodes: function (data) {
+        return post('/api/Syllabus/SaveOrUpdateAsNodes', data)
+    },
 
 }

+ 90 - 24
TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue

@@ -10,7 +10,8 @@
                 <span class="custom-tree-node" slot-scope="{ node, data }">
                     <span>{{node.label}}</span>
                     <span class="custom-tree-tools">
-                        <Icon v-show="data.pid !== 'Root'" type="ios-paper" size="20" title="编辑" @click="onEditItem(node,data,$event)" />
+                        <Icon v-show="data.pid !== 'Root'" type="ios-folder-open" size="20" title="内容" @click="onRelatedContent(node,data,$event)" />
+                        <Icon v-show="data.pid !== 'Root'" type="md-create" size="20" title="编辑" @click="onEditItem(node,data,$event)" />
                         <Icon type="md-add" size="22" title="添加" @click="onAddNode(data,$event)" />
                         <Icon v-show="data.pid !== 'Root'" type="md-remove" size="22" title="删除" @click="remove(node,data)" />
                     </span>
@@ -19,25 +20,29 @@
         </vuescroll>
 
         <!-- 新增或者编辑弹窗 -->
-        <Modal v-model="isEditOrAdd" width="560" footer-hide class="tree-modal">
+        <Modal v-model="isEditOrAdd" width="500" footer-hide class="tree-modal">
             <div class="modal-header" slot="header">{{ isEditItem ? '编辑节点':'新增节点'}}</div>
-            <vuescroll>
                 <div class="modal-content">
                     <p class="node-title">父节点</p>
                     <Input v-model="nodeInfo.parent" style="width: 100%" disabled />
                     <p class="node-title">节点名称</p>
                     <Input v-model="nodeInfo.title" placeholder="请输入节点名称..." style="width: 100%" />
-                    <p class="node-title">资源内容</p>
-                    <div class="resource-box">
+                </div>
+            <Button @click="onSubmitNode" class="modal-btn">确认</Button>
+        </Modal>
 
-                    </div>
-                    <p class="node-title">关联知识点</p>
-                    <div class="resource-box">
 
-                    </div>
-                </div>
-            </vuescroll>
-            <Button @click="onSubmitNode">确认</Button>
+        <!-- 关联内容弹窗 -->
+        <Modal v-model="isRelatedContent" width="880" footer-hide class="tree-modal related-modal">
+            <div class="modal-header" slot="header">内容关联</div>
+            <Tabs>
+                <TabPane label="资源文件" icon="md-folder">
+                    <BaseResource :volume="volume" :currentNode="currentEditData"></BaseResource>
+                </TabPane>
+                <TabPane label="知识点" icon="md-cube">
+                    <BaseKnowledge  :volume="volume" :currentNode="currentEditData" @addPointsFinish="addPointsFinish"></BaseKnowledge>
+                </TabPane>
+            </Tabs>
         </Modal>
     </div>
 </template>
@@ -45,8 +50,11 @@
 
 <script>
     import '@/utils/Math.uuid'
+    import BaseResource from '@/view/syllabus/newSyllabus/operation/BaseResource'
+    import BaseKnowledge from '@/view/syllabus/newSyllabus/operation/BaseKnowledge'
     export default {
         props: ['volume', 'treeData'],
+        components: { BaseResource , BaseKnowledge }, 
         data() {
             return {
                 treeDatas: [],
@@ -55,6 +63,7 @@
                     label: 'title'
                 },
                 isEditOrAdd: false,
+                isRelatedContent:false,
                 isEditItem: false,
                 currentVolume: null,
                 currentEditData: null,
@@ -141,6 +150,18 @@
 
             },
 
+            onRelatedContent(node, data, e) {
+                e.stopPropagation(); //防止点击事件穿透到父层
+                this.isRelatedContent = true
+                this.currentEditData = data
+            },
+
+            addPointsFinish(node) {
+                console.log(this)
+                this.isRelatedContent = false
+                this.$emit('onTreeUpdate')
+            },
+
             // 提交编辑或者新增
             onSubmitNode() {
                 if (!this.nodeInfo.title) {
@@ -157,6 +178,8 @@
                     newChild.pid = parentNode.id
                     newChild.volumeCode = parentNode.volumeCode
                     newChild.children = []
+                    newChild.resources = []
+                    newChild.knowledges = []
                     if (!this.currentParentData.children) {
                         this.$set(this.currentParentData, 'children', []);
                     }
@@ -188,6 +211,12 @@
                     this.treeDatas = defaultTree
                 }
             },
+            // 监听课纲数据变化
+            volume: {
+                handler: function (n, o) {
+                    this.volume = n
+                }
+            },
         }
     };
 </script>
@@ -250,14 +279,17 @@
 
     .tree-modal .ivu-modal-content {
         background: #3c3c3c;
-        height: 600px;
         overflow: hidden;
         color: #fff;
         font-family: '微軟正黑體', 'Heiti TC';
     }
 
     .tree-modal .ivu-modal-body {
-        height: 450px;
+        height: 400px;
+        padding:20px;
+    }
+    .related-modal .ivu-modal-body {
+        height: 700px;
     }
 
     .tree-modal .ivu-modal-header {
@@ -273,7 +305,7 @@
 
         .tree-modal .modal-content .node-title {
             color: #fff;
-            margin: 10px 0;
+            margin: 30px 0;
             font-size: 14px;
         }
 
@@ -288,20 +320,54 @@
                 color: #808080;
             }
 
-        .tree-modal .modal-content .resource-box {
-            width: 100%;
-            height: 250px;
-            background: #575757;
-            border-radius: 4px;
-        }
-
-    .tree-modal .ivu-btn {
+    .tree-modal .modal-btn {
         margin-left: 35px;
-        width: 460px;
+        width: 400px;
         height: 40px;
         background: rgb(11, 151, 117);
         border: none;
         color: #fff;
         margin-top: 30px;
     }
+
+
+    /*修改iview Tab标签页样式重写*/
+    .tree-modal .ivu-tabs-nav {
+        width:100%;
+    }
+
+     .tree-modal .ivu-tabs {
+        height:100%;
+    }
+
+        .tree-modal .ivu-tabs-nav .ivu-icon {
+            font-size:20px;
+            margin-right:15px;
+        }
+    
+    .tree-modal .ivu-tabs-nav .ivu-tabs-tab {
+        width:50%;
+        text-align:center;
+        color:#fff;
+        margin:0;
+        padding-bottom:20px;
+    }
+
+    .tree-modal .ivu-tabs-bar {
+        border-bottom:none;
+    }
+
+    .tree-modal .ivu-tabs-nav-container:focus .ivu-tabs-tab-focused {
+        border-color:rgb(11, 151, 117) !important;
+    }
+
+    .tree-modal .ivu-tabs-ink-bar {
+        background:rgb(11, 151, 117) !important;
+        height:4px;
+        bottom:0;
+    }
+
+    .tree-modal .ivu-tabs-content {
+        height:100%;
+    }
 </style>

+ 5 - 0
TEAMModelOS/ClientApp/src/router/routes.js

@@ -230,6 +230,11 @@ export const routes = [
                 path: 'teachcontent',
                 name: 'teachcontent',
                 component: resolve => require(['@/view/teachcontent/index.vue'], resolve)
+            },
+            {
+                path: 'knowledge',
+                name: 'knowledge',
+                component: resolve => require(['@/view/knowledge-point/index/index.vue'], resolve)
             }
         ]
     }

+ 22 - 4
TEAMModelOS/ClientApp/src/view/knowledge-point/index/Index.less

@@ -61,7 +61,7 @@
                 font-size: @primary-fontSize;
                 font-weight: bold;
                 color: @primary-textColor;
-                border-bottom: 1px solid @borderColor;
+                border-bottom: 1px solid #353535;
 
                 &-content {
                     height: 50px;
@@ -119,7 +119,7 @@
                 }
 
                 .gl-item-name {
-                    width:70%;
+                    width: 70%;
                     overflow: hidden;
                     text-overflow: ellipsis;
                     white-space: nowrap;
@@ -185,13 +185,31 @@
             .points-wrap {
                 display: flex;
                 flex-wrap: wrap;
+                padding-top:20px;
 
                 .point-item {
                     margin: 10px;
-                    padding: 5px 10px;
-                    border: 1px solid #a5a5a5;
+                    padding: 5px 30px;
+                    /*border: 1px solid #a5a5a5;*/
                     border-radius: 50px;
+                    background: #545454;
+                    box-shadow: 1px 4px 0px 0px #000000;
                     cursor: pointer;
+
+                    &-tools {
+                        margin-left: 10px;
+                        display: none;
+
+                        .btn-delete {
+                            margin-left: 4px;
+                        }
+                    }
+                }
+
+                .point-item:hover {
+                    .point-item-tools {
+                        display: unset;
+                    }
                 }
             }
         }

+ 286 - 133
TEAMModelOS/ClientApp/src/view/knowledge-point/index/index.vue

@@ -12,14 +12,14 @@
             </div>
             <div class="new-syllabus-select">
                 <span>当前学段:</span>
-                <Select ref="periodSelect" v-model="currentPeriod" style="width:200px" @on-change="onPeriodChange">
+                <Select ref="periodSelect" v-model="currentPeriodIndex" style="width:200px" @on-change="onPeriodChange">
                     <Option v-for="(item,index) in periodList" :value="index" :key="index">{{ item.periodName }}</Option>
                 </Select>
             </div>
         </div>
         <!-- 课纲主体内容 -->
         <div class="new-syllabus-content">
-            <!-- 选择科 -->
+            <!-- 选择科 -->
             <div class="ns-col ns-col">
                 <Loading :top="200" bgColor="rgba(103, 103, 103, 0.27)" type="1" v-show="isLoadSubject"></Loading>
                 <div class="ns-header">
@@ -27,14 +27,14 @@
                     <div class="ns-header-content" v-if="!isSearchSubject">
                         <span>
                             <Icon type="md-bookmark" color="#fff" size="20" />
-                            <span style="margin-left:5px">科</span>
+                            <span style="margin-left:5px">科</span>
                         </span>
                         <Icon type="ios-search" color="#fff" size="18" style="cursor:pointer" @click="isSearchSubject = true" />
                     </div>
                     <div class="ns-header-search" v-else>
                         <Input icon="ios-close"
                                v-model="searchSubject"
-                               placeholder="搜索科..."
+                               placeholder="搜索科..."
                                autofocus
                                style="width: 100%"
                                @on-click="isSearchSubject = false"
@@ -57,8 +57,8 @@
                 </vuescroll>
             </div>
             <!-- 选择知识块 -->
-            <div class="ns-col ns-col2">
-                <Loading :top="200" bgColor="rgba(103, 103, 103, 0.27)" type="1" v-show="isLoadVolumes"></Loading>
+            <div class="ns-col ns-col2" ref="colRef2" v-if="tabIndex === 0">
+                <Loading :top="200" bgColor="rgba(103, 103, 103, 0.27)" type="1" v-show="isLoadBlocks"></Loading>
                 <div class="ns-header">
                     <!-- 切换头部以及搜索框 -->
                     <div class="ns-header-content" v-if="!isSearchBlock">
@@ -67,20 +67,7 @@
                             <span style="margin-left:5px">知识块</span>
                         </span>
                         <div>
-                            <Icon type="md-add" color="#fff" size="18" style="cursor:pointer;margin-right:10px" @click="onAddVolume" />
-                            <Poptip title="筛选知识块" placement="bottom-end" @on-popper-show="onPopperShow">
-                                <Icon type="ios-funnel" color="#fff" size="18" style="cursor:pointer;margin-right:10px" />
-                                <div class="funnel-box" slot="content">
-                                    <p>年级</p>
-                                    <Select v-model="filterGrade" style="width:200px" @on-change="onFilterGrade">
-                                        <Option v-for="(item,index) in gradeList" :value="item.gradeCode" :key="index">{{ item.gradeName }}</Option>
-                                    </Select>
-                                    <p>学期</p>
-                                    <Select v-model="filterSemester" style="width:200px" @on-change="onFilterSemester">
-                                        <Option v-for="(item,index) in semesterList" :value="item.semesterCode" :key="index">{{ item.semesterName }}</Option>
-                                    </Select>
-                                </div>
-                            </Poptip>
+                            <Icon type="md-add" color="#fff" size="18" style="cursor:pointer;margin-right:10px" @click="onAddBlock" />
                             <Icon type="ios-search" color="#fff" size="18" style="cursor:pointer" @click="isSearchBlock = true" />
                         </div>
                     </div>
@@ -107,50 +94,65 @@
                             <div :class='["gl-item","animated","slideInUp",index == activeBlockIndex ? "item-active":""]'
                                  v-for="(item,index) in blockList"
                                  :key="index"
-                                 @click="hasModify ? handleConfirmSave({index,item},'1') : handleBlockTap(index,item)"
+                                 @click="handleBlockTap(index,item)"
                                  :style="{ animationDelay: ((index+1)*0.05) + 's'}">
                                 <p class="gl-item-name" :title="item.name">{{item.name}}</p>
-                                <p class="gl-item-info"><span></span>知识点数:{{item.points.length}}</p>
-                                <span class="btn-edit" title="编辑" @click.stop="onEditVolume(item)"><Icon type="md-create" size="20" color="#d2d2d2" /></span>
-                                <span class="btn-delete" title="删除" @click.stop="onDeleteVolume(item)"><Icon type="md-trash" size="22" color="#d2d2d2" /></span>
+                                <p class="gl-item-info"><span></span>知识点数:{{item.points ? item.points.length : 0}}</p>
+                                <span class="btn-edit" title="编辑" @click.stop="onEditBlock(item)"><Icon type="md-create" size="20" color="#d2d2d2" /></span>
+                                <span class="btn-delete" title="删除" @click.stop="onDeleteBlock(item)"><Icon type="md-trash" size="22" color="#d2d2d2" /></span>
                             </div>
                         </div>
                     </div>
                 </vuescroll>
             </div>
             <!-- 展示课纲树形结构部分 -->
-            <div class="ns-col ns-col3">
+            <div class="ns-col ns-col3" ref="colRef3">
                 <Loading :top="200" bgColor="rgba(103, 103, 103, 0.27)" type="1" v-show="isLoadPoints"></Loading>
                 <div class="ns-header">
                     <!-- 切换头部以及搜索框 -->
                     <div class="ns-header-content" v-if="!isSearchPoint">
                         <span>
-                            <Icon type="md-bookmarks" color="#fff" size="20" />
+                            <Icon type="md-apps" color="#fff" size="20" />
                             <span style="margin-left:5px">知识点</span>
                         </span>
                         <div>
-                            <Icon type="md-add" color="#fff" size="18" style="cursor:pointer;margin-right:10px" @click="onAddVolume" />
-                            <Icon type="ios-search" color="#fff" size="18" style="cursor:pointer" @click="isSearchPoint = true" />
+                            <Icon type="md-add" v-if="blockList.length !== 0" color="#fff" size="18" style="cursor:pointer;margin-right:10px" @click="onAddPoint" />
+                            <Icon type="ios-search" v-if="blockList.length !== 0" color="#fff" size="18" style="cursor:pointer" @click="isSearchPoint = true" />
                         </div>
                     </div>
                     <div class="ns-header-search" v-else>
                         <!-- 搜索知识点部分 -->
                         <Input icon="ios-close"
                                v-model="searchPoint"
-                               placeholder="搜索知识..."
+                               placeholder="搜索知识..."
                                autofocus
                                style="width: 100%"
                                @on-click="isSearchPoint = false"
                                @on-blur="isSearchPoint = false"
-                               @on-change="onSearchBlockChange"
-                               @on-enter="onSearchBlockChange" />
+                               @on-change="onSearchPointChange"
+                               @on-enter="onSearchPointChange" />
                     </div>
                     <div>
                         <div v-if="pointList.length === 0">
                             <EmptyBox :top="100"></EmptyBox>
                         </div>
                         <div class="points-wrap" v-else>
-                            <span class="point-item" v-for="(item,index) in pointList" :key="index">{{item.name}}</span>
+                            <div class="point-item" v-for="(item,index) in pointList" :key="index">
+                                <span>{{item.name}}</span>
+                                <span class="point-item-tools">
+                                    <span class="btn-edit" title="编辑" @click.stop="onEditPoint(index,item)"><Icon type="md-create" size="18" color="#d2d2d2" /></span>
+                                    <span class="btn-delete" title="删除" @click.stop="onDeletePoint(item)"><Icon type="md-trash" size="20" color="#d2d2d2" /></span>
+                                </span>
+                            </div>
+                            <Page :total="pointList.length || 0"
+                                  show-elevator
+                                  show-sizer
+                                  show-total
+                                  :page-size-opts="pageSizeOpt"
+                                  :current="currentPage"
+                                  :page-size="pageSize"
+                                  @on-page-size-change="pageSizeChange"
+                                  @on-change="pageChange" />
                         </div>
                     </div>
                 </div>
@@ -158,18 +160,32 @@
         </div>
 
         <!-- 新增知识块弹窗 -->
-        <Modal v-model="isAddVolume" width="560" footer-hide class="add-volume-modal">
-            <div class="modal-header" slot="header">{{ isEditVolume ? '编辑知识块' : '新增知识块'}}</div>
+        <Modal v-model="isAddBlock" width="560" footer-hide class="add-volume-modal">
+            <div class="modal-header" slot="header">{{ isEditBlock ? '编辑知识块' : '新增知识块'}}</div>
             <div class="modal-content">
                 <AddBlock :originData="originSchoolData"
-                          :periodIndex="currentPeriod"
-                          :subjectIndex="currentSubject"
-                          :editVolume="editVolume"
+                          :periodIndex="currentPeriodIndex"
+                          :subjectIndex="currentSubjectIndex"
+                          :editBlock="editBlock"
                           @addFinish="onFinishAddVolume">
                 </AddBlock>
             </div>
         </Modal>
-    </div> 
+
+        <!-- 新增知识点弹窗 -->
+        <Modal v-model="isAddPoint" width="560" footer-hide class="add-volume-modal">
+            <div class="modal-header" slot="header">{{ isEditPoint ? '编辑知识点' : '新增知识点'}}</div>
+            <div class="modal-content">
+                <AddPoint :editPointIndex="editPointIndex"
+                          :schoolParams="schoolParams"
+                          :blockData="currentBlock"
+                          :pointData="currentPoint"
+                          :addType="pointOwn"
+                          @addFinish="onFinishAddPoint">
+                </AddPoint>
+            </div>
+        </Modal>
+    </div>
 </template>
 
 <script>
@@ -177,19 +193,7 @@
     import EmptyBox from '@/common/EmptyData'
     import Loading from '@/common/Loading'
     import AddBlock from './operation/addBlock'
-
-    let defaultBlock = {
-          type: 0,
-          name: "",
-          alias: "",
-          subjectCode: "",
-          schoolCode: "2151002664",
-          order: 706,
-          status: 1,
-          knowledgeId: "0aa85eec-34fd-468c-95b7-39ff3eb51e61",
-          points: [],
-          source: 1
-    }
+    import AddPoint from './operation/addPoint'
 
     export default {
         data() {
@@ -199,69 +203,78 @@
                     areaCode: "86"
                 },
                 currentParams: {
-                    schoolCode: "2151002664",
-                    subjectCode: ""
+                    schoolCode: "",
+                    subjectCode: "",
+                    period: ""
                 },
                 isLoadSubject: false,
-                isLoadVolumes: false,
+                isLoadBlocks: false,
                 isLoadPoints: false,
-                currentPeriod: null,
-                currentSubject: null,
+                schoolParams: null,
+                currentPeriodIndex: null,
+                currentSubjectIndex: null,
                 currentBlock: null,
+                currentPoint: null,
                 tabIndex: 0,
                 originData: {},
                 originSchoolData: {},
                 periodList: [],
-                gradeList: [],
-                semesterList: [],
                 subjectList: [],
                 originSubjectList: [],
                 blockList: [],
                 originBlockList: [],
                 pointList: [],
+                originPointList:[],
                 activePeriodIndex: 0,
                 activeSubjectIndex: 0,
                 activeBlockIndex: 0,
                 isSearchSubject: false,
                 isSearchBlock: false,
                 isSearchPoint: false,
-                isAddVolume: false,
-                isEditVolume: false,
-                filterGrade: 'all',
-                filterSemester: 'all',
+                isAddBlock: false,
+                isEditBlock: false,
+                isAddPoint: false,
+                isEditPoint: false,
                 searchBlock: '',
                 searchPoint: '',
                 searchSubject: '',
-                editVolume: null,
+                editBlock: null,
+                editPointIndex: null,
                 hasModify: false,
-                preSelectVal: null
+                preSelectVal: null,
+                pageSize: 20,
+                currentPage: 1,
+                pageSizeOpt: [5, 10, 15, 20],
+                pointOwn:"block"
             }
         },
         components: {
-            Tree, AddBlock, EmptyBox, Loading
+            Tree, AddBlock, EmptyBox, Loading, AddPoint
         },
         created() {
             this.initSchoolData()
         },
         methods: {
-            //获取当前学校学段科等基本信息
+            //获取当前学校学段科等基本信息
             initSchoolData() {
                 this.$api.syllabus.GetSchoolInfo(this.schoolInfo).then(res => {
                     if (!res.error && res.result.data.length) {
                         this.originSchoolData = res.result.data[0] //默认选择第一个
                         this.originData = res.result.data[0] //默认选择第一个
                         this.periodList = this.originData.period
-                        //this.currentParams.schoolCode = this.originData.schoolCode
-                        //this.currentParams.periodCode = this.originData.period[0].periodCode
-                        this.currentPeriod = 0 //默认选择第一个学段
+                        this.currentParams.schoolCode = this.originData.schoolCode
+                        this.currentParams.period = this.originData.period[0].periodCode
+                        this.currentPeriodIndex = 0 //默认选择第一个学段
                         this.onPeriodChange(0)
+
                     } else {
                         this.$Message.warning("暂无学段数据")
                     }
                 })
             },
-            //根据科目获取所有知识块信息
-            getVolumesData() {
+
+            //根据学科获取所有知识块信息
+            getBlocksData() {
                 let that = this
                 this.$api.knowledge.GetSchoolBlocks({ PointParams: this.currentParams }).then(res => {
                     if (!res.error && res.result.data) {
@@ -270,8 +283,8 @@
                         this.originBlockList = list
                         this.handleBlockTap(0, list.length ? list[0] : null)
                         setTimeout(function () {
-                            that.isLoadVolumes = false
-                        }, 1000)
+                            that.isLoadBlocks = false
+                        }, 400)
 
                     } else {
                         this.$Message.warning("获取数据失败")
@@ -279,24 +292,39 @@
                 })
             },
 
-            //根据知识块CODE来获取对应树形课纲数据
-            getTreeByVolume(volumeCode) {
+            //根据学科获取学科下所有知识点数据
+            getPointsData() {
                 let that = this
-                this.$api.knowledge.GetTreeByVolume({ volumeCode: volumeCode }).then(res => {
+                this.$api.knowledge.GetSchoolPoints(this.currentParams).then(res => {
                     if (!res.error && res.result.data) {
-                        this.treeData = res.result.data
+                        this.pointList = res.result.data
+                        this.originPointList = res.result.data
                         setTimeout(function () {
                             that.isLoadPoints = false
-                        }, 1000)
+                        },800)
                     } else {
                         this.$Message.warning("获取数据失败")
                     }
                 })
             },
 
-            //校本课纲与个人课纲切换
+            //校本知识块与知识点仓库切换
             handleTabClick(index) {
                 this.tabIndex = index
+                switch (index) {
+                    case 0:
+                        this.$refs.colRef3.style.width = '66%'
+                        this.pointOwn = "block"
+                        break
+                    case 1:
+                        this.$refs.colRef3.style.width = '85%'
+                        this.pointOwn = "school"
+                        break
+                    default:
+                        break
+                }
+
+                this.handleSubjectTap(0)
             },
 
             //学段切换处理
@@ -308,43 +336,34 @@
                     let that = this
                     this.isLoadSubject = true
                     this.activePeriodIndex = index
-                    //this.currentParams.periodCode = this.originData.period[index].periodCode
-                    this.subjectList = this.periodList[index].subjects //切换学段后更新 科目 列表
-                    this.originSubjectList = this.periodList[index].subjects // 筛选科目源数据
-                    this.gradeList = this.periodList[index].grades //切换学段后更新 年级 列表
-                    this.semesterList = this.periodList[index].semesters //切换学段后更新 学期 列表
+                    this.currentParams.period = this.originData.period[index].periodCode
+                    this.subjectList = this.periodList[index].subjects //切换学段后更新 学科 列表
+                    this.originSubjectList = this.periodList[index].subjects // 筛选学科源数据
                     this.handleSubjectTap(0)
                     setTimeout(function () {
                         that.isLoadSubject = false
-                    }, 1000)
+                    }, 400)
                 }
             },
 
-            //科点击事件
+            //科点击事件
             handleSubjectTap(index) {
-                if (this.hasModify) {
-                    this.$Modal.confirm({
-                        title: '修改提示',
-                        content: '<p>您有未保存的课纲,将会丢失所有更改,确认放弃修改?</p>',
-                        okText: '确认',
-                        cancelText: '取消',
-                        onOk: () => {
-                            this.hasModify = false
-                            this.isLoadVolumes = true
-                            this.currentSubject = index;
-                            this.currentParams.subjectCode = this.subjectList[index].subjectCode
-                            this.activeSubjectIndex = index
-                            this.getVolumesData()
-                        }
-                    })
+                this.schoolParams = {
+                    schoolCode: this.originData.schoolCode,
+                    subjectCode: this.subjectList[index].subjectCode,
+                    period: this.currentParams.period
+                }
+                this.currentSubjectIndex = index;
+                this.currentParams.subjectCode = this.subjectList[index].subjectCode
+                this.activeSubjectIndex = index
+                if (this.tabIndex === 0) {
+                    this.isLoadBlocks = true
+                    this.getBlocksData()
                 } else {
-                    this.isLoadVolumes = true
-                    this.currentSubject = index;
-                    this.currentParams.subjectCode = this.subjectList[index].subjectCode
-                    this.activeSubjectIndex = index
-                    this.getVolumesData()
-
+                    this.isLoadPoints = true
+                    this.getPointsData()
                 }
+
             },
 
             //知识块点击事件
@@ -354,36 +373,48 @@
                 this.currentBlock = item
                 this.isLoadPoints = true
                 setTimeout(function () {
-                    that.pointList = item ? item.points : []
+                    that.pointList = item ? item.points.slice(0, this.pageSize) : []
+                    that.pageSizeChange(20)
                     that.isLoadPoints = false
-                }, 1000)
+                }, 400)
             },
 
             //添加知识块完成
             onFinishAddVolume(val) {
-                if (val) {
-                    let isExist = this.blockList.filter(item => item.id === val).length //判断列表是否已存在该学期下的知识块,有则更新,无则添加
-                    if (isExist) {
-                        this.$Message.success("知识块已存在,已为您更新数据")
-                    } else {
-                        this.$Message.success("添加新知识块成功")
-                    }
-                    this.handleSubjectTap(this.currentSubject); //获取最新知识块数据
+                this.$Message.success("操作成功!")
+                this.handleSubjectTap(this.currentSubjectIndex) //获取最新知识块数据
+                this.isAddBlock = false  //关闭窗口
+            },
+
+            //添加知识点完成
+            onFinishAddPoint(val) {
+                let that = this
+                this.isLoadPoints = true
 
+                if (this.tabIndex === 0) {
+                    this.currentBlock = val
+                    this.blockList[this.activeBlockIndex] = val //更新当前知识块数据
+                    this.pointList = val.points.slice(0, this.pageSize) // 更新当前知识点数据
+                } else {
+                    this.handleSubjectTap(this.currentSubjectIndex)
                 }
-                this.isAddVolume = false  //关闭窗口
+                this.pageChange(this.currentPage)
+                this.$Message.success("操作成功!")
+                this.isAddPoint = false  //关闭窗口
+                setTimeout(function () {
+                    that.isLoadPoints = false
+                }, 400)
             },
 
             // 删除知识块事件
-            onDeleteVolume(data) {
-                data.status = 0
+            onDeleteBlock(data) {
                 this.$Modal.confirm({
-                    title: '删除科目',
+                    title: '提示',
                     content: '<p>确认删除该知识块?</p>',
                     okText: '确认',
                     cancelText: '取消',
                     onOk: () => {
-                        this.$api.knowledge.DeleteVolume(data).then(res => {
+                        this.$api.knowledge.DeleteSchoolBlock({ id: data.id }).then(res => {
                             if (res.result.data) {
                                 this.blockList.splice(this.blockList.indexOf(data), 1)
                                 this.$Message.success('删除成功')
@@ -396,18 +427,77 @@
                 })
             },
 
+            // 删除知识点事件
+            onDeletePoint(data) {
+                this.$Modal.confirm({
+                    title: '提示',
+                    content: '<p>确认删除该知识点?</p>',
+                    okText: '确认',
+                    cancelText: '取消',
+                    onOk: () => {
+                        this.isLoadPoints = true
+                        if (this.tabIndex === 0) {
+                            let list = this.currentBlock.points
+                            list.splice(list.indexOf(data), 1)
+                            this.$api.knowledge.SaveOrUpdateSchoolBlock([this.currentBlock]).then(res => {
+                                if (!res.error && res.result.data) {
+                                    this.$Message.success("删除成功")
+                                    this.pageChange(this.currentPage)
+                                    this.isLoadPoints = false
+                                } else {
+                                    this.$Message.warning("删除失败,错误代码:" + res.error.code + ",错误信息:" + res.error.message)
+                                }
+                            }).catch(err => {
+                                this.$Message.warning("删除失败")
+                            })
+                        } else {
+                            let list = this.pointList
+                            list.splice(list.indexOf(data), 1)
+                            this.$api.knowledge.DeleteSchoolPoint({ id : data.id }).then(res => {
+                                if (!res.error && res.result.data) {
+                                    this.$Message.success("删除成功")
+                                    this.pageChange(this.currentPage)
+                                    this.isLoadPoints = false
+                                } else {
+                                    this.$Message.warning("删除失败,错误代码:" + res.error.code + ",错误信息:" + res.error.message)
+                                }
+                            }).catch(err => {
+                                this.$Message.warning("删除失败")
+                            })
+                        }
+
+                    }
+                })
+            },
+
             // 编辑知识块事件
-            onEditVolume(data) {
-                this.isAddVolume = true // 打开新增窗口
-                this.isEditVolume = true //设置成编辑状态
-                this.editVolume = data
+            onEditBlock(data) {
+                this.isAddBlock = true // 打开新增窗口
+                this.isEditBlock = true //设置成编辑状态
+                this.editBlock = data
+            },
+
+            // 新增知识块事件
+            onAddBlock() {
+                this.isAddBlock = true
+                this.isEditBlock = false
+                this.editBlock = null
             },
 
-            //新增知识块事件
-            onAddVolume() {
-                this.isAddVolume = true
-                this.isEditVolume = false
-                this.editVolume = null
+            // 新增知识点事件
+            onAddPoint() {
+                this.isAddPoint = true
+                this.isEditPoint = false
+                this.editPointIndex = null
+                this.currentPoint = null
+            },
+
+            // 编辑知识点事件
+            onEditPoint(index,data) {
+                this.isAddPoint = true // 打开新增窗口
+                this.isEditPoint = true //设置成编辑状态
+                this.editPointIndex = index
+                this.currentPoint = this.tabIndex === 0 ? null : data
             },
 
             //搜索知识块输入框onchange事件
@@ -417,15 +507,40 @@
 
             //搜索知识点输入框onchange事件
             onSearchPointChange() {
-                //this.blockList = this.originBlockList.filter(item => item.volumeName.indexOf(this.searchBlock) > -1);
+                let list = this.tabIndex === 0 ? this.currentBlock.points : this.originPointList
+                this.pointList = list.filter(item => item.name.indexOf(this.searchPoint) > -1);
             },
 
-            //搜索科输入框onchange事件
+            //搜索科输入框onchange事件
             onSearchSubjectChange() {
                 this.subjectList = this.originSubjectList.filter(item => item.subjectName.indexOf(this.searchSubject) > -1);
                 this.handleSubjectTap(0)
             },
 
+            // 切换页码返回截取数据
+            pageChange(page) {
+                this.currentPage = page
+                let start = this.pageSize * (page - 1)
+                let end = this.pageSize * page
+                if (this.tabIndex === 0) {
+                    this.pointList = this.currentBlock ? this.currentBlock.points.slice(start, end) : []
+
+                } else {
+                    this.pointList = this.originPointList ? this.originPointList.slice(start, end) : []
+                }
+                // 如果删除的是仅剩的一个元素 则往前翻页
+                if (this.pointList.length === 0 && page > 1) {
+                    this.pageChange(page - 1)
+                }
+            },
+
+            // 切换每页显示页数
+            pageSizeChange(val) {
+                this.pageSize = val
+                this.currentPage = 1
+                this.pageChange(1)
+            },
+
 
         },
     }
@@ -497,4 +612,42 @@
     .ns-col .ivu-poptip-popper[x-placement^=bottom] .ivu-poptip-arrow:after {
         border-bottom-color: #494949;
     }
+
+    .ns-col .points-wrap .ivu-page {
+        position: absolute;
+        bottom: 40px;
+        left: 0;
+        width: 100%;
+        text-align: center;
+    }
+
+        .ns-col .points-wrap .ivu-page .ivu-page-item,
+        .ns-col .points-wrap .ivu-page .ivu-page-next,
+        .ns-col .points-wrap .ivu-page .ivu-page-prev {
+            background: none;
+            border: none;
+            line-height: 32px;
+        }
+
+            .ns-col .points-wrap .ivu-page .ivu-page-item a,
+            .ns-col .points-wrap .ivu-page .ivu-page-next a,
+            .ns-col .points-wrap .ivu-page .ivu-page-prev a {
+                color: #fff;
+            }
+
+    .ns-col .points-wrap .ivu-page-item-active {
+        border: none;
+        background: rgb(11, 151, 117) !important;
+    }
+
+    .ns-col .points-wrap .ivu-select-selection,
+    .ns-col .points-wrap .ivu-page-options-elevator input {
+        border: none;
+        background: #605f5f;
+    }
+
+    .ns-col .points-wrap .ivu-select,
+    .ns-col .points-wrap .ivu-page-options-elevator input {
+        color: #fff;
+    }
 </style>

+ 48 - 37
TEAMModelOS/ClientApp/src/view/knowledge-point/index/operation/addBlock.vue

@@ -20,12 +20,13 @@
 <script>
     import '@/utils/Math.uuid'
     export default {
-        props: ['originData', 'periodIndex','subjectIndex','editVolume'],
+        props: ['originData', 'periodIndex', 'subjectIndex', 'editBlock'],
         data() {
             return {
                 originDatas: {},
                 currentPeriod: {},
-                editItem: {},
+                editItem: null,
+                uuid:"",
                 formTop: {
                     subject: '',
                     grade: '',
@@ -41,37 +42,45 @@
         methods: {
             // 提交添加
             handleSubmit() {
-                console.log("提交的ITEM")
-                console.log(this.editItem)
-                let params = {
-                    type: 0,
-                    name: this.formTop.name,
-                    alias: this.formTop.name,
-                    subjectCode: this.formTop.subject,
-                    schoolCode: "2151002664111",
-                    order: 706,
-                    status: 1,
-                    knowledgeId: Math.uuid(),
-                    points: [],
-                    source: 1
-                }
-                this.$api.knowledge.SaveOrUpdateSchoolBlock([params]).then(res => {
-                    if (!res.error && res.result.data) {
-                        this.$emit('addFinish',res.result.data.id)
-                    } else {
-                        this.$Message.warning("添加册别失败,错误代码:" + res.error.code + ",错误信息:"  + res.error.message)
+                let newName = this.formTop.name
+                if (!newName) {
+                    this.$Message.warning("知识块名称不能为空!")
+                } else {
+                    this.uuid = Math.uuid()
+                    let params = {
+                        type: 0,
+                        name: this.formTop.name,
+                        alias: this.formTop.name,
+                        subjectCode: this.formTop.subject,
+                        schoolCode: this.originDatas.schoolCode,
+                        order: 706,
+                        status: 1,
+                        knowledgeId: this.uuid,
+                        period: this.currentPeriod.periodCode,
+                        points: [],
+                        source: 1
+                    }
+                    if (this.editItem) {
+                        params.knowledgeId = this.editItem.knowledgeId
+                        params.id = this.editItem.id
                     }
-                    this.closeModal();
-                    this.editItem = {};
-                }).catch(err => {
-                     this.$Message.warning("添加册别失败")
-                })
+                    this.$api.knowledge.SaveOrUpdateSchoolBlock([params]).then(res => {
+                        if (!res.error && res.result.data) {
+                            this.$emit('addFinish', false)
+                        } else {
+                            this.$Message.warning("添加册别失败,错误代码:" + res.error.code + ",错误信息:" + res.error.message)
+                        }
+                        this.closeModal();
+                        this.editItem = null;
+                    }).catch(err => {
+                        this.$Message.warning("添加册别失败")
+                    })
+                }
             },
 
             //添加完成 关闭窗口
             closeModal() {
-                this.$emit('addFinish', false)
-                this.formTop.volume = ''
+                this.formTop.name = ''
             }
         },
         mounted() {
@@ -94,7 +103,7 @@
                     this.formTop.subject = this.currentPeriod.subjects[newValue].subjectCode
                 },
             },
-            editVolume: {
+            editBlock: {
                 handler(newValue, oldValue) {
                     if (newValue) {  // 有编辑册别传过来则为编辑状态
                         this.editItem = newValue
@@ -103,8 +112,9 @@
                     } else { //否则为新增状态
                         this.formTop.subject = this.currentPeriod.subjects[0].subjectCode
                         this.formTop.name = ""
+                        this.editItem = newValue
                     }
-                    
+
                 },
             }
         },
@@ -115,20 +125,21 @@
 <style>
     .form-container .ivu-form .ivu-form-item-label {
         color: #fff;
-        margin:10px 0;
-        font-size:16px;
+        margin: 10px 0;
+        font-size: 16px;
     }
 
     .form-container .ivu-input {
         background: #575757;
         border-color: transparent;
         height: 35px;
-        color:#fff;
-    }
-    .form-container .ivu-input::-webkit-input-placeholder {
-        color:#808080;
+        color: #fff;
     }
 
+        .form-container .ivu-input::-webkit-input-placeholder {
+            color: #808080;
+        }
+
     .form-container .ivu-select-single .ivu-select-selection {
         background: #575757;
         color: #fbfbfb;
@@ -145,6 +156,6 @@
         height: 40px;
         background: rgb(11, 151, 117);
         border: none;
-        color:#fff;
+        color: #fff;
     }
 </style>

+ 230 - 0
TEAMModelOS/ClientApp/src/view/knowledge-point/index/operation/addPoint.vue

@@ -0,0 +1,230 @@
+
+<template>
+    <div class="form-container">
+        <Form :model="formTop" label-position="top">
+            <FormItem label="知识块" v-if="addPointType === 'block'">
+                <Input v-model="formTop.blockName" disabled></Input>
+            </FormItem>
+            <FormItem label="名称">
+                <Input v-model="formTop.name" placeholder="请输入知识点名称,必填项"></Input>
+            </FormItem>
+            <FormItem>
+                <Button @click="addPointType === 'block' ? handleBlockSubmit() : handleSchoolSubmit()" :loading="isLoading">确认</Button>
+            </FormItem>
+        </Form>
+    </div>
+</template>
+
+<script>
+    import '@/utils/Math.uuid'
+    export default {
+        props: ['blockData', 'pointData', 'editPointIndex', 'addType', 'schoolParams'],
+        data() {
+            return {
+                blockDatas: {},
+                currentPeriod: {},
+                currentPoint: {},
+                schoolInfos: {},
+                editItemIndex: null,
+                addPointType: 'block',
+                isLoading:false,
+                uuid: "",
+                formTop: {
+                    blockName: '',
+                    name: ''
+                }
+            }
+        },
+
+        created() {
+            console.log(this.addType)
+        },
+        methods: {
+            // 提交添加
+            handleBlockSubmit() {
+                this.isLoading = true
+                let newName = this.formTop.name
+                if (!newName) {
+                    this.$Message.warning("知识点名称不能为空!")
+                } else {
+                    this.uuid = Math.uuid()
+                    let params = {
+                        type: 0,
+                        name: newName,
+                        alias: newName,
+                        subjectCode: this.blockDatas.subjectCode,
+                        schoolCode: this.blockDatas.schoolCode,
+                        order: 706,
+                        status: 1,
+                        knowledgeId: this.uuid,
+                        period: this.blockDatas.period,
+                        source: 1,
+                        id: null
+                    }
+                    if (this.editItemIndex || this.editItemIndex === 0) {
+                        this.blockDatas.points[this.editItemIndex].name = newName
+                    } else {
+                        this.blockDatas.points.push(params)
+                    }
+                    this.$api.knowledge.SaveOrUpdateSchoolBlock([this.blockDatas]).then(res => {
+                        if (!res.error && res.result.data) {
+                            this.isLoading = false
+                            this.$emit('addFinish', res.result.data[0])
+                        } else {
+                            this.$Message.warning("添加册别失败,错误代码:" + res.error.code + ",错误信息:" + res.error.message)
+                        }
+                        this.closeModal();
+                        this.editItemIndex = null;
+                    }).catch(err => {
+                        this.$Message.warning("添加册别失败")
+                    })
+                }
+            },
+
+            handleSchoolSubmit() {
+                this.isLoading = true
+                let newName = this.formTop.name
+                if (!newName) {
+                    this.$Message.warning("知识点名称不能为空!")
+                } else {
+                    this.uuid = Math.uuid()
+                    let params = {
+                        type: 1,
+                        name: newName,
+                        alias: newName,
+                        subjectCode: this.schoolInfos.subjectCode,
+                        schoolCode: this.schoolInfos.schoolCode,
+                        order: 706,
+                        status: 1,
+                        knowledgeId: '',
+                        period: this.schoolInfos.period,
+                        source: 1,
+                        id: this.currentPoint.id || null
+                    }
+
+                    params.knowledgeId = this.currentPoint.knowledgeId || Math.uuid()
+                    
+                    this.$api.knowledge.SaveOrUpdateSchoolPoint([params]).then(res => {
+                        if (!res.error && res.result.data) {
+                             this.isLoading = false
+                            this.$emit('addFinish',false)
+                        } else {
+                            this.$Message.warning("添加册别失败,错误代码:" + res.error.code + ",错误信息:" + res.error.message)
+                        }
+                        this.closeModal();
+                        this.currentPoint = null;
+                    }).catch(err => {
+                        this.$Message.warning("添加册别失败")
+                    })
+
+
+                }
+
+
+
+            },
+
+            //添加完成 关闭窗口
+            closeModal() {
+                this.formTop.name = ''
+            }
+        },
+        mounted() {
+        },
+        watch: {
+            addType: {
+                handler(newValue, oldValue) {
+                    if (newValue) {
+                        console.log("!!!!!!!!!!")
+                        console.log(newValue)
+                        this.addPointType = newValue
+                    }
+
+                },
+            },
+
+            blockData: {
+                handler(newValue, oldValue) {
+                    if (newValue) {
+                        this.blockDatas = newValue
+                        this.formTop.blockName = newValue.name
+                    }
+
+                },
+            },
+
+            pointData: {
+                handler(newValue, oldValue) {
+                    if (newValue) {
+                        this.currentPoint = newValue
+                        this.formTop.name = newValue.name
+                    }
+
+                },
+            },
+
+            schoolParams: {
+                handler(newValue, oldValue) {
+                    if (newValue) {
+                        this.schoolInfos = newValue
+                    }
+
+                },
+            },
+
+            editPointIndex: {
+                handler(newValue, oldValue) {
+                    if (newValue || newValue === 0) {  // 有编辑册别传过来则为编辑状态
+                        this.editItemIndex = newValue
+                        this.formTop.blockName = this.blockDatas.name
+                        this.formTop.name = this.currentPoint ? this.currentPoint.name : this.blockDatas.points[newValue].name
+                    } else { //否则为新增状态
+                        this.formTop.blockName = this.blockDatas.name
+                        this.formTop.name = ""
+                        this.editItemIndex = newValue
+                    }
+
+                },
+            }
+        },
+
+    }
+</script>
+
+<style>
+    .form-container .ivu-form .ivu-form-item-label {
+        color: #fff;
+        margin: 10px 0;
+        font-size: 16px;
+    }
+
+    .form-container .ivu-input {
+        background: #575757;
+        border-color: transparent;
+        height: 35px;
+        color: #fff;
+    }
+
+        .form-container .ivu-input::-webkit-input-placeholder {
+            color: #808080;
+        }
+
+    .form-container .ivu-select-single .ivu-select-selection {
+        background: #575757;
+        color: #fbfbfb;
+        border-color: transparent;
+        height: 35px;
+    }
+
+    .form-container .ivu-select-single .ivu-select-arrow {
+        color: #fbfbfb;
+    }
+
+    .form-container .ivu-btn {
+        width: 100%;
+        height: 40px;
+        background: rgb(11, 151, 117);
+        border: none;
+        color: #fff;
+    }
+</style>

+ 47 - 50
TEAMModelOS/ClientApp/src/view/syllabus/newSyllabus/index.vue

@@ -12,14 +12,14 @@
             </div>
             <div class="new-syllabus-select">
                 <span>当前学段:</span>
-                <Select ref="periodSelect" v-model="currentPeriod" style="width:200px" @on-change="onPeriodChange">
+                <Select ref="periodSelect" v-model="currentPeriodIndex" style="width:200px" @on-change="onPeriodChange">
                     <Option v-for="(item,index) in periodList" :value="index" :key="index">{{ item.periodName }}</Option>
                 </Select>
             </div>
         </div>
         <!-- 课纲主体内容 -->
         <div class="new-syllabus-content">
-            <!-- 选择科 -->
+            <!-- 选择科 -->
             <div class="ns-col ns-col">
                 <Loading :top="200" bgColor="rgba(103, 103, 103, 0.27)" type="1" v-show="isLoadSubject"></Loading>
                 <div class="ns-header">
@@ -27,14 +27,14 @@
                     <div class="ns-header-content" v-if="!isSearchSubject">
                         <span>
                             <Icon type="md-bookmark" color="#fff" size="20" />
-                            <span style="margin-left:5px">科</span>
+                            <span style="margin-left:5px">科</span>
                         </span>
                         <Icon type="ios-search" color="#fff" size="18" style="cursor:pointer" @click="isSearchSubject = true" />
                     </div>
                     <div class="ns-header-search" v-else>
                         <Input icon="ios-close"
                                v-model="searchSubject"
-                               placeholder="搜索科..."
+                               placeholder="搜索科..."
                                autofocus
                                style="width: 100%"
                                @on-click="isSearchSubject = false"
@@ -45,11 +45,10 @@
                 </div>
                 <vuescroll>
                     <div class="gl">
-                        <div :class='["gl-item","animated","slideInUp",index == activeSubjectIndex ? "item-active":""]'
+                        <div :class='["gl-item",index == activeSubjectIndex ? "item-active":""]'
                              v-for="(item,index) in subjectList"
                              :key="index"
-                             @click="hasModify ? handleConfirmSave({index},'2') : handleSubjectTap(index)"
-                             :style="{ animationDelay: ((index+1)*0.05) + 's'}">
+                             @click="hasModify ? handleConfirmSave({index},'2') : handleSubjectTap(index)">
                             <p class="gl-item-name">{{item.subjectName}}</p>
                             <p class="gl-item-info"><span></span>册别数:{{index}}</p>
                         </div>
@@ -104,11 +103,10 @@
                             <EmptyBox :top="50"></EmptyBox>
                         </div>
                         <div v-else>
-                            <div :class='["gl-item","animated","slideInUp",index == activeVolumeIndex ? "item-active":""]'
+                            <div :class='["gl-item",index == activeVolumeIndex ? "item-active":""]'
                                  v-for="(item,index) in volumeList"
                                  :key="index"
-                                 @click="hasModify ? handleConfirmSave({index,item},'1') : handleVolumeTap(index,item)"
-                                 :style="{ animationDelay: ((index+1)*0.05) + 's'}">
+                                 @click="hasModify ? handleConfirmSave({index,item},'1') : handleVolumeTap(index,item)">
                                 <p class="gl-item-name">{{item.volumeName}}</p>
                                 <p class="gl-item-info">{{item.gradeName}}<span></span>{{item.semesterName}}</p>
                                 <p class="gl-item-info">共编使用者:{{item.editors ? item.editors.length : '0'}}</p>
@@ -137,7 +135,7 @@
                             <Button @click="onSaveSyllabus" v-show="hasModify">存储变更</Button>
                         </div>
                     </div>
-                    <Tree :volume="currentVolume" :treeData="treeData" ref="treeRef"></Tree>
+                    <Tree :volume="currentVolume" :treeData="treeData" ref="treeRef" @onTreeUpdate="onTreeUpdate"></Tree>
                 </div>
             </div>
         </div>
@@ -147,13 +145,15 @@
             <div class="modal-header" slot="header">{{ isEditVolume ? '编辑册别' : '新增册别'}}</div>
             <div class="modal-content">
                 <AddVolume :originData="originSchoolData"
-                           :periodIndex="currentPeriod"
-                           :subjectIndex="currentSubject"
+                           :periodIndex="currentPeriodIndex"
+                           :subjectIndex="currentSubjectIndex"
+                           :addType="addType"
                            :editVolume="editVolume"
                            @addFinish="onFinishAddVolume">
                 </AddVolume>
             </div>
         </Modal>
+
     </div>
 </template>
 
@@ -176,11 +176,12 @@
                     type: 0,
                     status: 1
                 },
+                addType:'school',
                 isLoadSubject: false,
                 isLoadVolumes: false,
                 isLoadSyllabus: false,
-                currentPeriod: null,
-                currentSubject: null,
+                currentPeriodIndex: null,
+                currentSubjectIndex: null,
                 currentVolume: null,
                 tabIndex: 0,
                 originData: {},
@@ -216,7 +217,7 @@
             this.initSchoolData()
         },
         methods: {
-            //获取当前学校学段科等基本信息
+            //获取当前学校学段科等基本信息
             initSchoolData() {
                 this.$api.syllabus.GetSchoolInfo(this.schoolInfo).then(res => {
                     if (!res.error && res.result.data.length) {
@@ -225,29 +226,29 @@
                         this.periodList = this.originData.period
                         this.currentParams.schoolCode = this.originData.schoolCode
                         this.currentParams.periodCode = this.originData.period[0].periodCode
-                        this.currentPeriod = 0 //默认选择第一个学段
+                        this.currentPeriodIndex = 0 //默认选择第一个学段
                         this.onPeriodChange(0)
                     } else {
                         this.$Message.warning("暂无学段数据")
                     }
                 })
             },
-            //根据科获取所有册别信息
+            //根据科获取所有册别信息
             getVolumesData() {
                 let that = this
                 this.$api.syllabus.GetVolumes(this.currentParams).then(res => {
                     if (!res.error && res.result.data) {
                         let list = res.result.data
                         list.forEach(item => {
-                            item.gradeName = this.periodList[this.currentPeriod].grades.filter(grade => grade.gradeCode === item.gradeCode)[0].gradeName
-                            item.semesterName = this.periodList[this.currentPeriod].semesters.filter(semester => semester.semesterCode === item.semesterCode)[0].semesterName
+                            item.gradeName = this.periodList[this.currentPeriodIndex].grades.filter(grade => grade.gradeCode === item.gradeCode)[0].gradeName
+                            item.semesterName = this.periodList[this.currentPeriodIndex].semesters.filter(semester => semester.semesterCode === item.semesterCode)[0].semesterName
                         })
                         this.volumeList = list
                         this.originVolumeList = list
                         this.handleVolumeTap(0, list.length > 0 ? list[0] : null)
                         setTimeout(function () {
                             that.isLoadVolumes = false
-                        }, 1000)
+                        }, 400)
 
                     } else {
                         this.$Message.warning("获取数据失败")
@@ -263,7 +264,7 @@
                         this.treeData = res.result.data
                         setTimeout(function () {
                             that.isLoadSyllabus = false
-                        }, 1000)
+                        }, 400)
                     } else {
                         this.$Message.warning("获取数据失败")
                     }
@@ -273,6 +274,14 @@
             //校本课纲与个人课纲切换
             handleTabClick(index) {
                 this.tabIndex = index
+                this.currentParams.type = index
+                if (index === 0 && this.currentParams.TEAMModelId) {
+                    delete this.currentParams.TEAMModelId
+                } else {
+                    this.currentParams.TEAMModelId = 'habook#0001'
+                }
+                this.addType = index === 0 ? 'school' : 'private'
+                this.onPeriodChange(0)
             },
 
             //学段切换处理
@@ -285,44 +294,26 @@
                     this.isLoadSubject = true
                     this.activePeriodIndex = index
                     this.currentParams.periodCode = this.originData.period[index].periodCode
-                    this.subjectList = this.periodList[index].subjects //切换学段后更新 科 列表
-                    this.originSubjectList = this.periodList[index].subjects // 筛选科源数据
+                    this.subjectList = this.periodList[index].subjects //切换学段后更新 科 列表
+                    this.originSubjectList = this.periodList[index].subjects // 筛选科源数据
                     this.gradeList = this.periodList[index].grades //切换学段后更新 年级 列表
                     this.semesterList = this.periodList[index].semesters //切换学段后更新 学期 列表
                     this.handleSubjectTap(0)
                     setTimeout(function () {
                         that.isLoadSubject = false
-                    }, 1000)
+                    }, 400)
                 }
 
 
             },
 
-            //科点击事件
+            //科点击事件
             handleSubjectTap(index) {
-                if (this.hasModify) {
-                    this.$Modal.confirm({
-                        title: '修改提示',
-                        content: '<p>您有未保存的课纲,将会丢失所有更改,确认放弃修改?</p>',
-                        okText: '确认',
-                        cancelText: '取消',
-                        onOk: () => {
-                            this.hasModify = false
-                            this.isLoadVolumes = true
-                            this.currentSubject = index;
-                            this.currentParams.subjectCode = this.subjectList[index].subjectCode
-                            this.activeSubjectIndex = index
-                            this.getVolumesData()
-                        }
-                    })
-                } else {
                     this.isLoadVolumes = true
-                    this.currentSubject = index;
+                    this.currentSubjectIndex = index;
                     this.currentParams.subjectCode = this.subjectList[index].subjectCode
                     this.activeSubjectIndex = index
                     this.getVolumesData()
-
-                }
             },
 
             //册别点击事件
@@ -344,7 +335,7 @@
                     } else {
                         this.$Message.success("添加新册别成功")
                     }
-                    this.handleSubjectTap(this.currentSubject); //获取最新册别数据
+                    this.handleSubjectTap(this.currentSubjectIndex); //获取最新册别数据
 
                 }
                 this.isAddVolume = false  //关闭窗口
@@ -354,7 +345,7 @@
             onDeleteVolume(data) {
                 data.status = 0
                 this.$Modal.confirm({
-                    title: '删除科',
+                    title: '删除科',
                     content: '<p>确认删除该册别?</p>',
                     okText: '确认',
                     cancelText: '取消',
@@ -422,7 +413,7 @@
                 this.volumeList = this.originVolumeList.filter(item => item.volumeName.indexOf(this.searchVolume) > -1);
             },
 
-            //搜索科输入框onchange事件
+            //搜索科输入框onchange事件
             onSearchSubjectChange() {
                 this.subjectList = this.originSubjectList.filter(item => item.subjectName.indexOf(this.searchSubject) > -1);
                 this.handleSubjectTap(0)
@@ -456,6 +447,12 @@
                 })
             },
 
+            //更新当前课纲数据
+            onTreeUpdate() {
+                this.handleVolumeTap(this.activeVolumeIndex, this.currentVolume)
+                this.$Message.success("更新完成")
+            },
+
             // 判断用户是否放弃修改
             handleConfirmSave(param,type) {
                 this.$Modal.confirm({
@@ -473,7 +470,7 @@
                                 this.handleSubjectTap(param.index)
                                 break
                             case '3':
-                                this.onPeriodChange(this.currentPeriod)
+                                this.onPeriodChange(this.currentPeriodIndex)
                                 break
                             default:
                                 break
@@ -482,7 +479,7 @@
                     onCancel: () => {
                         switch (type) {
                             case '3':
-                                this.currentPeriod = this.preSelectVal
+                                this.currentPeriodIndex = this.preSelectVal
                                 break
                             default:
                                 break

+ 336 - 0
TEAMModelOS/ClientApp/src/view/syllabus/newSyllabus/operation/BaseKnowledge.vue

@@ -0,0 +1,336 @@
+
+<template>
+    <div class="knowledge-container">
+        <vuescroll>
+            <div class="select-wrap">
+                <p class="wrap-title">选择知识点</p>
+                <div class="select-content">
+                    <div class="knowledge-left">
+                        <div :class='["knowledge-left-item",activeIndex === 0 ? "item-active" : ""]' @click="onChangeOrigin(0)">校本知识块</div>
+                        <div :class='["knowledge-left-item",activeIndex === 1 ? "item-active" : ""]' @click="onChangeOrigin(1)">校本知识点</div>
+                        <div :class='["knowledge-left-item",activeIndex === 2 ? "item-active" : ""]' @click="onChangeOrigin(2)">标准知识块</div>
+                        <div :class='["knowledge-left-item",activeIndex === 3 ? "item-active" : ""]' @click="onChangeOrigin(3)">标准知识点</div>
+                    </div>
+                    <div class="knowledge-right">
+                        <vuescroll>
+                            <el-tree :data="treeData"
+                                     :props="defaultProps"
+                                     node-key="id"
+                                     ref="elTree"
+                                     show-checkbox
+                                     default-expand-all
+                                     @check-change="handleCheckChange">
+                                <span class="custom-tree-node" slot-scope="{ node, data }">
+                                    <span>{{data.name}}</span>
+                                </span>
+                            </el-tree>
+                        </vuescroll>
+                    </div>
+                </div>
+            </div>
+            <div class="show-wrap">
+                <div class="wrap-title">
+                    已选知识点
+                    <Button @click="onSaveNode" v-show="hasModify" :loading="isLoading">存储变更</Button>
+                </div>
+                <div v-if="checkedPoints.length === 0">
+                    <EmptyBox :top="10"></EmptyBox>
+                </div>
+                <div class="point-box" v-else>
+                    <span class="checked-point-item" v-for="(item,index) in checkedPoints" :key="index">{{item.name}}</span>
+                </div>
+            </div>
+        </vuescroll>
+
+    </div>
+</template>
+
+<script>
+    import EmptyBox from '@/common/EmptyData'
+    export default {
+        props: ['volume', 'currentNode'],
+        components: { EmptyBox },
+        data() {
+            return {
+                currentVolume: null,
+                currentNodeInfo: null,
+                currentParams:null,
+                activeIndex: 0,
+                checkedPoints: [],
+                originPoints:[],
+                treeData: [],
+                defaultProps: {
+                    children: 'points',
+                    label: 'name'
+                },
+                hasModify:false
+
+            }
+        },
+
+        created() {
+            //拿到当前册别信息 作为获取知识点数据参数
+            this.currentVolume = this.volume
+            this.currentParams = {
+                subjectCode: this.currentVolume.subjectCode,
+                schoolCode: this.currentVolume.schoolCode,
+                period: this.currentVolume.periodCode
+            }
+            console.log(this.currentParams.subjectCode)
+            console.log(this.currentParams.subjectCode)
+            this.getSchoolBlocks()
+        },
+        methods: {
+            //切换知识点数据来源
+            onChangeOrigin(index) {
+                this.activeIndex = index;
+                switch (index) {
+                    case 0:
+                        this.getSchoolBlocks()
+                        break
+                    case 1:
+                        this.getSchoolPoints()
+                        break
+                    default:
+                        break
+                }
+            },
+
+            //获取校本知识块
+            getSchoolBlocks() {
+                this.$api.knowledge.GetSchoolBlocks({ PointParams: this.currentParams }).then(res => {
+                    if (!res.error && res.result.data) {
+                        let list = res.result.data
+                        this.treeData = list
+                    } else {
+                        this.$Message.warning("获取数据失败")
+                    }
+                })
+            },
+
+            //获取校本知识点仓库
+            getSchoolPoints() {
+                this.$api.knowledge.GetSchoolPoints(this.currentParams).then(res => {
+                    if (!res.error && res.result.data) {
+                        let list = res.result.data
+                        this.treeData = list
+                    } else {
+                        this.$Message.warning("获取数据失败")
+                    }
+                })
+            },
+
+            // 节点复选框被点击时事件
+            handleCheckChange() {
+                this.checkedPoints = this.$refs.elTree.getCheckedNodes(true)
+                this.hasModify = !(this.isEqual(this.checkedPoints, this.originPoints))
+            },
+
+            onSaveNode() {
+                this.isLoading = true
+                this.currentNodeInfo.knowledges = this.checkedPoints.map(item => item.id)
+                this.$api.syllabus.SaveOrUpdateAsNodes([this.currentNodeInfo]).then(res => {
+                    if (!res.error && res.result.data) {
+                        this.$emit("addPointsFinish", res.result.data)
+                        this.isLoading = false
+                    } else {
+                        this.$Message.warning("获取数据失败")
+                    }
+                })
+                
+            },
+
+            isEqual(arr1, arr2) {
+                return (JSON.stringify(arr1) === JSON.stringify(arr2))
+            }
+
+
+
+        },
+        mounted() {
+        },
+        watch: {
+            // 监听册别数据变化
+            volume: {
+                handler: function (n, o) {
+                    this.currentVolume = n
+                    this.currentParams = {
+                        subjectCode: n.subjectCode,
+                        schoolCode: n.schoolCode,
+                        period: n.periodCode
+                    }
+                    this.getSchoolBlocks()
+                },
+                deep:true
+            },
+            // 监听册别数据变化
+            currentNode: {
+                handler: function (n, o) {
+                    this.currentNodeInfo = n
+                    this.onChangeOrigin(0)
+                    this.checkedPoints = n.knowledges
+                    this.originPoints = n.knowledges
+                    this.hasModify = false
+                },
+                deep:true
+            },
+
+        },
+
+    }
+</script>
+
+<style scoped>
+    .knowledge-container {
+        width: 100%;
+        height: 100%;
+        background: #464646;
+        border-radius:4px;
+        overflow:hidden;
+    }
+
+        .knowledge-container .select-wrap {
+            width:100%;
+            height:60%;
+        }
+
+        .knowledge-container .select-content {
+            display:flex;
+            height:320px;
+            border-top:1px solid #565656;
+            border-bottom:1px solid #565656;
+        }
+
+        .knowledge-container .show-wrap{
+            width:100%;
+            height:auto;
+        }
+
+        .knowledge-container .point-box {
+            padding:30px 10px;
+            height:300px;
+            border-top:1px solid #565656;
+            border-bottom:1px solid #565656;
+
+
+        }
+            .knowledge-container .show-wrap .checked-point-item {
+                padding:5px 20px;
+                color:#fff;
+                background:#6d6d6d;
+                margin:10px;
+                border-radius:50px;
+                display:inline-block;
+                cursor:pointer;
+            }
+
+        .knowledge-container .wrap-title {
+            position:relative;
+            font-size:16px;
+            font-weight:bold;
+            color:#fff;
+            width:100%;
+            height:50px;
+            line-height:50px;
+            padding-left:20px;
+            background:#525252;
+        }
+
+            .knowledge-container .wrap-title .ivu-btn {
+                position:absolute;
+                right:20px;
+                top:10px;
+                width:100px;
+                height:30px;
+                background:#0f9272;
+                color:#fff;
+                border:none;
+             }
+
+    .knowledge-left {
+        width: 18%;
+        border-right: 1px solid #565656;
+    }
+
+        .knowledge-left .knowledge-left-item {
+            width: 100%;
+            height: 25%;
+            display:flex;
+            justify-content:center;
+            align-items:center;
+            color: #fff;
+            font-size: 14px;
+            font-weight: bold;
+            border-bottom: 1px solid #565656;
+            cursor: pointer;
+        }
+
+        .knowledge-left .item-active {
+            background:#0f9272;
+        }
+
+    .knowledge-right {
+        width:82%;
+        height:100%;
+        padding:0 10px 0 20px;
+        overflow:hidden;
+    }
+
+
+
+    .knowledge-container /deep/ .__view {
+        min-height:unset !important;
+    }
+
+
+    .knowledge-container /deep/ .ivu-checkbox-checked .ivu-checkbox-inner,
+    .knowledge-container /deep/ .ivu-checkbox-indeterminate .ivu-checkbox-inner {
+        border-color: #0f9272;
+        background: #0f9272;
+    }
+
+    .knowledge-container /deep/ .ivu-tree-title-selected,
+    .knowledge-container /deep/ .ivu-tree-title-selected:hover,
+    .knowledge-container /deep/ .ivu-tree-title:hover {
+        background:transparent;
+    }
+
+    .knowledge-container .el-tree {
+            background: transparent;
+            color: #fff;
+            padding-top: 10px;
+            padding-bottom: 100px;
+        }
+
+        .knowledge-container .el-tree-node__content {
+            height: 50px;
+        }
+
+            .knowledge-container .el-tree-node__content:hover {
+                height: 50px;
+                background: #464646;
+            }
+
+        .knowledge-container .el-tree-node:focus > .el-tree-node__content {
+            background: #464646;
+        }
+
+        .knowledge-container .el-tree__empty-block {
+            display: none;
+        }
+
+    .knowledge-container /deep/ .el-tree-node__content {
+        height:36px;
+    }
+
+    .knowledge-container /deep/ .el-tree-node__content:hover,
+    .knowledge-container /deep/ .el-tree-node:focus>.el-tree-node__content{
+        background:#565656;
+    }
+
+    .knowledge-container /deep/ .el-checkbox__input.is-checked .el-checkbox__inner,
+    .knowledge-container /deep/ .el-checkbox__input.is-indeterminate .el-checkbox__inner {
+        border-color: #0f9272;
+        background: #0f9272;
+    }
+</style>

+ 38 - 0
TEAMModelOS/ClientApp/src/view/syllabus/newSyllabus/operation/BaseResource.vue

@@ -0,0 +1,38 @@
+
+<template>
+    <div class="resource-container">
+
+    </div>
+</template>
+
+<script>
+    export default {
+        props: [],
+        data() {
+            return {
+               
+            }
+        },
+
+        created() {
+
+        },
+        methods: {
+           
+        },
+        mounted() {
+        },
+        watch: {
+            
+        },
+
+    }
+</script>
+
+<style scoped>
+    .resource-container {
+        width:100%;
+        height:100%;
+        background:#464646;
+    }
+</style>

+ 19 - 5
TEAMModelOS/ClientApp/src/view/syllabus/newSyllabus/operation/addVolume.vue

@@ -29,12 +29,13 @@
 
 <script>
     export default {
-        props: ['originData', 'periodIndex','subjectIndex','editVolume'],
+        props: ['originData', 'periodIndex','subjectIndex','editVolume','addType'],
         data() {
             return {
                 originDatas: {},
                 currentPeriod: {},
                 editItem: {},
+                addVolumeType:'school',
                 formTop: {
                     subject: '',
                     grade: '',
@@ -50,10 +51,8 @@
         methods: {
             // 提交添加
             handleSubmit() {
-                console.log("提交的ITEM")
-                console.log(this.editItem)
                 let params = {
-                    type: 0,
+                    type: this.addVolumeType === 'school' ? 0 : 1,
                     schoolCode: this.originDatas.schoolCode,
                     periodCode: this.currentPeriod.periodCode,
                     subjectCode: this.currentPeriod.subjects[this.subjectIndex].subjectCode,
@@ -62,7 +61,13 @@
                     volumeName: this.getNewVolumeName(),
                     status: 1
                 }
-                if (this.editItem) { params.id = this.editItem.id }
+                if (this.editItem) {
+                    params.id = this.editItem.id
+                    params.volumeCode = this.editItem.volumeCode
+                }
+                if (this.addVolumeType === 'private') {
+                    params.TEAMModelId = 'habook#0001'
+                }
                 this.$api.syllabus.SaveOrUpdateVolume(params).then(res => {
                     if (!res.error && res.result.data) {
                         this.$emit('addFinish',res.result.data.id)
@@ -97,6 +102,14 @@
         mounted() {
         },
         watch: {
+            addType: {
+                handler(newValue, oldValue) {
+                    if (newValue) {
+                        this.addVolumeType = newValue
+                    }
+
+                },
+            },
             originData: {
                 handler(newValue, oldValue) {
                     this.originDatas = newValue
@@ -129,6 +142,7 @@
                         this.formTop.grade = this.currentPeriod.grades[0].gradeCode
                         this.formTop.semester = this.currentPeriod.semesters[0].semesterCode
                         this.formTop.volume = ""
+                        this.editItem = newValue
                     }
                     
                 },

+ 2 - 1
TEAMModelOS/ClientApp/vue.config.js

@@ -15,5 +15,6 @@ module.exports = {
             filename: 'silent-renew-oidc.html',
             excludeChunks: ['app']
         }
-    }
+    },
+
 }

+ 1 - 1
TEAMModelOS/Controllers/Core/StudentController.cs

@@ -77,7 +77,7 @@ namespace TEAMModelOS.Controllers.Syllabus
             List<Student> students = new List<Student>();
             foreach (string key in dictInfo.Keys)
             {
-                List<Classroom> classrooms = await azureCosmosDBRepository.FindByParams<Classroom>(new Dictionary<string, object> { { "classroomCode", key } });
+                List<Classroom> classrooms = await azureCosmosDBRepository.FindByDict<Classroom>(new Dictionary<string, object> { { "classroomCode", key } } ,true);
                 if (classrooms.IsNotEmpty())
                 {
                     long createDate = DateTimeOffset.UtcNow.Ticks;

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

@@ -334,7 +334,7 @@ namespace TEAMModelOS.Controllers.Syllabus
         {
             Type t = typeof(T);
             string message = "";
-            List<T> schoolBlocks = await _cosmos.FindByParams<T>(new Dictionary<string, object> {
+            List<T> schoolBlocks = await _cosmos.FindByDict<T>(new Dictionary<string, object> {
                 { "id", t.GetProperty("id").GetValue(schoolBlock) }
             });
             if (schoolBlocks.IsNotEmpty())
@@ -394,7 +394,7 @@ namespace TEAMModelOS.Controllers.Syllabus
 
         private async Task Delete<T>(JosnRPCRequest<Dictionary<string, object>> request, JsonRPCResponseBuilder builder)
         {
-            List<T> schoolBlocks = await _cosmos.FindByParams<T>(request.@params);
+            List<T> schoolBlocks = await _cosmos.FindByDict<T>(request.@params,true);
             if (schoolBlocks.IsNotEmpty())
             {
                 schoolBlocks.ForEach(x => { _cosmos.DeleteAsync<T>(x); });

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

@@ -80,7 +80,7 @@ namespace TEAMModelOS.Controllers.Syllabus
             if (request.@params != null)
             {
                 List<SyllabusResource> data = new List<SyllabusResource>();
-                data = await _cosmos.FindByParams<SyllabusResource>(request.@params);
+                data = await _cosmos.FindByDict<SyllabusResource>(request.@params);
                 if (data.IsNotEmpty()) {
                 return builder.Data(data.OrderBy(m => m.createTime)).Extend(new Dictionary<string, object> { { "count", data.Count } }).build();
 
@@ -107,7 +107,7 @@ namespace TEAMModelOS.Controllers.Syllabus
 
         private async Task Delete<T>(JosnRPCRequest<Dictionary<string, object>> request, JsonRPCResponseBuilder builder)
         {
-            List<T> schoolBlocks = await _cosmos.FindByParams<T>(request.@params);
+            List<T> schoolBlocks = await _cosmos.FindByDict<T>(request.@params,true);
             Type t = typeof(T);
             if (schoolBlocks.IsNotEmpty())
             {

+ 1 - 1
TEAMModelOS/Controllers/Syllabus/SyllabusController.cs

@@ -149,7 +149,7 @@ namespace TEAMModelOS.Controllers.Syllabus
         public async Task<BaseJosnRPCResponse> Find(JosnRPCRequest<Dictionary<string, object>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            List<SyllabusNode> data =await azureCosmosDBRepository.FindByParams<SyllabusNode>(request.@params);
+            List<SyllabusNode> data =await azureCosmosDBRepository.FindByDict<SyllabusNode>(request.@params);
 
             if (request.@params.TryGetValue("id", out object id))
             {

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

@@ -170,7 +170,7 @@ namespace TEAMModelOS.Controllers.Syllabus
             List<Volume> volumes ;
             if (request.@params.TryGetValue("schoolCode", out _))
             {
-                volumes = await azureCosmosDBRepository.FindByParams<Volume>(request.@params);
+                volumes = await azureCosmosDBRepository.FindByDict<Volume>(request.@params,true);
             }
             else
             {

+ 1 - 0
TEAMModelOS/Models/CommonQuery.cs

@@ -9,5 +9,6 @@ namespace TEAMModelOS.Models
     {
         public string collectionName { get; set; }
         public Dictionary<string ,object> queryDict { get; set; }
+      
     }
 }

+ 6 - 2
TEAMModelOS/Startup.cs

@@ -23,6 +23,8 @@ using TEAMModelOS.SDK.Extension.JwtAuth;
 using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
 using TEAMModelOS.SDK.Module.AzureCosmosDB.Configuration;
 using TEAMModelOS.SDK.Module.AzureTable.Configuration;
+using TEAMModelOS.SDK.Module.AzureTable.Implements;
+using TEAMModelOS.SDK.Module.AzureTable.Interfaces;
 using VueCliMiddleware;
 
 namespace TEAMModelOS
@@ -102,8 +104,10 @@ namespace TEAMModelOS
                 x.MultipartBodyLengthLimit = long.MaxValue; // In case of multipart
                 x.MultipartHeadersLengthLimit = int.MaxValue;
             });
+
+
             // TableÅäÖÃ
-            services.AddAzureTableStorage().AddConnection(Configuration.GetSection("Azure:Table").Get<AzureTableOptions>());
+            services.AddScoped<IAzureTableDBRepository, AzureTableDBRepository>();
             //ʹÓÃBlobÅäÖÃ
             services.AddAzureBlobStorage().AddConnection(Configuration.GetSection("Azure:Blob").Get<AzureBlobOptions>());
             //ʹÓÃCosmosDB
@@ -118,7 +122,7 @@ namespace TEAMModelOS
             services.Scan(scan => scan.FromApplicationDependencies()
                .AddClasses(classes => classes.AssignableTo<IBusinessService>())
                    .AsImplementedInterfaces()
-                   .WithSingletonLifetime());
+                   .WithScopedLifetime());
         }
      
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.