zhousheng 4 år sedan
förälder
incheckning
f6c1f40512
100 ändrade filer med 3449 tillägg och 2033 borttagningar
  1. 1 0
      .gitignore
  2. 264 0
      TEAMModelFunction/.gitignore
  3. 35 0
      TEAMModelFunction/MonitorCosmosDB.cs
  4. 17 0
      TEAMModelFunction/MonitorServicesBus.cs
  5. 8 0
      TEAMModelFunction/Properties/serviceDependencies.json
  6. 9 0
      TEAMModelFunction/Properties/serviceDependencies.local.json
  7. 19 0
      TEAMModelFunction/Startup.cs
  8. 24 0
      TEAMModelFunction/TEAMModelFunction.csproj
  9. 11 0
      TEAMModelFunction/host.json
  10. 2 2
      TEAMModelGrpc/Services/BlobSASService.cs
  11. 5 5
      TEAMModelGrpc/Startup.cs
  12. 3 3
      TEAMModelOS.SDK/Context/Filters/HttpGlobalExceptionInvoke.cs
  13. 30 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosExtensions.cs
  14. 45 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactory.cs
  15. 22 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryExtensions.cs
  16. 14 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryOptions.cs
  17. 18 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisExtensions.cs
  18. 47 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactory.cs
  19. 22 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryExtensions.cs
  20. 14 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryOptions.cs
  21. 33 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs
  22. 222 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs
  23. 22 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryExtensions.cs
  24. 14 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryOptions.cs
  25. 232 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageTableExtensions.cs
  26. 114 0
      TEAMModelOS.SDK/DI/DingDing/DingDing.cs
  27. 154 0
      TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeID.cs
  28. 28 0
      TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDExtensions.cs
  29. 20 0
      TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDOptions.cs
  30. 4 4
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/AzureTokenJsonRPCRequest.cs
  31. 16 0
      TEAMModelOS.SDK/Extension/DataResult/JsonRequest/BaseJosnRequest.cs
  32. 3 2
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/JosnRPCRequest.cs
  33. 15 0
      TEAMModelOS.SDK/Extension/DataResult/JsonRequest/PaginationRequest.cs
  34. 13 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/BaseResponse.cs
  35. 19 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/DataJsonResponse.cs
  36. 14 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/EmptyJosnResponse.cs
  37. 19 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/ErrorJosnResponse.cs
  38. 15 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/ErrorModel.cs
  39. 3 3
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JsonRPCResult.cs
  40. 20 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/PageJosnResponse.cs
  41. 15 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/PageJsonResult.cs
  42. 175 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/ResponseBuilder.cs
  43. 20 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/TokenJosnResponse.cs
  44. 18 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/TokenJsonResult.cs
  45. 0 16
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/BaseJosnRPCRequest.cs
  46. 0 15
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/PaginationJosnRPCRequest.cs
  47. 0 14
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/BaseJosnRPCResponse.cs
  48. 0 16
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/DataJosnRPCResponse.cs
  49. 0 16
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/ErrorJosnRPCResponse.cs
  50. 0 13
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/ErrorModel.cs
  51. 0 13
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JosnRPCResponse.cs
  52. 0 176
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JsonRPCResponseBuilder.cs
  53. 0 17
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/PageJosnRPCResponse.cs
  54. 0 15
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/PageJsonRPCResult.cs
  55. 0 17
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/TokenJosnRPCResponse.cs
  56. 0 16
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/TokenJsonRPCResult.cs
  57. 1 1
      TEAMModelOS.SDK/Extension/DataResult/PageToken/AzurePagination.cs
  58. 1 1
      TEAMModelOS.SDK/Extension/DataResult/PageToken/AzureTableToken.cs
  59. 1 1
      TEAMModelOS.SDK/Extension/DataResult/PageToken/Pagination.cs
  60. 0 12
      TEAMModelOS.SDK/Extension/DataResult/PageToken/PaginationData.cs
  61. 2 2
      TEAMModelOS.SDK/Extension/DataResult/RequestData/AzureTokenRequest.cs
  62. 1 1
      TEAMModelOS.SDK/Extension/DataResult/RequestData/BaseRequest.cs
  63. 2 2
      TEAMModelOS.SDK/Extension/DataResult/RequestData/PaginationRequest.cs
  64. 0 16
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/BaseResponse.cs
  65. 0 14
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/DataResponse.cs
  66. 0 15
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/PageDatasResponse.cs
  67. 0 162
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/ResponseBuilder.cs
  68. 0 16
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/TimeStampResponse.cs
  69. 0 14
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/TokenPageDatasResponse.cs
  70. 22 0
      TEAMModelOS.SDK/Extension/EnumExtensions.cs
  71. 94 0
      TEAMModelOS.SDK/Extension/HttpContextExtensions.cs
  72. 52 0
      TEAMModelOS.SDK/Extension/JsonExtensions.cs
  73. 94 0
      TEAMModelOS.SDK/Extension/Utils.cs
  74. 44 44
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobServiceCollectionExtensions.cs
  75. 14 0
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobAuth.cs
  76. 38 38
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobClientSingleton.cs
  77. 0 1
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobFileDto.cs
  78. 7 7
      TEAMModelOS.SDK/Module/AzureBlob/Container/AzureBlobModel.cs
  79. 913 875
      TEAMModelOS.SDK/Module/AzureBlob/Implements/AzureBlobDBRepository.cs
  80. 34 8
      TEAMModelOS.SDK/Module/AzureBlob/Interfaces/IAzureBlobDBRepository.cs
  81. 14 1
      TEAMModelOS.SDK/Module/AzureCosmosDBV3/AzureCosmosDBV3Repository.cs
  82. 1 1
      TEAMModelOS.SDK/Module/AzureTable/Configuration/HaBookTableContinuationToken.cs
  83. 1 1
      TEAMModelOS.SDK/Module/AzureTable/Implements/AzureTableDBRepository.cs
  84. 1 1
      TEAMModelOS.SDK/Module/AzureTable/Interfaces/IAzureTableDBRepository.cs
  85. 0 1
      TEAMModelOS.SDK/Module/Cache/CSRedisCacheService.cs
  86. 0 307
      TEAMModelOS.SDK/Module/Cache/RedisCacheService.cs
  87. 14 10
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  88. 39 0
      TEAMModelOS.Service/Models/SchoolInfo/Paper.cs
  89. 1 1
      TEAMModelOS.Service/Services/ChangeFeed/SyllabusVolumeChangeFeed.cs
  90. 4 4
      TEAMModelOS.Service/Services/PowerPoint/Implement/HtexService.cs
  91. 6 6
      TEAMModelOS.Service/Services/PowerPoint/Implement/ShapeSvg.cs
  92. 61 0
      TEAMModelOS.Service/TEAMModelOS.Model.xml
  93. 6 0
      TEAMModelOS.sln
  94. 30 88
      TEAMModelOS/ClientApp/src/common/UploadFile.vue
  95. 23 3
      TEAMModelOS/ClientApp/src/components/learnactivity/ChooseContent.vue
  96. 22 0
      TEAMModelOS/ClientApp/src/components/learnactivity/QuestionList.vue
  97. 3 2
      TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue
  98. 6 7
      TEAMModelOS/ClientApp/src/store/index.js
  99. 79 7
      TEAMModelOS/ClientApp/src/utils/public.js
  100. 0 0
      TEAMModelOS/ClientApp/src/utils/upload.js

+ 1 - 0
.gitignore

@@ -254,3 +254,4 @@ _Pvt_Extensions
 /.idea
 /TEAMModelOS/wwwroot/dist
 /TEAMModelOS/wwwroot
+*.log.*

+ 264 - 0
TEAMModelFunction/.gitignore

@@ -0,0 +1,264 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# Azure Functions localsettings file
+local.settings.json
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+#*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc

+ 35 - 0
TEAMModelFunction/MonitorCosmosDB.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.Azure.Documents;
+using Microsoft.Azure.WebJobs;
+using Microsoft.Azure.WebJobs.Host;
+using Microsoft.Extensions.Logging;
+
+namespace TEAMModelFunction
+{
+    public class MonitorCosmosDB
+    {
+        private readonly IHttpClientFactory _clientFactory;        
+
+        public MonitorCosmosDB(IHttpClientFactory clientFactory)
+        {
+            _clientFactory = clientFactory;            
+        }
+
+        [FunctionName("School")]
+        public async Task School([CosmosDBTrigger(
+            databaseName: "TEAMModelOS",
+            collectionName: "School",
+            ConnectionStringSetting = "CosmosConnection",
+            LeaseCollectionName = "leases")]IReadOnlyList<Document> input, ILogger log)
+        {           
+                if (input != null && input.Count > 0)
+                {
+                    log.LogInformation("Documents modified " + input.Count);
+                    log.LogInformation("First document Id " + input[0].Id);
+                }           
+        }
+    }
+}

+ 17 - 0
TEAMModelFunction/MonitorServicesBus.cs

@@ -0,0 +1,17 @@
+using System;
+using Microsoft.Azure.WebJobs;
+using Microsoft.Azure.WebJobs.Host;
+using Microsoft.Extensions.Logging;
+
+namespace TEAMModelFunction
+{
+    public static class MonitorServicesBus
+    {
+        [FunctionName("test_queue_activetask")]
+        public static void Run([ServiceBusTrigger("test_queue_activetask", Connection = "ServiceBusConnection")]string myQueueItem, ILogger log)
+        {
+            ///ÖØÊÔ´ÎÊý
+            log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
+        }
+    }
+}

+ 8 - 0
TEAMModelFunction/Properties/serviceDependencies.json

@@ -0,0 +1,8 @@
+{
+  "dependencies": {
+    "storage1": {
+      "type": "storage",
+      "connectionId": "AzureWebJobsStorage"
+    }
+  }
+}

+ 9 - 0
TEAMModelFunction/Properties/serviceDependencies.local.json

@@ -0,0 +1,9 @@
+{
+  "dependencies": {
+    "storage1": {
+      "resourceId": "/subscriptions/[parameters('subscriptionId')]/resourceGroups/[parameters('resourceGroup')]/providers/Microsoft.Storage/storageAccounts/teammodelstorage",
+      "type": "storage.azure",
+      "connectionId": "AzureWebJobsStorage"
+    }
+  }
+}

+ 19 - 0
TEAMModelFunction/Startup.cs

@@ -0,0 +1,19 @@
+using Microsoft.Azure.Functions.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+[assembly: FunctionsStartup(typeof(TEAMModelFunction.Startup))]
+namespace TEAMModelFunction
+{
+    public class Startup : FunctionsStartup
+    {
+        public override void Configure(IFunctionsHostBuilder builder)
+        {
+            builder.Services.AddHttpClient();            
+        }
+    }
+}

