Ver Fonte

調整Code中,可啟動,尚未完成

JAELYS há 4 anos atrás
pai
commit
6a69135351
39 ficheiros alterados com 2313 adições e 1057 exclusões
  1. 0 1
      TEAMModelFunction/MonitorCosmosDB.cs
  2. 0 1
      TEAMModelFunction/Startup.cs
  3. 5 2
      TEAMModelFunction/TEAMModelFunction.csproj
  4. 5 5
      TEAMModelGrpc/Startup.cs
  5. 30 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosExtensions.cs
  6. 45 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactory.cs
  7. 22 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryExtensions.cs
  8. 14 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryOptions.cs
  9. 18 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisExtensions.cs
  10. 47 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactory.cs
  11. 22 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryExtensions.cs
  12. 14 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryOptions.cs
  13. 33 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs
  14. 173 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs
  15. 22 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryExtensions.cs
  16. 14 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryOptions.cs
  17. 232 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageTableExtensions.cs
  18. 114 0
      TEAMModelOS.SDK/DI/DingDing/DingDing.cs
  19. 154 0
      TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeID.cs
  20. 28 0
      TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDExtensions.cs
  21. 20 0
      TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDOptions.cs
  22. 22 0
      TEAMModelOS.SDK/Extension/EnumExtensions.cs
  23. 94 0
      TEAMModelOS.SDK/Extension/HttpContextExtensions.cs
  24. 52 0
      TEAMModelOS.SDK/Extension/JsonExtensions.cs
  25. 94 0
      TEAMModelOS.SDK/Extension/Utils.cs
  26. 44 44
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobServiceCollectionExtensions.cs
  27. 38 38
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobClientSingleton.cs
  28. 0 1
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobFileDto.cs
  29. 912 914
      TEAMModelOS.SDK/Module/AzureBlob/Implements/AzureBlobDBRepository.cs
  30. 1 2
      TEAMModelOS.SDK/Module/AzureBlob/Interfaces/IAzureBlobDBRepository.cs
  31. 5 1
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  32. 4 3
      TEAMModelOS/Controllers/Client/HiTeachController.cs
  33. 0 1
      TEAMModelOS/Controllers/Core/FileController.cs
  34. 1 2
      TEAMModelOS/Controllers/Task/VoteController.cs
  35. 1 2
      TEAMModelOS/Controllers/Teacher/SchoolUserController.cs
  36. 1 2
      TEAMModelOS/Controllers/Test/TestAPIController.cs
  37. 29 33
      TEAMModelOS/Startup.cs
  38. 0 2
      TEAMModelOS/TEAMModelOS.csproj
  39. 3 3
      TEAMModelOS/appsettings.json

+ 0 - 1
TEAMModelFunction/MonitorCosmosDB.cs

@@ -2,7 +2,6 @@ using System;
 using System.Collections.Generic;
 using System.Net.Http;
 using System.Threading.Tasks;
-using CoreSDK.DingDing;
 using Microsoft.Azure.Documents;
 using Microsoft.Azure.WebJobs;
 using Microsoft.Azure.WebJobs.Host;

+ 0 - 1
TEAMModelFunction/Startup.cs

@@ -1,4 +1,3 @@
-using CoreSDK.DingDing;
 using Microsoft.Azure.Functions.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection;
 using System;

+ 5 - 2
TEAMModelFunction/TEAMModelFunction.csproj

@@ -4,11 +4,14 @@
     <AzureFunctionsVersion>v3</AzureFunctionsVersion>
   </PropertyGroup>
   <ItemGroup>
-    <PackageReference Include="CoreSDK" Version="1.0.0" />
+    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
     <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.7" />
-    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="4.1.0" />
+    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="4.1.2" />
     <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
   </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\TEAMModelOS.SDK\TEAMModelOS.SDK.csproj" />
+  </ItemGroup>
   <ItemGroup>
     <None Update="host.json">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

+ 5 - 5
TEAMModelGrpc/Startup.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.IdentityModel.Tokens.Jwt;
 using System.Linq;
@@ -76,12 +76,12 @@ namespace TEAMModelGrpc
                 });
 
             // Table配置
-            services.AddScoped<IAzureTableDBRepository, AzureTableDBRepository>();
+            //services.AddScoped<IAzureTableDBRepository, AzureTableDBRepository>();
             //使用Blob配置
-            services.AddAzureBlobStorage().AddConnection(_conf.GetSection("Azure:Blob").Get<AzureBlobOptions>());
+            //services.AddAzureBlobStorage().AddConnection(_conf.GetSection("Azure:Blob").Get<AzureBlobOptions>());
             //使用CosmosDB
-            services.AddAzureCosmosDBV3().AddCosmosDBV3Connection(_conf.GetSection("Azure:CosmosDB").Get<AzureCosmosDBOptions>())
-                .AddCosmosSerializer(new SystemTextJsonCosmosSerializer(new JsonSerializerOptions() { IgnoreNullValues = true }));
+            //services.AddAzureCosmosDBV3().AddCosmosDBV3Connection(_conf.GetSection("Azure:CosmosDB").Get<AzureCosmosDBOptions>())
+            //    .AddCosmosSerializer(new SystemTextJsonCosmosSerializer(new JsonSerializerOptions() { IgnoreNullValues = true }));
  
             //注入CSRedis
             var csredis = new CSRedis.CSRedisClient(_conf.GetSection("Azure:Redis:ConnectionString").Get<string>());

+ 30 - 0
TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosExtensions.cs

@@ -0,0 +1,30 @@
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Azure.Cosmos.Table.Queryable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+using Azure;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureCosmosExtensions
+    {
+        public static int RU(this Response response)
+        {
+            try
+            {
+                response.Headers.TryGetValue("x-ms-request-charge", out var value);
+                var ru = Convert.ToInt32(value);
+                return ru;
+            }
+            catch (Exception)
+            {
+                return 0;
+            }
+        }
+    }
+}

+ 45 - 0
TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactory.cs

@@ -0,0 +1,45 @@
+using Azure.Cosmos;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Concurrent;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureCosmosFactory
+    {
+        private readonly IServiceProvider _services;
+        private readonly IOptionsMonitor<AzureCosmosFactoryOptions> _optionsMonitor;
+        private readonly ILogger _logger;
+        private ConcurrentDictionary<string, CosmosClient> CosmosClients { get; } = new ConcurrentDictionary<string, CosmosClient>();
+        public AzureCosmosFactory(IServiceProvider services, IOptionsMonitor<AzureCosmosFactoryOptions> optionsMonitor, ILogger<AzureCosmosFactory> logger)
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));
+            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));
+
+            _services = services;
+            _optionsMonitor = optionsMonitor;
+            _logger = logger;
+        }
+
+        /// <summary>
+        /// 取得CosmosClient,支持安全執行緒
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="region">可以使用Regions.{區域}設置,指定此屬性後,SDK會首選該區域來執行操作。此外,SDK會自動選擇後備的地理複製區域以實現高可用性。如果未指定此屬性,則SDK會將寫區域用作所有操作的首選區域</param>
+        /// <returns></returns>
+        public CosmosClient GetCosmosClient( string region = null, string name="Default")
+        {            
+            try
+            {
+                var cm = CosmosClients.GetOrAdd(name, x => new CosmosClient(_optionsMonitor.Get(name).CosmosConnectionString, new CosmosClientOptions() { ApplicationRegion = region }));
+                return cm;
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+    }
+}

+ 22 - 0
TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryExtensions.cs

@@ -0,0 +1,22 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureCosmosFactoryExtensions
+    {
+        public static IServiceCollection AddAzureCosmos(this IServiceCollection services, string connectionString, string name = "Default")
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));            
+            if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
+
+            services.TryAddSingleton<AzureCosmosFactory>();
+            services.Configure<AzureCosmosFactoryOptions>(name, o => { o.Name = name; o.CosmosConnectionString = connectionString; });
+
+            return services;
+        }
+    }
+}