+ 24 - 0
TEAMModelFunction/TEAMModelFunction.csproj

@@ -0,0 +1,24 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
+  </PropertyGroup>
+  <ItemGroup>
+    <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.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>
+    </None>
+    <None Update="local.settings.json">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
+    </None>
+  </ItemGroup>
+</Project>

+ 11 - 0
TEAMModelFunction/host.json

@@ -0,0 +1,11 @@
+{
+    "version": "2.0",
+    "logging": {
+        "applicationInsights": {
+            "samplingExcludedTypes": "Request",
+            "samplingSettings": {
+                "isEnabled": true
+            }
+        }
+    }
+}

+ 2 - 2
TEAMModelGrpc/Services/BlobSASService.cs

@@ -51,8 +51,8 @@ namespace TEAMModelGrpc.Services
             bool flg = IsBlobName(BlobName);
             if (flg)
             {
-                string SAS = await _azureBlobDBRepository.GetBlobSasUriRead(ContainerName, BlobName);
-                return new BlobSASDto { Url = SAS };
+                var SAS = await _azureBlobDBRepository.GetBlobSasUriRead(ContainerName, BlobName);
+                return new BlobSASDto { Url = SAS.url+SAS.sas };
             }
             else throw new BizException("文件名错误", ResponseCode.PARAMS_ERROR);
         }

+ 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>());

+ 3 - 3
TEAMModelOS.SDK/Context/Filters/HttpGlobalExceptionInvoke.cs

@@ -154,8 +154,8 @@ namespace TEAMModelOS.SDK.Context.Filter
                 error.devmsg = devMessage;
             }
 
-            public string jsonrpc { get; set; } = "2.0";
-            public double id { get; set; } = 1;
+           // public string jsonrpc { get; set; } = "2.0";
+           // public double id { get; set; } = 1;
             private object result { get; set; } = null;
             public ErrorModel<T> error { get; set; } = null;
         }
@@ -163,7 +163,7 @@ namespace TEAMModelOS.SDK.Context.Filter
 
     public class ErrorModel<E>
     {
-        public long responseTime = DateTime.Now.Ticks;
+      //  public long responseTime = DateTime.Now.Ticks;
         public int code { get; set; } = 1;
         public string message { get; set; }
         public string devmsg { get; set; }

+ 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;
+            }
+        }
+    }
+}

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

@@ -0,0 +1,222 @@
+
+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 Container SAS (有效期預設一天)
+        /// </summary>
+        /// <param name="containerName">容器名稱</param>
+        /// <param name="blobName"></param>
+        /// <param name="blobContainerSasPermissions"></param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public (string uri ,string sas) GetBlobContainerSAS(string containerName, BlobContainerSasPermissions blobContainerSasPermissions, 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(blobContainerSasPermissions);
+                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
+                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
+                UriBuilder fullUri = new UriBuilder()
+                {
+                    Scheme = "https",
+                    Host = $"{accountname}.blob.{endpoint}",
+                    Path = containerName
+                    //Query = sasQueryParameters.ToString()
+                };
+
+                return (fullUri.Uri.ToString(), sasQueryParameters.ToString());
+            }
+            catch
+            {
+                return (null, null);
+            }
+        }
+
+        /// <summary>
+        /// 取得Blob SAS (有效期預設一天)
+        /// </summary>
+        /// <param name="containerName">容器名稱</param>
+        /// <param name="blobName"></param>
+        /// <param name="blobSasPermissions"></param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        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,
+                    BlobName = blobName
+                };
+
+                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 = $"{containerName}/{blobName}",
+                    Query = sasQueryParameters.ToString()
+                };
+
+                return fullUri.Uri.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; }
+    }
+
+   
+}

+ 4 - 4
TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/AzureTokenJsonRPCRequest.cs

@@ -1,18 +1,18 @@
-using TEAMModelOS.SDK.Extension.DataResult.RequestData;
+using TEAMModelOS.SDK;
 using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest
+namespace TEAMModelOS.SDK
 {
     /// <summary>
     /// 
     /// </summary>
     /// <typeparam name="T"></typeparam>
-    public class AzureTokenJsonRPCRequest<T> : BaseJosnRPCRequest
+    public class AzureJsonRequest<T> : BaseJosnRequest
     {
 
-        public AzureTokenJsonRPCRequest (){
+        public AzureJsonRequest (){
             @params = new AzureTokenRequest<T>();
         }
         public AzureTokenRequest<T> @params { get; set; }

+ 16 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonRequest/BaseJosnRequest.cs

@@ -0,0 +1,16 @@
+
+using System;
+
+namespace TEAMModelOS.SDK
+{
+    
+    public abstract class BaseJosnRequest
+    {
+      //  public long requestTime { get; set; } = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
+       // public string jsonrpc { get; set; } = "2.0";
+        public string method { get; set; }
+    //    public int id { get; set; } = 1;
+      //  public int timeOffset { get; set; }
+        public string lang { get; set; } = "zh-CN";
+    }
+}

+ 3 - 2
TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/JosnRPCRequest.cs

@@ -3,11 +3,12 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest
+namespace TEAMModelOS.SDK
 {
     
-    public class JosnRPCRequest<T>:BaseJosnRPCRequest
+    public class JosnRequest<T>:BaseJosnRequest
     {
+
         public T @params { get; set; }
     }
 }

+ 15 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonRequest/PaginationRequest.cs

@@ -0,0 +1,15 @@
+
+
+using TEAMModelOS.SDK;
+
+namespace TEAMModelOS.SDK
+{
+    public  class PaginationJsonRequest<T> : BaseJosnRequest
+    {
+        public PaginationJsonRequest()
+        {
+            @params = new PaginationRequest<T>();
+        }
+        public PaginationRequest<T> @params { get; set; }
+    }
+}

+ 13 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/BaseResponse.cs

@@ -0,0 +1,13 @@
+
+using Microsoft.VisualBasic;
+
+namespace TEAMModelOS.SDK
+{
+    
+    public class BaseResponse 
+    {
+      //  public string jsonrpc { get; set; } = "2.0";
+       // public double id { get; set; } = 1;
+       
+    }
+}

+ 19 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/DataJsonResponse.cs

@@ -0,0 +1,19 @@
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK
+{
+    
+    public class DataJsonResponse<T> : BaseResponse
+    {
+		public DataJsonResponse() { 
+		  result=  new JsonRPCResult<T>();
+		}
+        public Dictionary<string, object> error { get; set; } = null;
+        public   JsonRPCResult<T> result { get; set; }
+        public int code { get; set; } = 0;
+        public string message { get; set; } = "Success";
+    }
+}

+ 14 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/EmptyJosnResponse.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK
+{
+    public class EmptyJosnResponse :BaseResponse
+    {
+        public object result { get; set; } = null;
+        public Dictionary<string,object> error { get; set; } = null;
+        public int code { get; set; } = 1;
+        public string message { get; set; } = "Empty";
+    }
+}

+ 19 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/ErrorJosnResponse.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK
+{
+
+    public class ErrorJosnResponse : BaseResponse
+    {
+        public ErrorJosnResponse()
+        {
+            error = new Dictionary<string, object>();
+        }
+        public object result { get; set; } = null;
+        public Dictionary<string, object> error { get; set; }
+        public int code { get; set; } = 0;
+        public string message { get; set; } = "Error";
+    }
+}

+ 15 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/ErrorModel.cs

@@ -0,0 +1,15 @@
+
+
+using System.Collections.Generic;
+
+namespace TEAMModelOS.SDK
+{
+    
+   
+
+    public class ErrorModel {
+        public int code { get; set; }
+        public string message { get; set; }
+        public Dictionary<string, object> data { get; set; } = null;
+    }
+}

+ 3 - 3
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JsonRPCResult.cs

@@ -3,14 +3,14 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
     
     public class JsonRPCResult<T>
     {
         public Dictionary<string, object> extend { get; set; } = null;
-        public long responseTime { get; set; } = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
+     //   public long responseTime { get; set; } = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
         public T data { get; set; }
-        public string message { get; set; } = "";
+       
     }
 }

+ 20 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/PageJosnResponse.cs

@@ -0,0 +1,20 @@
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK
+{
+    
+    public class PageJosnResponse<T> : BaseResponse
+    {
+		public PageJosnResponse()
+		{
+			result = new PageJsonResult<T>();
+		}
+		public   PageJsonResult<T> result { get; set; }
+		public Dictionary<string, object> error { get; set; } = null;
+		public int code { get; set; } = 0;
+		public string message { get; set; } = "Success";
+	}
+}

+ 15 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/PageJsonResult.cs

@@ -0,0 +1,15 @@
+using TEAMModelOS.SDK;
+
+
+namespace TEAMModelOS.SDK
+{
+    
+    public class PageJsonResult<T> : JsonRPCResult<T>
+    {
+        public Pagination page { get; set; }
+
+        public PageJsonResult()
+        {
+        }
+    }
+}

+ 175 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/ResponseBuilder.cs

@@ -0,0 +1,175 @@
+using TEAMModelOS.SDK;
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK
+{
+    
+    public  class ResponseBuilder
+    {
+        private string message="Success";
+        private object data;
+        private long total;
+        private int currPage;
+        private int pageSize;
+        private int totalPage;
+        private Dictionary<string, object> extend;
+        private Pagination page;
+        private AzureTableToken token;
+        private ErrorModel error =null;
+        
+        public ResponseBuilder()
+        {
+        }
+        public ResponseBuilder Success()
+        {
+            error = null;
+            return this;
+        }
+
+        public ResponseBuilder Success(String message)
+        {
+            this.message = message;
+            return this;
+        }
+        public static ResponseBuilder custom()
+        {
+            return new ResponseBuilder();
+        }
+
+        public ResponseBuilder Data(object data)
+        {
+            this.data = data;
+            return this;
+        }
+		public ResponseBuilder Error( int code, string message)
+		{
+			
+			this.error = new ErrorModel { code=code, message=message, data = null };
+			return this;
+		}
+        public ResponseBuilder Error(int code, Dictionary<string,object> errorData)
+        {
+           
+            this.error = new ErrorModel { code = code, message = message ,data= errorData };
+            return this;
+        }
+        public ResponseBuilder Error( int code)
+		{
+
+            this.error = new ErrorModel { code = code, message = "Error", data = null };
+            return this;
+		}
+        public ResponseBuilder Error(int code, string message, Dictionary<string, object> errorData)
+        {
+
+            this.error = new ErrorModel { code = code, message = message, data = errorData };
+            return this;
+        }
+
+        public ResponseBuilder Extend(Dictionary<String, object> extend)
+        {
+            this.extend = extend;
+            return this;
+        }
+        public ResponseBuilder Token(AzureTableToken token)
+        {
+            this.token = token;
+            return this;
+        }
+        public ResponseBuilder Page(Pagination page)
+        {
+            this.pageSize = page.pageSize;
+            this.currPage = page.currPage;
+            this.total = page.total;
+            this.page = page;
+            this.totalPage = (int)Math.Ceiling((double)this.total / (double)this.pageSize);
+            return this;
+        }
+        public ResponseBuilder totalCount(int totalCount)
+        {
+            this.total = totalCount;
+            return this;
+        }
+
+        public ResponseBuilder CurrPage(int currPage)
+        {
+            this.currPage = currPage;
+            return this;
+        }
+
+        public ResponseBuilder PageSize(int pageSize)
+        {
+            this.pageSize = pageSize;
+            return this;
+        }
+
+        public ResponseBuilder TotalPage(int totalPage)
+        {
+            this.totalPage = totalPage;
+            return this;
+        }
+        public BaseResponse build()
+        {
+
+            object baseResponse = null;
+            if (error != null) {
+                ErrorJosnResponse errorJosnRPCResponse = new ErrorJosnResponse();
+                errorJosnRPCResponse.error = error.data;
+                error.code = error.code;
+                error.message = error.message;
+                return errorJosnRPCResponse;
+            }
+            if (this.total > 0 && this.pageSize > 0)
+            {
+                this.totalPage = (int)Math.Ceiling((double)this.total / (double)this.pageSize);
+            }
+            if (null != this.data && this.token != null)
+            {
+                TokenJosnResponse<object> response = new TokenJosnResponse<object>();
+                response.result.data = this.data;
+                response.result.extend = this.extend;
+                response.result.azureToken = this.token;
+                response.code = 0;
+                response.message = message;
+
+                baseResponse = response;
+            }
+            else if (null != this.data && this.total > 0 && this.currPage > 0 && this.pageSize > 0 && this.totalPage > 0)
+            {
+                PageJosnResponse<object> response = new PageJosnResponse<object>();
+                response.result.data = this.data;
+                response.result.page = new Pagination(this.total, this.currPage, this.pageSize, this.totalPage);
+                response.result.extend = this.extend;
+                response.message = message;
+                response.code = 0;
+                baseResponse = response;
+            }
+            else if (this.data != null)
+            {
+                DataJsonResponse<object> response = new DataJsonResponse<object>();
+                response.result.data = this.data;
+                response.result.extend = this.extend;
+                response.message = message;
+                response.code = 0;
+                baseResponse = response;
+            }
+            else if (this.data == null) {
+                DataJsonResponse<object> response = new DataJsonResponse<object>();
+                response.result.data = this.data;
+                response.result.extend = this.extend;
+                response.message = message;
+                response.code = 0;
+                baseResponse = response;
+            }
+            else
+            {
+                return new EmptyJosnResponse() ;
+            }
+            return (BaseResponse)baseResponse;
+        }
+         
+    }
+}

+ 20 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/TokenJosnResponse.cs

@@ -0,0 +1,20 @@
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK
+{
+    
+    public class TokenJosnResponse<T>: BaseResponse
+    {
+		public TokenJosnResponse()
+		{
+			result = new TokenJsonResult<T>();
+		}
+		public  TokenJsonResult<T> result { get; set; }
+		public Dictionary<string, object> error { get; set; } = null;
+		public int code { get; set; } = 0;
+		public string message { get; set; } = "Success";
+	}
+}

+ 18 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/TokenJsonResult.cs

@@ -0,0 +1,18 @@
+using TEAMModelOS.SDK;
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK
+{
+    
+    public class TokenJsonResult<T> : JsonRPCResult<T>
+    {
+       
+        public AzureTableToken azureToken { get; set; }
+        public TokenJsonResult() { }
+       // public int code { get; set; } = 0;
+      //  public string message { get; set; } = "Success";
+    }
+}

+ 0 - 16
TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/BaseJosnRPCRequest.cs

@@ -1,16 +0,0 @@
-
-using System;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest
-{
-    
-    public abstract class BaseJosnRPCRequest
-    {
-        public long requestTime { get; set; } = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
-        public string jsonrpc { get; set; } = "2.0";
-        public string method { get; set; }
-        public int id { get; set; } = 1;
-        public int timeOffset { get; set; }
-        public string lang { get; set; } = "zh-CN";
-    }
-}

+ 0 - 15
TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/PaginationJosnRPCRequest.cs

@@ -1,15 +0,0 @@
-
-
-using TEAMModelOS.SDK.Extension.DataResult.RequestData;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest
-{
-    public  class PaginationJosnRPCRequest<T> : BaseJosnRPCRequest
-    {
-        public PaginationJosnRPCRequest()
-        {
-            @params = new PaginationRequest<T>();
-        }
-        public PaginationRequest<T> @params { get; set; }
-    }
-}

+ 0 - 14
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/BaseJosnRPCResponse.cs

@@ -1,14 +0,0 @@
-
-using Microsoft.VisualBasic;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class BaseJosnRPCResponse 
-    {
-        public string jsonrpc { get; set; } = "2.0";
-        public double id { get; set; } = 1;
-        private object result { get; set; }
-        public object error { get; set; } = null;
-    }
-}

+ 0 - 16
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/DataJosnRPCResponse.cs

@@ -1,16 +0,0 @@
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class DataJosnRPCResponse<T> : BaseJosnRPCResponse
-    {
-		public DataJosnRPCResponse() { 
-		  result=  new JsonRPCResult<T>();
-		}
-		public   JsonRPCResult<T> result { get; set; } 
-    }
-}

+ 0 - 16
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/ErrorJosnRPCResponse.cs

@@ -1,16 +0,0 @@
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class ErrorJosnRPCResponse<E> : BaseJosnRPCResponse
-    {
-        public ErrorJosnRPCResponse() {
-            error = new ErrorModel<E>();
-        }
-        public new ErrorModel<E> error { get; set; }
-    }
-}

+ 0 - 13
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/ErrorModel.cs

@@ -1,13 +0,0 @@
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class ErrorModel<E>
-    {
-        public int code { get; set; }
-        public string message { get; set; }
-        public string devmsg { get; set; }
-        public E data { get; set; }
-    }
-}

+ 0 - 13
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JosnRPCResponse.cs

@@ -1,13 +0,0 @@
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class JosnRPCResponse<T>:BaseJosnRPCResponse
-    {
-        public  T result { get; set; }
-    }
-}

+ 0 - 176
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JsonRPCResponseBuilder.cs

@@ -1,176 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public  class JsonRPCResponseBuilder
-    {
-        private string message="Success";
-        private string devmsg = "Error";
-        private int code = 0;
-        private object data;
-        private long total;
-        private int currPage;
-        private int pageSize;
-        private int totalPage;
-        private Dictionary<string, object> extend;
-        private Pagination page;
-        private AzureTableToken token;
-        private object error=null;
-        
-        public JsonRPCResponseBuilder()
-        {
-        }
-        public JsonRPCResponseBuilder Success()
-        {
-            error = null;
-            return this;
-        }
-
-        public JsonRPCResponseBuilder Success(String message)
-        {
-            this.message = message;
-            return this;
-        }
-        public static JsonRPCResponseBuilder custom()
-        {
-            return new JsonRPCResponseBuilder();
-        }
-
-        public JsonRPCResponseBuilder Data(object data)
-        {
-            this.data = data;
-            return this;
-        }
-		public JsonRPCResponseBuilder Error(object error, string message)
-		{
-			this.code = 1;
-			this.message = message;
-			this.error = error;
-			return this;
-		}
-		public JsonRPCResponseBuilder Error(object error, int code,string message)
-		{
-			this.code = code;
-			this.message = message;
-			this.error = error;
-			return this;
-		}
-		public JsonRPCResponseBuilder Error(object error,int code)
-		{
-			this.code = code;
-			this.message = "Error";
-			this.error = error;
-			return this;
-		}
-		public JsonRPCResponseBuilder Error(object error)
-        {
-			this.code = 1;
-			this.message = "Error";
-            this.error = error;
-            return this;
-        }
-        public JsonRPCResponseBuilder Extend(Dictionary<String, object> extend)
-        {
-            this.extend = extend;
-            return this;
-        }
-        public JsonRPCResponseBuilder Token(AzureTableToken token)
-        {
-            this.token = token;
-            return this;
-        }
-        public JsonRPCResponseBuilder Page(Pagination page)
-        {
-            this.pageSize = page.pageSize;
-            this.currPage = page.currPage;
-            this.total = page.total;
-            this.page = page;
-            this.totalPage = (int)Math.Ceiling((double)this.total / (double)this.pageSize);
-            return this;
-        }
-        public JsonRPCResponseBuilder totalCount(int totalCount)
-        {
-            this.total = totalCount;
-            return this;
-        }
-
-        public JsonRPCResponseBuilder CurrPage(int currPage)
-        {
-            this.currPage = currPage;
-            return this;
-        }
-
-        public JsonRPCResponseBuilder PageSize(int pageSize)
-        {
-            this.pageSize = pageSize;
-            return this;
-        }
-
-        public JsonRPCResponseBuilder TotalPage(int totalPage)
-        {
-            this.totalPage = totalPage;
-            return this;
-        }
-        public BaseJosnRPCResponse build()
-        {
-            object baseResponse= null;
-
-            if (error != null) {
-                ErrorJosnRPCResponse<object> errorJosnRPCResponse = new ErrorJosnRPCResponse<object>();
-                errorJosnRPCResponse.error.code = code;
-                errorJosnRPCResponse.error.message = message;
-                errorJosnRPCResponse.error.data = error;
-                errorJosnRPCResponse.error.devmsg = devmsg;
-                baseResponse = errorJosnRPCResponse;
-                return (BaseJosnRPCResponse)baseResponse;
-            }
-            if (this.total > 0 && this.pageSize > 0)
-            {
-                this.totalPage = (int)Math.Ceiling((double)this.total / (double)this.pageSize);
-            }
-            if (null != this.data && this.token != null)
-            {
-                TokenJosnRPCResponse<object> tokenJosnRPCResponse = new TokenJosnRPCResponse<object>();
-                tokenJosnRPCResponse.result.data = this.data;
-                tokenJosnRPCResponse.result.extend = this.extend;
-                tokenJosnRPCResponse.result.azureToken = this.token;
-                tokenJosnRPCResponse.result.message = message;
-                baseResponse = tokenJosnRPCResponse;
-            }
-            else if (null != this.data && this.total > 0 && this.currPage > 0 && this.pageSize > 0 && this.totalPage > 0)
-            {
-                PageJosnRPCResponse<object> pageDatasResponse = new PageJosnRPCResponse<object>();
-                pageDatasResponse.result.data = this.data;
-                pageDatasResponse.result.page = new Pagination(this.total, this.currPage, this.pageSize, this.totalPage);
-                pageDatasResponse.result.extend = this.extend;
-                pageDatasResponse.result.message = message;
-                baseResponse = pageDatasResponse;
-            }
-            else if (this.data != null)
-            {
-                DataJosnRPCResponse<object> datasResponse = new DataJosnRPCResponse<object>();
-                datasResponse.result.data = this.data;
-                datasResponse.result.extend = this.extend;
-                datasResponse.result.message = message;
-                baseResponse = datasResponse;
-            }
-            else if (this.data == null) {
-                DataJosnRPCResponse<object> datasResponse = new DataJosnRPCResponse<object>();
-                datasResponse.result.data = this.data;
-                datasResponse.result.extend = this.extend;
-                datasResponse.result.message = message;
-                baseResponse = datasResponse;
-            }
-            else
-            {
-                baseResponse = new BaseJosnRPCResponse();
-            }
-            return (BaseJosnRPCResponse)baseResponse;
-        }
-    }
-}