+ 14 - 0
TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryOptions.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureCosmosFactoryOptions
+    {
+        public string Name { get; set; }
+        public string CosmosConnectionString { get; set; }
+    }
+
+   
+}

+ 18 - 0
TEAMModelOS.SDK/DI/AzureRedis/AzureRedisExtensions.cs

@@ -0,0 +1,18 @@
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Azure.Cosmos.Table.Queryable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+using StackExchange.Redis;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureRedisExtensions
+    {
+       
+    }
+}

+ 47 - 0
TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactory.cs

@@ -0,0 +1,47 @@
+
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Extensions.DependencyInjection;
+using Azure.Storage.Blobs;
+using Azure.Storage.Blobs.Models;
+using Azure.Storage.Blobs.Specialized;
+using StackExchange.Redis;
+using System.Collections.Concurrent;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureRedisFactory
+    {
+        private readonly IServiceProvider _services;
+        private readonly IOptionsMonitor<AzureRedisFactoryOptions> _optionsMonitor;
+        private readonly ILogger _logger;
+        private ConcurrentDictionary<string, ConnectionMultiplexer> ConnectionMultiplexers { get; } = new ConcurrentDictionary<string, ConnectionMultiplexer>();
+        public AzureRedisFactory(IServiceProvider services, IOptionsMonitor<AzureRedisFactoryOptions> optionsMonitor, ILogger<AzureRedisFactory> logger)
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));
+            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));
+
+            _services = services;
+            _optionsMonitor = optionsMonitor;
+            _logger = logger;
+        }
+
+        public IDatabase GetRedisClient( int dbnum = -1,string name = "Default")
+        {           
+            try
+            {
+                var cm = ConnectionMultiplexers.GetOrAdd(name, x => ConnectionMultiplexer.Connect(_optionsMonitor.Get(name).RedisConnectionString));
+                return cm.GetDatabase(dbnum);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+    }
+}

+ 22 - 0
TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryExtensions.cs

@@ -0,0 +1,22 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureRedisFactoryExtensions
+    {
+        public static IServiceCollection AddAzureRedis(this IServiceCollection services, string connectionString, string name = "Default")
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));            
+            if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
+
+            services.TryAddSingleton<AzureRedisFactory>();
+            services.Configure<AzureRedisFactoryOptions>(name, o => { o.Name = name; o.RedisConnectionString = connectionString; });
+
+            return services;
+        }
+    }
+}

+ 14 - 0
TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryOptions.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureRedisFactoryOptions
+    {
+        public string Name { get; set; }
+        public string RedisConnectionString { get; set; }
+    }
+
+   
+}

+ 33 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs

@@ -0,0 +1,33 @@
+using System.Threading.Tasks;
+using Azure.Storage;
+using Azure.Storage.Blobs;
+using Azure.Storage.Blobs.Models;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureStorageBlobExtensions
+    {
+        /// <summary>
+        /// 取得指定前置詞的 Blob 名稱的總大小(Bytes),例如指定目錄名稱為前置詞
+        /// </summary>      
+        /// <param name="prefix">篩選開頭名稱,Null代表容器總大小</param>
+        /// <returns>總大小(Bytes),如果為Null代表查無前置詞或者發生錯誤</returns>
+        public static async Task<long?> GetBlobsSize(this BlobContainerClient client, string prefix = null)
+        {
+            long? size = 0;
+            try
+            {                
+                await foreach (var item in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, prefix))
+                {
+                    size += item.Properties.ContentLength;
+                };
+
+                return size;
+            }
+            catch 
+            {
+                return null;
+            }
+        }
+    }
+}

+ 173 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs

@@ -0,0 +1,173 @@
+
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Extensions.DependencyInjection;
+using Azure.Storage.Blobs;
+using Azure.Storage.Blobs.Models;
+using Azure.Storage.Blobs.Specialized;
+using Azure.Storage.Sas;
+using Azure.Storage;
+using TEAMModelOS.SDK.Extension;
+using Azure.Storage.Queues;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureStorageFactory
+    {
+        private readonly IServiceProvider _services;
+        private readonly IOptionsMonitor<AzureStorageFactoryOptions> _optionsMonitor;
+        private readonly ILogger _logger;
+        public AzureStorageFactory(IServiceProvider services, IOptionsMonitor<AzureStorageFactoryOptions> optionsMonitor, ILogger<AzureStorageFactory> logger)
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));
+            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));
+
+            _services = services;
+            _optionsMonitor = optionsMonitor;
+            _logger = logger;
+        }
+
+        public BlobServiceClient GetBlobServiceClient(string name = "Default")
+        {            
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                return new BlobServiceClient(options.StorageAccountConnectionString);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+
+        }
+
+        public BlobContainerClient GetBlobContainerClient(string containerName, string name = "Default")
+        {            
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                return new BlobContainerClient(options.StorageAccountConnectionString, containerName);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+
+        public BlobBatchClient GetBlobBatchClient(string name = "Default")
+        {           
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                BlobServiceClient blobServiceClient = new BlobServiceClient(options.StorageAccountConnectionString);
+                return blobServiceClient.GetBlobBatchClient();
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 取得Blob SAS (有效期預設一天)
+        /// </summary>       
+        public string GetBlobSAS(string containerName, string blobName, BlobSasPermissions blobSasPermissions, string name = "Default")
+        {
+            try
+            {
+                var keys = Utils.ParseConnectionString(_optionsMonitor.Get(name).StorageAccountConnectionString);
+                var accountname = keys["AccountName"];
+                var accountkey = keys["AccountKey"];
+                var endpoint = keys["EndpointSuffix"];
+
+                var blobSasBuilder = new BlobSasBuilder
+                {
+                    StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
+                    ExpiresOn = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0)),
+                    BlobContainerName = containerName
+                };
+
+                blobSasBuilder.SetPermissions(blobSasPermissions);
+                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
+                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
+                UriBuilder fullUri = new UriBuilder()
+                {
+                    Scheme = "https",
+                    Host = $"{accountname}.blob.{endpoint}",
+                    Path = blobName,
+                    Query = sasQueryParameters.ToString()
+                };
+
+                return sasQueryParameters.ToString();
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        public CloudTableClient GetCloudTableClient(string name = "Default")
+        {            
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(options.StorageAccountConnectionString);
+                return storageAccount.CreateCloudTableClient();
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+
+       
+
+        /// <summary>
+        /// 可讓您管理儲存體帳戶中的所有佇列
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public QueueServiceClient GetQueueServiceClient(string name = "Default")
+        {            
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                return new QueueServiceClient(options.StorageAccountConnectionString);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 可讓您管理和操作個別佇列及其訊息
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="queueName"></param>
+        /// <returns></returns>
+        public QueueClient GetQueueClient(string queueName, string name = "Default")
+        {
+            if (name == null) throw new ArgumentNullException(nameof(name));
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                return new QueueClient(options.StorageAccountConnectionString, queueName);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+    }
+}

+ 22 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryExtensions.cs

@@ -0,0 +1,22 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureStorageFactoryExtensions
+    {
+        public static IServiceCollection AddAzureStorage(this IServiceCollection services, string connectionString,string name = "Default")
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));            
+            if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
+
+            services.TryAddSingleton<AzureStorageFactory>();
+            services.Configure<AzureStorageFactoryOptions>(name, o => { o.Name = name; o.StorageAccountConnectionString = connectionString; });
+
+            return services;
+        }
+    }
+}

+ 14 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryOptions.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureStorageFactoryOptions
+    {
+        public string Name { get; set; }
+        public string StorageAccountConnectionString { get; set; }
+    }
+
+   
+}

+ 232 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageTableExtensions.cs