+ 0 - 17
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/PageJosnRPCResponse.cs

@@ -1,17 +0,0 @@
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class PageJosnRPCResponse<T> : BaseJosnRPCResponse
-    {
-		public PageJosnRPCResponse()
-		{
-			result = new PageJsonRPCResult<T>();
-		}
-		public   PageJsonRPCResult<T> result { get; set; }
-    }
-}

+ 0 - 15
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/PageJsonRPCResult.cs

@@ -1,15 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class PageJsonRPCResult<T> : JsonRPCResult<T>
-    {
-        public Pagination page { get; set; }
-
-        public PageJsonRPCResult()
-        {
-        }
-    }
-}

+ 0 - 17
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/TokenJosnRPCResponse.cs

@@ -1,17 +0,0 @@
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class TokenJosnRPCResponse<T>: BaseJosnRPCResponse
-    {
-		public TokenJosnRPCResponse()
-		{
-			result = new TokenJsonRPCResult<T>();
-		}
-		public  TokenJsonRPCResult<T> result { get; set; }
-    }
-}

+ 0 - 16
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/TokenJsonRPCResult.cs

@@ -1,16 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class TokenJsonRPCResult<T> : JsonRPCResult<T>
-    {
-       
-        public AzureTableToken azureToken { get; set; }
-        public TokenJsonRPCResult() { }
-    }
-}

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/PageToken/AzurePagination.cs

@@ -1,7 +1,7 @@
 
 using System.Collections.Generic;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.PageToken
+namespace TEAMModelOS.SDK
 {
     
     public class AzurePagination<T>

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/PageToken/AzureTableToken.cs

@@ -1,7 +1,7 @@
 
 using System.ComponentModel.DataAnnotations;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.PageToken
+namespace TEAMModelOS.SDK
 {
     
     public class AzureTableToken

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/PageToken/Pagination.cs

@@ -2,7 +2,7 @@
 using System;
 using System.Collections.Generic;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.PageToken
+namespace TEAMModelOS.SDK
 {
     
     public class Pagination

+ 0 - 12
TEAMModelOS.SDK/Extension/DataResult/PageToken/PaginationData.cs

@@ -1,12 +0,0 @@
-using System.Collections.Generic;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.PageToken
-{
-    public class PaginationData<T>:Pagination
-    {
-        public PaginationData(int currPage, int pageSize, int total) : base(currPage, pageSize, total)
-        {
-        }
-        public List<T> data { get; set; }
-    }
-}

+ 2 - 2
TEAMModelOS.SDK/Extension/DataResult/RequestData/AzureTokenRequest.cs

@@ -1,9 +1,9 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
+using TEAMModelOS.SDK;
 using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.RequestData
+namespace TEAMModelOS.SDK
 {
    public class AzureTokenRequest<T> :BaseRequest
    {

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/RequestData/BaseRequest.cs

@@ -1,7 +1,7 @@
 using System;
 using System.Collections.Generic;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.RequestData
+namespace TEAMModelOS.SDK
 {
     public class BaseRequest
     {

+ 2 - 2
TEAMModelOS.SDK/Extension/DataResult/RequestData/PaginationRequest.cs

@@ -1,6 +1,6 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
+using TEAMModelOS.SDK;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.RequestData
+namespace TEAMModelOS.SDK
 {
     public class PaginationRequest<T> : BaseRequest
     {

+ 0 - 16
TEAMModelOS.SDK/Extension/DataResult/ResponseData/BaseResponse.cs

@@ -1,16 +0,0 @@
-
-using System.Collections.Generic;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class BaseResponse : TimeStampResponse
-    {
-        public Dictionary<string, object> extend { get; set; }
-        public string message { get; set; } = "success";
-        public int code { get; set; }
-        public BaseResponse()
-        {
-        }
-    }
-}

+ 0 - 14
TEAMModelOS.SDK/Extension/DataResult/ResponseData/DataResponse.cs

@@ -1,14 +0,0 @@
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class DataResponse<T> : BaseResponse
-    {
-        public T data { get; set; }
-
-        public DataResponse()
-        {
-        }
-    }
-}

+ 0 - 15
TEAMModelOS.SDK/Extension/DataResult/ResponseData/PageDatasResponse.cs

@@ -1,15 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class PageDatasResponse<T> : DataResponse<T>
-    {
-        public Pagination page { get; set; }
-
-        public PageDatasResponse()
-        {
-        }
-    }
-}

+ 0 - 162
TEAMModelOS.SDK/Extension/DataResult/ResponseData/ResponseBuilder.cs

@@ -1,162 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-using System;
-using System.Collections.Generic;
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class ResponseBuilder
-    {
-        private string message = "success";
-        private object data;
-        private int code = 0;
-       // private IList<object> datas;
-        private long total;
-        private int currPage;
-        private int pageSize;
-        private int totalPage;
-        private Dictionary<string, object> extend;
-        private Pagination page;
-        private AzureTableToken  token;
-        public ResponseBuilder()
-        {
-        }
-
-        public static ResponseBuilder custom()
-        {
-            return new ResponseBuilder();
-        }
-
-        public BaseResponse build()
-        {
-            if (this.total > 0 && this.pageSize > 0 )
-            {
-                this.totalPage = (int)Math.Ceiling((double)this.total / (double)this.pageSize);
-            }
-            object baseResponse;
-           
-             if (null != this.data && this.token!=null)
-            {
-                TokenPageDatasResponse<object> pageDatasResponse = new TokenPageDatasResponse<object>();
-                pageDatasResponse.code= this.code;
-                pageDatasResponse.data= this.data;
-                pageDatasResponse.message= this.message;
-                pageDatasResponse.extend=this.extend;
-                pageDatasResponse.azureToken = this.token;
-                baseResponse = pageDatasResponse;
-            }
-            else if (null != this.data && this.total > 0 && this.currPage > 0 && this.pageSize > 0 && this.totalPage > 0)
-            {
-                PageDatasResponse<object> pageDatasResponse = new PageDatasResponse<object>();
-                pageDatasResponse.code = this.code;
-                pageDatasResponse.data = this.data;
-                pageDatasResponse.message = this.message;
-                pageDatasResponse.page = new Pagination(this.total, this.currPage, this.pageSize, this.totalPage);
-                pageDatasResponse.extend = this.extend;
-                baseResponse = pageDatasResponse;
-            }
-            else if (this.data != null)
-            {
-                DataResponse<object> datasResponse = new DataResponse<object>();
-                datasResponse.code=this.code;
-                datasResponse.data=this.data;
-                datasResponse.message=this.message;
-                datasResponse.extend=this.extend;
-                baseResponse = datasResponse;
-            }
-            else
-            {
-                baseResponse = new BaseResponse();
-                ((BaseResponse)baseResponse).message=this.message;
-                ((BaseResponse)baseResponse).code=this.code;
-                ((BaseResponse)baseResponse).extend=this.extend;
-            }
-            return (BaseResponse)baseResponse;
-        }
-
-        
-
-        public ResponseBuilder Extend(Dictionary<String, object> extend)
-        {
-            this.extend = extend;
-            return this;
-        }
-        public ResponseBuilder Token(AzureTableToken token)
-        {
-            this.token = token;
-            return this;
-        }
-        public ResponseBuilder Data(object data)
-        {
-            this.data = data;
-            return this;
-        }
-       
-        public ResponseBuilder Page(Pagination page)
-        {
-            this.pageSize = page.pageSize;
-            this.currPage = page.currPage;
-            this.total = page.total;
-            this.page = page;
-            this.totalPage = (int)Math.Ceiling((double)this.total / (double)this.pageSize);
-            return this;
-        }
-        public ResponseBuilder totalCount(int totalCount)
-        {
-            this.total = totalCount;
-            return this;
-        }
-
-        public ResponseBuilder CurrPage(int currPage)
-        {
-            this.currPage = currPage;
-            return this;
-        }
-
-        public ResponseBuilder PageSize(int pageSize)
-        {
-            this.pageSize = pageSize;
-            return this;
-        }
-
-        public ResponseBuilder TotalPage(int totalPage)
-        {
-            this.totalPage = totalPage;
-            return this;
-        }
-
-        public ResponseBuilder success()
-        {
-            return this;
-        }
-
-        public ResponseBuilder success(String message)
-        {
-            this.message = message;
-            return this;
-        }
-
-        public ResponseBuilder success(String message, int code)
-        {
-            this.message = message;
-            this.code = code;
-            return this;
-        }
-
-        public ResponseBuilder failed(String message, int code)
-        {
-            this.code = code;
-            this.message = message;
-            return this;
-        }
-
-        public ResponseBuilder failed(String message)
-        {
-            this.code = 1;
-            this.message = message;
-            return this;
-        }
-    }
-}

+ 0 - 16
TEAMModelOS.SDK/Extension/DataResult/ResponseData/TimeStampResponse.cs

@@ -1,16 +0,0 @@
-
-using System;
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class TimeStampResponse
-    {
-        public long responseTime { get; set; } = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
-        public TimeStampResponse()
-        {
-
-        }
-    }
-}

+ 0 - 14
TEAMModelOS.SDK/Extension/DataResult/ResponseData/TokenPageDatasResponse.cs

@@ -1,14 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class TokenPageDatasResponse<T> : DataResponse<T>
-    {
-        public AzureTableToken azureToken { get; set; }
-
-        public TokenPageDatasResponse() { }
-    }
-}

+ 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;
+//        }
+//    }
+//}

+ 14 - 0
TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobAuth.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
+{
+    public class BlobAuth
+    {
+        public string url { get; set; }
+        public string sas { get; set; }
+        public long timeout { get; set; }
+        public string name { get; set; }
+    }
+}

+ 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;

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

@@ -15,13 +15,13 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
 
         public AzureBlobModel()
         {
-            long time = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
-            Timestamp = DateTimeHelper.ConvertToDateTime(time);
+            long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
+            Timestamp = DateTime.UtcNow;
         }
 
         public AzureBlobModel(IFormFile f, string Container ,string groupName ,string newName)
         {
-            long time= DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
+            long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
             ContentType = f.ContentType;
             ContentDisposition = f.ContentDisposition;
             FileName = f.FileName;
@@ -39,7 +39,7 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
 
         public AzureBlobModel(FileInfo f, string Container, string groupName, string newName ,string  contentType)
         {
-            long time = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
+            long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
             ContentType = contentType;
             ContentDisposition = "form-data; name=\"file\"; filename=\"" + f.Name + "\"";
             FileName = f.Name;
@@ -57,7 +57,7 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
 
         public AzureBlobModel(string fileName, string Container, string groupName, string newName, string contentType ,long length)
         {
-            long time = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
+            long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
             ContentType = contentType;
             ContentDisposition = "form-data; name=\"file\"; filename=\"" + fileName + "\"";
             FileName = fileName;
@@ -74,7 +74,7 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
         }
         public AzureBlobModel(string fileName, string Container, string groupName, string newName,string sha1Code, string contentType, long length)
         {
-            long time = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
+            long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
             ContentType = contentType;
             ContentDisposition = "form-data; name=\"file\"; filename=\"" + fileName + "\"";
             FileName = fileName;
@@ -88,7 +88,7 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
             PartitionKey = Container;
             RowKey = Guid.NewGuid().ToString();
             Extension = fileName.Substring(fileName.LastIndexOf(".") + 1, (fileName.Length - fileName.LastIndexOf(".") - 1)); //扩展名
-            Timestamp = DateTimeHelper.ConvertToDateTime(time);
+            Timestamp = DateTime.UtcNow;
         }
         [Required(ErrorMessage = "{0} 必须填写")]
         public string Folder { get; set; }

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 913 - 875
TEAMModelOS.SDK/Module/AzureBlob/Implements/AzureBlobDBRepository.cs


+ 34 - 8
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
@@ -20,17 +19,44 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Interfaces
         AzureBlobModel UploadFileByFolderNAsyn(Stream fileSteam, string folder, string fileName, string fileSpace = "pptx", bool contentTypeDefault = true);
         Task<string> GetBlobSasUri(string blobName, string containerName=null,  string policyName = null);
         Task<string> GetBlobSasUriRead(string containerName, string blobName, string policyName = null);
-        Task<dynamic> GetBlobSasUriRead(string containerName, string blobName);
-       Task<(string, string, string)> GetContainerSasUri(string containerName=null, string policyName = null);
+        Task<(string, string, string)> GetContainerSasUri(string containerName=null, string policyName = null);
         Task<(string, string)> GetContainerSasUriRead(string containerName, string policyName = null);
         Task<bool> CreateSharedAccessPolicyAsync(string policyName , string  containerName = null);
         Task DeleteSharedAccessPolicyAsync(string policyName, string  containerName = null);
         Task Deleteblob(string sasUri);
-
-         Task<List<BlobFileDto>> GetBlobDirectory(string containerName, string blobName);
-
+        Task<List<BlobFileDto>> GetBlobDirectory(string containerName, string blobName);
         Task<Dictionary<string, object>> GetBlobSasUri(BlobSas blobSas,bool isRead);
-        Task<dynamic> GetContainerSasUri(BlobSas blobSas, bool isRead);
 
+        /// <summary>
+        /// 获取某个文件的共享访问签名
+        /// </summary>
+        /// <param name="containerName"></param>
+        /// <param name="blobName"></param>
+        /// <returns></returns>
+        Task<BlobAuth> GetBlobSasUriRead(string containerName, string blobName);
+        /// <summary>
+        /// 获取某个角色及对应的容器的共享访问签名
+        /// </summary>
+        /// <param name="blobSas"></param>
+        /// <param name="isRead"></param>
+        /// <returns></returns>
+        Task<BlobAuth> GetContainerSasUri(BlobSas blobSas, bool isRead);
+        /// <summary>
+        /// 系统管理员 资源,题目关联,htex关联,学习活动学生上传文件关联,基本信息关联,教室平面图关联,评测冷数据关联
+        /// "system": [ "res", "item", "htex", "task", "info", "room", "exam" ],
+        /// 资源,题目关联,htex关联,学习活动学生上传文件关联,基本信息关联,教室平面图关联,评测冷数据关联
+        /// "school": [ "res", "item", "htex", "task", "info", "room", "exam" ],
+        /// 资源,题目关联,htex关联,学习活动关联,教师基本信息关联
+        /// "teacher": [ "res", "item", "htex", "task", "info" ],
+        /// 答案及学习活动上传的文件,学生基本信息关联
+        ///"student": [ "stu/{studentId}/ans", "stu/{studentId}/task" ]
+        /// </summary>
+        /// <param name="name">容器名称</param>
+        /// <param name="text">文件内容的流</param>
+        /// <param name="folder">业务文件夹</param>
+        /// <param name="fileName">文件名</param>
+        /// <param name="contentTypeDefault">是否存放文件后缀对应的contentType</param>
+        /// <returns></returns>
+        Task<AzureBlobModel> UploadFileByContainer(string name, string text, string folder, string fileName, bool contentTypeDefault = true);
     }
 }

+ 14 - 1
TEAMModelOS.SDK/Module/AzureCosmosDBV3/AzureCosmosDBV3Repository.cs

@@ -17,6 +17,8 @@ using System.Threading.Tasks;
 using TEAMModelOS.SDK.Context.Attributes.Azure;
 using TEAMModelOS.SDK.Context.Exception;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+using TEAMModelOS.SDK.Helper.Common.JsonHelper;
+using TEAMModelOS.SDK.Helper.Common.LogHelper;
 using TEAMModelOS.SDK.Helper.Common.ReflectorExtensions;
 using TEAMModelOS.SDK.Module.AzureCosmosDB.Configuration;
 
@@ -411,6 +413,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
             if (dict.Keys.Count > 0)
             {
                 List<T> list = await FindByDict<T>(dict);
+               
                 return await DeleteAll(list);
             }
             else
@@ -425,7 +428,17 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
             string pk = GetPartitionKey<T>();
             CosmosModelInfo container = await InitializeCollection<T>();
             List<IdPk> idPks = new List<IdPk>();
-
+            //log4net 日志記錄
+            string uuidKey = Guid.NewGuid().ToString();
+            string logkey = "\r\n【" + uuidKey + "】\r\n";
+            LogHelper.Info(this,
+                           logkey
+                           + "删除------->>\r\n"
+                           + "表:"
+                           + type.Name+ "\r\n"
+                           + "数据:"
+                           + enyites.ToApiJson()
+                           + "\r\n"+ logkey);
             if (container.monitor)
             {
                 enyites = await DeleteTTL(enyites);

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

@@ -2,7 +2,7 @@
 using Microsoft.Azure.Cosmos.Table;
 using System;
 using System.ComponentModel.DataAnnotations;
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
+using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Helper.Common.ValidateHelper;
 
 namespace TEAMModelOS.SDK.Module.AzureTable.Configuration

+ 1 - 1
TEAMModelOS.SDK/Module/AzureTable/Implements/AzureTableDBRepository.cs

@@ -1,6 +1,6 @@
 using TEAMModelOS.SDK.Module.AzureTable.Configuration;
 using TEAMModelOS.SDK.Module.AzureTable.Interfaces;
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
+using TEAMModelOS.SDK;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;

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

@@ -1,5 +1,5 @@
 using TEAMModelOS.SDK.Module.AzureTable.Configuration;
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
+using TEAMModelOS.SDK;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using Microsoft.Azure.Cosmos.Table;

+ 0 - 1
TEAMModelOS.SDK/Module/Cache/CSRedisCacheService.cs

@@ -1,7 +1,6 @@
 using Microsoft.Extensions.Caching.Distributed;
 using Microsoft.Extensions.Caching.Redis;
  
-using StackExchange.Redis;
 using System;
 using System.Collections.Generic;
 using System.Linq;

+ 0 - 307
TEAMModelOS.SDK/Module/Cache/RedisCacheService.cs

@@ -1,307 +0,0 @@
-using Microsoft.Extensions.Caching.Redis;
-using Newtonsoft.Json;
-using StackExchange.Redis;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace TEAMModelOS.SDK.Module.Cache
-{
-    public class RedisCacheService : ICacheService,IDisposable
-    {
-        protected IDatabase _cache;
-
-        private ConnectionMultiplexer _connection;
-
-        private readonly string _instance;
-        public RedisCacheService(RedisCacheOptions options, int database = 0)
-        {
-            _connection = ConnectionMultiplexer.Connect(options.Configuration);
-            _cache = _connection.GetDatabase(database);
-            _instance = options.InstanceName;
-        }
-
-        public string GetKeyForRedis(string key)
-        {
-            return _instance + key;
-        }/// <summary>
-         /// 验证缓存项是否存在
-         /// </summary>
-         /// <param name="key">缓存Key</param>
-         /// <returns></returns>
-        public bool Exists(string key)
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-            return _cache.KeyExists(GetKeyForRedis(key));
-        }/// <summary>
-         /// 添加缓存
-         /// </summary>
-         /// <param name="key">缓存Key</param>
-         /// <param name="value">缓存Value</param>
-         /// <returns></returns>
-        public bool Add(string key, object value)
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-            return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)));
-        }
-        /// <summary>
-        /// 添加缓存
-        /// </summary>
-        /// <param name="key">缓存Key</param>
-        /// <param name="value">缓存Value</param>
-        /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>
-        /// <param name="expiressAbsoulte">绝对过期时长</param>
-        /// <returns></returns>
-        public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-            return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), expiressAbsoulte);
-        }
-        /// <summary>
-        /// 添加缓存
-        /// </summary>
-        /// <param name="key">缓存Key</param>
-        /// <param name="value">缓存Value</param>
-        /// <param name="expiresIn">缓存时长</param>
-        /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>
-        /// <returns></returns>
-        public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-
-
-            return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), expiresIn);
-        }/// <summary>
-         /// 删除缓存
-         /// </summary>
-         /// <param name="key">缓存Key</param>
-         /// <returns></returns>
-        public bool Remove(string key)
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-            return _cache.KeyDelete(GetKeyForRedis(key));
-        }
-        /// <summary>
-        /// 批量删除缓存
-        /// </summary>
-        /// <param name="key">缓存Key集合</param>
-        /// <returns></returns>
-        public void RemoveAll(IEnumerable<string> keys)
-        {
-            if (keys == null)
-            {
-                throw new ArgumentNullException(nameof(keys));
-            }
-
-            keys.ToList().ForEach(item => Remove(item));
-        }
-
-
-        /// <summary>
-        /// 获取缓存
-        /// </summary>
-        /// <param name="key">缓存Key</param>
-        /// <returns></returns>
-        public T Get<T>(string key) where T : class
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-
-            var value = _cache.StringGet(GetKeyForRedis(key));
-
-            if (!value.HasValue)
-            {
-                return default(T);
-            }
-
-            return JsonConvert.DeserializeObject<T>(value);
-        }
-
-        /// <summary>
-        /// 获取缓存
-        /// </summary>
-        /// <param name="key">缓存Key</param>
-        /// <returns></returns>
-        public object Get(string key)
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-
-            var value = _cache.StringGet(GetKeyForRedis(key));
-
-            if (!value.HasValue)
-            {
-                return null;
-            }
-         
-
-            return JsonConvert.DeserializeObject(value);
-        }   /// <summary>
-            /// 获取缓存集合
-            /// </summary>
-            /// <param name="keys">缓存Key集合</param>
-            /// <returns></returns>
-        public IDictionary<string, object> GetAll(IEnumerable<string> keys)
-        {
-            if (keys == null)
-            {
-                throw new ArgumentNullException(nameof(keys));
-            }
-            var dict = new Dictionary<string, object>();
-
-            keys.ToList().ForEach(item => dict.Add(item, Get(GetKeyForRedis(item))));
-
-            return dict;
-        }
-
-        /// <summary>
-        /// 修改缓存
-        /// </summary>
-        /// <param name="key">缓存Key</param>
-        /// <param name="value">新的缓存Value</param>
-        /// <returns></returns>
-        public bool Replace(string key, object value)
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-
-            if (Exists(key))
-                if (!Remove(key))
-                    return false;
-
-            return Add(key, value);
-
-        }
-        /// <summary>
-        /// 修改缓存
-        /// </summary>
-        /// <param name="key">缓存Key</param>
-        /// <param name="value">新的缓存Value</param>
-        /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
-        /// <param name="expiressAbsoulte">绝对过期时长</param>
-        /// <returns></returns>
-        public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-
-            if (Exists(key))
-                if (!Remove(key))
-                    return false;
-
-            return Add(key, value, expiresSliding, expiressAbsoulte);
-        }
-        /// <summary>
-        /// 修改缓存
-        /// </summary>
-        /// <param name="key">缓存Key</param>
-        /// <param name="value">新的缓存Value</param>
-        /// <param name="expiresIn">缓存时长</param>
-        /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
-        /// <returns></returns>
-        public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
-        {
-            if (key == null)
-            {
-                throw new ArgumentNullException(nameof(key));
-            }
-
-            if (Exists(key))
-                if (!Remove(key)) return false;
-
-            return Add(key, value, expiresIn, isSliding);
-        }
-        public void Dispose()
-        {
-            if (_connection != null)
-                _connection.Dispose();
-            GC.SuppressFinalize(this);
-        }
-
-
-        public async Task<bool> ExistsAsync(string key)
-        {
-            return await Task.Run(() => Exists(key));
-        }
-
-        public async Task<bool> AddAsync(string key, object value)
-        {
-            return await Task.Run(() => Add(key, value));
-        }
-
-        public async Task<bool> AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
-        {
-            return await Task.Run(() => Add(key, value, expiresSliding, expiressAbsoulte));
-        }
-
-        public async Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)
-        {
-            return await Task.Run(() => Add(key, value, expiresIn, isSliding));
-        }
-
-        public async Task<bool> RemoveAsync(string key)
-        {
-            return await Task.Run(() => Remove(key));
-        }
-
-        public async Task RemoveAllAsync(IEnumerable<string> keys)
-        {
-            await Task.Run(() => RemoveAll(keys));
-        }
-
-        public async Task<T> GetAsync<T>(string key) where T : class
-        {
-            return await Task.Run(() => Get<T>(key));
-        }
-
-        public async Task<object> GetAsync(string key)
-        {
-            return await Task.Run(() => Get(key));
-        }
-
-        public async Task<IDictionary<string, object>> GetAllAsync(IEnumerable<string> keys)
-        {
-            return await Task.Run(() => GetAll(keys));
-        }
-
-        public async Task<bool> ReplaceAsync(string key, object value)
-        {
-            return await Task.Run(() => Replace(key, value));
-        }
-
-        public async Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
-        {
-            return await Task.Run(() => Replace(key, value, expiresSliding, expiressAbsoulte));
-        }
-
-        public async Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)
-        {
-            return await Task.Run(() => Replace(key, value, expiresIn, isSliding));
-        }
-    }
-}