@@ -0,0 +1,232 @@
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Azure.Cosmos.Table.Queryable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureStorageTableExtensions
+    {
+
+        #region CloudTable 批次操作    
+
+        /// <summary>
+        /// 批次新增資料至Table儲存區。
+        /// </summary>
+        /// <param name="entities">欲快取的集合</param>
+        /// <returns></returns>
+        public static async Task<TableBatchResult> BatchInsertAsync<T>(this CloudTable table, IEnumerable<T> entities) where T : ITableEntity, new()
+        {
+            TableBatchOperation batchOperation = new TableBatchOperation();
+            foreach (var cache in entities)
+            {
+                batchOperation.Insert(cache);
+            }
+
+            return await table.ExecuteBatchAsync(batchOperation);
+        }
+
+        #endregion
+
+        #region CloudTable Get
+
+        /// <summary>
+        /// (同步)取得 table 中指定 PartitionKey 的所有集合。
+        /// </summary>
+        /// <returns></returns>
+        public static IEnumerable<T> Get<T>(this CloudTable table, string partitionKey) where T : ITableEntity, new()
+        {
+            TableQuery<T> query = new TableQuery<T>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey));
+            return table.ExecuteQuery(query);
+        }
+
+        /// <summary>
+        /// (同步)取得指定 PartitionKey與 RowKey 的數據,效能:點查詢,最佳。
+        /// </summary>
+        /// <typeparam name="T">T</typeparam>       
+        /// <param name="partitionKey">PartitionKey</param>   
+        /// <param name="rowKey">RowKey</param>  
+        /// <returns></returns>
+        public static T Get<T>(this CloudTable table, string partitionKey, string rowKey) where T : ITableEntity, new()
+        {
+            TableOperation retrieveOperation = TableOperation.Retrieve<T>(partitionKey, rowKey);
+            var retrieveResult = table.Execute(retrieveOperation);
+            if (retrieveResult.Result != null)
+            {
+                //DynamicTableEntityJsonSeria1lizer
+                return (T)retrieveResult.Result;
+            }
+            else
+            {
+                return default(T);
+            }
+        }
+
+        public static DynamicTableEntity Get(this CloudTable table, string partitionKey, string rowKey)
+        {
+            TableOperation retrieveOperation = TableOperation.Retrieve(partitionKey, rowKey);
+            var retrieveResult = table.Execute(retrieveOperation);
+            if (retrieveResult.Result != null)
+            {
+                return retrieveResult.Result as DynamicTableEntity;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 取得指定 PartitionKey 的所有集合(分頁),效能:範圍查詢,次佳。
+        /// </summary>
+        /// <typeparam name="T">T</typeparam>       
+        /// <param name="partitionKey">PartitionKey</param>
+        /// <param name="takeCount">指定每次返回數量</param>
+        /// <param name="specifyPropertys">指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本</param>
+        /// <param name="onProgress">要返回集合的委派</param>
+        /// <param name="ct">CancellationToken</param>
+        /// <returns></returns>
+        public static async Task GetAsync<T>(this CloudTable table, string partitionKey, int? takeCount = null, List<string> specifyPropertys = null, Action<IList<T>> onProgress = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
+        {
+            TableQuery<T> tableQuery = null;
+            TableContinuationToken token = null;
+            var filter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey);
+
+            if (specifyPropertys != null)
+                tableQuery = new TableQuery<T>().Where(filter).Select(specifyPropertys);
+            else
+                tableQuery = new TableQuery<T>().Where(filter);
+
+            if (takeCount != null) tableQuery.TakeCount = takeCount;
+
+            do
+            {
+                var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
+                token = queryResponse.ContinuationToken;
+                onProgress?.Invoke(queryResponse.Results);
+            } while (token != null && !ct.IsCancellationRequested);
+        }
+
+        /// <summary>
+        /// 取得指定 PartitionKey 的所有集合,效能:範圍查詢,次佳。
+        /// </summary>
+        /// <typeparam name="T">T</typeparam>       
+        /// <param name="partitionKey">PartitionKey</param>
+        /// <param name="takeCount">指定每次返回數量</param>
+        /// <param name="specifyPropertys">指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本</param>
+        /// <param name="onProgress">要返回集合的委派</param>
+        /// <param name="ct">CancellationToken</param>
+        /// <returns></returns>
+        public static async Task<IEnumerable<T>> GetAsync<T>(this CloudTable table, string partitionKey, int? takeCount = null, List<string> specifyPropertys = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
+        {
+            TableQuery<T> tableQuery = null;
+            TableContinuationToken token = null;
+            var filter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey);
+
+            if (specifyPropertys != null)
+                tableQuery = new TableQuery<T>().Where(filter).Select(specifyPropertys);
+            else
+                tableQuery = new TableQuery<T>().Where(filter);
+
+            if (takeCount != null) tableQuery.TakeCount = takeCount;
+            var items = new List<T>();
+
+            do
+            {
+                var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
+                token = queryResponse.ContinuationToken;
+                items.AddRange(queryResponse.Results);
+            } while (token != null && !ct.IsCancellationRequested);
+            return items;
+        }
+
+        /// <summary>
+        /// 傳回指定partitionKey的Count數量
+        /// </summary>        
+        /// <param name="partitionKey"></param>
+        /// <returns></returns>
+        public static int GetCount(this CloudTable table, string partitionKey)
+        {           
+
+            TableQuery query = new TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey)).Select(new List<string> { "PartitionKey" });
+            var queryResponse = table.ExecuteQuery(query).ToList();
+            return queryResponse.Count();
+        }
+
+
+
+        #endregion
+
+        #region CloudTable Get All
+        /// <summary>
+        /// (同步)取得 table 的所有集合,效能:資料表掃描,不佳。
+        /// </summary>
+        /// <returns></returns>
+        public static IEnumerable<T> GetAll<T>(this CloudTable table) where T : ITableEntity, new()
+        {
+            return table.ExecuteQuery(new TableQuery<T>());
+        }
+
+        /// <summary>
+        /// 取得 table 的所有集合(分頁),效能:資料表掃描,不佳。
+        /// </summary>
+        /// <param name="takeCount">指定每次返回數量</param>
+        /// <param name="specifyPropertys">指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本</param>
+        /// <param name="onProgress">要返回集合的委派</param>
+        /// <returns></returns>        
+        public static async Task GetAllAsync<T>(this CloudTable table, int? takeCount = null, List<string> specifyPropertys = null, Action<IList<T>> onProgress = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
+        {
+            TableContinuationToken token = null;
+            TableQuery<T> tableQuery = new TableQuery<T>();
+            if (specifyPropertys != null)
+                tableQuery = new TableQuery<T>().Select(specifyPropertys);
+            else
+                tableQuery = new TableQuery<T>();
+            if (takeCount != null) tableQuery.TakeCount = takeCount;
+            var items = new List<T>();
+
+            do
+            {
+                var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
+                token = queryResponse.ContinuationToken;
+                items.AddRange(queryResponse.Results);
+                onProgress?.Invoke(queryResponse.Results);
+            } while (token != null && !ct.IsCancellationRequested);
+        }
+
+        /// <summary>
+        /// 取得 table 的所有集合,效能:資料表掃描,不佳。
+        /// </summary>
+        /// <param name="takeCount">指定每次返回數量</param>
+        /// <param name="specifyPropertys">指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本</param>       
+        /// <returns></returns>        
+        public static async Task<IEnumerable<T>> GetAllAsync<T>(this CloudTable table, int? takeCount = null, List<string> specifyPropertys = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
+        {
+            TableContinuationToken token = null;
+            TableQuery<T> tableQuery = new TableQuery<T>();
+            if (takeCount != null) tableQuery.TakeCount = takeCount;
+            if (specifyPropertys != null)
+                tableQuery = new TableQuery<T>().Select(specifyPropertys);
+            else
+                tableQuery = new TableQuery<T>();
+            var items = new List<T>();
+
+            do
+            {
+                var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
+                token = queryResponse.ContinuationToken;
+                items.AddRange(queryResponse.Results);
+            } while (token != null && !ct.IsCancellationRequested);
+            return items;
+        }
+        #endregion
+
+
+
+    }
+}