+ 14 - 10
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" />
@@ -20,29 +24,29 @@
     <PackageReference Include="Jaeger" Version="0.3.7" />
     <PackageReference Include="LiteDB" Version="5.0.5" />
     <PackageReference Include="log4net" Version="2.0.8" />
-    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.3" />
-    <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.3" />
+    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.6" />
+    <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.6" />
     <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
-    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="3.1.3" />
-    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.3" />
+    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="3.1.6" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.6" />
     <PackageReference Include="Microsoft.Azure.CosmosDB.BulkExecutor" Version="2.4.1-preview" />
     <PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="2.10.1" />
     <PackageReference Include="Microsoft.Azure.ServiceBus" Version="4.1.3" />
     <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
-    <PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" />
-    <PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.3" />
-    <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.3" />
-    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.3" />
+    <PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.6" />
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.6" />
+    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.6" />
     <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.5.0" />
     <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.8.0" />
+    <PackageReference Include="Microsoft.Azure.Cosmos" Version="3.11.0" />
     <PackageReference Include="Microsoft.Azure.Cosmos.Table" Version="2.0.0-preview" />
     <PackageReference Include="Caching.CSRedis" Version="3.5.5" />
+    <PackageReference Include="CoreSDK" Version="1.0.0" />
   </ItemGroup>
 </Project>

+ 39 - 0
TEAMModelOS.Service/Models/SchoolInfo/Paper.cs

@@ -34,27 +34,66 @@ namespace TEAMModelOS.Service.Models
         /// 试卷的基本信息
         /// </summary>
         public string url { get; set; }
+        /// <summary>
+        /// 题目信息
+        /// </summary>
         public List<ItemInfo> item { get; set; }
+        /// <summary>
+        /// 科目
+        /// </summary>
         public string subjectCode { get; set; }
+        /// <summary>
+        /// 学段
+        /// </summary>
         public string periodCode { get; set; }
+        /// <summary>
+        /// 年级
+        /// </summary>
         public List<string> gradeCode { get; set; }
+
+        /// <summary>
+        /// 试卷名称
+        /// </summary>
         public string name { get; set; }
+        /// <summary>
+        /// 题目总数
+        /// </summary>
         public int itemCount { get; set; }
+        /// <summary>
+        /// 题目难度
+        /// </summary>
         public double level { get; set; }
+        /// <summary>
+        /// 总分
+        /// </summary>
         public double score { get; set; }
         /// <summary>
         /// type:{
         ///     pointkey:[num1,num2....]
         /// }
+        /// 题型的分数占比
         /// </summary>
+      
         public Dictionary<string, ScoreCount> typeScore { get; set; }
+        /// <summary>
+        /// 题目难度分数占比
+        /// </summary>
         public Dictionary<string, ScoreCount> levelScore { get; set; }
+        /// <summary>
+        /// 知识点分数占比
+        /// </summary>
         public Dictionary<string, ScoreItem> pointScore { get; set; }
+        /// <summary>
+        /// 创建时间
+        /// </summary>
         public long createTime { get; set; }
         /// <summary>
         /// 正确答案
         /// </summary>
         public List<Answer> answers { get; set; }
+        /// <summary>
+        /// 阅卷规则
+        /// </summary>
         public MarkConfig markConfig { get; set; }
 
     }

+ 1 - 1
TEAMModelOS.Service/Services/ChangeFeed/SyllabusVolumeChangeFeed.cs

@@ -8,7 +8,7 @@ using TEAMModelOS.Service.Models;
 
 namespace TEAMModelOS.Service.Services.ChangeFeed
 {
-    class SyllabusVolumeChangeFeed : IChangeFeedService<Volume>, IChangeService
+    public class SyllabusVolumeChangeFeed : IChangeFeedService<Volume>, IChangeService
     {
         private IAzureCosmosDBV3Repository cosmosDBV3Repository;
         public SyllabusVolumeChangeFeed(IAzureCosmosDBV3Repository azureCosmos)

+ 4 - 4
TEAMModelOS.Service/Services/PowerPoint/Implement/HtexService.cs

@@ -1343,8 +1343,8 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
                 }
                 // type: none, triangle, stealth, diamond, oval, arrow
 
-                if ((headEndNodeAttrs != null && (headEndNodeAttrs.GetTextByPath("@type").Value == "triangle" || (headEndNodeAttrs.GetTextByPath("@type").Value == "arrow")) ||
-                    (tailEndNodeAttrs != null && (tailEndNodeAttrs.GetTextByPath("@type").Value == "triangle" || (tailEndNodeAttrs.GetTextByPath("@type").Value == "arrow")))))
+                if ((headEndNodeAttrs != null && headEndNodeAttrs.GetTextByPath("@type") !=null&& (headEndNodeAttrs.GetTextByPath("@type").Value == "triangle" || (headEndNodeAttrs.GetTextByPath("@type").Value == "arrow")) ||
+                    (tailEndNodeAttrs != null && tailEndNodeAttrs.GetTextByPath("@type") != null && (tailEndNodeAttrs.GetTextByPath("@type").Value == "triangle" || (tailEndNodeAttrs.GetTextByPath("@type").Value == "arrow")))))
                 {
                   //  var triangleMarker = "<marker id='markerTriangle_" + order + "' viewBox='0 0 10 10' refX='1' refY='5' markerWidth='5' markerHeight='5' stroke='" + shapeBorder.Color + "' fill='" + shapeBorder.Color +
                              //       "' orient='auto-start-reverse' markerUnits='strokeWidth'><path d='M 0 0 L 10 5 L 0 10 z' /></marker>";
@@ -1523,8 +1523,8 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
                         //StrokeWidth = shapeBorder.Width + "",
                         //StrokeDasharray = shapeBorder.Stroke,
                         d=d,
-                        start=headEndNodeAttrs!=null?headEndNodeAttrs.GetTextByPath("@type").Value:null,
-                        end=tailEndNodeAttrs!=null?tailEndNodeAttrs.GetTextByPath("@type").Value:null,
+                        start=headEndNodeAttrs!=null&&headEndNodeAttrs.GetTextByPath("@type")!=null?headEndNodeAttrs.GetTextByPath("@type").Value:null,
+                        end=tailEndNodeAttrs!=null&&tailEndNodeAttrs.GetTextByPath("@type")!=null?tailEndNodeAttrs.GetTextByPath("@type").Value:null,
                     }
                 };
                 shapeSvg.svgShape = shapes;