+ 114 - 0
TEAMModelOS.SDK/DI/DingDing/DingDing.cs

@@ -0,0 +1,114 @@
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Net.Http;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Security.Cryptography;
+using TEAMModelOS.SDK.Extension;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class DingDing
+    {
+        private const string url = "https://oapi.dingtalk.com/robot/send?access_token=";
+        private readonly HttpClient _httpClient;
+
+        public DingDing(HttpClient httpClient)
+        {
+            _httpClient = httpClient;
+        }
+
+        // <summary>
+        /// 發送需要加簽驗證的Bot訊息(msgtype為text)
+        /// </summary>
+        /// <param name="robotUrl">釘釘Robot發送Url</param>
+        /// <param name="secret">加簽密鑰</param>
+        /// <param name="msg">發送訊息</param>
+        /// <returns></returns>
+        public async Task SendBotMsg(string msg, GroupNames groupkey)
+        {
+            JObject jObject = new JObject()
+            {
+                new JProperty("msgtype","text"),
+                new JProperty("text",new JObject(
+                    new JProperty("content",msg)))
+            };
+            var content = new StringContent(jObject.ToString(), Encoding.UTF8, "application/json");
+            var keys = groupkey.GetDescriptionText().Split(',');
+            if (keys.Length == 1) await _httpClient.PostAsync($"{url}{keys[0]}", content);
+            else
+            {
+                var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                await _httpClient.PostAsync($"{url}{keys[0]}&timestamp={timestamp}&sign={BotAddSign(keys[1], timestamp)}", content);
+            }
+        }
+
+        // <summary>
+        /// 發送需要加簽驗證的Bot訊息(msgtype為text)
+        /// </summary>
+        /// <param name="robotUrl">釘釘Robot發送Url</param>
+        /// <param name="secret">加簽密鑰</param>
+        /// <param name="msg">發送訊息</param>
+        /// <returns></returns>
+        public async Task SendBotMsg(string msg, string accesstoken, string secret = null)
+        {
+            JObject jObject = new JObject()
+            {
+                new JProperty("msgtype","text"),
+                new JProperty("text",new JObject(
+                    new JProperty("content",msg)))
+            };
+
+            var content = new StringContent(jObject.ToString(), Encoding.UTF8, "application/json");
+            if (string.IsNullOrWhiteSpace(secret))
+                await _httpClient.PostAsync($"{url}{accesstoken}", content);
+            else
+            {
+                var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                await _httpClient.PostAsync($"{url}{accesstoken}&timestamp={timestamp}&sign={BotAddSign(secret, timestamp)}", content);
+            }
+
+
+        }
+
+        #region private
+        /// <summary>
+        /// 釘釘Bot簽名生成方法
+        /// </summary>
+        /// <param name="zTime"></param>
+        /// <returns></returns>
+        private static string BotAddSign(string secret, long zTime)
+        {
+            //"SEC6a6822db6567f79854a474002407cd9ac36da4d194b5fb79e073c35ef61119ed";
+            string stringToSign = zTime + "\n" + secret;
+            var encoding = new System.Text.ASCIIEncoding();
+            byte[] keyByte = encoding.GetBytes(secret);
+            byte[] messageBytes = encoding.GetBytes(stringToSign);
+            using (var hmacsha256 = new HMACSHA256(keyByte))
+            {
+                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
+                return System.Web.HttpUtility.UrlEncode(Convert.ToBase64String(hashmessage), Encoding.UTF8);
+            }
+        }
+        #endregion
+    }
+
+    public enum GroupNames
+    {
+        [Description("ce63217d9c734a92fd91c7c9ceaa9b25e109cce94615a7f75288dc43865a6e20,SEC6a6822db6567f79854a474002407cd9ac36da4d194b5fb79e073c35ef61119ed")]
+        研發C組,
+        [Description("2c5ced0725b592b1a96f1fb800d6d9a15727986ef75923a838a4d24e6b8c9147,SEC66ff954306c1fd98b5b160e23c253649f22205e69a16fb26e18d136f49875a9e")]
+        客戶回饋群組,
+        [Description("f8bf19c9363e3b288e018856014bcbf89708f19b3aae009e203edd68af25c9fe")]
+        BB訂單群組,
+        [Description("a27b099b15a054374da41b9f66f72e5fc6b378e98418859f7c0ef46408941808")]
+        測試群組,
+        [Description("1a316ce4edc2db88231d40d80072b00f2751d7d9e2e5871c5dc061885b01c48d,SECff60201ac9b219943b9f8fc397fda1a617d0cbc140850f5ea9cb4f131479d39a")]
+        醍摩豆服務運維群組
+    }
+
+
+}

+ 154 - 0
TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeID.cs

@@ -0,0 +1,154 @@
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class SnowflakeId
+    {
+        private readonly IOptionsMonitor<SnowflakeIDOptions> _optionsMonitor;
+
+        // 開始時間截((new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc)-Jan1st1970).TotalMilliseconds)
+        private const long twepoch = 1577836800000L;
+        // 機器ID所佔的位數
+        private const int workerIdBits = 5;
+        // 數據標識ID所佔的位數
+        private const int datacenterIdBits = 5;
+        // 支持的最大機器ID,結果是31 (這個移位算法可以很快的計算出幾位二進制數所能表示的最大十進制數)
+        private const long maxWorkerId = -1L ^ (-1L << workerIdBits);
+        // 支持的最大數據標識ID,結果是31
+        private const long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+        // 序列在ID中佔的位數 
+        private const int sequenceBits = 12;
+        // 數據標識ID向左移17位(12+5)
+        private const int datacenterIdShift = sequenceBits + workerIdBits;
+        // 機器ID向左移12位 
+        private const int workerIdShift = sequenceBits;
+        // 時間截向左移22位(5+5+12)
+        private const int timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+        // 生成序列的掩碼,這里為4095 (0b111111111111=0xfff=4095)
+        private const long sequenceMask = -1L ^ (-1L << sequenceBits);
+        // 毫秒內序列(0~4095) 
+        private long sequence = 0L;
+        // 上次生成ID的時間截 
+        private long lastTimestamp = -1L;
+
+
+        // 數據中心ID(0~31,China請填8,Global請填1)
+        public long DatacenterId { get; private set; }
+        // 工作機器ID(0~31,依照數據中心,各地區自定)
+        public long WorkerId { get; private set; }
+
+
+
+        /// <summary>
+        /// 分散式ID產生器 (Snowflake算法,支援線程安全)
+        /// </summary>
+        /// <param name="datacenterId">數據中心ID (0~31)</param>
+        /// <param name="workerId">工作機器ID (0~31)</param>
+        public SnowflakeId(IOptionsMonitor<SnowflakeIDOptions> optionsMonitor)
+        {
+            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));
+            _optionsMonitor = optionsMonitor;
+            this.DatacenterId = optionsMonitor.CurrentValue.DatacenterId;
+            this.WorkerId = optionsMonitor.CurrentValue.WorkerId;
+        }
+
+        /// <summary>
+        /// 獲得下一個ID
+        /// </summary>
+        /// <returns></returns>
+        public long NextId()
+        {
+            lock (this)
+            {
+                long timestamp = GetCurrentTimestamp();
+                if (timestamp > lastTimestamp) //時間戳改變,毫秒內序列重置
+                {
+                    sequence = 0L;
+                }
+                else if (timestamp == lastTimestamp) //如果是同一時間生成的,則進行毫秒內序列
+                {
+                    sequence = (sequence + 1) & sequenceMask;
+                    if (sequence == 0) //毫秒內序列溢出
+                    {
+                        timestamp = GetNextTimestamp(lastTimestamp); //阻塞到下一個毫秒,獲得新的時間戳
+                    }
+                }
+                else   //當前時間小於上一次ID生成的時間戳,證明系統時鐘被回撥,此時需要做回撥處理
+                {
+                    sequence = (sequence + 1) & sequenceMask;
+                    if (sequence > 0)
+                    {
+                        timestamp = lastTimestamp;     //停留在最後一次時間戳上,等待系統時間追上後即完全度過了時鐘回撥問題
+                    }
+                    else   //毫秒內序列溢出
+                    {
+                        timestamp = lastTimestamp + 1;   //直接進位到下一個毫秒                          
+                    }
+                    //throw new Exception(string.Format("Clock moved backwards.  Refusing to generate id for {0} milliseconds", lastTimestamp - timestamp));
+                }
+
+                lastTimestamp = timestamp;       //上次生成ID的時間截
+
+                //移位並通過或運算拼到一起組成64位的ID
+                var id = ((timestamp - twepoch) << timestampLeftShift)
+                        | (DatacenterId << datacenterIdShift)
+                        | (WorkerId << workerIdShift)
+                        | sequence;
+                return id;
+            }
+        }
+
+        /// <summary>
+        /// 解析分散式ID
+        /// </summary>
+        /// <returns></returns>
+        public string ParseId(long Id)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            var timestamp = (Id >> timestampLeftShift);
+            var time = Jan1st1970.AddMilliseconds(timestamp + twepoch);
+            sb.Append(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss:fff"));
+
+            var datacenterId = (Id ^ (timestamp << timestampLeftShift)) >> datacenterIdShift;
+            sb.Append("_" + datacenterId);
+
+            var workerId = (Id ^ ((timestamp << timestampLeftShift) | (datacenterId << datacenterIdShift))) >> workerIdShift;
+            sb.Append("_" + workerId);
+
+            var sequence = Id & sequenceMask;
+            sb.Append("_" + sequence);
+
+            return sb.ToString();
+        }
+
+        /// <summary>
+        /// 阻塞到下一個毫秒,直到獲得新的時間戳
+        /// </summary>
+        /// <param name="lastTimestamp">上次生成ID的時間截</param>
+        /// <returns>當前時間戳</returns>
+        private static long GetNextTimestamp(long lastTimestamp)
+        {
+            long timestamp = GetCurrentTimestamp();
+            while (timestamp <= lastTimestamp)
+            {
+                timestamp = GetCurrentTimestamp();
+            }
+            return timestamp;
+        }
+
+        /// <summary>
+        /// 獲取當前時間戳
+        /// </summary>
+        /// <returns></returns>
+        private static long GetCurrentTimestamp()
+        {
+            return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;
+        }
+
+        private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+    }
+}

+ 28 - 0
TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDExtensions.cs

@@ -0,0 +1,28 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class SnowflakeIDExtensions
+    {
+        /// <summary>
+        /// 分散式ID產生器 (Snowflake算法,支援線程安全)
+        /// </summary>
+        /// <param name="datacenterId">數據中心ID (0~31)</param>
+        /// <param name="workerId">工作機器ID (0~31)</param>
+        public static IServiceCollection AddSnowflakeId(this IServiceCollection services, long datacenterId, long workerId)
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));            
+            if (datacenterId > 31 || datacenterId < 0) throw new Exception("datacenterId only 0-31");            
+            if (workerId > 31 || workerId < 0) throw new Exception("workerId only 0-31");
+            
+            services.TryAddSingleton<SnowflakeId>();
+            services.Configure<SnowflakeIDOptions>(o => { o.DatacenterId = datacenterId; o.WorkerId = workerId; });
+
+            return services;
+        }
+    }
+}

+ 20 - 0
TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDOptions.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class SnowflakeIDOptions
+    {
+        /// <summary>
+        /// 數據中心ID (0~31)
+        /// </summary>
+        public long DatacenterId { get; set; }
+        /// <summary>
+        /// 工作機器ID (0~31)
+        /// </summary>
+        public long WorkerId { get; set; }
+    }
+
+   
+}

+ 22 - 0
TEAMModelOS.SDK/Extension/EnumExtensions.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Reflection;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public static class EnumExtensions
+    {
+        /// <summary>
+        /// 取得Enum描述值
+        /// </summary>       
+        public static string GetDescriptionText(this Enum source)
+        {
+            FieldInfo fi = source.GetType().GetField(source.ToString());
+            DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
+            if (attributes.Length > 0) return attributes[0].Description;
+            else return source.ToString();
+        }
+    }
+}

+ 94 - 0
TEAMModelOS.SDK/Extension/HttpContextExtensions.cs