+ 6 - 6
TEAMModelOS.Service/Services/PowerPoint/Implement/ShapeSvg.cs

@@ -2801,8 +2801,8 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
                 // StrokeWidth = border.Width + "",
                 // StrokeDasharray = border.Stroke,
                 d=d,
-                start=headEndNodeAttrs!=null?headEndNodeAttrs.GetTextByPath("@type").Value:null,
-                end=tailEndNodeAttrs!=null?tailEndNodeAttrs.GetTextByPath("@type").Value:null,
+                 start=headEndNodeAttrs!=null&&headEndNodeAttrs.GetTextByPath("@type")!=null?headEndNodeAttrs.GetTextByPath("@type").Value:null,
+                end=tailEndNodeAttrs!=null&&tailEndNodeAttrs.GetTextByPath("@type")!=null?tailEndNodeAttrs.GetTextByPath("@type").Value:null,
                 //MarkerStart="url(#markerTriangle_" + shpId + ")",
                 //MarkerEnd="url(#markerTriangle_" + shpId + ")"
             } };
@@ -4556,8 +4556,8 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
                 // StrokeWidth = border.Width + "",
                 // StrokeDasharray = border.Stroke,
                 points=points,
-                 start=headEndNodeAttrs!=null?headEndNodeAttrs.GetTextByPath("@type").Value:null,
-                end=tailEndNodeAttrs!=null?tailEndNodeAttrs.GetTextByPath("@type").Value:null,
+                 start=headEndNodeAttrs!=null&&headEndNodeAttrs.GetTextByPath("@type")!=null?headEndNodeAttrs.GetTextByPath("@type").Value:null,
+                end=tailEndNodeAttrs!=null&&tailEndNodeAttrs.GetTextByPath("@type")!=null?tailEndNodeAttrs.GetTextByPath("@type").Value:null,
             } };
             return new Svg { /*SvgData = result,*/ svgShape = shapes };
         }
@@ -7076,8 +7076,8 @@ namespace TEAMModelOS.Service.Services.PowerPoint.Implement
                // Stroke = "#" + border.Color,
                 // StrokeWidth = border.Width + "",
                 // StrokeDasharray = border.Stroke,
-                start=headEndNodeAttrs!=null?headEndNodeAttrs.GetTextByPath("@type").Value:null,
-                end=tailEndNodeAttrs!=null?tailEndNodeAttrs.GetTextByPath("@type").Value:null,
+                start=headEndNodeAttrs!=null&&headEndNodeAttrs.GetTextByPath("@type")!=null?headEndNodeAttrs.GetTextByPath("@type").Value:null,
+                end=tailEndNodeAttrs!=null&&tailEndNodeAttrs.GetTextByPath("@type")!=null?tailEndNodeAttrs.GetTextByPath("@type").Value:null,
                 x1=X1,
                 x2=X2,
                 y1=Y1,

+ 61 - 0
TEAMModelOS.Service/TEAMModelOS.Model.xml

@@ -546,11 +546,67 @@
             试卷的基本信息
             </summary>
         </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.item">
+            <summary>
+            题目信息
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.subjectCode">
+            <summary>
+            科目
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.periodCode">
+            <summary>
+            学段
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.gradeCode">
+            <summary>
+            年级
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.name">
+            <summary>
+            试卷名称
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.itemCount">
+            <summary>
+            题目总数
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.level">
+            <summary>
+            题目难度
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.score">
+            <summary>
+            总分
+            </summary>
+        </member>
         <member name="P:TEAMModelOS.Service.Models.Paper.typeScore">
             <summary>
             type:{
                 pointkey:[num1,num2....]
             }
+            题型的分数占比
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.levelScore">
+            <summary>
+            题目难度分数占比
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.pointScore">
+            <summary>
+            知识点分数占比
+            </summary>
+        </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.createTime">
+            <summary>
+            创建时间
             </summary>
         </member>
         <member name="P:TEAMModelOS.Service.Models.Paper.answers">
@@ -558,6 +614,11 @@
             正确答案
             </summary>
         </member>
+        <member name="P:TEAMModelOS.Service.Models.Paper.markConfig">
+            <summary>
+            阅卷规则
+            </summary>
+        </member>
         <member name="T:TEAMModelOS.Service.Models.MarkConfig">
             <summary>
             阅卷规则

+ 6 - 0
TEAMModelOS.sln