@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public static class HttpContextExtensions
+    {
+        /// <summary>
+        /// 取得驗證金鑰,Authorization
+        /// </summary>        
+        public static string GetToken(this HttpContext httpContext)
+        {
+            return httpContext.Request.Headers["Authorization"].ToString();
+        }
+
+        /// <summary>
+        /// 取得JWT驗證金鑰,Authorization Bearer
+        /// </summary>
+        /// <param name="httpContext"></param>
+        /// <returns></returns>
+        public static string GetJwtToken(this HttpContext httpContext)
+        {
+            var token = string.Empty;
+            string authorization = httpContext.Request.Headers["Authorization"].ToString();
+            if (!string.IsNullOrWhiteSpace(authorization) && authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
+            {
+                token = authorization.Substring("Bearer ".Length).Trim();
+            }
+            return token;
+        }
+
+        /// <summary>
+        /// 取得遠端呼叫的IP
+        /// </summary>        
+        public static string GetRemoteIP(this HttpContext httpContext)
+        {            
+                return httpContext?.Connection?.RemoteIpAddress?.ToString();            
+        }
+
+        /// <summary>
+        /// 取得X-Auth-Key值
+        /// </summary>        
+        /// <param name="key">Key Name</param>
+        /// <returns></returns>
+        public static string GetXAuth(this HttpContext httpContext, string key = null)
+        {
+            try
+            {
+                if (httpContext.Request.Headers.TryGetValue($"X-Auth-{key}", out StringValues value))
+                    return value.ToString();
+                else
+                    return null;
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 取得User-Agent值
+        /// </summary>       
+        public static string GetUserAgent(this HttpContext httpContext)
+        {
+            try
+            {
+                return httpContext.Request.Headers["User-Agent"].ToString();
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 取得Scheme值
+        /// </summary>      
+        public static string GetScheme(this HttpContext httpContext)
+        {           
+                return httpContext?.Request?.Scheme;           
+        }
+
+        /// <summary>
+        /// 取得HostName值
+        /// </summary>        
+        public static string GetHostName(this HttpContext httpContext)
+        {            
+                return httpContext?.Request?.Host.ToString();          
+        }
+    }
+}

+ 52 - 0
TEAMModelOS.SDK/Extension/JsonExtensions.cs

@@ -0,0 +1,52 @@
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Text.Json;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public static class JsonExtensions
+    {
+        public static string ToJsonString(this JsonDocument jdoc)
+        {
+            var bufferWriter = new ArrayBufferWriter<byte>();
+            using var writer = new Utf8JsonWriter(bufferWriter, new JsonWriterOptions { Indented = true });
+            jdoc.WriteTo(writer);
+            writer.Flush();
+            return Encoding.UTF8.GetString(bufferWriter.WrittenSpan);
+        }
+
+        public static string ToJsonString(this JsonElement jelement)
+        {
+            var bufferWriter = new ArrayBufferWriter<byte>();
+            using var writer = new Utf8JsonWriter(bufferWriter, new JsonWriterOptions { Indented = true });
+            jelement.WriteTo(writer);
+            writer.Flush();
+            return Encoding.UTF8.GetString(bufferWriter.WrittenSpan);
+        }
+
+        public static string ToJsonString(this Object obj, JsonSerializerOptions option = null)
+        {
+            var json = JsonSerializer.Serialize(obj, option);
+            return json;
+        }
+
+        public static T ToObject<T>(this JsonDocument jdoc, JsonSerializerOptions options = null)
+        {
+            return jdoc.RootElement.ToObject<T>(options);
+        }
+
+        public static T ToObject<T>(this JsonElement jelement, JsonSerializerOptions options = null)
+        {
+            var bufferWriter = new ArrayBufferWriter<byte>();
+            using var writer = new Utf8JsonWriter(bufferWriter);
+            jelement.WriteTo(writer);
+            writer.Flush();
+            return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
+        }        
+
+        
+    }
+}

+ 94 - 0
TEAMModelOS.SDK/Extension/Utils.cs

@@ -0,0 +1,94 @@
+using Microsoft.AspNetCore.Cryptography.KeyDerivation;
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public class Utils
+    {
+        private static RNGCryptoServiceProvider _random = new RNGCryptoServiceProvider();
+
+        public static string HashedPassword(string password, string salt)
+        {
+            byte[] hashBytes = KeyDerivation.Pbkdf2(
+                password: password,
+                salt: Encoding.UTF8.GetBytes(salt), //SHA1鹽(8-20字節),SHA256(32字節)
+                prf: KeyDerivationPrf.HMACSHA1,
+                iterationCount: 10000, //hash次數,越多次代表破解難度變高,但效能會差點
+                numBytesRequested: 256 / 8 //指定得出結果長度
+            );
+
+            string hashText = BitConverter.ToString(hashBytes).Replace("-", string.Empty);
+            return hashText;
+        }
+
+        /// <summary>
+        /// 建立真隨機字串(CSPRNG),適用密碼、鹽
+        /// </summary>
+        /// <param name="stringLength">長度</param>
+        /// <param name="key">要限制的字元串(長度需大於等於8),如果為null或者小於8,預設為"abcdefghijklmnopqrstuvwxyz1234567890"</param>
+        /// <returns></returns>
+        public static string CreatSaltString(int stringLength, string key = null)
+        {
+            ReadOnlySpan<char> span;
+            if (key == null || key.Length < 8)
+                span = "abcdefghijklmnopqrstuvwxyz1234567890";
+            else
+                span = key.AsSpan();
+
+            int length = span.Length;
+            StringBuilder randomString = new StringBuilder(length);
+            for (int i = 0; i < stringLength; ++i)
+            {
+                randomString.Append(span[SetRandomSeeds(length)]);
+            }
+            return randomString.ToString();
+        }
+
+        /// <summary>
+        /// 建立真隨機整數數字(CSPRNG),適用亂數、隨機編號
+        /// </summary>
+        /// <param name="max">最大值</param>
+        public static int CreatSaltInt(int max)
+        {
+            var bytes = new byte[4];
+            _random.GetBytes(bytes);
+            int value = BitConverter.ToInt32(bytes, 0);
+            value = value % (max + 1);
+            if (value < 0) value = -value;
+            return value;
+        }
+
+        /// <summary>
+        /// 建立真隨機整數數字(CSPRNG),適用亂數、隨機編號
+        /// </summary>
+        /// <param name="min">最小值</param>
+        /// <param name="max">最大值</param>
+        public static int CreatSaltInt(int min, int max)
+        {
+            int value = CreatSaltInt(max - min) + min;
+            return value;
+        }        
+
+        public static Dictionary<string, string> ParseConnectionString(string connectionString)
+        {
+            var d = new Dictionary<string, string>();
+            foreach (var item in connectionString.Split(';',StringSplitOptions.RemoveEmptyEntries))
+            {
+                var a = item.IndexOf('=');
+                d.Add(item.Substring(0, a), item.Substring(a + 1));
+            }
+            return d;
+        }
+
+        private static int SetRandomSeeds(int length)
+        {
+            decimal maxValue = (decimal)long.MaxValue;
+            byte[] array = new byte[8];
+            _random.GetBytes(array);
+            return (int)(Math.Abs(BitConverter.ToInt64(array, 0)) / maxValue * length);
+        }
+    }
+}

+ 44 - 44
TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobServiceCollectionExtensions.cs

@@ -1,48 +1,48 @@
-using TEAMModelOS.SDK.Module.AzureBlob.Implements;
-using TEAMModelOS.SDK.Module.AzureBlob.Interfaces;
-using Microsoft.Extensions.DependencyInjection;
+////using TEAMModelOS.SDK.Module.AzureBlob.Implements;
+//using TEAMModelOS.SDK.Module.AzureBlob.Interfaces;
+//using Microsoft.Extensions.DependencyInjection;
 
-namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
-{
-    public static class AzureBlobServiceCollectionExtensions
-    {
-        public static AzureBlobServiceBuilder Builder { get; set; }
+//namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
+//{
+//    public static class AzureBlobServiceCollectionExtensions
+//    {
+//        public static AzureBlobServiceBuilder Builder { get; set; }
 
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="services"></param>
-        /// <returns></returns>
-        private static AzureBlobServiceBuilder AddServerBuilder(this IServiceCollection services)
-        {
-            return new AzureBlobServiceBuilder(services);
-        }
+//        /// <summary>
+//        /// 
+//        /// </summary>
+//        /// <param name="services"></param>
+//        /// <returns></returns>
+//        private static AzureBlobServiceBuilder AddServerBuilder(this IServiceCollection services)
+//        {
+//            return new AzureBlobServiceBuilder(services);
+//        }
 
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="services"></param>
-        /// <returns></returns>
-        public static AzureBlobServiceBuilder AddAzureBlobStorage(this IServiceCollection services)
-        {
-            if (Builder == null)
-            {
-                Builder = services.AddServerBuilder();
-            }
-            services.AddSingleton<IAzureBlobDBRepository, AzureBlobDBRepository>();
-            return Builder;
-        }
+//        /// <summary>
+//        /// 
+//        /// </summary>
+//        /// <param name="services"></param>
+//        /// <returns></returns>
+//        public static AzureBlobServiceBuilder AddAzureBlobStorage(this IServiceCollection services)
+//        {
+//            if (Builder == null)
+//            {
+//                Builder = services.AddServerBuilder();
+//            }
+//            services.AddSingleton<IAzureBlobDBRepository, AzureBlobDBRepository>();
+//            return Builder;
+//        }
 
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="builder"></param>
-        /// <param name="_connectionString"></param>
-        /// <returns></returns>
-        public static AzureBlobServiceBuilder AddConnection(this AzureBlobServiceBuilder builder, AzureBlobOptions databaseOptions)
-        {
-            builder.Services.AddSingleton(databaseOptions);
-            return builder;
-        }
-    }
-}
+//        /// <summary>
+//        /// 
+//        /// </summary>
+//        /// <param name="builder"></param>
+//        /// <param name="_connectionString"></param>
+//        /// <returns></returns>
+//        public static AzureBlobServiceBuilder AddConnection(this AzureBlobServiceBuilder builder, AzureBlobOptions databaseOptions)
+//        {
+//            builder.Services.AddSingleton(databaseOptions);
+//            return builder;
+//        }
+//    }
+//}

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

@@ -1,43 +1,43 @@
-
-using Microsoft.WindowsAzure.Storage;
-using Microsoft.WindowsAzure.Storage.Blob;
-using System;
 
-namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
-{
-    public sealed class BlobClientSingleton
-    {
-        private static string _connectionString;
-        private CloudBlobClient BlobClient;
+//using Microsoft.WindowsAzure.Storage;
+//using Microsoft.WindowsAzure.Storage.Blob;
+//using System;
 
-        private BlobClientSingleton() { }
+//namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
+//{
+//    public sealed class BlobClientSingleton
+//    {
+//        private static string _connectionString;
+//        private CloudBlobClient BlobClient;
 
-        public CloudBlobClient GetBlobClient()
-        {
-            if (BlobClient != null)
-            {
-                return BlobClient;
-            }
-            else
-            {
-                getInstance(_connectionString);
-                return BlobClient;
-            }
-        }
+//        private BlobClientSingleton() { }
 
-        public static BlobClientSingleton getInstance(string connectionString)
-        {
-            _connectionString = connectionString;
-            return SingletonInstance.instance;
-        }
+//        public CloudBlobClient GetBlobClient()
+//        {
+//            if (BlobClient != null)
+//            {
+//                return BlobClient;
+//            }
+//            else
+//            {
+//                getInstance(_connectionString);
+//                return BlobClient;
+//            }
+//        }
 
-        private static class SingletonInstance
-        {
-            public static BlobClientSingleton instance = new BlobClientSingleton()
-            {
-                BlobClient = CloudStorageAccount.Parse(_connectionString).CreateCloudBlobClient()
-               //BlobClient = new  CloudBlobClient(new Uri(_connectionString))
-            };
-        }
-    }
-}
+//        public static BlobClientSingleton getInstance(string connectionString)
+//        {
+//            _connectionString = connectionString;
+//            return SingletonInstance.instance;
+//        }
+
+//        private static class SingletonInstance
+//        {
+//            public static BlobClientSingleton instance = new BlobClientSingleton()
+//            {
+//                BlobClient = CloudStorageAccount.Parse(_connectionString).CreateCloudBlobClient()
+//               //BlobClient = new  CloudBlobClient(new Uri(_connectionString))
+//            };
+//        }
+//    }
+//}

+ 0 - 1
TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobFileDto.cs

@@ -1,4 +1,3 @@
-using Microsoft.WindowsAzure.Storage.Blob;
 using System;
 using System.Collections.Generic;
 using System.Text;

Diff do ficheiro suprimidas por serem muito extensas
+ 912 - 914
TEAMModelOS.SDK/Module/AzureBlob/Implements/AzureBlobDBRepository.cs


+ 1 - 2
TEAMModelOS.SDK/Module/AzureBlob/Interfaces/IAzureBlobDBRepository.cs

@@ -1,9 +1,8 @@
-using TEAMModelOS.SDK.Module.AzureBlob.Container;
+using TEAMModelOS.SDK.Module.AzureBlob.Container;
 using Microsoft.AspNetCore.Http;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using System.IO;
-using Microsoft.WindowsAzure.Storage.Blob;
 using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
 
 namespace TEAMModelOS.SDK.Module.AzureBlob.Interfaces

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

@@ -10,6 +10,10 @@
 
   <ItemGroup>
     <PackageReference Include="AspectCore.Extensions.Reflection" Version="2.1.0" />
+    <PackageReference Include="Azure.Cosmos" Version="4.0.0-preview3" />
+    <PackageReference Include="Azure.Storage.Blobs" Version="12.4.0" />
+    <PackageReference Include="Azure.Storage.Blobs.Batch" Version="12.2.1" />
+    <PackageReference Include="Azure.Storage.Queues" Version="12.3.2" />
     <PackageReference Include="ClouDASLibx" Version="1.1.4" />
     <PackageReference Include="Consul" Version="0.7.2.6" />
     <PackageReference Include="DocumentFormat.OpenXml" Version="2.10.1" />
@@ -36,9 +40,9 @@
     <PackageReference Include="OpenTracing" Version="0.12.1" />
     <PackageReference Include="protobuf-net" Version="2.4.6" />
     <PackageReference Include="Scrutor" Version="3.2.0" />
+    <PackageReference Include="StackExchange.Redis" Version="2.1.30" />
     <PackageReference Include="System.Drawing.Common" Version="4.7.0" />
     <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.5.0" />
-    <PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
     <PackageReference Include="XC.Framework.Security.RSAUtil" Version="1.0.1" />
     <PackageReference Include="Microsoft.Azure.Cosmos" Version="3.11.0" />
     <PackageReference Include="Microsoft.Azure.Cosmos.Table" Version="2.0.0-preview" />

+ 4 - 3
TEAMModelOS/Controllers/Client/HiTeachController.cs

@@ -1,4 +1,3 @@
-using CoreSDK.DingDing;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
@@ -8,8 +7,9 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 using TEAMModelOS.Models;
-using TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest;
-using TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse;
+using TEAMModelOS.SDK.DI;
+//using TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest;
+//using TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse;
 using TEAMModelOS.SDK.Helper.Common.JsonHelper;
 using TEAMModelOS.SDK.Helper.Common.LogHelper;
 using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
@@ -48,6 +48,7 @@ namespace TEAMModelOS.Controllers.Client
                 await _dingDing.SendBotMsg($"CoreAPI2,{_option.Location},Channel/Create()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                 return BadRequest();
             }
+            return Ok();
         }
     }
 }

+ 0 - 1
TEAMModelOS/Controllers/Core/FileController.cs

@@ -1,6 +1,5 @@
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.WindowsAzure.Storage.Blob;
 using System;
 using System.Collections.Generic;
 using System.Linq;

+ 1 - 2
TEAMModelOS/Controllers/Task/VoteController.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
@@ -10,7 +10,6 @@ using Microsoft.Azure.Documents.SystemFunctions;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Context.Exception;
 using TEAMModelOS.SDK;
-using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
 using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
 using TEAMModelOS.Service.Models;

+ 1 - 2
TEAMModelOS/Controllers/Teacher/SchoolUserController.cs

@@ -1,10 +1,9 @@
-using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc;
 using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Threading.Tasks;
 using TEAMModelOS.SDK;
-using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Module.AzureCosmosDB.Interfaces;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
 using TEAMModelOS.SDK.Module.AzureCosmosDBV3;

+ 1 - 2
TEAMModelOS/Controllers/Test/TestAPIController.cs

@@ -7,10 +7,9 @@ using TEAMModelOS.SDK.Module.AzureCosmosDB.Interfaces;
 using System.Linq;
 using Microsoft.Azure.Documents.Client;
 using System.Collections.Generic;
-using Microsoft.WindowsAzure.Storage.Table;
-using Microsoft.WindowsAzure.Storage;
 using Newtonsoft.Json;
 using TEAMModelOS.SDK;
+using Microsoft.Azure.Cosmos.Table;
 
 namespace TEAMModelOS.Controllers.Test
 {

+ 29 - 33
TEAMModelOS/Startup.cs

@@ -20,14 +20,16 @@ using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Hosting;
 using Microsoft.IdentityModel.Tokens;
 using Scrutor;
+using TEAMModelOS.Models;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Context.Attributes.Azure;
 using TEAMModelOS.SDK.Context.Configuration;
 using TEAMModelOS.SDK.Context.Filter;
+using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension.JwtAuth;
 using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
 using TEAMModelOS.SDK.Module.AzureCosmosDB.Configuration;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+//using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
 using TEAMModelOS.SDK.Module.AzureServiceBus;
 using TEAMModelOS.SDK.Module.AzureTable.Implements;
 using TEAMModelOS.SDK.Module.AzureTable.Interfaces;
@@ -55,7 +57,6 @@ namespace TEAMModelOS
             // true,默認情況下,聲明映射將以舊格式映射聲明名稱,以適應較早的SAML應用程序,RoleClaimType = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role'
             // false,RoleClaimType = 'roles'             
             JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
-
             services.AddAuthentication(options => options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme)
                 .AddJwtBearer(options => //AzureADJwtBearer
                 {
@@ -85,22 +86,17 @@ namespace TEAMModelOS
                         await Task.FromResult(0);
                     };
                 });