@@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TEAMModelOS.Service", "TEAM
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TEAMModelGrpc", "TEAMModelGrpc\TEAMModelGrpc.csproj", "{B10346B6-FE98-47AF-A77C-148605EFF0E5}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TEAMModelFunction", "TEAMModelFunction\TEAMModelFunction.csproj", "{78470113-6261-4F9A-9EF3-E315F060813D}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -33,6 +35,10 @@ Global
 		{B10346B6-FE98-47AF-A77C-148605EFF0E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{B10346B6-FE98-47AF-A77C-148605EFF0E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{B10346B6-FE98-47AF-A77C-148605EFF0E5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{78470113-6261-4F9A-9EF3-E315F060813D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{78470113-6261-4F9A-9EF3-E315F060813D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{78470113-6261-4F9A-9EF3-E315F060813D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{78470113-6261-4F9A-9EF3-E315F060813D}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 30 - 88
TEAMModelOS/ClientApp/src/common/UploadFile.vue

@@ -21,15 +21,11 @@
     import '@/icons/svg/loading3.svg'
     import sha1 from 'js-sha1'
     import { Array } from 'core-js'
-    //require('@/utils/azure-storage-blob.js') //v10
     const { BlobServiceClient } = require("@azure/storage-blob")//v12
     export default {
         data() {
             return {
-                urlString: '',
-                blobContainer: '',
                 containerURL: undefined,
-                sasString: '',
                 uploadedList: [],
                 contentTypes: [
                     ['JPG', 'JPEG', 'PNG', 'GIF'],
@@ -40,32 +36,44 @@
             }
         },
         props: {
+            //默认文件列表
             defaultFileList: {
                 default: () => {
                     return []
                 },
                 type: Array
             },
-            accountName: {
-                default: 'teammodelostest',
+            //文件夹
+            folder: {
+                default: 'res',
                 type: String
             },
-            containerName: {
-                default: 'teammodelos',
+            //授权信息
+            sasString:{
+                default: 'res',
                 type: String
             },
-            pathName: {
+            //blob链接
+            urlString:{
                 default: '',
                 type: String
             },
+            //容器名称
+            containerName:{
+                default: '',
+                type: String
+            },
+            //缩略图压缩质量
             quality: {
                 default: 0.2,
                 type: Number
             },
+            //文件大小限制
             maxSize: {
                 default: 2 * 1024 * 1024 * 1024,
                 type: Number
             },
+            //文件格式限制
             format: {
                 default: () => {
                     return []
@@ -87,13 +95,10 @@
                 this.$emit('deleteFile', this.uploadedList[index])
                 this.uploadedList.splice(index, 1)
             },
+            //初始化blob
             initBlob() {
-                /**
-                 * v12
-                 * */
-                const blobServiceClient = new BlobServiceClient(this.urlString + this.sasString);
-                const containerName = this.blobContainer
-                this.containerURL = blobServiceClient.getContainerClient(containerName);
+                let blobServiceClient = new BlobServiceClient(this.urlString + this.sasString)
+                this.containerURL = blobServiceClient.getContainerClient(this.containerName)
             },
             dataURLtoFile(dataurl, filename) {
                 var arr = dataurl.split(','); var mime = arr[0].match(/:(.*?);/)[1]
@@ -103,6 +108,7 @@
                 }
                 return new File([u8arr], filename, { type: mime })
             },
+            //处理图片缩略图和视频封面
             compressFile(file, fileInfo) {
                 if (fileInfo.type == 'picture') {
                     let reader = new FileReader()
@@ -120,31 +126,10 @@
                             let newImgData = canvas.toDataURL(file.type, this.quality)
                             var resultFile = this.dataURLtoFile(newImgData, file.name)
                             this.initBlob()
-                            let options = {
-                                blockSize: 10 * 1024 * 1024
-                            }
-                            /**
-                             * v10
-                             * */
-                            //const compressBlobURL = this.$azblob.BlockBlobURL.fromContainerURL(
-                            //    this.containerURL,
-                            //    'compress' + file.name
-                            //)
-
-                            //this.$azblob.uploadBrowserDataToBlockBlob(
-                            //    this.$azblob.Aborter.none,
-                            //    resultFile,
-                            //    compressBlobURL,
-                            //    options
-                            //)
-
-                            /**
-                             * v12
-                             * */
-                            const blockBlobClient = this.containerURL.getBlockBlobClient(this.pathName + "/compress" + file.name)
+                            const blockBlobClient = this.containerURL.getBlockBlobClient(this.folder + "/compress" + file.name)
                             blockBlobClient.uploadBrowserData(resultFile).then(
                                 res => {
-                                    fileInfo['compressUrl'] = this.urlString + '/' + this.blobContainer + '/' + this.pathName + '/compress' + file.name
+                                    fileInfo['compressUrl'] = this.urlString + '/' + this.containerName + '/' + this.folder + '/compress' + file.name
                                     this.$emit('successData', fileInfo)
                                 },
                                 err => {
@@ -170,26 +155,10 @@
                         let resultFile = this.dataURLtoFile(newVideoData, file.name)
                         this.initBlob()
                         let posterName = 'compress' + file.name.replace(fileInfo.extension, 'png')
-                        /**
-                         * v10
-                         * */
-                        //const compressBlobURL = this.$azblob.BlockBlobURL.fromContainerURL(
-                        //    this.containerURL,
-                        //    posterName
-                        //)
-                        //this.$azblob.uploadBrowserDataToBlockBlob(
-                        //    this.$azblob.Aborter.none,
-                        //    resultFile,
-                        //    compressBlobURL
-                        //)
-
-                        /**
-                         * v12
-                         **/
-                        const blockBlobClient = this.containerURL.getBlockBlobClient(this.pathName + "/" + posterName)
+                        const blockBlobClient = this.containerURL.getBlockBlobClient(this.folder + "/" + posterName)
                         blockBlobClient.uploadBrowserData(resultFile).then(
                             res => {
-                                fileInfo['compressUrl'] = this.urlString + '/' + this.blobContainer + '/' + this.pathName + '/' + posterName
+                                fileInfo['compressUrl'] = this.urlString + '/'+ this.containerName + '/' + this.folder + '/' + posterName
                                 this.$emit('successData', fileInfo)
                             },
                             err => {
@@ -201,10 +170,9 @@
                 }
             },
             uploadToBlob(file) {
-                console.log(file)
                 let fileItem = {}
                 fileItem['fileName'] = file.name
-                fileItem['blobUrl'] = this.urlString + '/' + this.blobContainer + '/' + this.pathName + '/' + file.name
+                fileItem['blobUrl'] = this.urlString + '/' + this.containerName + '/' + this.folder + '/' + file.name
                 fileItem['extension'] = file.name.substring(file.name.lastIndexOf('.') + 1)
                 fileItem['size'] = file.size
                 fileItem['status'] = 0
@@ -231,19 +199,8 @@
                 fileItem['type'] = type
                 this.uploadedList.push(fileItem)
 
-                //v10
-                //const blockBlobURL = this.$azblob.BlockBlobURL.fromContainerURL(
-                //    this.containerURL,
-                //    file.name
-                //)
-                //this.$azblob.uploadBrowserDataToBlockBlob(
-                //    this.$azblob.Aborter.none,
-                //    file,
-                //    blockBlobURL
-                //)
-
                 //v12
-                const blockBlobClient = this.containerURL.getBlockBlobClient(this.pathName + "/" + file.name)
+                const blockBlobClient = this.containerURL.getBlockBlobClient(this.folder + "/" + file.name)
                 blockBlobClient.uploadBrowserData(file).then(
                     res => {
                         let reader = new FileReader()
@@ -291,23 +248,9 @@
                     })
                     return false
                 }
-
-                this.$api.uploadFile.getContainerSAS().then(
-                    (res) => {
-                        if (res.error == null) {
-                            this.sasString = res.result.data.SAS
-                            this.blobContainer = res.result.data.Container
-                            this.urlString = res.result.data.Url
-                            this.initBlob()
-                            this.uploadToBlob(file)
-                        } else {
-                            alert('API error!')
-                        }
-                    },
-                    (err) => {
-                        alert('API error!')
-                    }
-                )
+                this.initBlob()
+                this.uploadToBlob(file)
+                
                 return false
             },
             getIndex(_arr, _obj) {
@@ -335,7 +278,6 @@
             }
         },
         mounted() {
-            //this.uploadedList = []
             this.uploadedList = this.defaultFileList
         },
         created() {

+ 23 - 3
TEAMModelOS/ClientApp/src/components/learnactivity/ChooseContent.vue

@@ -1,4 +1,4 @@
-<template>
+<template>
     <div class="choose-content">
         <Tabs type="card" name="chooseContent">
             <!-- 选择课纲内容 -->
@@ -420,6 +420,7 @@
                 let queryData = {
                     '@CURRPAGE': this.pageNum,
                     '@PAGESIZE': this.pageSize,
+                    '@DESC': "createTime",
                     'code': this.questionFilter.code.indexOf('all') !== -1 ? [this.$store.state.userInfo.TEAMModelId, this.$store.state.userInfo.schoolCode]:this.questionFilter.code,
                     'periodCode': this.questionFilter.periodCode == "" ? []:[this.questionFilter.periodCode],
                     'level': this.deleteAll(this.questionFilter.level),
@@ -429,8 +430,27 @@
 
                 }
                 this.isLoading = true
-                this.$api.newEvaluation.FindExerciseList(queryData).then(res => {
-                    this.questionList = res.result.data
+                this.$api.newEvaluation.FindExerciseList(queryData).then(async res => {
+                    let privateSas = await this.$tools.getPrivateSas()
+                    let schoolSas = await this.$tools.getSchoolSas()
+                    /* 拿到Summary的题目之后要通过每个题目的JSON URL 换取完整题目数据 */
+                    let list = res.result.data
+                    list.forEach(async (i, index) => {
+                        if (i.url) {
+							try{
+								let sasString = i.code === this.$store.state.userInfo.TEAMModelId ? privateSas : schoolSas
+								let jsonInfo = await this.$tools.getFile(i.url + sasString.sas)
+								let jsonData = JSON.parse(jsonInfo)
+								jsonData.id = i.id
+								jsonData.fileName = i.url.split('/')[i.url.split('/').length - 1].split('.json')[0]
+								this.$set(list, index, jsonData)
+							}catch(e){
+								this.$Message.warning('存在试题读取异常!')
+							}
+                            
+                        }
+                    })
+                    this.questionList = list
                     setTimeout(() => {
                         this.isLoading = false
                     }, 500)

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

@@ -43,6 +43,12 @@
                     return []
                 }
             },
+            selQue: {
+                type: Array,
+                default: () => {
+                    return []
+                }
+            },
             config: {
                 type: Object,
                 default: () => {
@@ -118,6 +124,19 @@
             }
         },
         mounted() {
+			// this.selectedId = this.selQue.map(i => i.id)
+        },
+        watch: {
+            selQue: {
+                handler(o, n){
+                    this.selectedId = this.selQue.map((item) => {
+                        return item.id
+                    })
+					console.log(this.selectedId)
+                }, 
+                deep: true,
+				immediate:true
+            }
         }
     }
 </script>
@@ -130,4 +149,7 @@
         border-radius: 0px;
         border-bottom: 1px solid #aaaaaa;
     }
+    .question-text p {
+        display: inline-block !important;
+    }
 </style>

+ 3 - 2
TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue

@@ -218,11 +218,12 @@
             },
 
             onShowContent(val, data) {
+				console.log(data)
                 this.contentIndex = val
                 this.currentItems = []
                 this.currentResources = []
-                data.items && this.findQuestionById(data.items)
-                data.resources && this.findResourceById(data.resources)
+                data.items.length && this.findQuestionById(data.items)
+                data.resources.length && this.findResourceById(data.resources)
                 this.isShowContent = true
             },
 

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

@@ -19,14 +19,13 @@ const mutations = {
     [MAIN_SET_COUNTER](state, obj) {
         state.counter = obj.counter
     },
-    setFileSas(state, obj) {
-        state.fileSas = obj
+    setPrivateSas(state, obj) {
+        console.log('state')
+        state.privateSas = obj
     },
-    setBlobR(state, obj) {
-        state.blobR = obj
-    },
-    setBlobRW(state, obj) {
-        state.blobRW = obj
+    setSchoolSas(state, obj) {
+        console.log('state')
+        state.schoolSas = obj
     }
 }
 

+ 79 - 7
TEAMModelOS/ClientApp/src/utils/public.js

@@ -246,9 +246,6 @@ export default {
                         $api.uploadFile.urlSasR(param.data).then(
                             (res) => {
                                 if (res.error == null) {
-                                    console.log('新的')
-                                    store.commit('setFileSas', res.result.data)
-                                    console.log(store)
                                     r(res.result.data)
                                 } else {
                                     j(500)
@@ -267,8 +264,7 @@ export default {
                         $api.uploadFile.blobSasR(param.data).then(
                             (res) => {
                                 if (res.error == null) {
-                                    console.log('新的')
-                                    store.commit('setBlobR', res.result.data)
+                                    store.commit('setBlobR')
                                     r(res.result.data)
                                 } else {
                                     j(500)
@@ -279,7 +275,6 @@ export default {
                             }
                         )
                     } else {
-                        console.log('vuex缓存的')
                         r(store.state.blobR)
                     }
                     break
@@ -288,7 +283,7 @@ export default {
                         $api.uploadFile.blobSasRCW(param.data).then(
                             (res) => {
                                 if (res.error == null) {
-                                    store.commit('setBlobRw', res.result.data)
+                                    store.commit('setBlobRW', res.result.data)
                                     r(res.result.data)
                                 } else {
                                     j(500)
@@ -306,6 +301,83 @@ export default {
                     j('getSas() 参数错误:type')
             }
         })
+    },
+
+
+    /**
+     * 获取个人容器授权
+     */
+    getPrivateSas() {
+        return new Promise((r, j) => {
+            if (!store.state.privateSas || checkSas(store.state.privateSas.timeout)) {
+                $api.uploadFile.blobSasRCW({
+                    name: store.state.userInfo.TEAMModelId,
+                    role: 'teacher'
+                }).then(
+                    (res) => {
+                        if (res.error == null) {
+                            store.commit('setPrivateSas', res.result.data)
+                            r(res.result.data)
+                        } else {
+                            j(500)
+                        }
+                    },
+                    (err) => {
+                        j(500)
+                    }
+                )
+            } else {
+                console.log(store)
+                r(store.state.privateSas)
+            }
+        })
+    },
+    /**
+     * 获取学校容器授权
+     */
+    getSchoolSas() {
+        return new Promise((r, j) => {
+            if (!store.state.schoolSas || checkSas(store.state.schoolSas.timeout)) {
+                $api.uploadFile.blobSasRCW({
+                    name: store.state.userInfo.schoolCode,
+                    role: 'school'
+                }).then(
+                    (res) => {
+                        if (res.error == null) {
+                            store.commit('setSchoolSas', res.result.data)
+                            r(res.result.data)
+                        } else {
+                            j(500)
+                        }
+                    },
+                    (err) => {
+                        j(500)
+                    }
+                )
+            } else {
+                r(store.state.schoolSas)
+            }
+        })
+    },
+    /**
+     * 获取单个文件授权
+     */
+    getFileSas(param) {
+        return new Promise((r, j) => {
+            $api.uploadFile.urlSasR(param).then(
+                (res) => {
+                    if (res.error == null) {
+                        store.commit('setBlobRW', res.result.data)
+                        r(res.result.data)
+                    } else {
+                        j(500)
+                    }
+                },
+                (err) => {
+                    j(500)
+                }
+            )
+        })
     }
 
 }

+ 0 - 0
TEAMModelOS/ClientApp/src/utils/upload.js


Vissa filer visades inte eftersom för många filer har ändrats