-
-            //設定跨域請求
-            //services.AddCors(options =>
-            //{
-            //    options.AddPolicy(MyAllowSpecificOrigins,
-            //    builder =>
-            //    {
-            //        builder.WithOrigins("http://example.com",
-            //                            "http://www.contoso.com")
-            //        .AllowAnyHeader()
-            //        .AllowAnyMethod(); 
-            //    });
-            //});
-            services.AddMemoryCache();
-            //  services.AddJsonRpc();
+            
+            services.AddAzureStorage(Configuration.GetValue<string>("Azure:Starage:ConnectionString"));
+            services.AddAzureRedis( Configuration.GetValue<string>("Azure:Redis:ConnectionString"));            
+            services.AddAzureCosmos(Configuration.GetValue<string>("Azure:CosmosDB:ConnectionString"));
+            services.AddSnowflakeId(0, 1);
+            services.AddHttpClient();
+            services.AddHttpClient<DingDing>();            
+            services.AddMemoryCache();            
             services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = false; });
+            services.Configure<Option>(options => Configuration.GetSection("Option").Bind(options));
+            
             //.AddNewtonsoftJson().AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = true; });
             //上传文件最大处理
             services.Configure<FormOptions>(x =>
@@ -112,17 +108,17 @@ namespace TEAMModelOS
             });
 
             // Table配置
-            services.AddScoped<IAzureTableDBRepository, AzureTableDBRepository>();
+            //services.AddScoped<IAzureTableDBRepository, AzureTableDBRepository>();
             //使用Blob配置
-            services.AddAzureBlobStorage().AddConnection(Configuration.GetSection("Azure:Blob").Get<AzureBlobOptions>());
+            //services.AddAzureBlobStorage().AddConnection(Configuration.GetSection("Azure:Blob").Get<AzureBlobOptions>());
             //使用CosmosDB
-            services.AddAzureCosmosDBV3().AddCosmosDBV3Connection(Configuration.GetSection("Azure:CosmosDB").Get<AzureCosmosDBOptions>())
-                .AddCosmosSerializer(new SystemTextJsonCosmosSerializer(new JsonSerializerOptions() { IgnoreNullValues = true }));
+            //services.AddAzureCosmosDBV3().AddCosmosDBV3Connection(Configuration.GetSection("Azure:CosmosDB").Get<AzureCosmosDBOptions>())
+            //    .AddCosmosSerializer(new SystemTextJsonCosmosSerializer(new JsonSerializerOptions() { IgnoreNullValues = true }));
             //使用AzureServiceBus
-            services.AddServiceBus().AddServiceBusOptions(Configuration.GetSection("Azure:ServiceBus").Get<AzureServiceBusOptions>());
+            //services.AddServiceBus().AddServiceBusOptions(Configuration.GetSection("Azure:ServiceBus").Get<AzureServiceBusOptions>());
             //HttpContextAccessor,并用来访问HttpContext。
             services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
-            services.AddSingleton<IServiceBusReviceService, ServiceBusReviceService>();
+            //services.AddSingleton<IServiceBusReviceService, ServiceBusReviceService>();
             //注入CSRedis
             var csredis = new CSRedis.CSRedisClient(Configuration.GetSection("Azure:Redis:ConnectionString").Get<string>());
             // CSRedis.CSRedisClient.Serialize = obj =>System.Text.Json.JsonSerializer.Serialize(obj);
@@ -133,25 +129,25 @@ namespace TEAMModelOS
 
 
             //全局扫描基于IBusinessService接口的实现类
-            services.Scan(scan => scan.FromApplicationDependencies()
-               .AddClasses(classes => classes.AssignableTo<IBusinessService>())
-                   .AsImplementedInterfaces()
-                   .WithScopedLifetime());
-            services.Scan(scan => scan.FromApplicationDependencies()
-               .AddClasses(classes => classes.AssignableTo<IChangeService>()).UsingRegistrationStrategy(RegistrationStrategy.Skip)
-                   .AsImplementedInterfaces()
-                  .WithSingletonLifetime());
+            //services.Scan(scan => scan.FromApplicationDependencies()
+            //   .AddClasses(classes => classes.AssignableTo<IBusinessService>())
+            //       .AsImplementedInterfaces()
+            //       .WithScopedLifetime());
+            //services.Scan(scan => scan.FromApplicationDependencies()
+            //   .AddClasses(classes => classes.AssignableTo<IChangeService>()).UsingRegistrationStrategy(RegistrationStrategy.Skip)
+            //       .AsImplementedInterfaces()
+            //      .WithSingletonLifetime());
            // _services = services;
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
-        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAzureCosmosDBV3Repository cosmosDBV3Repository )
+        public void Configure(IApplicationBuilder app, IWebHostEnvironment env )
         {
             if (env.IsDevelopment())
             {
                 app.UseDeveloperExceptionPage();
             }
-            CosmosDict dict = cosmosDBV3Repository.InitializeDatabase().Result;
+            //CosmosDict dict = cosmosDBV3Repository.InitializeDatabase().Result;
             //changeFeedInvoke.MonitorChangeFeed(dict, _services);
             //azureServiceBusService.init();
             //serviceBusReviceService.ReciveMessageAsync();

+ 0 - 2
TEAMModelOS/TEAMModelOS.csproj

@@ -13,9 +13,7 @@
   <ItemGroup>
     <PackageReference Include="Bogus" Version="29.0.1" />
     <PackageReference Include="Caching.CSRedis" Version="3.5.5" />
-    <PackageReference Include="CoreSDK" Version="1.0.0" />
     <PackageReference Include="CSRedisCore" Version="3.5.5" />
-    <PackageReference Include="Microsoft.Azure.ServiceBus" Version="4.1.3" />
     <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.6" />
     <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.2" />
     <PackageReference Include="VueCliMiddleware" Version="3.0.0" />

+ 3 - 3
TEAMModelOS/appsettings.json

@@ -6,20 +6,20 @@
       "Microsoft": "Information"
     }
   },
-  "AllowedHosts": "*",
   "Option": {
     "Location": "China",
     "LocationNum": "1",
     "HostName": "localhost:5001",
+    "AllowedHosts": [ "localhost", "*.teammodel.cn", "*.teammodel.net", "*.habookaclass.biz", "test" ],
     "Authority": "https://login.chinacloudapi.cn/4807e9cf-87b8-4174-aa5b-e76497d7392b/v2.0", //China:"https://login.chinacloudapi.cn/4807e9cf-87b8-4174-aa5b-e76497d7392b/v2.0", //Global:"https://login.microsoftonline.com/73a2bcc5-fe99-4566-aa8a-07e7bb287df1/v2.0"
-    "Audience": "72643704-b2e7-4b26-b881-bd5865e7a7a5" //China:"72643704-b2e7-4b26-b881-bd5865e7a7a5",Global:"8768b06f-c5c5-4b0c-abfb-d7ded354626d"
+    "Audience": "72643704-b2e7-4b26-b881-bd5865e7a7a5", //China:"72643704-b2e7-4b26-b881-bd5865e7a7a5",Global:"8768b06f-c5c5-4b0c-abfb-d7ded354626d"
     "Issuer": "www.teammodel.cn",
     "JwtSecretKey": "fXO6ko/qyXeYrkecPeKdgXnuLXf9vMEtnBC9OB3s+aA=",
     "Exp": 86400,
     "IdTokenSalt": "8263692E2213497BB55E74792B7900B4"
   },
   "Azure": {
-    "Table": {
+    "Starage": {
       "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelstorage;AccountKey=Yq7D4dE6cFuer2d2UZIccTA/i0c3sJ/6ITc8tNOyW+K5f+/lWw9GCos3Mxhj47PyWQgDL8YbVD63B9XcGtrMxQ==;EndpointSuffix=core.chinacloudapi.cn"
     },
     "Blob": {