diff --git a/.gitignore b/.gitignore index 2cf0d709d..3a65f4c93 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,19 @@ -/bin -/src/Util/obj -/test/Util.Tests/obj -/.vs -obj/ -bin/ -BenchmarkDotNet.Artifacts/ -/output -/template/CodeSmith/CodeGenerator/02-Result -/sample/Util.Samples.Webs/wwwroot/lib -/sample/Util.Samples.Webs/node_modules -/sample/Util.Samples.Webs/wwwroot/dist -/sample/Util.Samples.Webs/wwwroot/test +*.suo +*.user +.vs +*.log +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ +output/ +node_modules/ +BenchmarkDotNet.Artifacts +**/ClientApp/**/html/** +/sample/Util.Ui.NgZorro.Sample/ClientApp/*.lock +/sample/Util.Ui.NgZorro.Sample/ClientApp/src/app/app.component.html +/document/demo/*.pdb +/document/Test/PowerDesigner/*.pdb +/test/Util.Data.Dapper.SqlServer.Tests/Document/PowerDesigner/*.pdb +/documents/PowerDesigner/*.pdb diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 000000000..f3c4d6364 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/NuGet.config b/NuGet.config deleted file mode 100644 index 3f0e00340..000000000 --- a/NuGet.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Util.sln b/Util.sln index 381709d99..9475258d6 100644 --- a/Util.sln +++ b/Util.sln @@ -1,180 +1,1055 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2027 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Samples.Webs", "sample\Util.Samples.Webs\Util.Samples.Webs.csproj", "{323B64B7-5CE0-4222-B9ED-9F418730897C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01-src", "01-src", "{ECBD28DE-AFFB-4C9A-8988-6297FA5ADDD5}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02-test", "02-test", "{DE1DF0B9-0403-4888-8B24-8208348E9AFA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01-Core", "01-Core", "{3746073A-1C5C-40A7-9D50-CB2A94CA888A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Tests", "test\Util.Tests\01-Util.Tests.csproj", "{4C93DBB6-7840-4277-BAF1-56148B62FB3D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01-Core", "01-Core", "{6FA93B2E-A5E5-44CA-9851-52FAA2BF5C57}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util", "src\Util\01-Util.csproj", "{5981ADBE-58A4-4F84-9529-E7D7F7E1610C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "05-Util.Datas", "src\Util.Datas\05-Util.Datas.csproj", "{CD83426E-2BA1-4DB0-94D9-1185C076276F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Datas.Tests.Integration", "test\Util.Datas.Tests.Integration\02-Util.Datas.Tests.Integration.csproj", "{411B666F-EDA0-47E0-BB34-3EAF047549A0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Logs", "src\Util.Logs\03-Util.Logs.csproj", "{0330EB27-814D-4CF6-B377-3BFA884D5FD2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03-sample", "03-sample", "{F1B4AAEF-9162-4DFA-8B62-4069FC914839}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02-Ui", "02-Ui", "{78CC88DA-0B25-45BC-86A8-FFE9628B34A6}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03-Biz", "03-Biz", "{62644B42-76EF-4FC2-8736-3E9B96C1D832}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Biz", "src\Util.Biz\01-Util.Biz.csproj", "{BAB54FFD-DF77-40B6-86A5-A1A3E0985468}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Security", "src\Util.Security\02-Util.Security.csproj", "{83E78951-5FBE-43D5-A6BE-7735721E4C1D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "06-Util.Applications", "src\Util.Applications\06-Util.Applications.csproj", "{7A5E9C1B-CE91-463D-B0D1-8117C9E29D30}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "04-Util.Events", "src\Util.Events\04-Util.Events.csproj", "{A93DFEEC-0DC7-4628-96F7-914A8053732B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Ui.Abstractions", "src\Util.Ui.Abstractions\01-Util.Ui.Abstractions.csproj", "{F93F72BE-F3F4-4CB6-A3A2-54CDBF3F9B18}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Ui.Core", "src\Util.Ui.Core\02-Util.Ui.Core.csproj", "{EB80F45C-FCC8-436C-900A-754A5E91A8E0}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02-Ui", "02-Ui", "{0629A068-957D-4920-9290-0B9288341E0D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Ui.Tests", "test\Util.Ui.Tests\Util.Ui.Tests.csproj", "{91F99541-D37F-46D5-8026-AD57C3F75B52}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "04-Tools", "04-Tools", "{1907A873-8368-4CFF-B5B3-98F04CD2E3A7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Ui.Angular", "src\Util.Ui.Angular\03-Util.Ui.Angular.csproj", "{AD7CD285-D899-443D-A02C-D62C7C0A351F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "07-Util.Webs", "src\Util.Webs\07-Util.Webs.csproj", "{0A32F32B-49DF-49AB-8F3C-AFDD28517A89}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Tools.QrCode", "src\Util.Tools.QrCode\01-Util.Tools.QrCode.csproj", "{ED44ED49-3F9E-4D14-A600-51D7792A3F64}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Tools.Sms", "src\Util.Tools.Sms\02-Util.Tools.Sms.csproj", "{883EF7C5-4234-4A1B-82BC-36597D280B57}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Biz.Payments", "src\Util.Biz.Payments\02-Util.Biz.Payments.csproj", "{69B79A60-3719-43E5-BE12-78E401C7BC0C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03-Biz", "03-Biz", "{D1083FEB-81A7-4BBF-ADDB-C03D143BC4AB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Biz.Tests.Integration", "test\Util.Biz.Tests.Integration\Util.Biz.Tests.Integration.csproj", "{F680DA14-282E-471E-8E1C-F4D2067B718E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {323B64B7-5CE0-4222-B9ED-9F418730897C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {323B64B7-5CE0-4222-B9ED-9F418730897C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {323B64B7-5CE0-4222-B9ED-9F418730897C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {323B64B7-5CE0-4222-B9ED-9F418730897C}.Release|Any CPU.Build.0 = Release|Any CPU - {4C93DBB6-7840-4277-BAF1-56148B62FB3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4C93DBB6-7840-4277-BAF1-56148B62FB3D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4C93DBB6-7840-4277-BAF1-56148B62FB3D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4C93DBB6-7840-4277-BAF1-56148B62FB3D}.Release|Any CPU.Build.0 = Release|Any CPU - {5981ADBE-58A4-4F84-9529-E7D7F7E1610C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5981ADBE-58A4-4F84-9529-E7D7F7E1610C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5981ADBE-58A4-4F84-9529-E7D7F7E1610C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5981ADBE-58A4-4F84-9529-E7D7F7E1610C}.Release|Any CPU.Build.0 = Release|Any CPU - {CD83426E-2BA1-4DB0-94D9-1185C076276F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CD83426E-2BA1-4DB0-94D9-1185C076276F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CD83426E-2BA1-4DB0-94D9-1185C076276F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CD83426E-2BA1-4DB0-94D9-1185C076276F}.Release|Any CPU.Build.0 = Release|Any CPU - {411B666F-EDA0-47E0-BB34-3EAF047549A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {411B666F-EDA0-47E0-BB34-3EAF047549A0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {411B666F-EDA0-47E0-BB34-3EAF047549A0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {411B666F-EDA0-47E0-BB34-3EAF047549A0}.Release|Any CPU.Build.0 = Release|Any CPU - {0330EB27-814D-4CF6-B377-3BFA884D5FD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0330EB27-814D-4CF6-B377-3BFA884D5FD2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0330EB27-814D-4CF6-B377-3BFA884D5FD2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0330EB27-814D-4CF6-B377-3BFA884D5FD2}.Release|Any CPU.Build.0 = Release|Any CPU - {BAB54FFD-DF77-40B6-86A5-A1A3E0985468}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BAB54FFD-DF77-40B6-86A5-A1A3E0985468}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BAB54FFD-DF77-40B6-86A5-A1A3E0985468}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BAB54FFD-DF77-40B6-86A5-A1A3E0985468}.Release|Any CPU.Build.0 = Release|Any CPU - {83E78951-5FBE-43D5-A6BE-7735721E4C1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {83E78951-5FBE-43D5-A6BE-7735721E4C1D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83E78951-5FBE-43D5-A6BE-7735721E4C1D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83E78951-5FBE-43D5-A6BE-7735721E4C1D}.Release|Any CPU.Build.0 = Release|Any CPU - {7A5E9C1B-CE91-463D-B0D1-8117C9E29D30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7A5E9C1B-CE91-463D-B0D1-8117C9E29D30}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7A5E9C1B-CE91-463D-B0D1-8117C9E29D30}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7A5E9C1B-CE91-463D-B0D1-8117C9E29D30}.Release|Any CPU.Build.0 = Release|Any CPU - {A93DFEEC-0DC7-4628-96F7-914A8053732B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A93DFEEC-0DC7-4628-96F7-914A8053732B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A93DFEEC-0DC7-4628-96F7-914A8053732B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A93DFEEC-0DC7-4628-96F7-914A8053732B}.Release|Any CPU.Build.0 = Release|Any CPU - {F93F72BE-F3F4-4CB6-A3A2-54CDBF3F9B18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F93F72BE-F3F4-4CB6-A3A2-54CDBF3F9B18}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F93F72BE-F3F4-4CB6-A3A2-54CDBF3F9B18}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F93F72BE-F3F4-4CB6-A3A2-54CDBF3F9B18}.Release|Any CPU.Build.0 = Release|Any CPU - {EB80F45C-FCC8-436C-900A-754A5E91A8E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EB80F45C-FCC8-436C-900A-754A5E91A8E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EB80F45C-FCC8-436C-900A-754A5E91A8E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EB80F45C-FCC8-436C-900A-754A5E91A8E0}.Release|Any CPU.Build.0 = Release|Any CPU - {91F99541-D37F-46D5-8026-AD57C3F75B52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {91F99541-D37F-46D5-8026-AD57C3F75B52}.Debug|Any CPU.Build.0 = Debug|Any CPU - {91F99541-D37F-46D5-8026-AD57C3F75B52}.Release|Any CPU.ActiveCfg = Release|Any CPU - {91F99541-D37F-46D5-8026-AD57C3F75B52}.Release|Any CPU.Build.0 = Release|Any CPU - {AD7CD285-D899-443D-A02C-D62C7C0A351F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AD7CD285-D899-443D-A02C-D62C7C0A351F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AD7CD285-D899-443D-A02C-D62C7C0A351F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AD7CD285-D899-443D-A02C-D62C7C0A351F}.Release|Any CPU.Build.0 = Release|Any CPU - {0A32F32B-49DF-49AB-8F3C-AFDD28517A89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0A32F32B-49DF-49AB-8F3C-AFDD28517A89}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0A32F32B-49DF-49AB-8F3C-AFDD28517A89}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0A32F32B-49DF-49AB-8F3C-AFDD28517A89}.Release|Any CPU.Build.0 = Release|Any CPU - {ED44ED49-3F9E-4D14-A600-51D7792A3F64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ED44ED49-3F9E-4D14-A600-51D7792A3F64}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ED44ED49-3F9E-4D14-A600-51D7792A3F64}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ED44ED49-3F9E-4D14-A600-51D7792A3F64}.Release|Any CPU.Build.0 = Release|Any CPU - {883EF7C5-4234-4A1B-82BC-36597D280B57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {883EF7C5-4234-4A1B-82BC-36597D280B57}.Debug|Any CPU.Build.0 = Debug|Any CPU - {883EF7C5-4234-4A1B-82BC-36597D280B57}.Release|Any CPU.ActiveCfg = Release|Any CPU - {883EF7C5-4234-4A1B-82BC-36597D280B57}.Release|Any CPU.Build.0 = Release|Any CPU - {69B79A60-3719-43E5-BE12-78E401C7BC0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {69B79A60-3719-43E5-BE12-78E401C7BC0C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {69B79A60-3719-43E5-BE12-78E401C7BC0C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {69B79A60-3719-43E5-BE12-78E401C7BC0C}.Release|Any CPU.Build.0 = Release|Any CPU - {F680DA14-282E-471E-8E1C-F4D2067B718E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F680DA14-282E-471E-8E1C-F4D2067B718E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F680DA14-282E-471E-8E1C-F4D2067B718E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F680DA14-282E-471E-8E1C-F4D2067B718E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {323B64B7-5CE0-4222-B9ED-9F418730897C} = {F1B4AAEF-9162-4DFA-8B62-4069FC914839} - {3746073A-1C5C-40A7-9D50-CB2A94CA888A} = {ECBD28DE-AFFB-4C9A-8988-6297FA5ADDD5} - {4C93DBB6-7840-4277-BAF1-56148B62FB3D} = {6FA93B2E-A5E5-44CA-9851-52FAA2BF5C57} - {6FA93B2E-A5E5-44CA-9851-52FAA2BF5C57} = {DE1DF0B9-0403-4888-8B24-8208348E9AFA} - {5981ADBE-58A4-4F84-9529-E7D7F7E1610C} = {3746073A-1C5C-40A7-9D50-CB2A94CA888A} - {CD83426E-2BA1-4DB0-94D9-1185C076276F} = {3746073A-1C5C-40A7-9D50-CB2A94CA888A} - {411B666F-EDA0-47E0-BB34-3EAF047549A0} = {6FA93B2E-A5E5-44CA-9851-52FAA2BF5C57} - {0330EB27-814D-4CF6-B377-3BFA884D5FD2} = {3746073A-1C5C-40A7-9D50-CB2A94CA888A} - {78CC88DA-0B25-45BC-86A8-FFE9628B34A6} = {ECBD28DE-AFFB-4C9A-8988-6297FA5ADDD5} - {62644B42-76EF-4FC2-8736-3E9B96C1D832} = {ECBD28DE-AFFB-4C9A-8988-6297FA5ADDD5} - {BAB54FFD-DF77-40B6-86A5-A1A3E0985468} = {62644B42-76EF-4FC2-8736-3E9B96C1D832} - {83E78951-5FBE-43D5-A6BE-7735721E4C1D} = {3746073A-1C5C-40A7-9D50-CB2A94CA888A} - {7A5E9C1B-CE91-463D-B0D1-8117C9E29D30} = {3746073A-1C5C-40A7-9D50-CB2A94CA888A} - {A93DFEEC-0DC7-4628-96F7-914A8053732B} = {3746073A-1C5C-40A7-9D50-CB2A94CA888A} - {F93F72BE-F3F4-4CB6-A3A2-54CDBF3F9B18} = {78CC88DA-0B25-45BC-86A8-FFE9628B34A6} - {EB80F45C-FCC8-436C-900A-754A5E91A8E0} = {78CC88DA-0B25-45BC-86A8-FFE9628B34A6} - {0629A068-957D-4920-9290-0B9288341E0D} = {DE1DF0B9-0403-4888-8B24-8208348E9AFA} - {91F99541-D37F-46D5-8026-AD57C3F75B52} = {0629A068-957D-4920-9290-0B9288341E0D} - {1907A873-8368-4CFF-B5B3-98F04CD2E3A7} = {ECBD28DE-AFFB-4C9A-8988-6297FA5ADDD5} - {AD7CD285-D899-443D-A02C-D62C7C0A351F} = {78CC88DA-0B25-45BC-86A8-FFE9628B34A6} - {0A32F32B-49DF-49AB-8F3C-AFDD28517A89} = {3746073A-1C5C-40A7-9D50-CB2A94CA888A} - {ED44ED49-3F9E-4D14-A600-51D7792A3F64} = {1907A873-8368-4CFF-B5B3-98F04CD2E3A7} - {883EF7C5-4234-4A1B-82BC-36597D280B57} = {1907A873-8368-4CFF-B5B3-98F04CD2E3A7} - {69B79A60-3719-43E5-BE12-78E401C7BC0C} = {62644B42-76EF-4FC2-8736-3E9B96C1D832} - {D1083FEB-81A7-4BBF-ADDB-C03D143BC4AB} = {DE1DF0B9-0403-4888-8B24-8208348E9AFA} - {F680DA14-282E-471E-8E1C-F4D2067B718E} = {D1083FEB-81A7-4BBF-ADDB-C03D143BC4AB} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {AA6E8E23-8AB6-4AB6-9B31-494CB7CE5E63} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01-Core", "01-Core", "{345739E2-E20C-4B1F-B1B2-725006FC9F72}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{0D42DE24-8D3C-4BE1-BAAE-7543281C3113}" + ProjectSection(SolutionItems) = preProject + build\common.props = build\common.props + build\version.props = build\version.props + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C01B9930-D67F-41C5-90C9-C87DC53F39CB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Build", "build\Build.csproj", "{12539757-7371-455D-B86B-DAF22F2DEE4E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Core", "src\Util.Core\01-Util.Core.csproj", "{5F1A7144-C954-4B47-B1FF-820FEA9B6B61}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Core.Tests", "test\Util.Core.Tests\Util.Core.Tests.csproj", "{1E50F81A-FBFF-4873-9731-FA8835A51080}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "14-Ui", "14-Ui", "{354B3720-D050-487D-A46A-22BCFEE56D43}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Ui", "src\Util.Ui\01-Util.Ui.csproj", "{5F7ACBE4-A1D8-4680-AA86-B87F8494BAC2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Ui.NgZorro", "src\Util.Ui.NgZorro\03-Util.Ui.NgZorro.csproj", "{BA79977F-6DCE-4787-9A0D-AF5E61EBC177}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Ui.NgZorro.Tests", "test\Util.Ui.NgZorro.Tests\Util.Ui.NgZorro.Tests.csproj", "{2B56E8AA-4DAB-4A70-9439-ED16470C0BFE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01-Core", "01-Core", "{9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "16-Ui", "16-Ui", "{DE39BB20-AE82-47C3-9141-8CFD4C673217}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Ui.Tests", "test\Util.Ui.Tests\Util.Ui.Tests.csproj", "{766CAB38-F064-419F-837B-D6DA8B61AF66}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Ui.Angular", "src\Util.Ui.Angular\02-Util.Ui.Angular.csproj", "{E8481A4C-0C24-4418-A2C1-742877BE4F0D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Core.Tests.Integration", "test\Util.Core.Tests.Integration\Util.Core.Tests.Integration.csproj", "{21064598-1418-422E-BA37-8EC09541DFC1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "08-Util.AspNetCore", "src\Util.AspNetCore\08-Util.AspNetCore.csproj", "{08EF3E38-E0C3-4E18-984C-3216CB6E8897}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.ObjectMapping.AutoMapper", "src\Util.ObjectMapping.AutoMapper\02-Util.ObjectMapping.AutoMapper.csproj", "{12C94395-09F1-42E4-8CE1-6E54D3FEBAA6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.ObjectMapping.AutoMapper.Tests", "test\Util.ObjectMapping.AutoMapper.Tests\Util.ObjectMapping.AutoMapper.Tests.csproj", "{955D94B8-747D-4CA4-832A-6377C9FF5B8F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Aop.AspectCore", "src\Util.Aop.AspectCore\03-Util.Aop.AspectCore.csproj", "{FB337B27-C6C6-43A1-BFA5-58B3CF381BA8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Aop.AspectCore.Tests", "test\Util.Aop.AspectCore.Tests\Util.Aop.AspectCore.Tests.csproj", "{B8825802-81F7-4671-82E8-3A6E3A21F570}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "10-Domain", "10-Domain", "{7AB71D86-D351-4009-A789-24097897E74A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "04-Util.Validation", "src\Util.Validation\04-Util.Validation.csproj", "{1DE277C2-EE56-4F4D-BB89-71107DE0E4C6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Validation.Tests", "test\Util.Validation.Tests\Util.Validation.Tests.csproj", "{166852FC-2F86-4A5B-9029-E16958798DD6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Domain", "src\Util.Domain\01-Util.Domain.csproj", "{61982C8D-5376-45EE-BCC3-D4F9E90AF3B0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "10-Domain", "10-Domain", "{FC5E00D1-ABA5-4168-8B8F-FA2A26D84068}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Domain.Tests", "test\Util.Domain.Tests\Util.Domain.Tests.csproj", "{7CA38535-297B-4DA9-AFF5-3199268EEAF6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Events", "src\Util.Events\02-Util.Events.csproj", "{EE426441-DE33-4F3B-B66A-E258AC725B78}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "11-Data", "11-Data", "{66A85767-2877-4B99-84F1-EEABC6DC5247}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "13-Data", "13-Data", "{CC492CA2-5D86-4DB8-AB15-B118DF27C344}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.Tests", "test\Util.Data.Tests\Util.Data.Tests.csproj", "{4D40321F-2C3F-4ACB-8AE0-7A228DF0551B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Data.EntityFrameworkCore", "src\Util.Data.EntityFrameworkCore\01-Util.Data.EntityFrameworkCore.csproj", "{7F7D9EE0-7263-4621-BA65-FC470B0F3C6B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01-Core", "01-Core", "{45E2ADF5-F386-44CD-A43D-A3AB47E9C39A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02-EntityFrameworkCore", "02-EntityFrameworkCore", "{4E99CBC5-1C74-44E7-9DEF-3FA44CADCCF0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Data.EntityFrameworkCore.SqlServer", "src\Util.Data.EntityFrameworkCore.SqlServer\02-Util.Data.EntityFrameworkCore.SqlServer.csproj", "{04E5EDDB-8440-4BAD-9531-F87A3AC826FB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Templates.Razor", "src\Util.Templates.Razor\02-Util.Templates.Razor.csproj", "{4656C609-DBBA-4F6B-B16F-5E1A8C9D9858}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Templates", "src\Util.Templates\01-Util.Templates.csproj", "{F7925EED-65E6-4CA2-9B8D-B7036F6DB3E8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Templates.Handlebars", "src\Util.Templates.Handlebars\03-Util.Templates.Handlebars.csproj", "{D22C3F6D-434A-4F09-9EB2-B0433CC43642}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Data.Metadata", "src\Util.Data.Metadata\03-Util.Data.Metadata.csproj", "{257A0A17-5D13-4DA4-8E91-8A3BB2711F49}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03-Dapper", "03-Dapper", "{4A955BB3-C1AF-45DB-9590-82C00996B608}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Data.Dapper.SqlServer", "src\Util.Data.Dapper.SqlServer\02-Util.Data.Dapper.SqlServer.csproj", "{9A2C7C42-086B-4482-828D-7B02D85372ED}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Data.Sql", "src\Util.Data.Sql\02-Util.Data.Sql.csproj", "{661B88AE-6F83-437C-9A7E-C5C1A565E650}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.Sql.Tests", "test\Util.Data.Sql.Tests\Util.Data.Sql.Tests.csproj", "{C99E1554-5039-42BD-B1FD-93814FBEBE44}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Data.Dapper.Core", "src\Util.Data.Dapper.Core\01-Util.Data.Dapper.Core.csproj", "{60424AB5-356A-4623-B1FB-7560334C0BE0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "06-Util.Data.Dapper.All", "src\Util.Data.Dapper.All\06-Util.Data.Dapper.All.csproj", "{C2A4E6AB-16B9-4457-9445-FFBF672DFBCF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Domain.Biz", "src\Util.Domain.Biz\02-Util.Domain.Biz.csproj", "{AFB629C5-00C2-492C-8787-C66D810A24DB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "12-Application", "12-Application", "{648CE3E3-CEC4-4F91-8696-6A3FB2F91220}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Application", "src\Util.Application\01-Util.Application.csproj", "{9404B5FE-3431-4EC0-BCC6-42525FC5D1B8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "14-Application", "14-Application", "{BB24822F-F104-4D8E-9CB5-0A94DEF04BAB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Application.Tests", "test\Util.Application.Tests\Util.Application.Tests.csproj", "{EF7BDA1B-22E7-4F3D-97E0-16C9C10AA1B0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Data.Core", "src\Util.Data.Core\01-Util.Data.Core.csproj", "{B5305F08-3856-42B5-92D5-6FD446B39931}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "06-Util.Data.Abstractions", "src\Util.Data.Abstractions\06-Util.Data.Abstractions.csproj", "{88FE7642-27D9-4693-A130-706FCE46194A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Application.EntityFrameworkCore.SqlServer.Tests.Integration", "test\Util.Application.EntityFrameworkCore.SqlServer.Tests.Integration\Util.Application.EntityFrameworkCore.SqlServer.Tests.Integration.csproj", "{CA43B145-9DF2-49D3-9371-B88BFB0E846A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Application.EntityFrameworkCore", "src\Util.Application.EntityFrameworkCore\02-Util.Application.EntityFrameworkCore.csproj", "{95842BB6-559E-4317-B1E9-FF19D39ADA24}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Application.WebApi", "src\Util.Application.WebApi\03-Util.Application.WebApi.csproj", "{3DE7DD7A-8500-46C9-91A1-A65DB60E0235}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Data.EntityFrameworkCore.PostgreSql", "src\Util.Data.EntityFrameworkCore.PostgreSql\03-Util.Data.EntityFrameworkCore.PostgreSql.csproj", "{8618EE3F-F120-4AEA-8A77-F7BD5DCCB888}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02-Logging", "02-Logging", "{D5CF25B2-1A91-4065-A647-06CDF55F4B96}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "04-Templates", "04-Templates", "{2697EEFB-06BE-4786-89C6-A566FD94A41B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02-Logging", "02-Logging", "{A6EB05D5-EF38-45B6-960A-0EB759373FDF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "04-Templates", "04-Templates", "{445850B7-1A9D-4E9D-8AC1-765F3792DC19}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03-Events", "03-Events", "{59F82491-51E3-4A12-B427-9815AEA23D10}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03-Events", "03-Events", "{3ABD7B4B-37F9-4D49-92D9-384190177286}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Logging", "src\Util.Logging\01-Util.Logging.csproj", "{577A7F6F-4836-4811-B715-32573127BDB3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Logging.Tests", "test\Util.Logging.Tests\Util.Logging.Tests.csproj", "{04EA7A93-CDC7-4C68-815D-699180D99DCE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Logging.Serilog", "src\Util.Logging.Serilog\02-Util.Logging.Serilog.csproj", "{A1186FB9-FB77-427C-9AEC-55E48A8D046A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Logging.Serilog.Exceptionless", "src\Util.Logging.Serilog.Exceptionless\03-Util.Logging.Serilog.Exceptionless.csproj", "{9960FA8A-98C1-45FB-8A09-33CA183AA140}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "11-Share", "11-Share", "{E3414144-C19E-40C0-A73A-2FD41AE514D1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.TestShare", "test\Util.TestShare\Util.TestShare.csproj", "{1855CAB7-6379-47A4-A0A4-F890C6C46403}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "04-Util.Data.EntityFrameworkCore.MySql", "src\Util.Data.EntityFrameworkCore.MySql\04-Util.Data.EntityFrameworkCore.MySql.csproj", "{C43539A5-8343-4381-B2FD-5323323F1DB6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Logging.Serilog.Tests.Integration", "test\Util.Logging.Serilog.Tests.Integration\Util.Logging.Serilog.Tests.Integration.csproj", "{D3C326CD-F1F1-4E06-962D-47F6C8090DEE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Logging.Serilog.Exceptionless.Tests.Integration", "test\Util.Logging.Serilog.Exceptionless.Tests.Integration\Util.Logging.Serilog.Exceptionless.Tests.Integration.csproj", "{13690AB8-9AA4-4936-A25F-7AF1AE3D4ED0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.EntityFrameworkCore.PostgreSql.Tests.Integration", "test\Util.Data.EntityFrameworkCore.PostgreSql.Tests.Integration\Util.Data.EntityFrameworkCore.PostgreSql.Tests.Integration.csproj", "{244A930D-5B84-4CBC-A3A7-7E8DE1E603D6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.EntityFrameworkCore.SqlServer.Tests.Integration", "test\Util.Data.EntityFrameworkCore.SqlServer.Tests.Integration\Util.Data.EntityFrameworkCore.SqlServer.Tests.Integration.csproj", "{0EDF10D7-D6D6-48E2-AC0C-BA6D814CB633}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.TestShare.SqlServer", "test\Util.TestShare.SqlServer\Util.TestShare.SqlServer.csproj", "{05D8A63F-B3E1-4A5E-AA66-337BCF8840C1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.TestShare.PostgreSql", "test\Util.TestShare.PostgreSql\Util.TestShare.PostgreSql.csproj", "{3993A838-71C9-49C5-80B3-16CC48A5F5C9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.EntityFrameworkCore.MySql.Tests.Integration", "test\Util.Data.EntityFrameworkCore.MySql.Tests.Integration\Util.Data.EntityFrameworkCore.MySql.Tests.Integration.csproj", "{D785A240-1115-41C8-943E-5058161D6478}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.TestShare.MySql", "test\Util.TestShare.MySql\Util.TestShare.MySql.csproj", "{B1952639-773B-4C82-9D95-7CB4ED8AC59E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.Dapper.SqlServer.Tests.Integration", "test\Util.Data.Dapper.SqlServer.Tests.Integration\Util.Data.Dapper.SqlServer.Tests.Integration.csproj", "{29792C72-565A-46DF-B887-494AC5352818}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Application.EntityFrameworkCore.PostgreSql.Tests.Integration", "test\Util.Application.EntityFrameworkCore.PostgreSql.Tests.Integration\Util.Application.EntityFrameworkCore.PostgreSql.Tests.Integration.csproj", "{C57D22E0-075B-4F27-87F1-E6CF5F203975}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Application.EntityFrameworkCore.MySql.Tests.Integration", "test\Util.Application.EntityFrameworkCore.MySql.Tests.Integration\Util.Application.EntityFrameworkCore.MySql.Tests.Integration.csproj", "{B9B66159-4FC7-4F94-8C21-ADC8CCED84F4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Application.WebApi.SqlServer.Tests.Integration", "test\Util.Application.WebApi.SqlServer.Tests.Integration\Util.Application.WebApi.SqlServer.Tests.Integration.csproj", "{24FFA5F1-37CD-408B-80A9-006B5A6E11E8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Application.WebApi.PostgreSql.Tests.Integration", "test\Util.Application.WebApi.PostgreSql.Tests.Integration\Util.Application.WebApi.PostgreSql.Tests.Integration.csproj", "{6FE28297-B958-4BC5-A320-A531874D7F58}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Application.WebApi.MySql.Tests.Integration", "test\Util.Application.WebApi.MySql.Tests.Integration\Util.Application.WebApi.MySql.Tests.Integration.csproj", "{838A27C6-F125-4C61-923E-7C855B598FBD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.Dapper.PostgreSql.Tests.Integration", "test\Util.Data.Dapper.PostgreSql.Tests.Integration\Util.Data.Dapper.PostgreSql.Tests.Integration.csproj", "{FDE43241-3C82-4005-87B3-FD1349FEF4B6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Data.Dapper.PostgreSql", "src\Util.Data.Dapper.PostgreSql\03-Util.Data.Dapper.PostgreSql.csproj", "{878A2744-5122-48A7-90E6-7D8CFABC29FD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "04-Util.Data.Dapper.MySql", "src\Util.Data.Dapper.MySql\04-Util.Data.Dapper.MySql.csproj", "{0C464725-DEDC-4894-84A3-7A155E43818B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.Dapper.MySql.Tests.Integration", "test\Util.Data.Dapper.MySql.Tests.Integration\Util.Data.Dapper.MySql.Tests.Integration.csproj", "{AC831843-CDE2-4B67-8BC5-8F2A0D09B273}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "05-Util.Data.EntityFrameworkCore.Sqlite", "src\Util.Data.EntityFrameworkCore.Sqlite\05-Util.Data.EntityFrameworkCore.Sqlite.csproj", "{2BE691A3-19C0-4FCF-85D2-D2371C9462C6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.EntityFrameworkCore.Sqlite.Tests.Integration", "test\Util.Data.EntityFrameworkCore.Sqlite.Tests.Integration\Util.Data.EntityFrameworkCore.Sqlite.Tests.Integration.csproj", "{B140F739-EC51-4265-B4B8-59467606E6EE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.TestShare.Sqlite", "test\Util.TestShare.Sqlite\Util.TestShare.Sqlite.csproj", "{00E8EE51-A263-4971-9431-C4A2DEA4993A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "06-Util.Data.EntityFrameworkCore.Oracle", "src\Util.Data.EntityFrameworkCore.Oracle\06-Util.Data.EntityFrameworkCore.Oracle.csproj", "{6B2BA282-5C97-4A71-885F-E5259274F714}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.TestShare.Oracle", "test\Util.TestShare.Oracle\Util.TestShare.Oracle.csproj", "{05CF624D-F42E-461A-A21D-41BEE0CCEB5C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.EntityFrameworkCore.Oracle.Tests.Integration", "test\Util.Data.EntityFrameworkCore.Oracle.Tests.Integration\Util.Data.EntityFrameworkCore.Oracle.Tests.Integration.csproj", "{C4A782C1-AA25-476B-B936-90433422D0A2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "09-Util.Localization", "src\Util.Localization\09-Util.Localization.csproj", "{D9E411DD-58B1-4160-8025-068D43ADE72C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Localization.Tests.Integration", "test\Util.Localization.Tests.Integration\Util.Localization.Tests.Integration.csproj", "{B2AADB36-8433-4EDB-B247-49A3EA82FE06}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Localization.Resources", "test\Util.Localization.Resources\Util.Localization.Resources.csproj", "{40F2A962-6209-42D0-9F21-CEACB411007B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "05-Caching", "05-Caching", "{22E49D65-F51D-4A45-A35E-B27FF7DE6787}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "05-Caching", "05-Caching", "{B85E8FC7-748E-4990-9279-1F06E095B6E6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Caching", "src\Util.Caching\01-Util.Caching.csproj", "{4170A699-C110-4136-92EA-D2BFEBF68230}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Caching.EasyCaching", "src\Util.Caching.EasyCaching\02-Util.Caching.EasyCaching.csproj", "{78B9EC26-ADC5-4934-9F31-000D4D678121}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Caching.EasyCaching.Tests.Integration", "test\Util.Caching.EasyCaching.Tests.Integration\Util.Caching.EasyCaching.Tests.Integration.csproj", "{027B0175-2D22-4168-A0B4-1E0DC5BE2A61}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Application.WebApi.Tests.Integration", "test\Util.Application.WebApi.Tests.Integration\Util.Application.WebApi.Tests.Integration.csproj", "{EA4C219B-D00A-4BDB-A787-A79FA9611303}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "04-Util.Ui.NgAlain", "src\Util.Ui.NgAlain\04-Util.Ui.NgAlain.csproj", "{B40CD480-D4A0-4A43-B855-0CD84EC537CC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Ui.NgAlain.Tests", "test\Util.Ui.NgAlain.Tests\Util.Ui.NgAlain.Tests.csproj", "{C3C7C037-B5B6-4CE0-BC02-820667D74F60}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.AspNetCore.Tests.Integration", "test\Util.AspNetCore.Tests.Integration\Util.AspNetCore.Tests.Integration.csproj", "{48F77D8F-60AE-4173-BA74-FC2E0B3578BB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "06-Scheduling", "06-Scheduling", "{76AA6040-AA3A-43DD-BD4B-7F931271BFD6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "12-Scheduling", "12-Scheduling", "{6493D592-7930-4979-A07D-B7CAA751C7BE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Scheduling.Quartz", "src\Util.Scheduling.Quartz\02-Util.Scheduling.Quartz.csproj", "{4E12B03E-D607-492E-BB28-96235993A39F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Scheduling.Quartz.Tests.Integration", "test\Util.Scheduling.Quartz.Tests.Integration\Util.Scheduling.Quartz.Tests.Integration.csproj", "{D2F38ACB-7158-4DE0-BDEA-B13E3D52A655}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Scheduling", "src\Util.Scheduling\01-Util.Scheduling.csproj", "{1272E006-8D8B-46B5-AD18-2E31CA9C6CBD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Scheduling.Hangfire", "src\Util.Scheduling.Hangfire\03-Util.Scheduling.Hangfire.csproj", "{E0D77981-E412-477D-B866-E43F055CAAFC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Scheduling.Hangfire.Tests.Integration", "test\Util.Scheduling.Hangfire.Tests.Integration\Util.Scheduling.Hangfire.Tests.Integration.csproj", "{66B96C01-6A08-4C7A-B5F5-A0489D8BBB47}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "05-Util.Security", "src\Util.Security\05-Util.Security.csproj", "{8BC69296-3C9A-45B3-B6C3-3DD575027CCD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Security.Tests", "test\Util.Security.Tests\Util.Security.Tests.csproj", "{B25D3B7A-AEAA-4EFB-9839-7C6E3F7C24BB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "07-Tools", "07-Tools", "{1F5EE147-BD88-4B6D-BA84-35B4F3BE4A4E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Images.ImageSharp", "src\Util.Images.ImageSharp\01-Util.Images.ImageSharp.csproj", "{22305349-51C7-4D80-A538-C7C0F4495895}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "06-Localization", "06-Localization", "{54800E45-FF91-4091-A146-EFA5432A6443}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02-Dapper", "02-Dapper", "{664F0DBE-CB31-4D63-858A-8C7E6411C76C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03-EntityFrameworkCore", "03-EntityFrameworkCore", "{7D087635-9E77-46B2-B647-962F7E2F8688}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01-Core", "01-Core", "{2864196E-3044-4FEC-B92A-D1D3C521C567}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "07-Tools", "07-Tools", "{96DFADC5-FAE8-4860-A57A-93F0534B1B7A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Images.ImageSharp.Tests.Integration", "test\Util.Images.ImageSharp.Tests.Integration\Util.Images.ImageSharp.Tests.Integration.csproj", "{5921A7FA-8C70-49A9-82E1-BE3FA5B50C33}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Images.Avatar", "src\Util.Images.Avatar\02-Util.Images.Avatar.csproj", "{599BAD8E-DB56-4967-8DDE-74BD21DA2B49}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Images.Avatar.Tests.Integration", "test\Util.Images.Avatar.Tests.Integration\Util.Images.Avatar.Tests.Integration.csproj", "{75A31AAB-B7E6-4F13-9B7A-B74216B2EDDE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "15-Generators", "15-Generators", "{411247A4-4665-4BE6-8E5C-08F6D0BA2213}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Generators", "src\Util.Generators\01-Util.Generators.csproj", "{36990D32-6F41-44A6-BB88-A3F15E12C35B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Generators.Razor", "src\Util.Generators.Razor\02-Util.Generators.Razor.csproj", "{21831A4F-B3C9-40E7-855B-75F9D679FF55}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "17-Generators", "17-Generators", "{F7D4E7CB-468D-4570-8D82-D065F08BE40D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Generators.Tests", "test\Util.Generators.Tests\Util.Generators.Tests.csproj", "{5996F536-14B9-4F95-A18B-716E5F7EE478}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "08-FileStorage", "08-FileStorage", "{E069CEB0-8092-4907-BC9D-C6B8BDE20AD2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.FileStorage", "src\Util.FileStorage\02-Util.FileStorage.csproj", "{6FC29D15-7581-4E29-9897-76DC5AEF2042}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.FileStorage.Minio", "src\Util.FileStorage.Minio\03-Util.FileStorage.Minio.csproj", "{3E81F8D0-06C7-4FD4-A5B0-E3D96E909646}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "04-Util.FileStorage.Aliyun", "src\Util.FileStorage.Aliyun\04-Util.FileStorage.Aliyun.csproj", "{C233FF83-E15D-4A17-8FF1-BBFF9E9DE210}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "08-FileStorage", "08-FileStorage", "{16175228-03CA-414A-8786-E5BA844110C4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.FileStorage.Minio.Tests.Integration", "test\Util.FileStorage.Minio.Tests.Integration\Util.FileStorage.Minio.Tests.Integration.csproj", "{AB2D6B9A-0EC8-402B-849A-95E826B09AB3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Templates.Handlebars.Tests.Integration", "test\Util.Templates.Handlebars.Tests.Integration\Util.Templates.Handlebars.Tests.Integration.csproj", "{87B6EF51-9F1B-4A81-9764-F359138B774D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Templates.Razor.Tests.Integration", "test\Util.Templates.Razor.Tests.Integration\Util.Templates.Razor.Tests.Integration.csproj", "{4FFD1073-9358-418D-BB4D-DB63FE0A11DF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Generators.Razor.Tests.Integration", "test\Util.Generators.Razor.Tests.Integration\Util.Generators.Razor.Tests.Integration.csproj", "{5BFF8BA0-EA27-4493-88A5-5BC57286D536}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Events.Tests.Integration", "test\Util.Events.Tests.Integration\Util.Events.Tests.Integration.csproj", "{FB11256C-06C0-4B24-863A-C87D78F8EE2A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "15-Microservices", "15-Microservices", "{547FD391-A56B-47A6-B20C-5FC04FA15C56}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Events.Abstractions", "src\Util.Events.Abstractions\01-Util.Events.Abstractions.csproj", "{6233BF36-9636-43BD-9462-2D31A05EE4ED}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "13-Microservices", "13-Microservices", "{1DEC52C8-6692-4DA7-AE34-B76D728F895A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Microservices", "src\Util.Microservices\01-Util.Microservices.csproj", "{F8417623-6936-43C4-A967-9D6BD002AD16}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Microservices.Dapr", "src\Util.Microservices.Dapr\03-Util.Microservices.Dapr.csproj", "{CAA32331-4A8E-4C16-BC7D-7CA646B393F4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Microservices.Dapr.Tests.Integration", "test\Util.Microservices.Dapr.Tests.Integration\Util.Microservices.Dapr.Tests.Integration.csproj", "{08B1A026-4F8C-4336-B5B8-3189023DFF2B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Microservices.Polly", "src\Util.Microservices.Polly\02-Util.Microservices.Polly.csproj", "{0BCB6FF1-E374-4AED-9888-83C7CFED0E98}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Microservices.Polly.Tests.Integration", "test\Util.Microservices.Polly.Tests.Integration\Util.Microservices.Polly.Tests.Integration.csproj", "{DF1E55A5-7EA8-41B2-BEBA-72544D256069}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "04-Util.Microservices.HealthChecks", "src\Util.Microservices.HealthChecks\04-Util.Microservices.HealthChecks.csproj", "{9C58E50F-0589-4A4E-B94D-2EC0BF02F61F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Microservices.Dapr.WebApiSample", "test\Util.Microservices.Dapr.WebApiSample\Util.Microservices.Dapr.WebApiSample.csproj", "{AE19ED93-AFC4-4F91-93BD-B00D343D3BA0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Microservices.Dapr.PubsubSample", "test\Util.Microservices.Dapr.PubsubSample\Util.Microservices.Dapr.PubsubSample.csproj", "{5D74BD1D-3142-4478-9062-4543FADA3E91}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Microservices.Dapr.Tests", "test\Util.Microservices.Dapr.Tests\Util.Microservices.Dapr.Tests.csproj", "{B737883C-9450-46CB-B81C-1A3405071D04}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-Util.Tenants", "src\Util.Tenants\02-Util.Tenants.csproj", "{156447ED-8515-4FB0-8B5A-D5A3A1E43AC6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Tenants.Tests", "test\Util.Tenants.Tests\Util.Tenants.Tests.csproj", "{DE51B662-C843-4E99-87F8-F367504D5640}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "09-Tenant", "09-Tenant", "{98F1FEAD-AFD5-4744-8A55-C57920461EB9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "09-Tenant", "09-Tenant", "{835A8155-411B-4DF2-AE58-D3FDEFB61E63}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.Tenants.Abstractions", "src\Util.Tenants.Abstractions\01-Util.Tenants.Abstractions.csproj", "{0C062400-58D1-4EE3-8EBB-C5B3AAEECF87}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.Events.MediatR", "src\Util.Events.MediatR\03-Util.Events.MediatR.csproj", "{FA6AF0F1-B4EE-4E46-B933-9573861A10FC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Events.MediatR.Tests.Integration", "test\Util.Events.MediatR.Tests.Integration\Util.Events.MediatR.Tests.Integration.csproj", "{4FECE655-7B06-4DED-BED0-B67731A43E0B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Tenants.Tests.Integration", "test\Util.Tenants.Tests.Integration\Util.Tenants.Tests.Integration.csproj", "{6A84E4B0-3A9C-4B40-9B64-AD3A26324DAC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Localization.Tests", "test\Util.Localization.Tests\Util.Localization.Tests.csproj", "{9B941AF9-34A0-4DFF-80F8-0418E212659A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.Data.Dapper.Oracle.Tests.Integration", "test\Util.Data.Dapper.Oracle.Tests.Integration\Util.Data.Dapper.Oracle.Tests.Integration.csproj", "{A44B570E-0676-4003-A827-E910A9332DEA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "05-Util.Data.Dapper.Oracle", "src\Util.Data.Dapper.Oracle\05-Util.Data.Dapper.Oracle.csproj", "{00C518D5-EFAC-43CC-AD1E-9837BDBD93BB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "10-Util.IdGenerator", "src\Util.IdGenerator\10-Util.IdGenerator.csproj", "{698AE3A0-65E3-433C-B56C-7D47A7A44263}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.IdGenerator.Tests", "test\Util.IdGenerator.Tests\Util.IdGenerator.Tests.csproj", "{BA78E270-92A7-46C2-932B-3109E9DC5824}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "07-Util.Http", "src\Util.Http\07-Util.Http.csproj", "{EDB3405A-58BD-444C-82FF-05FAB7CE72B4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.FileStorage.Tests.Integration", "test\Util.FileStorage.Tests.Integration\Util.FileStorage.Tests.Integration.csproj", "{A23BA1A3-8EC7-4937-B0AA-69CCEE40453C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "05-Util.FileStorage.All", "src\Util.FileStorage.All\05-Util.FileStorage.All.csproj", "{4938D59D-CF50-4090-B936-36DB29EBE344}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.FileStorage.Aliyun.Tests.Integration", "test\Util.FileStorage.Aliyun.Tests.Integration\Util.FileStorage.Aliyun.Tests.Integration.csproj", "{58C01936-5D8F-4077-8663-EE0E35776D65}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-Util.FileStorage.Abstractions", "src\Util.FileStorage.Abstractions\01-Util.FileStorage.Abstractions.csproj", "{814E42E9-508E-487F-BCD3-0F07AE7D1492}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-Util.QrCode.ZXing", "src\Util.QrCode.ZXing\03-Util.QrCode.ZXing.csproj", "{3F5120A6-9CA4-4B25-9507-86E9E5571DB6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.QrCode.ZXing.Tests.Integration", "test\Util.QrCode.ZXing.Tests.Integration\Util.QrCode.ZXing.Tests.Integration.csproj", "{79A40AC0-A182-49D0-AED9-DF8B6835432A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {12539757-7371-455D-B86B-DAF22F2DEE4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {12539757-7371-455D-B86B-DAF22F2DEE4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {12539757-7371-455D-B86B-DAF22F2DEE4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {12539757-7371-455D-B86B-DAF22F2DEE4E}.Release|Any CPU.Build.0 = Release|Any CPU + {5F1A7144-C954-4B47-B1FF-820FEA9B6B61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F1A7144-C954-4B47-B1FF-820FEA9B6B61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F1A7144-C954-4B47-B1FF-820FEA9B6B61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F1A7144-C954-4B47-B1FF-820FEA9B6B61}.Release|Any CPU.Build.0 = Release|Any CPU + {1E50F81A-FBFF-4873-9731-FA8835A51080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E50F81A-FBFF-4873-9731-FA8835A51080}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E50F81A-FBFF-4873-9731-FA8835A51080}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E50F81A-FBFF-4873-9731-FA8835A51080}.Release|Any CPU.Build.0 = Release|Any CPU + {5F7ACBE4-A1D8-4680-AA86-B87F8494BAC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F7ACBE4-A1D8-4680-AA86-B87F8494BAC2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F7ACBE4-A1D8-4680-AA86-B87F8494BAC2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F7ACBE4-A1D8-4680-AA86-B87F8494BAC2}.Release|Any CPU.Build.0 = Release|Any CPU + {BA79977F-6DCE-4787-9A0D-AF5E61EBC177}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA79977F-6DCE-4787-9A0D-AF5E61EBC177}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA79977F-6DCE-4787-9A0D-AF5E61EBC177}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA79977F-6DCE-4787-9A0D-AF5E61EBC177}.Release|Any CPU.Build.0 = Release|Any CPU + {2B56E8AA-4DAB-4A70-9439-ED16470C0BFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B56E8AA-4DAB-4A70-9439-ED16470C0BFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B56E8AA-4DAB-4A70-9439-ED16470C0BFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B56E8AA-4DAB-4A70-9439-ED16470C0BFE}.Release|Any CPU.Build.0 = Release|Any CPU + {766CAB38-F064-419F-837B-D6DA8B61AF66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {766CAB38-F064-419F-837B-D6DA8B61AF66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {766CAB38-F064-419F-837B-D6DA8B61AF66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {766CAB38-F064-419F-837B-D6DA8B61AF66}.Release|Any CPU.Build.0 = Release|Any CPU + {E8481A4C-0C24-4418-A2C1-742877BE4F0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8481A4C-0C24-4418-A2C1-742877BE4F0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8481A4C-0C24-4418-A2C1-742877BE4F0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8481A4C-0C24-4418-A2C1-742877BE4F0D}.Release|Any CPU.Build.0 = Release|Any CPU + {21064598-1418-422E-BA37-8EC09541DFC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21064598-1418-422E-BA37-8EC09541DFC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21064598-1418-422E-BA37-8EC09541DFC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21064598-1418-422E-BA37-8EC09541DFC1}.Release|Any CPU.Build.0 = Release|Any CPU + {08EF3E38-E0C3-4E18-984C-3216CB6E8897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08EF3E38-E0C3-4E18-984C-3216CB6E8897}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08EF3E38-E0C3-4E18-984C-3216CB6E8897}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08EF3E38-E0C3-4E18-984C-3216CB6E8897}.Release|Any CPU.Build.0 = Release|Any CPU + {12C94395-09F1-42E4-8CE1-6E54D3FEBAA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {12C94395-09F1-42E4-8CE1-6E54D3FEBAA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {12C94395-09F1-42E4-8CE1-6E54D3FEBAA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {12C94395-09F1-42E4-8CE1-6E54D3FEBAA6}.Release|Any CPU.Build.0 = Release|Any CPU + {955D94B8-747D-4CA4-832A-6377C9FF5B8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {955D94B8-747D-4CA4-832A-6377C9FF5B8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {955D94B8-747D-4CA4-832A-6377C9FF5B8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {955D94B8-747D-4CA4-832A-6377C9FF5B8F}.Release|Any CPU.Build.0 = Release|Any CPU + {FB337B27-C6C6-43A1-BFA5-58B3CF381BA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB337B27-C6C6-43A1-BFA5-58B3CF381BA8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB337B27-C6C6-43A1-BFA5-58B3CF381BA8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB337B27-C6C6-43A1-BFA5-58B3CF381BA8}.Release|Any CPU.Build.0 = Release|Any CPU + {B8825802-81F7-4671-82E8-3A6E3A21F570}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B8825802-81F7-4671-82E8-3A6E3A21F570}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B8825802-81F7-4671-82E8-3A6E3A21F570}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B8825802-81F7-4671-82E8-3A6E3A21F570}.Release|Any CPU.Build.0 = Release|Any CPU + {1DE277C2-EE56-4F4D-BB89-71107DE0E4C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1DE277C2-EE56-4F4D-BB89-71107DE0E4C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1DE277C2-EE56-4F4D-BB89-71107DE0E4C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1DE277C2-EE56-4F4D-BB89-71107DE0E4C6}.Release|Any CPU.Build.0 = Release|Any CPU + {166852FC-2F86-4A5B-9029-E16958798DD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {166852FC-2F86-4A5B-9029-E16958798DD6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {166852FC-2F86-4A5B-9029-E16958798DD6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {166852FC-2F86-4A5B-9029-E16958798DD6}.Release|Any CPU.Build.0 = Release|Any CPU + {61982C8D-5376-45EE-BCC3-D4F9E90AF3B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61982C8D-5376-45EE-BCC3-D4F9E90AF3B0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61982C8D-5376-45EE-BCC3-D4F9E90AF3B0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61982C8D-5376-45EE-BCC3-D4F9E90AF3B0}.Release|Any CPU.Build.0 = Release|Any CPU + {7CA38535-297B-4DA9-AFF5-3199268EEAF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CA38535-297B-4DA9-AFF5-3199268EEAF6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CA38535-297B-4DA9-AFF5-3199268EEAF6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CA38535-297B-4DA9-AFF5-3199268EEAF6}.Release|Any CPU.Build.0 = Release|Any CPU + {EE426441-DE33-4F3B-B66A-E258AC725B78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE426441-DE33-4F3B-B66A-E258AC725B78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE426441-DE33-4F3B-B66A-E258AC725B78}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE426441-DE33-4F3B-B66A-E258AC725B78}.Release|Any CPU.Build.0 = Release|Any CPU + {4D40321F-2C3F-4ACB-8AE0-7A228DF0551B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D40321F-2C3F-4ACB-8AE0-7A228DF0551B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D40321F-2C3F-4ACB-8AE0-7A228DF0551B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D40321F-2C3F-4ACB-8AE0-7A228DF0551B}.Release|Any CPU.Build.0 = Release|Any CPU + {7F7D9EE0-7263-4621-BA65-FC470B0F3C6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F7D9EE0-7263-4621-BA65-FC470B0F3C6B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F7D9EE0-7263-4621-BA65-FC470B0F3C6B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F7D9EE0-7263-4621-BA65-FC470B0F3C6B}.Release|Any CPU.Build.0 = Release|Any CPU + {04E5EDDB-8440-4BAD-9531-F87A3AC826FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04E5EDDB-8440-4BAD-9531-F87A3AC826FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04E5EDDB-8440-4BAD-9531-F87A3AC826FB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04E5EDDB-8440-4BAD-9531-F87A3AC826FB}.Release|Any CPU.Build.0 = Release|Any CPU + {4656C609-DBBA-4F6B-B16F-5E1A8C9D9858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4656C609-DBBA-4F6B-B16F-5E1A8C9D9858}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4656C609-DBBA-4F6B-B16F-5E1A8C9D9858}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4656C609-DBBA-4F6B-B16F-5E1A8C9D9858}.Release|Any CPU.Build.0 = Release|Any CPU + {F7925EED-65E6-4CA2-9B8D-B7036F6DB3E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7925EED-65E6-4CA2-9B8D-B7036F6DB3E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7925EED-65E6-4CA2-9B8D-B7036F6DB3E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7925EED-65E6-4CA2-9B8D-B7036F6DB3E8}.Release|Any CPU.Build.0 = Release|Any CPU + {D22C3F6D-434A-4F09-9EB2-B0433CC43642}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D22C3F6D-434A-4F09-9EB2-B0433CC43642}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D22C3F6D-434A-4F09-9EB2-B0433CC43642}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D22C3F6D-434A-4F09-9EB2-B0433CC43642}.Release|Any CPU.Build.0 = Release|Any CPU + {257A0A17-5D13-4DA4-8E91-8A3BB2711F49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {257A0A17-5D13-4DA4-8E91-8A3BB2711F49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {257A0A17-5D13-4DA4-8E91-8A3BB2711F49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {257A0A17-5D13-4DA4-8E91-8A3BB2711F49}.Release|Any CPU.Build.0 = Release|Any CPU + {9A2C7C42-086B-4482-828D-7B02D85372ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A2C7C42-086B-4482-828D-7B02D85372ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A2C7C42-086B-4482-828D-7B02D85372ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A2C7C42-086B-4482-828D-7B02D85372ED}.Release|Any CPU.Build.0 = Release|Any CPU + {661B88AE-6F83-437C-9A7E-C5C1A565E650}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {661B88AE-6F83-437C-9A7E-C5C1A565E650}.Debug|Any CPU.Build.0 = Debug|Any CPU + {661B88AE-6F83-437C-9A7E-C5C1A565E650}.Release|Any CPU.ActiveCfg = Release|Any CPU + {661B88AE-6F83-437C-9A7E-C5C1A565E650}.Release|Any CPU.Build.0 = Release|Any CPU + {C99E1554-5039-42BD-B1FD-93814FBEBE44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C99E1554-5039-42BD-B1FD-93814FBEBE44}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C99E1554-5039-42BD-B1FD-93814FBEBE44}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C99E1554-5039-42BD-B1FD-93814FBEBE44}.Release|Any CPU.Build.0 = Release|Any CPU + {60424AB5-356A-4623-B1FB-7560334C0BE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60424AB5-356A-4623-B1FB-7560334C0BE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60424AB5-356A-4623-B1FB-7560334C0BE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60424AB5-356A-4623-B1FB-7560334C0BE0}.Release|Any CPU.Build.0 = Release|Any CPU + {C2A4E6AB-16B9-4457-9445-FFBF672DFBCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C2A4E6AB-16B9-4457-9445-FFBF672DFBCF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C2A4E6AB-16B9-4457-9445-FFBF672DFBCF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C2A4E6AB-16B9-4457-9445-FFBF672DFBCF}.Release|Any CPU.Build.0 = Release|Any CPU + {AFB629C5-00C2-492C-8787-C66D810A24DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFB629C5-00C2-492C-8787-C66D810A24DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFB629C5-00C2-492C-8787-C66D810A24DB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFB629C5-00C2-492C-8787-C66D810A24DB}.Release|Any CPU.Build.0 = Release|Any CPU + {9404B5FE-3431-4EC0-BCC6-42525FC5D1B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9404B5FE-3431-4EC0-BCC6-42525FC5D1B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9404B5FE-3431-4EC0-BCC6-42525FC5D1B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9404B5FE-3431-4EC0-BCC6-42525FC5D1B8}.Release|Any CPU.Build.0 = Release|Any CPU + {EF7BDA1B-22E7-4F3D-97E0-16C9C10AA1B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF7BDA1B-22E7-4F3D-97E0-16C9C10AA1B0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF7BDA1B-22E7-4F3D-97E0-16C9C10AA1B0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF7BDA1B-22E7-4F3D-97E0-16C9C10AA1B0}.Release|Any CPU.Build.0 = Release|Any CPU + {B5305F08-3856-42B5-92D5-6FD446B39931}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5305F08-3856-42B5-92D5-6FD446B39931}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5305F08-3856-42B5-92D5-6FD446B39931}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5305F08-3856-42B5-92D5-6FD446B39931}.Release|Any CPU.Build.0 = Release|Any CPU + {88FE7642-27D9-4693-A130-706FCE46194A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {88FE7642-27D9-4693-A130-706FCE46194A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {88FE7642-27D9-4693-A130-706FCE46194A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {88FE7642-27D9-4693-A130-706FCE46194A}.Release|Any CPU.Build.0 = Release|Any CPU + {CA43B145-9DF2-49D3-9371-B88BFB0E846A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA43B145-9DF2-49D3-9371-B88BFB0E846A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA43B145-9DF2-49D3-9371-B88BFB0E846A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA43B145-9DF2-49D3-9371-B88BFB0E846A}.Release|Any CPU.Build.0 = Release|Any CPU + {95842BB6-559E-4317-B1E9-FF19D39ADA24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95842BB6-559E-4317-B1E9-FF19D39ADA24}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95842BB6-559E-4317-B1E9-FF19D39ADA24}.Release|Any CPU.ActiveCfg = Release|Any CPU + {95842BB6-559E-4317-B1E9-FF19D39ADA24}.Release|Any CPU.Build.0 = Release|Any CPU + {3DE7DD7A-8500-46C9-91A1-A65DB60E0235}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3DE7DD7A-8500-46C9-91A1-A65DB60E0235}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3DE7DD7A-8500-46C9-91A1-A65DB60E0235}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3DE7DD7A-8500-46C9-91A1-A65DB60E0235}.Release|Any CPU.Build.0 = Release|Any CPU + {8618EE3F-F120-4AEA-8A77-F7BD5DCCB888}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8618EE3F-F120-4AEA-8A77-F7BD5DCCB888}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8618EE3F-F120-4AEA-8A77-F7BD5DCCB888}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8618EE3F-F120-4AEA-8A77-F7BD5DCCB888}.Release|Any CPU.Build.0 = Release|Any CPU + {577A7F6F-4836-4811-B715-32573127BDB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {577A7F6F-4836-4811-B715-32573127BDB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {577A7F6F-4836-4811-B715-32573127BDB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {577A7F6F-4836-4811-B715-32573127BDB3}.Release|Any CPU.Build.0 = Release|Any CPU + {04EA7A93-CDC7-4C68-815D-699180D99DCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04EA7A93-CDC7-4C68-815D-699180D99DCE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04EA7A93-CDC7-4C68-815D-699180D99DCE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04EA7A93-CDC7-4C68-815D-699180D99DCE}.Release|Any CPU.Build.0 = Release|Any CPU + {A1186FB9-FB77-427C-9AEC-55E48A8D046A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A1186FB9-FB77-427C-9AEC-55E48A8D046A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1186FB9-FB77-427C-9AEC-55E48A8D046A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A1186FB9-FB77-427C-9AEC-55E48A8D046A}.Release|Any CPU.Build.0 = Release|Any CPU + {9960FA8A-98C1-45FB-8A09-33CA183AA140}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9960FA8A-98C1-45FB-8A09-33CA183AA140}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9960FA8A-98C1-45FB-8A09-33CA183AA140}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9960FA8A-98C1-45FB-8A09-33CA183AA140}.Release|Any CPU.Build.0 = Release|Any CPU + {1855CAB7-6379-47A4-A0A4-F890C6C46403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1855CAB7-6379-47A4-A0A4-F890C6C46403}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1855CAB7-6379-47A4-A0A4-F890C6C46403}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1855CAB7-6379-47A4-A0A4-F890C6C46403}.Release|Any CPU.Build.0 = Release|Any CPU + {C43539A5-8343-4381-B2FD-5323323F1DB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C43539A5-8343-4381-B2FD-5323323F1DB6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C43539A5-8343-4381-B2FD-5323323F1DB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C43539A5-8343-4381-B2FD-5323323F1DB6}.Release|Any CPU.Build.0 = Release|Any CPU + {D3C326CD-F1F1-4E06-962D-47F6C8090DEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3C326CD-F1F1-4E06-962D-47F6C8090DEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3C326CD-F1F1-4E06-962D-47F6C8090DEE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3C326CD-F1F1-4E06-962D-47F6C8090DEE}.Release|Any CPU.Build.0 = Release|Any CPU + {13690AB8-9AA4-4936-A25F-7AF1AE3D4ED0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13690AB8-9AA4-4936-A25F-7AF1AE3D4ED0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13690AB8-9AA4-4936-A25F-7AF1AE3D4ED0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13690AB8-9AA4-4936-A25F-7AF1AE3D4ED0}.Release|Any CPU.Build.0 = Release|Any CPU + {244A930D-5B84-4CBC-A3A7-7E8DE1E603D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {244A930D-5B84-4CBC-A3A7-7E8DE1E603D6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {244A930D-5B84-4CBC-A3A7-7E8DE1E603D6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {244A930D-5B84-4CBC-A3A7-7E8DE1E603D6}.Release|Any CPU.Build.0 = Release|Any CPU + {0EDF10D7-D6D6-48E2-AC0C-BA6D814CB633}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0EDF10D7-D6D6-48E2-AC0C-BA6D814CB633}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0EDF10D7-D6D6-48E2-AC0C-BA6D814CB633}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0EDF10D7-D6D6-48E2-AC0C-BA6D814CB633}.Release|Any CPU.Build.0 = Release|Any CPU + {05D8A63F-B3E1-4A5E-AA66-337BCF8840C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05D8A63F-B3E1-4A5E-AA66-337BCF8840C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05D8A63F-B3E1-4A5E-AA66-337BCF8840C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05D8A63F-B3E1-4A5E-AA66-337BCF8840C1}.Release|Any CPU.Build.0 = Release|Any CPU + {3993A838-71C9-49C5-80B3-16CC48A5F5C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3993A838-71C9-49C5-80B3-16CC48A5F5C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3993A838-71C9-49C5-80B3-16CC48A5F5C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3993A838-71C9-49C5-80B3-16CC48A5F5C9}.Release|Any CPU.Build.0 = Release|Any CPU + {D785A240-1115-41C8-943E-5058161D6478}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D785A240-1115-41C8-943E-5058161D6478}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D785A240-1115-41C8-943E-5058161D6478}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D785A240-1115-41C8-943E-5058161D6478}.Release|Any CPU.Build.0 = Release|Any CPU + {B1952639-773B-4C82-9D95-7CB4ED8AC59E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1952639-773B-4C82-9D95-7CB4ED8AC59E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1952639-773B-4C82-9D95-7CB4ED8AC59E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1952639-773B-4C82-9D95-7CB4ED8AC59E}.Release|Any CPU.Build.0 = Release|Any CPU + {29792C72-565A-46DF-B887-494AC5352818}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29792C72-565A-46DF-B887-494AC5352818}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29792C72-565A-46DF-B887-494AC5352818}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29792C72-565A-46DF-B887-494AC5352818}.Release|Any CPU.Build.0 = Release|Any CPU + {C57D22E0-075B-4F27-87F1-E6CF5F203975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C57D22E0-075B-4F27-87F1-E6CF5F203975}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C57D22E0-075B-4F27-87F1-E6CF5F203975}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C57D22E0-075B-4F27-87F1-E6CF5F203975}.Release|Any CPU.Build.0 = Release|Any CPU + {B9B66159-4FC7-4F94-8C21-ADC8CCED84F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9B66159-4FC7-4F94-8C21-ADC8CCED84F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9B66159-4FC7-4F94-8C21-ADC8CCED84F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9B66159-4FC7-4F94-8C21-ADC8CCED84F4}.Release|Any CPU.Build.0 = Release|Any CPU + {24FFA5F1-37CD-408B-80A9-006B5A6E11E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24FFA5F1-37CD-408B-80A9-006B5A6E11E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24FFA5F1-37CD-408B-80A9-006B5A6E11E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24FFA5F1-37CD-408B-80A9-006B5A6E11E8}.Release|Any CPU.Build.0 = Release|Any CPU + {6FE28297-B958-4BC5-A320-A531874D7F58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FE28297-B958-4BC5-A320-A531874D7F58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FE28297-B958-4BC5-A320-A531874D7F58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FE28297-B958-4BC5-A320-A531874D7F58}.Release|Any CPU.Build.0 = Release|Any CPU + {838A27C6-F125-4C61-923E-7C855B598FBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {838A27C6-F125-4C61-923E-7C855B598FBD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {838A27C6-F125-4C61-923E-7C855B598FBD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {838A27C6-F125-4C61-923E-7C855B598FBD}.Release|Any CPU.Build.0 = Release|Any CPU + {FDE43241-3C82-4005-87B3-FD1349FEF4B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDE43241-3C82-4005-87B3-FD1349FEF4B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDE43241-3C82-4005-87B3-FD1349FEF4B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDE43241-3C82-4005-87B3-FD1349FEF4B6}.Release|Any CPU.Build.0 = Release|Any CPU + {878A2744-5122-48A7-90E6-7D8CFABC29FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {878A2744-5122-48A7-90E6-7D8CFABC29FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {878A2744-5122-48A7-90E6-7D8CFABC29FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {878A2744-5122-48A7-90E6-7D8CFABC29FD}.Release|Any CPU.Build.0 = Release|Any CPU + {0C464725-DEDC-4894-84A3-7A155E43818B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C464725-DEDC-4894-84A3-7A155E43818B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C464725-DEDC-4894-84A3-7A155E43818B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C464725-DEDC-4894-84A3-7A155E43818B}.Release|Any CPU.Build.0 = Release|Any CPU + {AC831843-CDE2-4B67-8BC5-8F2A0D09B273}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC831843-CDE2-4B67-8BC5-8F2A0D09B273}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC831843-CDE2-4B67-8BC5-8F2A0D09B273}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC831843-CDE2-4B67-8BC5-8F2A0D09B273}.Release|Any CPU.Build.0 = Release|Any CPU + {2BE691A3-19C0-4FCF-85D2-D2371C9462C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BE691A3-19C0-4FCF-85D2-D2371C9462C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BE691A3-19C0-4FCF-85D2-D2371C9462C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BE691A3-19C0-4FCF-85D2-D2371C9462C6}.Release|Any CPU.Build.0 = Release|Any CPU + {B140F739-EC51-4265-B4B8-59467606E6EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B140F739-EC51-4265-B4B8-59467606E6EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B140F739-EC51-4265-B4B8-59467606E6EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B140F739-EC51-4265-B4B8-59467606E6EE}.Release|Any CPU.Build.0 = Release|Any CPU + {00E8EE51-A263-4971-9431-C4A2DEA4993A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00E8EE51-A263-4971-9431-C4A2DEA4993A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00E8EE51-A263-4971-9431-C4A2DEA4993A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00E8EE51-A263-4971-9431-C4A2DEA4993A}.Release|Any CPU.Build.0 = Release|Any CPU + {6B2BA282-5C97-4A71-885F-E5259274F714}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B2BA282-5C97-4A71-885F-E5259274F714}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B2BA282-5C97-4A71-885F-E5259274F714}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B2BA282-5C97-4A71-885F-E5259274F714}.Release|Any CPU.Build.0 = Release|Any CPU + {05CF624D-F42E-461A-A21D-41BEE0CCEB5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05CF624D-F42E-461A-A21D-41BEE0CCEB5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05CF624D-F42E-461A-A21D-41BEE0CCEB5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05CF624D-F42E-461A-A21D-41BEE0CCEB5C}.Release|Any CPU.Build.0 = Release|Any CPU + {C4A782C1-AA25-476B-B936-90433422D0A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4A782C1-AA25-476B-B936-90433422D0A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4A782C1-AA25-476B-B936-90433422D0A2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4A782C1-AA25-476B-B936-90433422D0A2}.Release|Any CPU.Build.0 = Release|Any CPU + {D9E411DD-58B1-4160-8025-068D43ADE72C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9E411DD-58B1-4160-8025-068D43ADE72C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9E411DD-58B1-4160-8025-068D43ADE72C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9E411DD-58B1-4160-8025-068D43ADE72C}.Release|Any CPU.Build.0 = Release|Any CPU + {B2AADB36-8433-4EDB-B247-49A3EA82FE06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2AADB36-8433-4EDB-B247-49A3EA82FE06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2AADB36-8433-4EDB-B247-49A3EA82FE06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2AADB36-8433-4EDB-B247-49A3EA82FE06}.Release|Any CPU.Build.0 = Release|Any CPU + {40F2A962-6209-42D0-9F21-CEACB411007B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40F2A962-6209-42D0-9F21-CEACB411007B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40F2A962-6209-42D0-9F21-CEACB411007B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40F2A962-6209-42D0-9F21-CEACB411007B}.Release|Any CPU.Build.0 = Release|Any CPU + {4170A699-C110-4136-92EA-D2BFEBF68230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4170A699-C110-4136-92EA-D2BFEBF68230}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4170A699-C110-4136-92EA-D2BFEBF68230}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4170A699-C110-4136-92EA-D2BFEBF68230}.Release|Any CPU.Build.0 = Release|Any CPU + {78B9EC26-ADC5-4934-9F31-000D4D678121}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78B9EC26-ADC5-4934-9F31-000D4D678121}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78B9EC26-ADC5-4934-9F31-000D4D678121}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78B9EC26-ADC5-4934-9F31-000D4D678121}.Release|Any CPU.Build.0 = Release|Any CPU + {027B0175-2D22-4168-A0B4-1E0DC5BE2A61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {027B0175-2D22-4168-A0B4-1E0DC5BE2A61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {027B0175-2D22-4168-A0B4-1E0DC5BE2A61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {027B0175-2D22-4168-A0B4-1E0DC5BE2A61}.Release|Any CPU.Build.0 = Release|Any CPU + {EA4C219B-D00A-4BDB-A787-A79FA9611303}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA4C219B-D00A-4BDB-A787-A79FA9611303}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA4C219B-D00A-4BDB-A787-A79FA9611303}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA4C219B-D00A-4BDB-A787-A79FA9611303}.Release|Any CPU.Build.0 = Release|Any CPU + {B40CD480-D4A0-4A43-B855-0CD84EC537CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B40CD480-D4A0-4A43-B855-0CD84EC537CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B40CD480-D4A0-4A43-B855-0CD84EC537CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B40CD480-D4A0-4A43-B855-0CD84EC537CC}.Release|Any CPU.Build.0 = Release|Any CPU + {C3C7C037-B5B6-4CE0-BC02-820667D74F60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3C7C037-B5B6-4CE0-BC02-820667D74F60}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3C7C037-B5B6-4CE0-BC02-820667D74F60}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3C7C037-B5B6-4CE0-BC02-820667D74F60}.Release|Any CPU.Build.0 = Release|Any CPU + {48F77D8F-60AE-4173-BA74-FC2E0B3578BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48F77D8F-60AE-4173-BA74-FC2E0B3578BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48F77D8F-60AE-4173-BA74-FC2E0B3578BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48F77D8F-60AE-4173-BA74-FC2E0B3578BB}.Release|Any CPU.Build.0 = Release|Any CPU + {4E12B03E-D607-492E-BB28-96235993A39F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E12B03E-D607-492E-BB28-96235993A39F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E12B03E-D607-492E-BB28-96235993A39F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E12B03E-D607-492E-BB28-96235993A39F}.Release|Any CPU.Build.0 = Release|Any CPU + {D2F38ACB-7158-4DE0-BDEA-B13E3D52A655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2F38ACB-7158-4DE0-BDEA-B13E3D52A655}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2F38ACB-7158-4DE0-BDEA-B13E3D52A655}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2F38ACB-7158-4DE0-BDEA-B13E3D52A655}.Release|Any CPU.Build.0 = Release|Any CPU + {1272E006-8D8B-46B5-AD18-2E31CA9C6CBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1272E006-8D8B-46B5-AD18-2E31CA9C6CBD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1272E006-8D8B-46B5-AD18-2E31CA9C6CBD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1272E006-8D8B-46B5-AD18-2E31CA9C6CBD}.Release|Any CPU.Build.0 = Release|Any CPU + {E0D77981-E412-477D-B866-E43F055CAAFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0D77981-E412-477D-B866-E43F055CAAFC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0D77981-E412-477D-B866-E43F055CAAFC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0D77981-E412-477D-B866-E43F055CAAFC}.Release|Any CPU.Build.0 = Release|Any CPU + {66B96C01-6A08-4C7A-B5F5-A0489D8BBB47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66B96C01-6A08-4C7A-B5F5-A0489D8BBB47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66B96C01-6A08-4C7A-B5F5-A0489D8BBB47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66B96C01-6A08-4C7A-B5F5-A0489D8BBB47}.Release|Any CPU.Build.0 = Release|Any CPU + {8BC69296-3C9A-45B3-B6C3-3DD575027CCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8BC69296-3C9A-45B3-B6C3-3DD575027CCD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8BC69296-3C9A-45B3-B6C3-3DD575027CCD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8BC69296-3C9A-45B3-B6C3-3DD575027CCD}.Release|Any CPU.Build.0 = Release|Any CPU + {B25D3B7A-AEAA-4EFB-9839-7C6E3F7C24BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B25D3B7A-AEAA-4EFB-9839-7C6E3F7C24BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B25D3B7A-AEAA-4EFB-9839-7C6E3F7C24BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B25D3B7A-AEAA-4EFB-9839-7C6E3F7C24BB}.Release|Any CPU.Build.0 = Release|Any CPU + {22305349-51C7-4D80-A538-C7C0F4495895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22305349-51C7-4D80-A538-C7C0F4495895}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22305349-51C7-4D80-A538-C7C0F4495895}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22305349-51C7-4D80-A538-C7C0F4495895}.Release|Any CPU.Build.0 = Release|Any CPU + {5921A7FA-8C70-49A9-82E1-BE3FA5B50C33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5921A7FA-8C70-49A9-82E1-BE3FA5B50C33}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5921A7FA-8C70-49A9-82E1-BE3FA5B50C33}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5921A7FA-8C70-49A9-82E1-BE3FA5B50C33}.Release|Any CPU.Build.0 = Release|Any CPU + {599BAD8E-DB56-4967-8DDE-74BD21DA2B49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {599BAD8E-DB56-4967-8DDE-74BD21DA2B49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {599BAD8E-DB56-4967-8DDE-74BD21DA2B49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {599BAD8E-DB56-4967-8DDE-74BD21DA2B49}.Release|Any CPU.Build.0 = Release|Any CPU + {75A31AAB-B7E6-4F13-9B7A-B74216B2EDDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75A31AAB-B7E6-4F13-9B7A-B74216B2EDDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75A31AAB-B7E6-4F13-9B7A-B74216B2EDDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75A31AAB-B7E6-4F13-9B7A-B74216B2EDDE}.Release|Any CPU.Build.0 = Release|Any CPU + {36990D32-6F41-44A6-BB88-A3F15E12C35B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36990D32-6F41-44A6-BB88-A3F15E12C35B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36990D32-6F41-44A6-BB88-A3F15E12C35B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36990D32-6F41-44A6-BB88-A3F15E12C35B}.Release|Any CPU.Build.0 = Release|Any CPU + {21831A4F-B3C9-40E7-855B-75F9D679FF55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21831A4F-B3C9-40E7-855B-75F9D679FF55}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21831A4F-B3C9-40E7-855B-75F9D679FF55}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21831A4F-B3C9-40E7-855B-75F9D679FF55}.Release|Any CPU.Build.0 = Release|Any CPU + {5996F536-14B9-4F95-A18B-716E5F7EE478}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5996F536-14B9-4F95-A18B-716E5F7EE478}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5996F536-14B9-4F95-A18B-716E5F7EE478}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5996F536-14B9-4F95-A18B-716E5F7EE478}.Release|Any CPU.Build.0 = Release|Any CPU + {6FC29D15-7581-4E29-9897-76DC5AEF2042}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FC29D15-7581-4E29-9897-76DC5AEF2042}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FC29D15-7581-4E29-9897-76DC5AEF2042}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FC29D15-7581-4E29-9897-76DC5AEF2042}.Release|Any CPU.Build.0 = Release|Any CPU + {3E81F8D0-06C7-4FD4-A5B0-E3D96E909646}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E81F8D0-06C7-4FD4-A5B0-E3D96E909646}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E81F8D0-06C7-4FD4-A5B0-E3D96E909646}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E81F8D0-06C7-4FD4-A5B0-E3D96E909646}.Release|Any CPU.Build.0 = Release|Any CPU + {C233FF83-E15D-4A17-8FF1-BBFF9E9DE210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C233FF83-E15D-4A17-8FF1-BBFF9E9DE210}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C233FF83-E15D-4A17-8FF1-BBFF9E9DE210}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C233FF83-E15D-4A17-8FF1-BBFF9E9DE210}.Release|Any CPU.Build.0 = Release|Any CPU + {AB2D6B9A-0EC8-402B-849A-95E826B09AB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB2D6B9A-0EC8-402B-849A-95E826B09AB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB2D6B9A-0EC8-402B-849A-95E826B09AB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB2D6B9A-0EC8-402B-849A-95E826B09AB3}.Release|Any CPU.Build.0 = Release|Any CPU + {87B6EF51-9F1B-4A81-9764-F359138B774D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87B6EF51-9F1B-4A81-9764-F359138B774D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87B6EF51-9F1B-4A81-9764-F359138B774D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87B6EF51-9F1B-4A81-9764-F359138B774D}.Release|Any CPU.Build.0 = Release|Any CPU + {4FFD1073-9358-418D-BB4D-DB63FE0A11DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FFD1073-9358-418D-BB4D-DB63FE0A11DF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FFD1073-9358-418D-BB4D-DB63FE0A11DF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FFD1073-9358-418D-BB4D-DB63FE0A11DF}.Release|Any CPU.Build.0 = Release|Any CPU + {5BFF8BA0-EA27-4493-88A5-5BC57286D536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BFF8BA0-EA27-4493-88A5-5BC57286D536}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BFF8BA0-EA27-4493-88A5-5BC57286D536}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BFF8BA0-EA27-4493-88A5-5BC57286D536}.Release|Any CPU.Build.0 = Release|Any CPU + {FB11256C-06C0-4B24-863A-C87D78F8EE2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB11256C-06C0-4B24-863A-C87D78F8EE2A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB11256C-06C0-4B24-863A-C87D78F8EE2A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB11256C-06C0-4B24-863A-C87D78F8EE2A}.Release|Any CPU.Build.0 = Release|Any CPU + {6233BF36-9636-43BD-9462-2D31A05EE4ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6233BF36-9636-43BD-9462-2D31A05EE4ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6233BF36-9636-43BD-9462-2D31A05EE4ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6233BF36-9636-43BD-9462-2D31A05EE4ED}.Release|Any CPU.Build.0 = Release|Any CPU + {F8417623-6936-43C4-A967-9D6BD002AD16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8417623-6936-43C4-A967-9D6BD002AD16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8417623-6936-43C4-A967-9D6BD002AD16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8417623-6936-43C4-A967-9D6BD002AD16}.Release|Any CPU.Build.0 = Release|Any CPU + {CAA32331-4A8E-4C16-BC7D-7CA646B393F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CAA32331-4A8E-4C16-BC7D-7CA646B393F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAA32331-4A8E-4C16-BC7D-7CA646B393F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CAA32331-4A8E-4C16-BC7D-7CA646B393F4}.Release|Any CPU.Build.0 = Release|Any CPU + {08B1A026-4F8C-4336-B5B8-3189023DFF2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08B1A026-4F8C-4336-B5B8-3189023DFF2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08B1A026-4F8C-4336-B5B8-3189023DFF2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08B1A026-4F8C-4336-B5B8-3189023DFF2B}.Release|Any CPU.Build.0 = Release|Any CPU + {0BCB6FF1-E374-4AED-9888-83C7CFED0E98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0BCB6FF1-E374-4AED-9888-83C7CFED0E98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0BCB6FF1-E374-4AED-9888-83C7CFED0E98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0BCB6FF1-E374-4AED-9888-83C7CFED0E98}.Release|Any CPU.Build.0 = Release|Any CPU + {DF1E55A5-7EA8-41B2-BEBA-72544D256069}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF1E55A5-7EA8-41B2-BEBA-72544D256069}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF1E55A5-7EA8-41B2-BEBA-72544D256069}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF1E55A5-7EA8-41B2-BEBA-72544D256069}.Release|Any CPU.Build.0 = Release|Any CPU + {9C58E50F-0589-4A4E-B94D-2EC0BF02F61F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C58E50F-0589-4A4E-B94D-2EC0BF02F61F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C58E50F-0589-4A4E-B94D-2EC0BF02F61F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C58E50F-0589-4A4E-B94D-2EC0BF02F61F}.Release|Any CPU.Build.0 = Release|Any CPU + {AE19ED93-AFC4-4F91-93BD-B00D343D3BA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE19ED93-AFC4-4F91-93BD-B00D343D3BA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE19ED93-AFC4-4F91-93BD-B00D343D3BA0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE19ED93-AFC4-4F91-93BD-B00D343D3BA0}.Release|Any CPU.Build.0 = Release|Any CPU + {5D74BD1D-3142-4478-9062-4543FADA3E91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D74BD1D-3142-4478-9062-4543FADA3E91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D74BD1D-3142-4478-9062-4543FADA3E91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D74BD1D-3142-4478-9062-4543FADA3E91}.Release|Any CPU.Build.0 = Release|Any CPU + {B737883C-9450-46CB-B81C-1A3405071D04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B737883C-9450-46CB-B81C-1A3405071D04}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B737883C-9450-46CB-B81C-1A3405071D04}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B737883C-9450-46CB-B81C-1A3405071D04}.Release|Any CPU.Build.0 = Release|Any CPU + {156447ED-8515-4FB0-8B5A-D5A3A1E43AC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {156447ED-8515-4FB0-8B5A-D5A3A1E43AC6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {156447ED-8515-4FB0-8B5A-D5A3A1E43AC6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {156447ED-8515-4FB0-8B5A-D5A3A1E43AC6}.Release|Any CPU.Build.0 = Release|Any CPU + {DE51B662-C843-4E99-87F8-F367504D5640}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE51B662-C843-4E99-87F8-F367504D5640}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE51B662-C843-4E99-87F8-F367504D5640}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE51B662-C843-4E99-87F8-F367504D5640}.Release|Any CPU.Build.0 = Release|Any CPU + {0C062400-58D1-4EE3-8EBB-C5B3AAEECF87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C062400-58D1-4EE3-8EBB-C5B3AAEECF87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C062400-58D1-4EE3-8EBB-C5B3AAEECF87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C062400-58D1-4EE3-8EBB-C5B3AAEECF87}.Release|Any CPU.Build.0 = Release|Any CPU + {FA6AF0F1-B4EE-4E46-B933-9573861A10FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA6AF0F1-B4EE-4E46-B933-9573861A10FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA6AF0F1-B4EE-4E46-B933-9573861A10FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA6AF0F1-B4EE-4E46-B933-9573861A10FC}.Release|Any CPU.Build.0 = Release|Any CPU + {4FECE655-7B06-4DED-BED0-B67731A43E0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FECE655-7B06-4DED-BED0-B67731A43E0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FECE655-7B06-4DED-BED0-B67731A43E0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FECE655-7B06-4DED-BED0-B67731A43E0B}.Release|Any CPU.Build.0 = Release|Any CPU + {6A84E4B0-3A9C-4B40-9B64-AD3A26324DAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A84E4B0-3A9C-4B40-9B64-AD3A26324DAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A84E4B0-3A9C-4B40-9B64-AD3A26324DAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6A84E4B0-3A9C-4B40-9B64-AD3A26324DAC}.Release|Any CPU.Build.0 = Release|Any CPU + {9B941AF9-34A0-4DFF-80F8-0418E212659A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9B941AF9-34A0-4DFF-80F8-0418E212659A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9B941AF9-34A0-4DFF-80F8-0418E212659A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9B941AF9-34A0-4DFF-80F8-0418E212659A}.Release|Any CPU.Build.0 = Release|Any CPU + {A44B570E-0676-4003-A827-E910A9332DEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A44B570E-0676-4003-A827-E910A9332DEA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A44B570E-0676-4003-A827-E910A9332DEA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A44B570E-0676-4003-A827-E910A9332DEA}.Release|Any CPU.Build.0 = Release|Any CPU + {00C518D5-EFAC-43CC-AD1E-9837BDBD93BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00C518D5-EFAC-43CC-AD1E-9837BDBD93BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00C518D5-EFAC-43CC-AD1E-9837BDBD93BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00C518D5-EFAC-43CC-AD1E-9837BDBD93BB}.Release|Any CPU.Build.0 = Release|Any CPU + {698AE3A0-65E3-433C-B56C-7D47A7A44263}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {698AE3A0-65E3-433C-B56C-7D47A7A44263}.Debug|Any CPU.Build.0 = Debug|Any CPU + {698AE3A0-65E3-433C-B56C-7D47A7A44263}.Release|Any CPU.ActiveCfg = Release|Any CPU + {698AE3A0-65E3-433C-B56C-7D47A7A44263}.Release|Any CPU.Build.0 = Release|Any CPU + {BA78E270-92A7-46C2-932B-3109E9DC5824}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA78E270-92A7-46C2-932B-3109E9DC5824}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA78E270-92A7-46C2-932B-3109E9DC5824}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA78E270-92A7-46C2-932B-3109E9DC5824}.Release|Any CPU.Build.0 = Release|Any CPU + {EDB3405A-58BD-444C-82FF-05FAB7CE72B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDB3405A-58BD-444C-82FF-05FAB7CE72B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDB3405A-58BD-444C-82FF-05FAB7CE72B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDB3405A-58BD-444C-82FF-05FAB7CE72B4}.Release|Any CPU.Build.0 = Release|Any CPU + {A23BA1A3-8EC7-4937-B0AA-69CCEE40453C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A23BA1A3-8EC7-4937-B0AA-69CCEE40453C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A23BA1A3-8EC7-4937-B0AA-69CCEE40453C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A23BA1A3-8EC7-4937-B0AA-69CCEE40453C}.Release|Any CPU.Build.0 = Release|Any CPU + {4938D59D-CF50-4090-B936-36DB29EBE344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4938D59D-CF50-4090-B936-36DB29EBE344}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4938D59D-CF50-4090-B936-36DB29EBE344}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4938D59D-CF50-4090-B936-36DB29EBE344}.Release|Any CPU.Build.0 = Release|Any CPU + {58C01936-5D8F-4077-8663-EE0E35776D65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58C01936-5D8F-4077-8663-EE0E35776D65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58C01936-5D8F-4077-8663-EE0E35776D65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58C01936-5D8F-4077-8663-EE0E35776D65}.Release|Any CPU.Build.0 = Release|Any CPU + {814E42E9-508E-487F-BCD3-0F07AE7D1492}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {814E42E9-508E-487F-BCD3-0F07AE7D1492}.Debug|Any CPU.Build.0 = Debug|Any CPU + {814E42E9-508E-487F-BCD3-0F07AE7D1492}.Release|Any CPU.ActiveCfg = Release|Any CPU + {814E42E9-508E-487F-BCD3-0F07AE7D1492}.Release|Any CPU.Build.0 = Release|Any CPU + {3F5120A6-9CA4-4B25-9507-86E9E5571DB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F5120A6-9CA4-4B25-9507-86E9E5571DB6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F5120A6-9CA4-4B25-9507-86E9E5571DB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F5120A6-9CA4-4B25-9507-86E9E5571DB6}.Release|Any CPU.Build.0 = Release|Any CPU + {79A40AC0-A182-49D0-AED9-DF8B6835432A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79A40AC0-A182-49D0-AED9-DF8B6835432A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79A40AC0-A182-49D0-AED9-DF8B6835432A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79A40AC0-A182-49D0-AED9-DF8B6835432A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {345739E2-E20C-4B1F-B1B2-725006FC9F72} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {12539757-7371-455D-B86B-DAF22F2DEE4E} = {0D42DE24-8D3C-4BE1-BAAE-7543281C3113} + {5F1A7144-C954-4B47-B1FF-820FEA9B6B61} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {1E50F81A-FBFF-4873-9731-FA8835A51080} = {9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5} + {354B3720-D050-487D-A46A-22BCFEE56D43} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {5F7ACBE4-A1D8-4680-AA86-B87F8494BAC2} = {354B3720-D050-487D-A46A-22BCFEE56D43} + {BA79977F-6DCE-4787-9A0D-AF5E61EBC177} = {354B3720-D050-487D-A46A-22BCFEE56D43} + {2B56E8AA-4DAB-4A70-9439-ED16470C0BFE} = {DE39BB20-AE82-47C3-9141-8CFD4C673217} + {9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {DE39BB20-AE82-47C3-9141-8CFD4C673217} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {766CAB38-F064-419F-837B-D6DA8B61AF66} = {DE39BB20-AE82-47C3-9141-8CFD4C673217} + {E8481A4C-0C24-4418-A2C1-742877BE4F0D} = {354B3720-D050-487D-A46A-22BCFEE56D43} + {21064598-1418-422E-BA37-8EC09541DFC1} = {9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5} + {08EF3E38-E0C3-4E18-984C-3216CB6E8897} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {12C94395-09F1-42E4-8CE1-6E54D3FEBAA6} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {955D94B8-747D-4CA4-832A-6377C9FF5B8F} = {9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5} + {FB337B27-C6C6-43A1-BFA5-58B3CF381BA8} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {B8825802-81F7-4671-82E8-3A6E3A21F570} = {9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5} + {7AB71D86-D351-4009-A789-24097897E74A} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {1DE277C2-EE56-4F4D-BB89-71107DE0E4C6} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {166852FC-2F86-4A5B-9029-E16958798DD6} = {9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5} + {61982C8D-5376-45EE-BCC3-D4F9E90AF3B0} = {7AB71D86-D351-4009-A789-24097897E74A} + {FC5E00D1-ABA5-4168-8B8F-FA2A26D84068} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {7CA38535-297B-4DA9-AFF5-3199268EEAF6} = {FC5E00D1-ABA5-4168-8B8F-FA2A26D84068} + {EE426441-DE33-4F3B-B66A-E258AC725B78} = {59F82491-51E3-4A12-B427-9815AEA23D10} + {66A85767-2877-4B99-84F1-EEABC6DC5247} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {CC492CA2-5D86-4DB8-AB15-B118DF27C344} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {4D40321F-2C3F-4ACB-8AE0-7A228DF0551B} = {2864196E-3044-4FEC-B92A-D1D3C521C567} + {7F7D9EE0-7263-4621-BA65-FC470B0F3C6B} = {4E99CBC5-1C74-44E7-9DEF-3FA44CADCCF0} + {45E2ADF5-F386-44CD-A43D-A3AB47E9C39A} = {66A85767-2877-4B99-84F1-EEABC6DC5247} + {4E99CBC5-1C74-44E7-9DEF-3FA44CADCCF0} = {66A85767-2877-4B99-84F1-EEABC6DC5247} + {04E5EDDB-8440-4BAD-9531-F87A3AC826FB} = {4E99CBC5-1C74-44E7-9DEF-3FA44CADCCF0} + {4656C609-DBBA-4F6B-B16F-5E1A8C9D9858} = {2697EEFB-06BE-4786-89C6-A566FD94A41B} + {F7925EED-65E6-4CA2-9B8D-B7036F6DB3E8} = {2697EEFB-06BE-4786-89C6-A566FD94A41B} + {D22C3F6D-434A-4F09-9EB2-B0433CC43642} = {2697EEFB-06BE-4786-89C6-A566FD94A41B} + {257A0A17-5D13-4DA4-8E91-8A3BB2711F49} = {45E2ADF5-F386-44CD-A43D-A3AB47E9C39A} + {4A955BB3-C1AF-45DB-9590-82C00996B608} = {66A85767-2877-4B99-84F1-EEABC6DC5247} + {9A2C7C42-086B-4482-828D-7B02D85372ED} = {4A955BB3-C1AF-45DB-9590-82C00996B608} + {661B88AE-6F83-437C-9A7E-C5C1A565E650} = {45E2ADF5-F386-44CD-A43D-A3AB47E9C39A} + {C99E1554-5039-42BD-B1FD-93814FBEBE44} = {2864196E-3044-4FEC-B92A-D1D3C521C567} + {60424AB5-356A-4623-B1FB-7560334C0BE0} = {4A955BB3-C1AF-45DB-9590-82C00996B608} + {C2A4E6AB-16B9-4457-9445-FFBF672DFBCF} = {4A955BB3-C1AF-45DB-9590-82C00996B608} + {AFB629C5-00C2-492C-8787-C66D810A24DB} = {7AB71D86-D351-4009-A789-24097897E74A} + {648CE3E3-CEC4-4F91-8696-6A3FB2F91220} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {9404B5FE-3431-4EC0-BCC6-42525FC5D1B8} = {648CE3E3-CEC4-4F91-8696-6A3FB2F91220} + {BB24822F-F104-4D8E-9CB5-0A94DEF04BAB} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {EF7BDA1B-22E7-4F3D-97E0-16C9C10AA1B0} = {BB24822F-F104-4D8E-9CB5-0A94DEF04BAB} + {B5305F08-3856-42B5-92D5-6FD446B39931} = {45E2ADF5-F386-44CD-A43D-A3AB47E9C39A} + {88FE7642-27D9-4693-A130-706FCE46194A} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {CA43B145-9DF2-49D3-9371-B88BFB0E846A} = {BB24822F-F104-4D8E-9CB5-0A94DEF04BAB} + {95842BB6-559E-4317-B1E9-FF19D39ADA24} = {648CE3E3-CEC4-4F91-8696-6A3FB2F91220} + {3DE7DD7A-8500-46C9-91A1-A65DB60E0235} = {648CE3E3-CEC4-4F91-8696-6A3FB2F91220} + {8618EE3F-F120-4AEA-8A77-F7BD5DCCB888} = {4E99CBC5-1C74-44E7-9DEF-3FA44CADCCF0} + {D5CF25B2-1A91-4065-A647-06CDF55F4B96} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {2697EEFB-06BE-4786-89C6-A566FD94A41B} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {A6EB05D5-EF38-45B6-960A-0EB759373FDF} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {445850B7-1A9D-4E9D-8AC1-765F3792DC19} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {59F82491-51E3-4A12-B427-9815AEA23D10} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {3ABD7B4B-37F9-4D49-92D9-384190177286} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {577A7F6F-4836-4811-B715-32573127BDB3} = {D5CF25B2-1A91-4065-A647-06CDF55F4B96} + {04EA7A93-CDC7-4C68-815D-699180D99DCE} = {A6EB05D5-EF38-45B6-960A-0EB759373FDF} + {A1186FB9-FB77-427C-9AEC-55E48A8D046A} = {D5CF25B2-1A91-4065-A647-06CDF55F4B96} + {9960FA8A-98C1-45FB-8A09-33CA183AA140} = {D5CF25B2-1A91-4065-A647-06CDF55F4B96} + {E3414144-C19E-40C0-A73A-2FD41AE514D1} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {1855CAB7-6379-47A4-A0A4-F890C6C46403} = {E3414144-C19E-40C0-A73A-2FD41AE514D1} + {C43539A5-8343-4381-B2FD-5323323F1DB6} = {4E99CBC5-1C74-44E7-9DEF-3FA44CADCCF0} + {D3C326CD-F1F1-4E06-962D-47F6C8090DEE} = {A6EB05D5-EF38-45B6-960A-0EB759373FDF} + {13690AB8-9AA4-4936-A25F-7AF1AE3D4ED0} = {A6EB05D5-EF38-45B6-960A-0EB759373FDF} + {244A930D-5B84-4CBC-A3A7-7E8DE1E603D6} = {7D087635-9E77-46B2-B647-962F7E2F8688} + {0EDF10D7-D6D6-48E2-AC0C-BA6D814CB633} = {7D087635-9E77-46B2-B647-962F7E2F8688} + {05D8A63F-B3E1-4A5E-AA66-337BCF8840C1} = {E3414144-C19E-40C0-A73A-2FD41AE514D1} + {3993A838-71C9-49C5-80B3-16CC48A5F5C9} = {E3414144-C19E-40C0-A73A-2FD41AE514D1} + {D785A240-1115-41C8-943E-5058161D6478} = {7D087635-9E77-46B2-B647-962F7E2F8688} + {B1952639-773B-4C82-9D95-7CB4ED8AC59E} = {E3414144-C19E-40C0-A73A-2FD41AE514D1} + {29792C72-565A-46DF-B887-494AC5352818} = {664F0DBE-CB31-4D63-858A-8C7E6411C76C} + {C57D22E0-075B-4F27-87F1-E6CF5F203975} = {BB24822F-F104-4D8E-9CB5-0A94DEF04BAB} + {B9B66159-4FC7-4F94-8C21-ADC8CCED84F4} = {BB24822F-F104-4D8E-9CB5-0A94DEF04BAB} + {24FFA5F1-37CD-408B-80A9-006B5A6E11E8} = {BB24822F-F104-4D8E-9CB5-0A94DEF04BAB} + {6FE28297-B958-4BC5-A320-A531874D7F58} = {BB24822F-F104-4D8E-9CB5-0A94DEF04BAB} + {838A27C6-F125-4C61-923E-7C855B598FBD} = {BB24822F-F104-4D8E-9CB5-0A94DEF04BAB} + {FDE43241-3C82-4005-87B3-FD1349FEF4B6} = {664F0DBE-CB31-4D63-858A-8C7E6411C76C} + {878A2744-5122-48A7-90E6-7D8CFABC29FD} = {4A955BB3-C1AF-45DB-9590-82C00996B608} + {0C464725-DEDC-4894-84A3-7A155E43818B} = {4A955BB3-C1AF-45DB-9590-82C00996B608} + {AC831843-CDE2-4B67-8BC5-8F2A0D09B273} = {664F0DBE-CB31-4D63-858A-8C7E6411C76C} + {2BE691A3-19C0-4FCF-85D2-D2371C9462C6} = {4E99CBC5-1C74-44E7-9DEF-3FA44CADCCF0} + {B140F739-EC51-4265-B4B8-59467606E6EE} = {7D087635-9E77-46B2-B647-962F7E2F8688} + {00E8EE51-A263-4971-9431-C4A2DEA4993A} = {E3414144-C19E-40C0-A73A-2FD41AE514D1} + {6B2BA282-5C97-4A71-885F-E5259274F714} = {4E99CBC5-1C74-44E7-9DEF-3FA44CADCCF0} + {05CF624D-F42E-461A-A21D-41BEE0CCEB5C} = {E3414144-C19E-40C0-A73A-2FD41AE514D1} + {C4A782C1-AA25-476B-B936-90433422D0A2} = {7D087635-9E77-46B2-B647-962F7E2F8688} + {D9E411DD-58B1-4160-8025-068D43ADE72C} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {B2AADB36-8433-4EDB-B247-49A3EA82FE06} = {54800E45-FF91-4091-A146-EFA5432A6443} + {40F2A962-6209-42D0-9F21-CEACB411007B} = {54800E45-FF91-4091-A146-EFA5432A6443} + {22E49D65-F51D-4A45-A35E-B27FF7DE6787} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {B85E8FC7-748E-4990-9279-1F06E095B6E6} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {4170A699-C110-4136-92EA-D2BFEBF68230} = {22E49D65-F51D-4A45-A35E-B27FF7DE6787} + {78B9EC26-ADC5-4934-9F31-000D4D678121} = {22E49D65-F51D-4A45-A35E-B27FF7DE6787} + {027B0175-2D22-4168-A0B4-1E0DC5BE2A61} = {B85E8FC7-748E-4990-9279-1F06E095B6E6} + {EA4C219B-D00A-4BDB-A787-A79FA9611303} = {BB24822F-F104-4D8E-9CB5-0A94DEF04BAB} + {B40CD480-D4A0-4A43-B855-0CD84EC537CC} = {354B3720-D050-487D-A46A-22BCFEE56D43} + {C3C7C037-B5B6-4CE0-BC02-820667D74F60} = {DE39BB20-AE82-47C3-9141-8CFD4C673217} + {48F77D8F-60AE-4173-BA74-FC2E0B3578BB} = {9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5} + {76AA6040-AA3A-43DD-BD4B-7F931271BFD6} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {6493D592-7930-4979-A07D-B7CAA751C7BE} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {4E12B03E-D607-492E-BB28-96235993A39F} = {76AA6040-AA3A-43DD-BD4B-7F931271BFD6} + {D2F38ACB-7158-4DE0-BDEA-B13E3D52A655} = {6493D592-7930-4979-A07D-B7CAA751C7BE} + {1272E006-8D8B-46B5-AD18-2E31CA9C6CBD} = {76AA6040-AA3A-43DD-BD4B-7F931271BFD6} + {E0D77981-E412-477D-B866-E43F055CAAFC} = {76AA6040-AA3A-43DD-BD4B-7F931271BFD6} + {66B96C01-6A08-4C7A-B5F5-A0489D8BBB47} = {6493D592-7930-4979-A07D-B7CAA751C7BE} + {8BC69296-3C9A-45B3-B6C3-3DD575027CCD} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {B25D3B7A-AEAA-4EFB-9839-7C6E3F7C24BB} = {9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5} + {1F5EE147-BD88-4B6D-BA84-35B4F3BE4A4E} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {22305349-51C7-4D80-A538-C7C0F4495895} = {1F5EE147-BD88-4B6D-BA84-35B4F3BE4A4E} + {54800E45-FF91-4091-A146-EFA5432A6443} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {664F0DBE-CB31-4D63-858A-8C7E6411C76C} = {CC492CA2-5D86-4DB8-AB15-B118DF27C344} + {7D087635-9E77-46B2-B647-962F7E2F8688} = {CC492CA2-5D86-4DB8-AB15-B118DF27C344} + {2864196E-3044-4FEC-B92A-D1D3C521C567} = {CC492CA2-5D86-4DB8-AB15-B118DF27C344} + {96DFADC5-FAE8-4860-A57A-93F0534B1B7A} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {5921A7FA-8C70-49A9-82E1-BE3FA5B50C33} = {96DFADC5-FAE8-4860-A57A-93F0534B1B7A} + {599BAD8E-DB56-4967-8DDE-74BD21DA2B49} = {1F5EE147-BD88-4B6D-BA84-35B4F3BE4A4E} + {75A31AAB-B7E6-4F13-9B7A-B74216B2EDDE} = {96DFADC5-FAE8-4860-A57A-93F0534B1B7A} + {411247A4-4665-4BE6-8E5C-08F6D0BA2213} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {36990D32-6F41-44A6-BB88-A3F15E12C35B} = {411247A4-4665-4BE6-8E5C-08F6D0BA2213} + {21831A4F-B3C9-40E7-855B-75F9D679FF55} = {411247A4-4665-4BE6-8E5C-08F6D0BA2213} + {F7D4E7CB-468D-4570-8D82-D065F08BE40D} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {5996F536-14B9-4F95-A18B-716E5F7EE478} = {F7D4E7CB-468D-4570-8D82-D065F08BE40D} + {E069CEB0-8092-4907-BC9D-C6B8BDE20AD2} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {6FC29D15-7581-4E29-9897-76DC5AEF2042} = {E069CEB0-8092-4907-BC9D-C6B8BDE20AD2} + {3E81F8D0-06C7-4FD4-A5B0-E3D96E909646} = {E069CEB0-8092-4907-BC9D-C6B8BDE20AD2} + {C233FF83-E15D-4A17-8FF1-BBFF9E9DE210} = {E069CEB0-8092-4907-BC9D-C6B8BDE20AD2} + {16175228-03CA-414A-8786-E5BA844110C4} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {AB2D6B9A-0EC8-402B-849A-95E826B09AB3} = {16175228-03CA-414A-8786-E5BA844110C4} + {87B6EF51-9F1B-4A81-9764-F359138B774D} = {445850B7-1A9D-4E9D-8AC1-765F3792DC19} + {4FFD1073-9358-418D-BB4D-DB63FE0A11DF} = {445850B7-1A9D-4E9D-8AC1-765F3792DC19} + {5BFF8BA0-EA27-4493-88A5-5BC57286D536} = {F7D4E7CB-468D-4570-8D82-D065F08BE40D} + {FB11256C-06C0-4B24-863A-C87D78F8EE2A} = {3ABD7B4B-37F9-4D49-92D9-384190177286} + {547FD391-A56B-47A6-B20C-5FC04FA15C56} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {6233BF36-9636-43BD-9462-2D31A05EE4ED} = {59F82491-51E3-4A12-B427-9815AEA23D10} + {1DEC52C8-6692-4DA7-AE34-B76D728F895A} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {F8417623-6936-43C4-A967-9D6BD002AD16} = {1DEC52C8-6692-4DA7-AE34-B76D728F895A} + {CAA32331-4A8E-4C16-BC7D-7CA646B393F4} = {1DEC52C8-6692-4DA7-AE34-B76D728F895A} + {08B1A026-4F8C-4336-B5B8-3189023DFF2B} = {547FD391-A56B-47A6-B20C-5FC04FA15C56} + {0BCB6FF1-E374-4AED-9888-83C7CFED0E98} = {1DEC52C8-6692-4DA7-AE34-B76D728F895A} + {DF1E55A5-7EA8-41B2-BEBA-72544D256069} = {547FD391-A56B-47A6-B20C-5FC04FA15C56} + {9C58E50F-0589-4A4E-B94D-2EC0BF02F61F} = {1DEC52C8-6692-4DA7-AE34-B76D728F895A} + {AE19ED93-AFC4-4F91-93BD-B00D343D3BA0} = {547FD391-A56B-47A6-B20C-5FC04FA15C56} + {5D74BD1D-3142-4478-9062-4543FADA3E91} = {547FD391-A56B-47A6-B20C-5FC04FA15C56} + {B737883C-9450-46CB-B81C-1A3405071D04} = {547FD391-A56B-47A6-B20C-5FC04FA15C56} + {156447ED-8515-4FB0-8B5A-D5A3A1E43AC6} = {98F1FEAD-AFD5-4744-8A55-C57920461EB9} + {DE51B662-C843-4E99-87F8-F367504D5640} = {835A8155-411B-4DF2-AE58-D3FDEFB61E63} + {98F1FEAD-AFD5-4744-8A55-C57920461EB9} = {C01B9930-D67F-41C5-90C9-C87DC53F39CB} + {835A8155-411B-4DF2-AE58-D3FDEFB61E63} = {E6328DC1-C8F0-4DC6-941F-C6CAFFF783DF} + {0C062400-58D1-4EE3-8EBB-C5B3AAEECF87} = {98F1FEAD-AFD5-4744-8A55-C57920461EB9} + {FA6AF0F1-B4EE-4E46-B933-9573861A10FC} = {59F82491-51E3-4A12-B427-9815AEA23D10} + {4FECE655-7B06-4DED-BED0-B67731A43E0B} = {3ABD7B4B-37F9-4D49-92D9-384190177286} + {6A84E4B0-3A9C-4B40-9B64-AD3A26324DAC} = {835A8155-411B-4DF2-AE58-D3FDEFB61E63} + {9B941AF9-34A0-4DFF-80F8-0418E212659A} = {54800E45-FF91-4091-A146-EFA5432A6443} + {A44B570E-0676-4003-A827-E910A9332DEA} = {664F0DBE-CB31-4D63-858A-8C7E6411C76C} + {00C518D5-EFAC-43CC-AD1E-9837BDBD93BB} = {4A955BB3-C1AF-45DB-9590-82C00996B608} + {698AE3A0-65E3-433C-B56C-7D47A7A44263} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {BA78E270-92A7-46C2-932B-3109E9DC5824} = {9BFB5DBE-8F64-45A9-BDB2-BAD91D44A4C5} + {EDB3405A-58BD-444C-82FF-05FAB7CE72B4} = {345739E2-E20C-4B1F-B1B2-725006FC9F72} + {A23BA1A3-8EC7-4937-B0AA-69CCEE40453C} = {16175228-03CA-414A-8786-E5BA844110C4} + {4938D59D-CF50-4090-B936-36DB29EBE344} = {E069CEB0-8092-4907-BC9D-C6B8BDE20AD2} + {58C01936-5D8F-4077-8663-EE0E35776D65} = {16175228-03CA-414A-8786-E5BA844110C4} + {814E42E9-508E-487F-BCD3-0F07AE7D1492} = {E069CEB0-8092-4907-BC9D-C6B8BDE20AD2} + {3F5120A6-9CA4-4B25-9507-86E9E5571DB6} = {1F5EE147-BD88-4B6D-BA84-35B4F3BE4A4E} + {79A40AC0-A182-49D0-AED9-DF8B6835432A} = {96DFADC5-FAE8-4860-A57A-93F0534B1B7A} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {94347832-A36D-4C42-9C4D-B848BD4F5DA9} + EndGlobalSection +EndGlobal diff --git a/build/Build.csproj b/build/Build.csproj new file mode 100644 index 000000000..154b7d157 --- /dev/null +++ b/build/Build.csproj @@ -0,0 +1,17 @@ + + + + $(NetTargetFramework) + + + + + + + + + + + + + diff --git a/build/BuildScript.cs b/build/BuildScript.cs new file mode 100644 index 000000000..b995f676f --- /dev/null +++ b/build/BuildScript.cs @@ -0,0 +1,229 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using FlubuCore.Context; +using FlubuCore.Context.Attributes.BuildProperties; +using FlubuCore.Context.FluentInterface.Interfaces; +using FlubuCore.IO; +using FlubuCore.Scripting; + +namespace Build { + /// + /// 构建脚本 + /// + public class BuildScript : DefaultBuildScript { + /// + /// 解决方案文件名 + /// + [SolutionFileName] + public string SolutionFileName { get; set; } = "../Util.sln"; + /// + /// 构建配置 + /// + [FromArg( "c|configuration" )] + [BuildConfiguration] + public string BuildConfiguration { get; set; } = "Release"; + /// + /// Nuget推送地址 + /// + [FromArg( "nugetUrl" )] + public string NugetUrl { get; set; } = "https://api.nuget.org/v3/index.json"; + /// + /// Nuget密钥 + /// + [FromArg( "nugetKey", "Nuget api key for publishing nuget packages." )] + public string NugetApiKey { get; set; } + /// + /// 源代码目录 + /// + public FullPath SourceDir => RootDirectory.CombineWith( "../src" ); + /// + /// 测试目录 + /// + public FullPath TestDir => RootDirectory.CombineWith( "../test" ); + /// + /// 输出目录 + /// + public FullPath OutputDir => RootDirectory.CombineWith( "../output" ); + /// + /// 项目文件列表 + /// + public List Projects { get; set; } + /// + /// 单元测试项目文件列表 + /// + public List UnitTestProjecs { get; set; } + /// + /// 集成测试项目文件列表 + /// + public List IntegrationTestProjecs { get; set; } + /// + /// 忽略测试项目文件列表 + /// + public List IgnoreTestProjecs { get; set; } + /// + /// 忽略打包项目文件列表 + /// + public List IgnorePackProjecs { get; set; } + + /// + /// 获取集成测试项目文件列表 + /// + protected List GetIntegrationTestProjecs() { + return IntegrationTestProjecs.Where( t => IgnoreTestProjecs.Exists( p => p.FileName == t.FileName ) == false ).ToList(); + } + + /// + /// 获取打包项目文件列表 + /// + protected List GetPackProjecs() { + return Projects.Where( t => IgnorePackProjecs.Exists( p => p.FileName == t.FileName ) == false ).ToList(); + } + + /// + /// 构建前操作 + /// + /// 构建任务上下文 + protected override void BeforeBuildExecution( ITaskContext context ) { + Projects = context.GetFiles( SourceDir, "*/*.csproj" ); + UnitTestProjecs = context.GetFiles( TestDir, "*/*.Tests.csproj" ); + IntegrationTestProjecs = context.GetFiles( TestDir, "*/*.Tests.Integration.csproj" ); + IgnoreTestProjecs = new List(); + IgnorePackProjecs = new List(); + AddIgnoreTestProjecs( context ); + AddIgnorePackProjecs( context ); + } + + /// + /// 添加忽略测试项目文件列表 + /// + private void AddIgnoreTestProjecs( ITaskContext context ) { + IgnoreTestProjecs.AddRange( context.GetFiles( TestDir, "*/Util.Images.*.Tests.Integration.csproj" ) ); + IgnoreTestProjecs.AddRange( context.GetFiles( TestDir, "*/*.Oracle.Tests.Integration.csproj" ) ); + IgnoreTestProjecs.AddRange( context.GetFiles( TestDir, "*/Util.Data.Dapper.PostgreSql.Tests.Integration.csproj" ) ); + IgnoreTestProjecs.AddRange( context.GetFiles( TestDir, "*/*.Dapr.Tests.Integration.csproj" ) ); + } + + /// + /// 添加忽略打包项目文件列表 + /// + private void AddIgnorePackProjecs( ITaskContext context ) { + IgnorePackProjecs.AddRange( context.GetFiles( SourceDir, "*/*.WebApiClient.csproj" ) ); + } + + /// + /// 配置构建目标 + /// + /// 构建任务上下文 + protected override void ConfigureTargets( ITaskContext context ) { + var clean = Clean( context ); + var restore = Restore( context, clean ); + var build = Build( context, restore ); + var test = Test( context ); + var pack = Pack( context, clean ); + PublishNuGetPackage( context, pack ); + } + + /// + /// 清理解决方案 + /// + private ITarget Clean( ITaskContext context ) { + return context.CreateTarget( "clean" ) + .SetDescription( "Clean the solution." ) + .AddCoreTask( t => t.Clean().AddDirectoryToClean( OutputDir, false ) ); + } + + /// + /// 还原包 + /// + private ITarget Restore( ITaskContext context, params ITarget[] dependTargets ) { + return context.CreateTarget( "restore" ) + .SetDescription( "Restore the solution." ) + .DependsOn( dependTargets ) + .AddCoreTask( t => t.Restore() ); + } + + /// + /// 编译解决方案 + /// + private ITarget Build( ITaskContext context, params ITarget[] dependTargets ) { + return context.CreateTarget( "compile" ) + .SetDescription( "Compiles the solution." ) + .DependsOn( dependTargets ) + .AddCoreTask( t => t.Build() ); + } + + /// + /// 运行测试 + /// + private ITarget Test( ITaskContext context, params ITarget[] dependTargets ) { + var unitTest = UnitTest( context, dependTargets ); + var integrationTest = IntegrationTest( context, dependTargets ); + return context.CreateTarget( "test" ) + .SetDescription( "Run all tests." ) + .DependsOn( unitTest, integrationTest ); + } + + /// + /// 运行单元测试 + /// + private ITarget UnitTest( ITaskContext context, params ITarget[] dependTargets ) { + return context.CreateTarget( "unit.test" ) + .SetDescription( "Run unit tests." ) + .DependsOn( dependTargets ) + .ForEach( UnitTestProjecs, ( project, target ) => { + target.AddCoreTask( t => t.Test().Project( project ) ); + } ); + } + + /// + /// 运行集成测试 + /// + private ITarget IntegrationTest( ITaskContext context, params ITarget[] dependTargets ) { + return context.CreateTarget( "integration.test" ) + .SetDescription( "Run integration tests." ) + .DependsOn( dependTargets ) + .ForEach( GetIntegrationTestProjecs(), ( project, target ) => { + target.AddCoreTask( t => t.Test().Project( project ) ); + } ); + } + + /// + /// 创建nuget包 + /// + private ITarget Pack( ITaskContext context, params ITarget[] dependTargets ) { + return context.CreateTarget( "pack" ) + .SetDescription( "Create nuget packages." ) + .DependsOn( dependTargets ) + .ForEach( GetPackProjecs(), ( project, target ) => { + target.AddCoreTask( t => t.Pack() + .Project( project ) + .IncludeSymbols() + .OutputDirectory( OutputDir ) ); + } ); + } + + /// + /// 发布nuget包 + /// + private void PublishNuGetPackage( ITaskContext context, params ITarget[] dependTargets ) { + context.CreateTarget( "nuget.publish" ) + .SetDescription( "Publishes nuget packages" ) + .DependsOn( dependTargets ) + .Do( t => { + var packages = Directory.GetFiles( OutputDir, "*.nupkg" ); + foreach ( var package in packages ) { + if( package.EndsWith( "symbols.nupkg", StringComparison.OrdinalIgnoreCase ) ) + continue; + context.CoreTasks().NugetPush( package ) + .DoNotFailOnError( ex => { Console.WriteLine( $"Failed to publish {package}.exception: {ex.Message}" ); } ) + .ServerUrl( NugetUrl ) + .ApiKey( NugetApiKey ) + .SkipDuplicate() + .Execute( context ); + } + } ); + } + } +} \ No newline at end of file diff --git a/build/common.props b/build/common.props new file mode 100644 index 000000000..08ea70dcb --- /dev/null +++ b/build/common.props @@ -0,0 +1,19 @@ + + + + net8.0 + + + Util Application Framework + ncc;何镇汐 + ncc;何镇汐 + xiadao521@qq.com + https://github.com/dotnetcore/Util + https://github.com/dotnetcore/Util + git + Util应用框架以MIT开源发布,可随意使用 + MIT + https://avatars2.githubusercontent.com/u/19421630 + util;applicationframework;dotnetcore;aspnetcore; + + \ No newline at end of file diff --git a/build/icon.jpg b/build/icon.jpg new file mode 100644 index 000000000..b591214cc Binary files /dev/null and b/build/icon.jpg differ diff --git a/build/version.props b/build/version.props new file mode 100644 index 000000000..e526b26c3 --- /dev/null +++ b/build/version.props @@ -0,0 +1,9 @@ + + + 8 + 0 + 19 + $(VersionMajor).$(VersionMinor).$(VersionPatch) + + + \ No newline at end of file diff --git a/clear-bin.ps1 b/clear-bin.ps1 new file mode 100644 index 000000000..719b86c28 --- /dev/null +++ b/clear-bin.ps1 @@ -0,0 +1,3 @@ +Write-Host "remove bin,obj..." +Get-ChildItem .\ -include bin,obj -Recurse | foreach ($_) { remove-item $_.fullname -Force -Recurse } +Write-Host "remove completed." \ No newline at end of file diff --git a/readme.md b/readme.md index 37eca4273..000441d5f 100644 --- a/readme.md +++ b/readme.md @@ -1,470 +1,714 @@ # Util应用框架介绍 -[](https://github.com/dotnetcore) +[](https://github.com/dotnetcore) [](https://mit-license.org/) -Util是一个.net core平台下的应用框架,旨在提升小型团队的开发输出能力,由常用公共操作类(工具类)、分层架构基类、Ui组件,第三方组件封装,第三方业务接口封装,配套代码生成模板,权限等组成。 + + + -## 引子 -几年前我在博客园写了一个 [应用程序框架实战](https://www.cnblogs.com/xiadao521) 的系列文章,受到不少.net同学的青睐,不过由于种种原因(想写的范围过大,技术更新过快,工作忙,人越来越懒,好吧,我承认主要是最后一点)而烂尾。 +## 什么是Util应用框架? -我在博客中放出过一些示例代码,由于未正式开源,修复过的bug也未能更新,所以将博客中提供的示例项目都删除了。 +Util是一个.Net平台下的应用框架,旨在提升中小团队的开发能力,由工具类、分层架构基类、Ui组件,配套代码生成模板,权限等组成。 -一些同学将这些代码应用在项目上,当碰到问题时,由于没有技术支持,也没有相关教程,苦不堪言。而另外一些同学没有下载到示例项目。 +## Util应用框架的作者: **何镇汐** -虽然博客断更2年,但时常有同学通过加QQ或发EMAIL的方式联系我,希望能够得到最新代码,并对用法和设计思路进行讲解。 +Util应用框架的主要作者为何镇汐。 -.net core发展迅猛,它为.net提供了更广阔的竞争力,同时也意味着新一轮的学习与代码移植工作开始,我也在这个大潮中跌跌撞撞的摸索着。 +## Util应用框架的开源协议: **MIT** -几位好友([AlexLEWIS](https://github.com/alexinea "刘怡") [Kiler](https://github.com/kiler398 "谢炀") [Lemon](https://github.com/liuhaoyang "刘浩杨") )发起了.net core学习小组,并打算为国内.net core开源大业作出贡献,我果断加入了队伍进行学习,并决定对Util应用框架进行开源。 +这是最宽松的开源协议,意味着可以以任何方式使用该代码。 -经讨论,大家决定将各自的开源项目统一发布到 [.NET China Foundation](https://github.com/dotnetcore) 之下,以方便国内.net core开源项目的推广,同时也欢迎国内.net core开源项目作者的加入。 +## Util应用框架的主要贡献者 -## 技术框架与应用框架 +[汪总](https://github.com/jianxuanbing "简楚恩") [胡兴业](https://github.com/huxingye) -框架是一种可复用的基础代码库,如果它只解决纯技术问题,可以认为是技术框架,如果它与你的业务相关,则可认为是应用框架(框架,应用框架均没有标准定义,我在此以个人理解描述术语含义,以方便后续讨论,并非权威定义)。 +这里只列出了主要贡献者,还有很多开发人员以不同形式对Util做出了宝贵贡献。 -.net提供的基础类库是最基础的技术框架,它提供了进行.net开发所需要的基础API,这些API都比较原始。完全使用原始API进行项目开发,会导致高昂的学习成本,更多的Bug,难以维护的重复代码,低效的开发进度。 +## Util应用框架的目标: **让开发更简单** -为了完成某项特定的技术需求,比如写日志,你可以使用原始API进行简单实现,并在多个地方复制粘贴进行调用。这很快会让你厌烦,除了冗余代码以外,你发现还需要经常扩展日志操作的功能,于是你想把日志操作封装成库来调用。 +Util应用框架让你的团队迅速进入业务开发状态,并在开发过程中持续提供帮助。 -等等,不要再重复造轮子了(为了学习目的造轮子,这绝对是值得肯定的,但确实准备拿来使用的,如果不是真有几把刷子,比如 [Lemon](https://github.com/liuhaoyang "刘浩杨") 同学,建议还是省省吧),一些前辈已经做了这些基础工作,并且他们的工作已经在全球大范围的使用,非常成熟,并且持续维护。 +## Util应用框架的特点: **简单易用** -这些能够解决特定技术问题的类库暂时统称为第三方技术框架,在项目上使用第三方技术框架是项目成功的必要保障。从此,你不再为如何实现某项技术问题而烦恼,也不需要为持续扩展的技术需求而疲于奔命,更多的精力被用在业务上,这才是你应该干的事。 +Util应用框架的设计理念是追求Api简单化,尽量少的配置,不用精确记忆Api,有个模糊印象即可使用。 -对于你的项目,每当碰到某种技术障碍时,你会四处打听有没有某个第三方技术框架解决了你的问题,找到以后,你通过调试一些Demo代码,简单的用起来了。每当需要这个功能的时候,你会从以前的代码复制粘贴,由于第三方技术框架已经高度封装,所以冗余代码不是特别显著,你没有理会它。 +Util应用框架的学习成本相对较低,对于有.Net基础的开发人员,进行常规业务开发,通常在3天内上手。 -如果你的团队并不经常沟通,处理同一问题的过程将在团队中反复发生,这将导致对于某个问题的技术实现不一致,并且付出高昂的学习成本。当调用代码被大量的复制粘贴后,如果发现调用代码有Bug,或需要增加一些健壮性,你才意识到虽然第三方技术框架已经比较完善,但对它的调用依然有封装的必要。 +## Util应用框架开发流程 -你开始封装一些经常需要操作的代码,这些代码可能是用.net原始Api封装的,也可能是封装了第三方技术框架的调用,这些封装好的代码被称为公共操作类,也叫工具类。 +> *搜集* - *整理* - *集成* - *封装* -对于最基础的Crud和业务代码的结构,你发现也可以抽取出来,形成分层架构基类。 +每当发现无法满足项目需求时,扩展框架的时刻来临。 -你的项目可能需要在网页上进行开发,采用原始的html,css,js技术,将面临界面美观,浏览器兼容性,开发效率低下等问题,有第三方技术框架提供了相关的解决方案,比如EasyUi,Bootstrap,Angularjs,ReactJs等。将第三方UI框架集成并封装起来,能够显著提升开发效率。 +从头造轮子是下策,所以总是先四处**搜集**相关资料。对于简单的需求,可能只需要找到一些代码片断即可。对于更专业的问题,需要寻求第三方技术框架的帮助。 -如果在项目中,你需要实现支付等业务功能,你可以对这些第三方业务接口进行封装。 +找到解决方案并调试通过后,需要对代码进行**整理**,以符合我们的编程风格。 -对于常规的项目,总是需要一些通用模块,比如权限,将它作为后续项目的起点是一个好主意。 +通常以Nuget包或Npm包的方式进行**集成**,为了降低学习成本,需要仔细考虑如何**封装**才能让调用者最省力。 -当这些基础代码被高度封装后,常规的Crud代码变得非常简洁,但你还是需要复制这些基础结构,通过反复整理,可以得到一个代码模板,通过代码生成工具将基础的Crud代码生成出来,可以大幅提升生产力。 +> 任何有技术含量的工作,均由第三方技术框架完成,Util应用框架仅对技术框架选型并集成封装。 +> +> Util应用框架只是很薄的一层外观,为复杂的技术框架提供一个简易视图。 +> +> 这导致更健壮的实现和更易用的API。 -这个持续封装过程演变为一套项目开发模式,支持这套模式的所有基础代码库,我将它称之为应用框架。 +## Util应用框架的使用方式 -应用框架为你项目的所有方面提供支持,你需要不断的完善它。由于应用框架需要解决你项目上的所有问题,所以没有绝对通用和包罗万象的应用框架,你必须在这些应用框架之上进行扩展。 +使用Util应用框架有几种不同的方式。 -## Util的由来 +最灵活的方式是将Util应用框架的代码复制到你自己的应用框架中,然后可以随意修改它们来满足项目需求。 -Util是我在.net开发生涯中不断积累而成的一套应用框架,最初的名字叫CommonUtilities,这是一个基本由公共操作类构成的类库。 +不过这种方式的代价也很大,很难合并Util的任何更新,你需要自行维护相当大的代码库。 -随着经验和水平的上升,我根据自己的习惯,逐步实现了经典图书中某些概念(比如规约),并吸收了一些流行应用框架( 比如 [ABP](https://github.com/aspnetboilerplate/aspnetboilerplate) [Nop](https://www.nopcommerce.com) )的部分代码。 +由于Util应用框架的体积在不断增长,维护这些代码库可能给你带来不小的负担。 -Util并不是一个完善的应用框架,我总是根据自己项目上的需求来扩展它,所以它基本只是为了满足我个人习惯和项目的产物。 +另一种可行的方式是将Util应用框架作为你的基础库,使用Nuget引入它们,基础的工作让Util应用框架帮你完成,你只需要扩展自己业务领域相关的功能。 -由于技术更新异常迅速,多年来大量的代码被持续重构,还有更多的代码被抛弃,这也是Util不完善的一个重要原因。 +这种方式的限制也很明显,Util提供的功能可能无法满足你的要求。 -发布Util的目的,是希望帮助技术还比较落后的.net小型团队能够搭建出自己的应用框架,提供一个示范,同时也希望它成为跟我有相似开发习惯和偏好的.net同学的重要工具。 +解决这个问题的关键是与Util开发团队保持沟通,将你的需求告诉我们。 -## 愿景 +对于通用功能,我们会尽量满足,这样会让更多的开发者受益,对于定制需求,我们也会为你提供扩展点,方便你能自行扩展。 -让开发更简单 +## 框架核心 -## 承诺 +- ### 启动器 -不必担心再次断更,代码会持续更新,使用文档将由Util核心开发团队成员编写,我会补充一些设计方面的文档上来。 +Util应用框架在项目启动时,会扫描全部程序集,并自动执行服务注册器,执行相关依赖配置. -## 特点 +启动器核心代码参考自 [NopCommerce](https://www.nopcommerce.com) . -**简单易用**的傻瓜式API设计,让你的团队能够快速上手进行开发。对于简单操作,通常采用静态方法或扩展方法进行调用,对于更加复杂的操作,尽量封装为链式API。 +- ### 服务注册器 -**强类型(*静态类型*)** 化风格,将UI组件封装为asp.net core razor组件,充分发挥VS开发工具的优势,比如智能提示,编译时检查。 +项目启动扫描时,会加载所有的服务注册器,并按顺序执行. -**代码整洁**,Util开发小组成员都有着代码洁癖,每行代码都经过反复斟酌。 +> 服务注册器类似其它应用框架的模块概念,但功能有限. +> +> 只能用于配置依赖注入关系,无法获取服务提供程序,所以不能执行复杂的操作. -地道的**中国味**,Util开发小组成员的英文水平比较菜,命名充满国风,并以中文注释进行补充。 +- ### 依赖注册器 -## 面向群体 +扫描 ISingletonDependency, IScopeDependency, ITransientDependency 接口,并自动配置依赖. -Util应用框架面向的是*架构初学者*,但不是.net初学者。 +## 框架基础 -如果你是.Net初学者,基本的Crud(增删改查)尚且完成不了,请缓一年再来。 +- ### 对象到对象映射 -你可能已经有了一些项目经验,甚至已经开发多年,但你的项目依然进度缓慢,很难按时交付,代码质量糟糕,难以继续维护,你迫切希望找到一种方法来改善这个过程,Util就是为你准备的。 +技术选型: [AutoMapper](http://automapper.org/). -如果你手里没有任何积累,Util将是你搭建自己框架的一个很好的起点。 +对象到对象映射主要用于分层对象之间的转换,比如从实体映射到DTO. -如果你已经身经百战,自己的框架也比较成熟,Util对你的帮助不会太大。 +Util 在所有对象上添加 **MapTo** 扩展方法,自动完成基础配置,如果映射的两端对象属性名相同,则无需配置,直接使用即可. -如果你对API的英文语法要求很高,Util可能无法达到你的要求,请自行修改命名或远离它。 +- ### AOP( 面向切面编程 ) -## 使用方式 +技术选型: [AspectCore](https://github.com/dotnetcore/AspectCore-Framework). -我推荐的方式是搭建你自己的应用框架,逐步吸收Util和其它应用框架的代码,但这需要你投入大量的学习时间。 +AOP用于在调用方法时进行拦截,在执行前后添加自定义逻辑. -我会逐步更新框架代码,当时机成熟时,将提供一个示例应用程序供大家参考。 +Util 主要使用AOP拦截器进行验证. -在把框架完全应用到你的项目之前,你的团队至少要有一名成员能够根据项目需求进行扩展。对于懒汉,通常希望拿到一套干货,直接在项目上当成黑盒来使用,除非你的项目异常简单,否则这种方式不可取。 +- ### 对象验证 -对于简单的操作,你可以运行和阅读相应单元测试代码,即可了解它们如何使用。对于复杂操作,一方面看单元测试,另外我们会编写相关文档以描述调用方式和工作机制。 +Util 使用 DataAnnotation 注解作为基础验证方式,并提供 **验证规则** 和 **验证处理器** 等构造块进行自定义验证和处理. -## 开发环境及类库依赖 +Util 在实体,DTO等对象上添加了 **Validate** 方法, 以标准化的方式进行对象验证. -以下是我们在项目开发和部署时使用的工具和组件,这个列表会经常更新。 +- ### 异常处理 -> 如果没有标注版本号,则采用最新版本。 +Util 提供了 **Warning** 类型,表示业务异常,并封装相关异常操作. -1. 开发工具: - - Visual Studio 2017 - - Resharper +- ### 身份认证和授权 -2. 数据库 - - Sql Server - - Mysql - - PostgreSQL +技术选型: [Identity](https://learn.microsoft.com/zh-cn/aspnet/core/security/authentication/identity), [Identity Server 4](https://github.com/IdentityServer/IdentityServer4) -3. 设计工具 - - PowerDesigner 16.5 - - XMind +Identity 是Asp.Net Core自带的身份认证框架,提供用户管理,登录认证等功能. -4. 版本控制 - - Git +> Identity Server 4 是一个身份认证服务器,用于颁发令牌和验证令牌等操作. +> +> Identity Server 4 已经停止更新,它的新版本是收费的,Util 仅使用 Identity Server 4 的基础功能,由于它的基础功能已经十分稳定,暂时不需要迁移到其它框架. -5. 部署环境 - - Ubuntu Server - - Docker +Util 除了集成 Identity 和 Identity Server 4,还扩展了Asp.Net Core自定义授权策略,提供简单易行的Api访问控制方法. -6. 开发平台 - - .Net Core 2.0 +Util Platform提供了基于角色和资源的权限管理功能,可以轻松设置前端UI菜单和按钮等权限,同时对后端API进行访问控制. -7. 单元测试及模拟框架 - - XUnit - - NSubstitute +- ### 本地化 -8. ORM - - EntityFrameworkCore 2.0 - - Microsoft.EntityFrameworkCore.SqlServer 2.0.0 - - Npgsql.EntityFrameworkCore.PostgreSQL 2.0.0 - - Pomelo.EntityFrameworkCore.MySql 2.0.x +技术选型: [My.Extensions.Localization.Json](https://github.com/hishamco/My.Extensions.Localization.Json) -9. Ioc框架 - - Autofac +Util 本地化支持Json文件或自定义数据存储方式. -10. Aop框架 - - [AspectCore](https://github.com/dotnetcore/AspectCore-Framework) +My.Extensions.Localization.Json 提供了Json本地化功能. -11. Json框架 - - Newtonsoft.Json( 即Json.Net ) +由于无法满足项目需求, 以源码方式引入, 对健壮性和性能进行了提升. -12. 映射框架 - - AutoMapper +- ### 日志 -13. 日志框架 - - [NLog](http://nlog-project.org/) - - [Exceptionless](https://github.com/exceptionless) +技术选型: [Serilog](https://serilog.net/), [Seq](https://datalust.co/), [Exceptionless](https://exceptionless.com/) -14. Id生成器 - - [ECommon.Utilities.ObjectId](https://github.com/tangxuehua/ecommon/blob/master/src/ECommon/Utilities/ObjectId.cs) +Serilog是.Net目前最流行的日志框架,支持结构化日志. -15. RSA加密算法 - - [DotnetCore.RSA](https://github.com/stulzq/DotnetCore.RSA/blob/master/DotnetCore.RSA/RSAHelper.cs) +Seq 和 Exceptionless 是日志管理系统,提供了操作日志的界面,可以使用Serilog写入. -16. 二维码操作 - - [QRCoder](https://github.com/codebude/QRCoder/) +Util 对它们进行了轻度封装,集成了常用配置,并提供日志上下文等扩展. -17. 短信操作 - - [Luosimao](https://luosimao.com/) +- ### 缓存 -18. Queryable动态扩展 - - [System.Linq.Dynamic.Core](https://github.com/StefH/System.Linq.Dynamic.Core) +技术选型: [EasyCaching](https://github.com/dotnetcore/EasyCaching) -19. Web框架 - - [Asp.Net Core](https://docs.microsoft.com/zh-cn/aspnet/core/) +Util 集成了内存缓存和Redis缓存两种提供程序. -20. UI - - 脚本语言 - - [TypeScript](https://www.tslang.cn) - - 脚本框架 - - [Angular 6](https://angular.cn/) - - Css预处理器 - - [Sass](http://www.sass-lang.com) - - 组件库 - - [Angular Material](https://material.angular.io/) - - [PrimeNg](https://www.primefaces.org/primeng) - - [Angular-Material-App](https://github.com/stbui/angular-material-app) - - 脚本库 - - [Moment](http://momentjs.cn/) - - 图标 - - [Material Design Icon](https://material.io/icons/) - - [Font Awesome Icon](http://fontawesome.io/) - - 打包 - - Webpack - - 测试 - - Karma - - Jasmine +- ### 事件总线 -21. 代码生成器 - - CodeSmith 6.5 +技术选型: [MediatR](https://github.com/jbogard/MediatR), [Dapr](https://dapr.io/) -22. 参考应用框架 - - [ABP](https://github.com/aspnetboilerplate/aspnetboilerplate) - - [Nop](https://www.nopcommerce.com) - - Nop是一个开源商城,封装了大量实用的基础代码。 +> 事件总线分为本地事件总线和集成事件总线. -## 框架开发流程 +Util 本地事件总线提供两种实现,默认使用Ioc方式实现,无需外部依赖. 另外引入了 MediatR 框架,它是流行的进程内事件处理框架. - > *搜集* - *整理* - *集成* - *封装* +集成事件总线用于微服务之间消息通信,Util 集成了 Dapr 微服务框架,基于 Dapr 的发布订阅实现集成事件总线. -每当发现框架无法满足项目中的需求时,扩展的时刻来临。 +- ### 模板引擎 -从头造轮子是下策,所以总是先四处**搜集**相关资料。对于简单的需求,可能只需要找到一些代码片断即可。对于更专业的问题,比如将对象转换为json字符串,需要寻求第三方技术框架的帮助。 +技术选型: [RazorEngineCore](https://github.com/adoconnection/razorenginecore) , [Handlebars.Net](https://github.com/Handlebars-Net/Handlebars.Net) -找到解决方案并调试通过后,需要对代码进行**整理**,以符合我们的编程风格。 +Util 以源码方式引入 RazorEngineCore ,并进行大量修改. + +Razor 模板引擎目前主要用在 Util 代码生成器. + +- ### 图像处理 + +技术选型: [ImageSharp](https://sixlabors.com/) + +ImageSharp 是一个图像处理库. + +Util 使用 ImageSharp 实现动态文本头像生成. + +- ### 文件存储 + +技术选型: [Minio](http://minio.org.cn/) + +Minio 是流行的对象存储系统,适合部署到内部服务器. + +Util 集成封装了 Minio SDK, 提供 存储桶名称处理策略, 文件名处理策略等构造块进行扩展处理. + +- ### 后台任务 + +技术选型: [Quartz](https://www.quartz-scheduler.net/) , [HangFire](https://www.hangfire.io/) + +Util 封装了 Quartz 和 HangFire, 用于处理后台任务. + +- ### 数据访问 + +技术选型: [EntityFrameworkCore](https://docs.microsoft.com/zh-cn/ef/core/) , [Dapper](https://github.com/DapperLib/Dapper) + +Util数据访问主要使用 EntityFrameworkCore ,它是.Net官方提供的ORM框架,属于重量级数据访问框架. + +EntityFrameworkCore 支持工作单元模式,对复杂的业务处理非常有效,但对复杂的查询操作无能为力. + +可以直接使用 EntityFrameworkCore 执行Sql语句, 但此操作非常原始,效率低下. + +Dapper是轻量级数据访问框架, Util引入它并进行封装,用于解决查询问题. + +目前 Util Dapper 封装尚不可用,它还缺乏分页,Lambda表达式支持等高级功能,现在仅用于代码生成读取元数据,后续会进行扩展. + +由于使用国产数据库的需求逐渐增多,后续将考虑引入 [FreeSql](https://github.com/dotnetcore/FreeSql) 数据访问框架. + +- ### 工具类 + +Util包含大量工具类,用于处理常用操作. + +- 类型转换操作 +- Lambda操作 +- 命令行操作 +- 配置操作 +- 枚举操作 +- Ioc操作 +- Json操作 +- 字符串操作 +- 时间操作 +- IP操作 +- Web操作 +- 加密操作 +- ... + +## 架构支持 + +### 多租户架构支持 + +Saas系统支持多家客户使用同一系统,客户数据彼此隔离. + +Util 参考了 [ABP](https://abp.io/) 应用框架的多租户架构设计的租户解析和数据过滤部分. + +Util 多租户架构在独立部署租户数据库方面基于 EntityFrameworkCore 的官方建议,有一些限制. + +### DDD分层架构支持 + +Util 分层架构基于领域驱动设计(DDD) 和 企业应用架构模式(POEAA) 的基础构造块. + +.Net 早期流行的分层架构是三层架构, 对于不熟悉 DDD 的开发人员,可以把它当成三层架构使用,不过术语的变化而已. + +但是对于有一定领域模型使用经验的开发人员,该架构在处理更复杂的业务时可以有效管控复杂性. + +对于复杂模块的开发,该架构与三层架构的主要区别在于,实体是作为简单数据容器,还是作为业务处理的场所. + +对于很多业务领域,将实体对应的业务操作封装到实体本身,可以提升业务表达能力和封装性. + +Util 分层架构分为四层. + +#### 领域层 + +领域层是Util分层架构的核心. + +领域层非常纯净, 没有对数据访问和UI的依赖,很容易对该层进行单元测试. + + - ##### 聚合根 + + 作为并发单元的最外层实体. + + - ##### 实体 + + 由唯一标识决定的业务对象. + + - ##### 值对象 + + 表示实体属性值的对象. + + - ##### 仓储 + + 表示聚合根的集合,用于进行数据访问. + + - ##### 领域服务 + + 用于封装多个聚合根的操作. + + - ##### 领域事件 + + 表示实体数据发生变化. + + 使用Util本地事件总线发布领域事件. + + 有几个标准领域事件: + + - EntityChangedEvent - 实体变更事件 + - EntityCreatedEvent - 实体创建事件 + - EntityUpdatedEvent - 实体修改事件 + - EntityDeletedEvent - 实体删除事件 + +#### 基础设施层 + +对于大多项目,基础设施层主要包含数据访问的实现. + +#### 应用层 + +集成了领域层和基础设施层,为UI提供服务. + + - ##### 应用服务 + + 应用服务接收UI请求,并将调用委托给实体,领域服务等构造块完成业务功能. + + 对于普通项目,业务逻辑直接在应用服务中实现即可,这与三层架构相似. + + - ##### 数据传输对象(DTO) + + 数据传输对象是一种用来传递参数的对象. + + - ##### 查询参数对象 + + 查询参数对象是一种专门用来传递查询参数的对象. + +#### 表现层 + +### 微服务架构支持 + +Util 集成了 [Dapr](https://dapr.io/) ,它是微软主推的微服务框架. + +Util 封装了 Dapr Http同步调用,异步事件发布订阅,状态存储等功能. + +并对身份认证,事件日志,事件重发等重要功能进行扩展. + +### 常见业务功能支持 + +#### 树形结构支持 + +有些数据包含层次结构. + +Util 分层架构包含对树形结构的支持. + +如果使用 Util UI,无论加载树形表格还是树形,继承基类即可实现功能. + +#### 审计支持 + +大多操作需要记录创建人,创建时间,修改人,修改时间等审计信息. + +Util支持保存时自动设置审计信息. + +Util 审计设计参考自 [ABP](https://abp.io/) 应用框架. + +#### 逻辑删除支持 + +Util 支持逻辑删除,删除时更新为已删除状态,查询时自动过滤已删除记录. + +Util 逻辑删除设计参考自 [ABP](https://abp.io/) 应用框架. + +#### 对象变更值支持 + +修改时可能需要获取对象哪些数据发生了变化. + +Util 提供多种方式获取对象变更值记录. + + +## 代码生成 + +由于 Util 采用 DDD分层架构,导致简单需求也需要创建大量的类型. + +手工创建这些类型效率低下,通过代码生成迅速创建它们,可以大幅提升开发效率和质量. + +Util 配套代码生成器, 简单易用, 可解决大部分机械工作. + +在生成的代码基础上进行修改,比从头开始工作要好得多. + +## UI 技术选型 + +- ### Js语言 + - #### [TypeScript](https://www.typescriptlang.org/zh/) + TypeScript 是 微软开发的脚本语言, 扩展了弱类型的 Javascript,提供增强的语法和强类型支持. + + 为编辑器代码提示和语法错误检测奠定坚实基础. + +- ### Js框架 + - #### [Angular](https://angular.io) + + Angular 是 Google开发的 Js框架. + + Angular使用 TypeScript 脚本语言开发, 并采用 [RxJs](https://github.com/ReactiveX/RxJS) 响应式编程框架. + + Angular 是前端Js三大框架之一,另外两个是 Vue 和 React. + + Util UI 用于开发管理后台,选择 Angular 是因为它的语法最优雅, 也最符合后端开发人员的习惯. + +- ### Angular 组件库 + + - #### [Ng Zorro](https://ng.ant.design/) + + Ng Zorro 是阿里 Ant Design 的 Angular 版本,提供 80+ 常用组件,覆盖大部分业务开发场景. + + - #### [Ng Alain](https://ng-alain.com/) + + 虽然 Ng Zorro 提供了大量常用组件,但项目开发需要一个集成度更高的环境. + + Ng Alain 是一个基架项目, 集成了 Ng Zorro 组件,提供业务开发的项目模板,除了菜单导航等框架元素,还有很多开箱即用的业务处理页面模板. + +- ### Angular 微前端框架 + + - #### [Angular Module Federation](https://github.com/angular-architects/module-federation-plugin) + + 如果你的项目包含大量 Angular 模块,所有文件在同一个项目中,会导致开发环境卡顿和缓慢. + + 发布项目也可能需要很长时间. + + 另外,如果某个模块需要进行修改,哪怕只修改一行代码,也需要对所有模块重新发布. + + 与后端的微服务类似,微前端是前端的项目拆分方法. + + 微前端将不同的 Angular 模块拆分到不同项目中,可以独立开发,独立测试和独立部署. + + > 无论你是否使用微服务架构,均可使用微前端拆分方式. + + Angular Module Federation 是基于Webpack模块联合的Angular微前端解决方案. + + +## Util Angular UI 特点 + +- ### 组件扩展支持 + + 除了支持 Ng Zorro 原生功能外,Util UI还对常用组件进行了扩展. + + 最重要的扩展是支持常用组件直接发出 Api 请求,而不用定义额外的服务. + +- ### Razor TagHelper 支持 + + Util Angular UI不仅可以使用 html 页面,还能使用 .Net Razor 页面. + + Razor 页面可以使用 TagHelper 服务端标签. + + Util 已将大部分 Ng Zorro 组件封装为 TagHelper 标签. + + 除了获得强类型提示外,TagHelper 作为抽象层,提供更简洁的标签语法. + + 另一个强大之处在于Lambda表达式支持, 可以将DTO直接绑定到 TagHelper 标签上. + + 能够从Lambda表达式提取元数据,并自动设置大量常用属性,比如name,验证,模型绑定等. -对于像autofac这样的类库,只需要nuget引用一下就完事,但对于UI层面的框架,需要进行更复杂的**集成**才能工作,我们可能还会修改一些源码以方便后续扩展。 +- ### 前后分离 -最后,为了达到复用的目的,需要仔细考虑如何**封装**才能让调用者最省力。 + 一些开发人员看到 Util Angular UI 使用 .Net Razor 页面,可能认为 UI 与 .Net 高度耦合,但现在的趋势是前后分离. -> 前几年,我喜欢把第三方技术框架的源码放到我的类库中,那是因为nuget经常连接失败,不过现在nuget比较稳定了,并且对包的嵌套引用支持得很好,所以不再采用山寨方式。 + 所谓前后分离,是前端UI和后端API没有依赖,更换某一端对另一端没有影响. -> 任何有技术含量的工作,均由第三方技术框架完成,Util应用框架仅对技术框架选型并集成封装。Util只是很薄的一层外观,为复杂的技术框架提供一个简易视图。这导致更健壮的实现和更易用的API。 + 另外,前后分离后,前端UI和后端API可以由不同的开发人员完成. -## 项目开发流程 + .Net Razor页面仅在开发阶段提供帮助,在发布时, Razor 页面会转换为 html ,后续发布流程与纯前端开发方式相同. -一套得心应手的应用框架,能让你的团队如虎添翼,开发效率和开发质量将同时提升N倍,这在拥有应用框架的公司已经是不争的事实。 + 一旦发布成功,将完全脱离.Net 环境,可以使用 Nginx 容器承载它. -那是不是意味着,只要下载到一套应用框架,你的团队马上就能脱胎换骨呢? 非也,梅花香自苦寒来,宝剑锋从磨砺出,路漫漫其修远兮,你将上下而求索。 + 发布后的产物,与你使用纯前端方式开发打包没有区别. -任何应用框架都属于辅助设施,能否高效完成项目,还是靠你团队本身的水平。要高效完成项目,需要对技术、架构、过程等方面达到一定认识,这是一个漫长的学习过程。我会为你分享一些项目开发流程上的经验,并提供一份经典图书的清单。 + 如果你喜欢,可以把后端API换成JAVA,也能正常运行. -对于普通的项目,大体由简单的基础管理模块和较复杂的业务模块构成。 +- ### 配套Api支持 -基础管理模块表现为Crud操作加上一些简单业务逻辑,它们的特点是功能简单但数量众多,解决它们的有效手段是代码生成器,由生成器生成全套代码(包括管理后台的UI代码),然后在这个基础上手工修改。 + 前端UI和后端API的开发是两个完全不同的领域. -对于复杂的业务模块,它们往往由权限(操作权限与数据权限)、流程控制、复杂的计算、绕脑的策略等问题交织在一起,解决它们的有效手段是DDD(领域驱动设计),TDD(测试驱动开发),设计模式。 + 但开发一个功能,又需要前端和后端的配合,他们需要沟通,作出一些约定. -> 遗憾的是,听过这些名词的部分开发人员,由于没有真正实践,还在道听途说的质疑这些方法的有效性,或是用这些方法来开发Crud操作,用大炮打蚊子,没用对地方反而质疑方法的作用。 + 对于配合不到位的团队,前后端的沟通成本可能很高,另外提供的API可能无法满足UI的需求,从而让前端代码变得畸形. -对于权限,目前发现最通用,最简单,最易理解的方法是基于*资源*和*角色*的权限设计。操作权限是通用的,但数据权限太灵活,目前我们配合规约模式来解决。 + 通常.Net开发人员的Js编程功底高于常规前端人员,前端人员更擅长样式布局. -由于项目开发流程是一个很大的主题,我会用专门的文章来进行介绍,以抛砖引玉。 + Util Angular UI 不仅提供对前端组件的封装,同时也为常见功能提供 Api 支持. -## 作者 + 对于使用 Util Angular UI 的团队, 将 UI 和 API 交给同一个.Net开发人员就是最好的选择. -何镇汐 + 前端人员仅调整界面样式即可. -## 核心开发团队 + 不仅减少了沟通成本, API和前端组件的高度集成封装,让常规功能的开发效率得到大幅提升. -[何镇汐](https://github.com/utilcore) [程序喵](https://github.com/program-meow "胡雲鹏") [Richfiter](https://github.com/xingwen1987 "邢文") + 当然,这对 .Net 开发人员的水平有一定要求. -应用框架的开发工作量很大,个人显得力不从心,我也迫切希望找到一些志同道合的同学共同完成,同时也欢迎你的加入。 +- ### 本地化支持 -对于Util核心开发团队成员,需要至少独立完成Util中的一个模块(比如微信公众号接口封装),并持续维护它。 + 得益于 Ng Alain 本地化的良好设计, 可以使用 i18n 管道进行文本的本地化转换. -> 为了保持代码风格的统一,Util核心开发团队必须以统一的编码规范提交代码,在必要的时候,我会对代码进行重构。 + ``` + '文本' | i18n + ``` -## 技术顾问团队 + 不过对于需要支持本地化的项目,这依然是一个负担,每个表单项,每个表格项,每个文本,可能都需要添加 i18n 管道. -[AlexLEWIS](https://github.com/alexinea "刘怡") [Kiler](https://github.com/kiler398 "谢炀") [Lemon](https://github.com/liuhaoyang "刘浩杨") [Savorboard](https://github.com/yuleyule66 "杨晓东") [Lyrics](https://github.com/lyricsyo "娄宇") + Util Angular UI 让本地化开发更进一步,对大部分组件提供了本地化支持,只有极少数文本需要手工添加 i18n 管道. -Util应用框架技术顾问团队负责对API易用性,代码健壮性,设计缺陷等内容进行审查,在发现问题时提出改善意见。 +- ### 授权访问支持 -> 如果您是一名资深.net开发专家,并希望为Util应用框架出谋划策,欢迎加入Util应用框架技术顾问团队。 + Ng Alain提供了授权访问的支持. -## 贡献与反馈 + Util Platform权限模块基于资源和角色的设计,可以很好的与 Ng Alain授权进行集成. -> 如果你在阅读或使用Util中任意一个代码片断时发现Bug,或有更佳实现方式,请通知我们。 + 你可以控制菜单和任意区域根据权限显示和隐藏. -> 为了保持代码简单,目前很多功能只建立了基本结构,细节特性未进行迁移,在后续需要时进行添加,如果你发现某个类无法满足你的需求,请通知我们。 +- ### 微前端支持 -> 你可以通过github的Issue或Pull Request向我们提交问题和代码,如果你更喜欢使用QQ进行交流,请加入我们的交流QQ群。 + Util Angular UI 引入了 [Angular Module Federation](https://github.com/angular-architects/module-federation-plugin) , 能够将 Angular 模块拆分到不同项目中,可以独立开发,独立测试和独立部署. -> 对于你提交的代码,如果我们决定采纳,可能会进行相应重构,以统一代码风格。 + 对于大中型项目,这是非常有必要的. -> 对于热心的同学,将会把你的名字放到**贡献者**名单中。 -## 贡献者 +## Util Angular UI 功能列表 -## 交流方式与技术支持 +Util Angular UI 主要由 util-angular 和 Util.Ui.NgZorro 两个库提供支持. - 当你在使用Util进行开发时,倘若碰到无法解决的问题,可以加群讨论,Util团队会尽力帮助你度过难关。 + - ### util-angular 功能列表 - - Util应用框架交流QQ群(一群):24791014 + [util-angular](https://github.com/util-core/util-angular) 是一个 Js 库, 由Curd组件基类, Ng Zorro常用组件扩展指令和一组工具类组成. - > 不论是Util应用框架的代码,还是交流活动都是免费的,所以你不能指望我们必须在短时间内响应你,同时也希望大家都保持开放的心态,为初学者提供一些便利。 + - #### 基础类型 - > 对于一些伸手党,本来百度3分钟就可以解决的问题,却四处找人问,对于这些家伙,我建议你们转JAVA。 + - ViewModel - 视图模型基类 + - TreeViewModel - 树形视图模型基类 + - TreeNode - 树形节点基类 + - PageList - 分页列表 + - QueryParameter - 查询参数基类 + - TreeQueryParameter - 树形查询参数基类 + - Result - 服务端返回结果 + - StateCode - 服务端状态码约定 + - SelectItem - 列表项 + - SelectList - 列表 + - SelectOptionGroup - 列表配置组 + - SelectOption - 列表配置项 -## 免责申明 + - #### 工具类 -- 虽然我们对代码已经进行高度审查,并用于自己的项目中,但依然可能存在某些未知的BUG,如果你的生产系统蒙受损失,Util团队不会对此负责。 + - 浏览器本地存储操作 + - Cookie操作 + - 事件总线操作 + - 本地化操作 + - Ioc操作 + - 加载操作 + - 路由操作 + - 弹出层操作 + - 抽屉操作 + - 表单操作 + - Http操作 + - Web Api操作 + - 消息操作 + - ... -- 出于成本的考虑,我们不会对已发布的API保持兼容,每当更新代码时,请注意该问题。 + - #### Crud组件基类 -## 开源地址 + - 编辑组件基类 + - 表格编辑组件基类 + - 树形编辑组件基类 + - 查询组件基类 + - 表格查询组件基类 + - 树形表格查询组件基类 -https://github.com/dotnetcore/util/ + - #### Ng Zorro指令扩展 -## License + - 必填项验证扩展指令 + - 验证消息扩展指令 + - Ng Zorro 按钮扩展指令 + - Ng Zorro 选择框扩展指令 + - Ng Zorro 表格扩展指令 + - Ng Zorro 表格编辑扩展指令 + - Ng Zorro 树形表格扩展指令 + - Ng Zorro 树形扩展指令 + - Ng Zorro 上传扩展指令 -**MIT** + - ### Util.Ui.NgZorro 库介绍 + + Util.Ui.NgZorro 是一个 C# 类库,包含 TagHelper标签和树形控制器等类型. + + 绝大部分 Ng Zorro 组件已经封装. + + 由于组件很多,就不一一列出. -> 这意味着你可以在任意场景下使用Util应用框架而不会有人找你要钱。 +## Util Angular UI 已知缺陷 -> Util会尽量引入开源免费的第三方技术框架,如有意外,还请自行了解。 +Util Angular UI 所有已知缺陷均已解决. -## 书单 +## Util Angular UI 适合你吗? -> 本清单会持续更新 +Util Angular UI 是为 .Net 全栈工程师准备的,如果你喜欢更简洁的语法,希望开发的成本更低,它就适合你. -- 面向对象 - - 《UML和模式应用》 作者:Craig Larman - - 《面向对象分析与设计》 作者:Grady Booch +## 参考应用框架 -- 架构模式 - - 《企业应用架构模式》 作者:Martin Fowler - - 《领域驱动设计》 作者:Eric Evans - - 《敏捷软件开发-原则、模式与实战》 作者:Robert C.Martin - - 《实现领域驱动设计》 作者:Vaughn Vernon +很明显,闭门造车不可取。 -- 设计模式 - - 《设计模式》 作者:Erich Gamma - - 《Head First设计模式》 作者:Eric Freeman +Util应用框架大部分依赖以Nuget方式引入,极少部分需要修改源码,则以复制源码方式使用。 -- TDD - - 《测试驱动开发》 作者:Kent Beck - - 《测试驱动开发的艺术》 作者:Lasse Koskela - - 《单元测试的艺术》 作者:Roy Osherove - - 《重构-改善既有代码的设计》 作者:Martin Fowler - - 《实现模式》 作者:Kent Beck - - 《代码整洁之道-Clean Code》 作者:Robert C.Martin - - 《重构与模式》 作者:Joshua Kerievsky +另外,.Net应用框架还有很多优秀的开源项目,从中学习和吸取养分是Util成长的关键。 -## 重大升级 +Util应用框架主要参考了以下开源项目,从中吸收架构和代码,并以Util风格进行整理。 -> 包括.net core版本的跳跃式升级等,比如从.net core1.x升级到2.0。 - -- 2017年7月21日,将.net core升级到2.0 Preview 2。 - -## 更新计划 - -> 不打算提供精确的更新计划,以免无法兑现。 - -> 对于已发布的代码,将标记为[已发布]。对于已迁移到.net core的代码,将标记为[已完成],并即将发布。对于正在开发或迁移的代码,标记为[开发中]。对于尚未启动的部分,标记为[待启动]。这个列表会经常更新。 - -- 公共操作类(工具类)及扩展 - - 类型转换操作 [已发布] - - Json操作 - 基于Newtonsoft.Json [已发布] - - 映射操作 - 基于AutoMapper [已发布] - - Ioc操作 - 基于Autofac [已发布] - - 应用程序异常操作 [已发布] - - 验证操作 [已发布] - - 验证操作拦截器 [已发布] - - 枚举操作 [已发布] - - 字符串操作 [已发布] - - Lambda表达式操作 [已发布] - - 日志操作 - 基于NLog和Exceptionless [已发布] - - 日志操作拦截器 [已发布] - - IQueryable查询扩展 [已发布] - - 时间操作 [已发布] - - 上下文操作 [已发布] - - 类型查找器 [已发布] - - 二维码操作 - 基于QRCoder [已发布] - - 短信操作 -基于LuoSiMao [已发布] - - 加密操作 [已发布] - - Url参数生成器 [已发布] -- 分层架构基类及组件 - - 实体基类 [已发布] - - 聚合根基类 [已发布] - - 值对象基类 [已发布] - - 树型实体基类 [已发布] - - 操作审计 [已发布] - - EF Core实体映射配置基类 [已发布] - - EF Core工作单元基类 [已发布] - - EF Core调试日志 [已发布] - - 仓储基类 [已发布] - - 查询对象 [已发布] - - 范围查询条件 [已发布] - - 分页参数 [已发布] - - 分页集合 [已发布] - - 查询参数 [已发布] - - 工作单元服务 [已发布] - - 工作单元拦截器 [已发布] - - Crud服务 [已发布] - - 树型Crud服务 [待启动] - - 持久化对象Po基类 [已发布] - - 持久化对象存储基类 [已发布] - - 事件总线 [已发布] -- UI组件 - 支持HtmlHelper和TagHelper两种方式 - - 组件基类 [已发布] - - TagHelper基类 [已发布] - - 图标 - 集成了Material Design和Font Awesome图标集 [已发布] - - 下拉列表 - 基于Material Select组件 [已发布] - - 文本框 - 基于Material 文本框和日期选择框组件 [已发布] - - 表单 [已发布] - - 按钮 - 基于Material 按钮组件 [已发布] - - 链接 - 基于Material 链接组件 [已发布] - - 复选框 - 基于Material 复选框组件 [已发布] - - 滑动开关 - 基于Material slide-toggle组件 [已发布] - - 单选框 - 基于Material 单选框组件 [已发布] - - 菜单 - 基于Material Menu组件 [已发布] - - 选项卡 - 基于Material Tabs组件 [已发布] - - 导航侧边栏 - 基于Material SideNav组件 [已发布] - - 工具栏 - 基于Material Toolbar组件 [已发布] - - 卡片 - 基于Material Card组件 [已发布] - - 面板 - 基于Material Panel组件 [已发布] - - 文件上传 - 基于PrimeNg 文件上传组件 [待启动] - - 表格 [待启动] -- 权限 [待启动] -- 公共业务基类 - - 地址 [已发布] -- 支付操作 - - 支付宝条码支付 [已发布] - -## 更新列表 - -- 2017年7月6日,更新了类型转换操作类,类型转换扩展方法,类型转换单元测试。 -- 2017年7月14日,更新了Json操作类,Json操作单元测试。更新了对象映射操作类,对象映射操作单元测试。 -- 2017年7月18日,更新了Ioc操作类,Ioc扩展方法,Ioc操作单元测试。 -- 2017年7月21日,将Util升级到.net core 2.0 prew。 -- 2017年7月26日,更新了应用程序异常操作类Warning及单元测试。 -- 2017年7月28日,更新了验证操作(Util/Validations目录)及单元测试。 -- 2017年8月1日,更新了枚举操作及单元测试。 -- 2017年8月2日,更新了实体、聚合根基类及单元测试。 -- 2017年8月3日,更新了值对象基类及单元测试。 -- 2017年8月4日,更新了字符串操作及扩展,Lambda表达式操作及扩展,以及相关单元测试。 -- 2017年8月5日,更新了映射操作的集合映射。更新了范围查询条件(Util/Datas/Queries/Criterias)及相关单元测试。 -- 2017年8月6日,更新了分页参数、分页集合、查询参数及相关单元测试。 -- 2017年8月8日,更新了查询对象及相关单元测试。 -- 2017年8月9日,更新了EF实体映射配置基类。更新了EF工作单元基类。 -- 2017年8月10日,更新了数据操作集成测试项目。 -- 2017年8月11日,更新了CodeSmith代码生成模板。 -- 2017年8月12日,更新了树型实体基类及单元测试。 -- 2017年8月14日,更新了持久化对象Po基类,仓储部分实现及相关单元测试。 -- 2017年8月19日,更新了操作审计(Util/Domains/Auditing)。 -- 2017年8月21日,更新了仓储基类,持久化对象存储基类,IQueryable查询扩展。 -- 2017年9月3日,更新了公共业务类型-地址(Address),修改了代码生成模板。 -- 2017年9月10日,更新了时间操作类,修改了代码生成模板。 -- 2017年9月15日,更新了上下文操作(Util/Contexts),更新了日期格式化扩展(Util/Extensions.DateTime)。 -- 2017年9月19日,更新了日志操作,日志提供程序支持NLog与Exceptionless。 -- 2017年9月20日,更新了日志操作拦截器(Util.Logs/Aspects)。 -- 2017年9月21日,更新了验证操作拦截器(Util/Validations/Aspects)。 -- 2017年9月27日,更新了工作单元服务(Util/Datas.UnitOfWorks),工作单元拦截器(Util.Applications/Aspects),Crud服务(Util.Applications)。 -- 2017年9月30日,更新了事件总线(Util/Events),类型查找器(Util/Reflections),支持了IOC扫描注册功能。 -- 2017年10月21日,更新了Ui组件基类及TagHelper基类,图标组件(Util.Ui.Angular/Material/Icons)及单元测试。 -- 2017年10月25日,更新了二维码操作(Util.Tools.QrCode,基于QRCoder)和短信操作(Util.Tools.Sms,封装了LuoSiMao接口)。 -- 2017年10月29日,更新了加密操作(Util.Helpers.Encrypt,集成了MD5,DES,AES,RSA加密操作)及单元测试。 -- 2017年10月30日,更新了Url参数生成器(Util.Parameters)及单元测试。 -- 2017年10月31日,更新了支付宝条码支付操作(Util.Biz.Payments/Alipay)及单元测试。 -- 2017年11月15日,更新了EF Core调试日志(Util.Datas/Logs)及单元测试。 -- 2018年1月2日,更新了下拉列表组件(Util.Ui.Angular/Material/Forms)及单元测试。 -- 2018年1月10日,更新了文本框组件(Util.Ui.Angular/Material/Forms)及单元测试。 -- 2018年1月12日,更新了表单组件(Util.Ui.Angular/Material/Forms)及单元测试。 -- 2018年1月14日,更新了按钮和链接组件(Util.Ui.Angular/Material/Buttons)及单元测试。 -- 2018年1月16日,更新了复选框组件(Util.Ui.Angular/Material/Forms)及单元测试。 -- 2018年1月17日,更新了滑动开关组件(Util.Ui.Angular/Material/Forms)及单元测试。 -- 2018年1月18日,更新了单选框组件(Util.Ui.Angular/Material/Forms)及单元测试。 -- 2018年2月18日,更新了菜单组件(Util.Ui.Angular/Material/Menus)及单元测试。 -- 2018年2月22日,更新了选项卡组件(Util.Ui.Angular/Material/Tabs)及单元测试。 -- 2018年2月25日,更新了导航侧边栏组件(Util.Ui.Angular/Material/SideNavs)及工具栏组件(Util.Ui.Angular/Material/Toolbars)。 -- 2018年2月26日,更新了卡片组件(Util.Ui.Angular/Material/Cards)。 -- 2018年2月27日,更新了面板组件(Util.Ui.Angular/Material/Panels)。 \ No newline at end of file +- [ABP](https://abp.io/) + +- [NopCommerce](https://www.nopcommerce.com) + +- [Csla](https://cslanet.com/) + +## Util应用框架相关资源 + +### Util教程目录 + +- 知乎: + +- 掘金: + +### Github项目地址 + +- **Util** + + 该项目包含Util应用框架全部源码。 +- **Util.Generator** + + 该项目提供Util代码生成模板,帮助你迅速创建业务项目基架。 +- **util-angular** + + 该项目是对angular,ng zorro,ng alain前端框架的二次封装Js库,与Util.Ui.NgZorro类库配合使用。 +- **Util.Platform.Single** + + 使用新的应用框架通常具有高昂的成本,为帮助你减轻初始负担,该项目提供一些常用业务功能,你可以将它作为项目起点。 + + 目前提供了权限管理模块,可以控制到菜单和按钮,并能基于角色资源对API进行访问控制,后续将不断完善其它常用功能。 + + 该项目提供单体和微服务两个版本,Util.Platform.Single是单体版本。 +- **Util.Platform.Dapr** + + 它是Util Platform的微服务版本,采用Dapr微服务框架,项目结构参考自eShopOnDapr。 +- **Util.Platform.Share** + + 包含Util.Platform.Single和Util.Platform.Dapr的共享代码,并发布到Nuget,供两个版本使用。 + +### Gitee项目地址 + +**由于国内访问Github非常缓慢,现在Util所有项目发布时会在Gitee进行同步更新。** + +- **Util** +- **Util.Generator** +- **util-angular** +- **Util.Platform.Single** +- **Util.Platform.Dapr** +- **Util.Platform.Share** + +### Nuget包 + +| 包名 | 版本 | 下载量 +|--------------| ------- | ---- +| Util.Core |  |  +| Util.ObjectMapping.AutoMapper |  |  +| Util.Aop.AspectCore |  |  +| Util.Validation |  |  +| Util.Security |  |  +| Util.Data.Abstractions |  |  +| Util.AspNetCore |  |  +| Util.Localization |  |  +| Util.Logging |  |  +| Util.Logging.Serilog |  |  +| Util.Logging.Serilog.Exceptionless |  |  +| Util.Events.Abstractions |  |  +| Util.Events |  |  +| Util.Events.MediatR |  |  +| Util.Templates |  |  +| Util.Templates.Razor |  |  +| Util.Templates.Handlebars |  |  +| Util.Caching |  |  +| Util.Caching.EasyCaching |  |  +| Util.Scheduling |  |  +| Util.Scheduling.Quartz |  |  +| Util.Scheduling.Hangfire |  |  +| Util.Images.ImageSharp |  |  +| Util.Images.Avatar |  |  +| Util.FileStorage.Abstractions |  |  +| Util.FileStorage |  |  +| Util.FileStorage.Minio |  |  +| Util.FileStorage.Aliyun |  |  +| Util.FileStorage.All |  |  +| Util.Tenants.Abstractions |  |  +| Util.Tenants |  |  +| Util.Domain |  |  +| Util.Domain.Biz |  |  +| Util.Data.Core |  |  +| Util.Data.Sql |  |  +| Util.Data.Metadata |  |  +| Util.Data.EntityFrameworkCore |  |  +| Util.Data.EntityFrameworkCore.SqlServer |  |  +| Util.Data.EntityFrameworkCore.PostgreSql |  |  +| Util.Data.EntityFrameworkCore.MySql |  |  +| Util.Data.EntityFrameworkCore.Sqlite |  |  +| Util.Data.EntityFrameworkCore.Oracle |  |  +| Util.Data.Dapper.Core |  |  +| Util.Data.Dapper.SqlServer |  |  +| Util.Data.Dapper.PostgreSql |  |  +| Util.Data.Dapper.MySql |  |  +| Util.Data.Dapper.All |  |  +| Util.Application |  |  +| Util.Application.EntityFrameworkCore |  |  +| Util.Application.WebApi |  |  +| Util.Microservices |  |  +| Util.Microservices.Polly |  |  +| Util.Microservices.Dapr |  |  +| Util.Microservices.HealthChecks |  |  +| Util.Ui |  |  +| Util.Ui.Angular |  |  +| Util.Ui.NgZorro |  |  +| Util.Ui.NgAlain |  |  +| Util.Generators |  |  +| Util.Generators.Razor |  |  + +### Npm包 + +**util-angular** +[](https://www.npmjs.org/package/util-angular) +[](https://npmjs.org/package/util-angular) \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Api/Customers/CustomersController.cs b/sample/Util.Samples.Webs/Api/Customers/CustomersController.cs deleted file mode 100644 index 0ca2c68a6..000000000 --- a/sample/Util.Samples.Webs/Api/Customers/CustomersController.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; -using Donau.Services.Abstractions.Customers; -using Donau.Services.Dtos.Customers; -using Donau.Services.Queries.Customers; -using Microsoft.AspNetCore.Mvc; -using Util.Webs.Controllers; - -namespace Util.Samples.Webs.Api.Customers { - public class CustomersController : CrudControllerBase { - public CustomersController(ICustomersService customersService) : base(customersService) { - } - - [HttpGet("test")] - public IActionResult Test() { - List items = new List { - new Item( "B","1",2,"Group1" ), - new Item( "A","2",1,"Group2" ), - new Item( "D","3",4,"Group1" ), - new Item( "C","4",3,"Group2" ), - }; - return Success( items ); - } - } -} diff --git a/sample/Util.Samples.Webs/Areas/Logs/Controllers/LogControllerBase.cs b/sample/Util.Samples.Webs/Areas/Logs/Controllers/LogControllerBase.cs deleted file mode 100644 index 90a989b8e..000000000 --- a/sample/Util.Samples.Webs/Areas/Logs/Controllers/LogControllerBase.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Util.Samples.Webs.Areas.Logs.Controllers { - /// - /// 日志控制器 - /// - [Area( "Logs" )] - public abstract class LogControllerBase : Controller { - } -} diff --git a/sample/Util.Samples.Webs/Areas/Logs/Controllers/NLog1Controller.cs b/sample/Util.Samples.Webs/Areas/Logs/Controllers/NLog1Controller.cs deleted file mode 100644 index 99baddfd9..000000000 --- a/sample/Util.Samples.Webs/Areas/Logs/Controllers/NLog1Controller.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Util.Logs; -using Util.Logs.Extensions; - -namespace Util.Samples.Webs.Areas.Logs.Controllers { - /// - /// NLog日志控制器 - /// - public class NLog1Controller : LogControllerBase { - /// - /// 初始化NLog日志控制器 - /// - /// 日志操作 - public NLog1Controller( ILog log ) { - Log = log; - } - - /// - /// 日志操作 - /// - public ILog Log { get; set; } - - /// - /// 首页 - /// - public IActionResult Index() { - return View(); - } - - /// - /// 写异步日志 - /// - public async Task LogAsync() { - await WriteLog(); - await WriteLog(); - await WriteLog(); - await WriteLog(); - return Content( "写入成功,请查看c:/log/application/debug目录" ); - } - - /// - /// 写日志 - /// - private Task WriteLog() { - return Task.Run( () => Log.Debug( "测试异步写入日志" ) ); - } - - /// - /// 写入业务日志 - /// - public IActionResult Info() { - Log.BusinessId( Guid.NewGuid().ToString() ) - .Module( "订单" ) - .Method( "PlaceOrder" ) - .Caption( "有人下单了" ) - .Params( "int","a","1" ) - .Params( "string", "b", "c" ) - .Content( $"购买商品数量: {100}" ) - .Content( $"购买商品总额:{200}" ) - .Sql( "select * from system.users" ) - .Sql( "select * from system.roles" ) - .SqlParams( $"@a={1},@b={2}" ) - .SqlParams( $"@userId={Guid.NewGuid().ToString()}" ) - .Info(); - return Content( "写入成功,请查看c:/log/application/info目录" ); - } - - /// - /// 写入错误日志 - /// - public IActionResult Error() { - try { - Throw(); - } - catch ( Exception ex ) { - Log.BusinessId( Guid.NewGuid().ToString() ) - .Exception( ex, "100" ) - .Error(); - } - return Content( "写入成功,请查看c:/log/application/error目录" ); - } - - /// - /// 抛出异常 - /// - private void Throw() { - throw new NotImplementedException( "我还没有实现" ); - } - } -} diff --git a/sample/Util.Samples.Webs/Areas/Logs/Views/NLog1/Index.cshtml b/sample/Util.Samples.Webs/Areas/Logs/Views/NLog1/Index.cshtml deleted file mode 100644 index 0d0b4271d..000000000 --- a/sample/Util.Samples.Webs/Areas/Logs/Views/NLog1/Index.cshtml +++ /dev/null @@ -1,7 +0,0 @@ -@{ - Layout = "_Layout"; -} - -测试异步方法 -写业务日志 -写错误日志 diff --git a/sample/Util.Samples.Webs/Configs/ServiceRegister.cs b/sample/Util.Samples.Webs/Configs/ServiceRegister.cs deleted file mode 100644 index d662ecffd..000000000 --- a/sample/Util.Samples.Webs/Configs/ServiceRegister.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Util.Datas.Tests.Samples.Datas.SqlServer.Repositories; -using Util.Datas.Tests.Samples.Domains.Repositories; -using Util.Dependency; -using Util.Domains.Sessions; -using Util.Files; -using Util.Files.Paths; -using Util.Randoms; - -namespace Util.Samples.Webs.Configs { - /// - /// 服务注册 - /// - public class ServiceRegister : IDependencyRegistrar { - /// - /// 注册依赖 - /// - public void Regist( IServiceCollection services ) { - services.AddSingleton(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - } - } -} diff --git a/sample/Util.Samples.Webs/Configs/UploadBasePath.cs b/sample/Util.Samples.Webs/Configs/UploadBasePath.cs deleted file mode 100644 index a00f16690..000000000 --- a/sample/Util.Samples.Webs/Configs/UploadBasePath.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Util.Files.Paths; - -namespace Util.Samples.Webs.Configs { - /// - /// 上传基路径 - /// - public class UploadBasePath : IBasePath { - /// - /// 获取基路径 - /// - public string GetPath() { - return "upload"; - } - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Controllers/HomeController.cs b/sample/Util.Samples.Webs/Controllers/HomeController.cs deleted file mode 100644 index a57ee5eaa..000000000 --- a/sample/Util.Samples.Webs/Controllers/HomeController.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Donau.Services.Dtos.Customers; -using Microsoft.AspNetCore.Mvc; - -namespace Util.Samples.Webs.Controllers { - - public class HomeController : Controller { - - public IActionResult Index() { - return View(); - } - - public IActionResult Main() { - return View(); - } - - public IActionResult Demo() { - return View(new CustomersDto()); - } - } -} diff --git a/sample/Util.Samples.Webs/Program.cs b/sample/Util.Samples.Webs/Program.cs deleted file mode 100644 index 4dc3f17d1..000000000 --- a/sample/Util.Samples.Webs/Program.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Util.Logs; -using Util.Logs.Extensions; - -namespace Util.Samples.Webs { - /// - /// 应用程序 - /// - public class Program { - /// - /// 应用程序入口点 - /// - /// 入口点参数 - public static void Main( string[] args ) { - try { - WebHost.CreateDefaultBuilder( args ) - .UseStartup() - .Build() - .Run(); - } - catch ( Exception ex ) { - WriteLog( ex ); - } - } - - /// - /// 记录错误日志 - /// - private static void WriteLog( Exception ex ) { - ex.Log( Log.GetLog().Caption( "应用程序启动失败" ) ); - } - } -} diff --git a/sample/Util.Samples.Webs/Properties/PublishProfiles/FolderProfile.pubxml b/sample/Util.Samples.Webs/Properties/PublishProfiles/FolderProfile.pubxml deleted file mode 100644 index 8b30094e1..000000000 --- a/sample/Util.Samples.Webs/Properties/PublishProfiles/FolderProfile.pubxml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - FileSystem - FileSystem - Release - Any CPU - - True - False - 323b64b7-5ce0-4222-b9ed-9f418730897c - D:\Github\Util\output\publish - True - - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Properties/PublishProfiles/FolderProfile.pubxml.user b/sample/Util.Samples.Webs/Properties/PublishProfiles/FolderProfile.pubxml.user deleted file mode 100644 index 44823a679..000000000 --- a/sample/Util.Samples.Webs/Properties/PublishProfiles/FolderProfile.pubxml.user +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - <_PublishTargetUrl>D:\Github\Util\output\publish - - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Properties/launchSettings.json b/sample/Util.Samples.Webs/Properties/launchSettings.json deleted file mode 100644 index 5fe7fa320..000000000 --- a/sample/Util.Samples.Webs/Properties/launchSettings.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:5200/", - "sslPort": 0 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "Util.Samples.Webs": { - "commandName": "Project", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "http://localhost:5201/" - } - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Services/Abstractions/Customers/ICustomersService.cs b/sample/Util.Samples.Webs/Services/Abstractions/Customers/ICustomersService.cs deleted file mode 100644 index 36dcaaaa3..000000000 --- a/sample/Util.Samples.Webs/Services/Abstractions/Customers/ICustomersService.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Util.Applications; -using Donau.Services.Queries.Customers; -using Donau.Services.Dtos.Customers; - -namespace Donau.Services.Abstractions.Customers { - /// - /// 客户服务 - /// - public interface ICustomersService : ICrudService { - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Services/Core/Customers/CustomersService.cs b/sample/Util.Samples.Webs/Services/Core/Customers/CustomersService.cs deleted file mode 100644 index 8c4d1f264..000000000 --- a/sample/Util.Samples.Webs/Services/Core/Customers/CustomersService.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Util; -using Util.Maps; -using Util.Domains.Repositories; -using Util.Datas.Queries; -using Util.Applications; -using Donau.Services.Dtos.Customers; -using Donau.Services.Queries.Customers; -using Donau.Services.Abstractions.Customers; -using Util.Datas.Tests.Samples.Datas.SqlServer.UnitOfWorks; -using Util.Datas.Tests.Samples.Domains.Models; -using Util.Datas.Tests.Samples.Domains.Repositories; - -namespace Donau.Services.Core.Customers { - /// - /// 客户服务 - /// - public class CustomersService : CrudServiceBase, ICustomersService { - /// - /// 初始化客户服务 - /// - /// 工作单元 - /// 客户仓储 - public CustomersService( ISqlServerUnitOfWork unitOfWork, ICustomerRepository customersRepository ) - : base( unitOfWork, customersRepository ) { - CustomersRepository = customersRepository; - } - - /// - /// 客户仓储 - /// - public ICustomerRepository CustomersRepository { get; set; } - - /// - /// 转换为数据传输对象 - /// - /// 实体 - protected override CustomersDto ToDto( Customer entity ) { - return entity.MapTo(); - } - - /// - /// 转换为实体 - /// - /// 数据传输对象 - protected override Customer ToEntity( CustomersDto dto ) { - return dto.MapTo( new Customer( dto.Id ) ); - } - - protected override bool IsTracking => true; - - - /// - /// 创建查询对象 - /// - /// 客户查询实体 - protected override IQueryBase CreateQuery( CustomersQuery param ) { - return new Query( param ) - .WhereIfNotEmpty(t => t.Name.Contains(param.Name)) - .WhereIfNotEmpty( t => t.Nickname.Contains(param.Nickname)) - .WhereIfNotEmpty( t => t.Mobile.Contains(param.Mobile)); - } - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Services/Dtos/Customers/CustomersDto.cs b/sample/Util.Samples.Webs/Services/Dtos/Customers/CustomersDto.cs deleted file mode 100644 index 551c50fa9..000000000 --- a/sample/Util.Samples.Webs/Services/Dtos/Customers/CustomersDto.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System; -using System.ComponentModel; -using System.ComponentModel.DataAnnotations; -using System.Runtime.Serialization; -using Util.Applications.Dtos; -using Util.Biz.Enums; -using Util.Ui.Attributes; -using Util.Ui.Enums; -using Util.Ui.Material.Enums; -using Util.Ui.Material.Menus.Datas; - -namespace Donau.Services.Dtos.Customers { - /// - /// 客户数据传输对象 - /// - [DataContract] - [Model("model")] - public class CustomersDto : DtoBase { - /// - /// 客户名称 - /// - [Required(ErrorMessage = "客户名称不能为空")] - [MaxLength(20)] - [Display( Name = "客户名称" )] - [DataMember] - public string Name { get; set; } - - /// - /// 昵称 - /// - [StringLength( 30, ErrorMessage = "昵称输入过长,不能超过30位",MinimumLength = 3)] - [Display( Name = "昵称" )] - [DataMember] - public string Nickname { get; set; } - - /// - /// 余额 - /// - [DataMember] - [StringLength( 6, ErrorMessage = "昵称输入过长,不能超过30位" )] - [Display( Name = "余额" )] - public double Balance { get; set; } - - /// - /// 性别 - /// - [Display( Name = "性别" )] - [DataMember] - public Gender Gender { get; set; } - - - /// - /// 性别 - /// - [Display( Name = "性别" )] - [DataMember] - public bool IsGender { get; set; } - - /// - /// 年龄 - /// - [Display( Name = "年龄" )] - [Required(ErrorMessage = "年龄不能为空")] - [DataMember] - public double Age { get; set; } - - /// - /// 民族 - /// - [Display( Name = "民族" )] - [Required(ErrorMessage = "必须选择一个民族" )] - [DataMember] - public Nation Nation { get; set; } - - /// - /// 联系电话 - /// - [StringLength( 20, ErrorMessage = "联系电话输入过长,不能超过20位" )] - [Display( Name = "联系电话" )] - [DataMember] - public string Tel { get; set; } - - /// - /// 手机号 - /// - [StringLength( 20, ErrorMessage = "手机号输入过长,不能超过20位" )] - [Display( Name = "手机号" )] - [DataMember] - public string Mobile { get; set; } - - /// - /// 电子邮件 - /// - [StringLength( 100, ErrorMessage = "电子邮件输入过长,不能超过100位" )] - [Display( Name = "电子邮件" )] - [DataMember] - [EmailAddress(ErrorMessage = "你的电子邮件是错的")] - public string Email { get; set; } - - /// - /// 创建时间 - /// - [Display( Name = "创建时间" )] - [DataMember] - public DateTime? CreationTime { get; set; } - - /// - /// 创建人 - /// - [Display( Name = "创建人" )] - [DataMember] - public Guid? CreatorId { get; set; } - - /// - /// 最后修改时间 - /// - [Display( Name = "最后修改时间" )] - [DataMember] - public DateTime? LastModificationTime { get; set; } - - /// - /// 最后修改人 - /// - [Display( Name = "最后修改人" )] - [DataMember] - public Guid? LastModifierId { get; set; } - - /// - /// 版本号 - /// - [Display( Name = "版本号" )] - [DataMember] - public Byte[] Version { get; set; } - - public MenuNodeCollection GetMenus() { - var result = new MenuNodeCollection(); - result.Overlap = false; - result.Nodes.Add( new MenuNode{Label = "A", MaterialIcon = MaterialIcon.Block,OnClick = "onChange()"} ); - result.Nodes.Add( new MenuNode { Id = "2", Label = "B", MaterialIcon = MaterialIcon.Android,Link = "/searchmenu" } ); - result.Nodes.Add( new MenuNode { Id = "3", Label = "C", MaterialIcon = MaterialIcon.Bluetooth, OnClick = "onChange()" } ); - result.Nodes.Add( new MenuNode { ParentId = "2", Label = "D", FontAwesomeIcon = FontAwesomeIcon.Apple, OnClick = "onChange()", Disabled="true" } ); - result.Nodes.Add( new MenuNode { ParentId = "2", Label = "E", FontAwesomeIcon = FontAwesomeIcon.Book, Link = "/searchmenu" } ); - result.Nodes.Add( new MenuNode { Id = "4", ParentId = "2", Label = "F", FontAwesomeIcon = FontAwesomeIcon.Anchor, Link = "/searchmenu" } ); - result.Nodes.Add( new MenuNode { ParentId = "3", Label = "H", FontAwesomeIcon = FontAwesomeIcon.Apple, OnClick = "onChange()", Disabled = "true" } ); - result.Nodes.Add( new MenuNode { ParentId = "3", Label = "I", FontAwesomeIcon = FontAwesomeIcon.Book, Link = "/searchmenu" } ); - result.Nodes.Add( new MenuNode { ParentId = "2", Label = "G", FontAwesomeIcon = FontAwesomeIcon.Anchor, Link = "/searchmenu" } ); - - result.Nodes.Add( new MenuNode { ParentId = "4", Label = "D", FontAwesomeIcon = FontAwesomeIcon.Apple, OnClick = "onChange()", Disabled = "true" } ); - result.Nodes.Add( new MenuNode { ParentId = "4", Label = "E", FontAwesomeIcon = FontAwesomeIcon.Book, Link = "/searchmenu" } ); - result.Nodes.Add( new MenuNode { ParentId = "4", Label = "F", FontAwesomeIcon = FontAwesomeIcon.Anchor, Link = "/searchmenu" } ); - result.Nodes.Add( new MenuNode { ParentId = "4", Label = "H", FontAwesomeIcon = FontAwesomeIcon.Apple, OnClick = "onChange()", Disabled = "true" } ); - result.Nodes.Add( new MenuNode { ParentId = "4", Label = "I", MaterialIcon = MaterialIcon.Android, Link = "/searchmenu" } ); - result.Nodes.Add( new MenuNode { ParentId = "4", Label = "G", FontAwesomeIcon = FontAwesomeIcon.Anchor, Link = "/searchmenu" } ); - return result; - } - } -} diff --git a/sample/Util.Samples.Webs/Services/Extensions/Customers/Extensions.CustomersDto.cs b/sample/Util.Samples.Webs/Services/Extensions/Customers/Extensions.CustomersDto.cs deleted file mode 100644 index d6389c2ea..000000000 --- a/sample/Util.Samples.Webs/Services/Extensions/Customers/Extensions.CustomersDto.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Util; -using Util.Maps; -using Donau.Services.Dtos.Customers; -using Util.Datas.Tests.Samples.Domains.Models; - -namespace Donau.Services.Extensions.Customers { - /// - /// 客户数据传输对象扩展 - /// - public static class CustomersDtoExtension { - /// - /// 转换为客户实体 - /// - /// 客户数据传输对象 - public static Customer ToEntity( this CustomersDto dto ) { - if ( dto == null ) - return new Customer(); - return dto.MapTo( new Customer( dto.Id ) ); - } - - /// - /// 转换为客户数据传输对象 - /// - /// 客户实体 - public static CustomersDto ToDto(this Customer entity) { - if( entity == null ) - return new CustomersDto(); - return entity.MapTo(); - } - - } -} diff --git a/sample/Util.Samples.Webs/Services/Queries/Customers/CustomersQuery.cs b/sample/Util.Samples.Webs/Services/Queries/Customers/CustomersQuery.cs deleted file mode 100644 index f0e7292a6..000000000 --- a/sample/Util.Samples.Webs/Services/Queries/Customers/CustomersQuery.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.ComponentModel.DataAnnotations; -using Util; -using Util.Datas.Queries; - -namespace Donau.Services.Queries.Customers { - /// - /// 客户查询实体 - /// - public class CustomersQuery : QueryParameter { - - private string _customerId = string.Empty; - /// - /// 客户编号 - /// - [Display(Name="客户编号")] - public string CustomerId { - get => _customerId == null ? string.Empty : _customerId.Trim(); - set => _customerId=value; - } - - private string _name = string.Empty; - /// - /// 客户名称 - /// - [Display(Name="客户名称")] - public string Name { - get => _name == null ? string.Empty : _name.Trim(); - set => _name=value; - } - - private string _nickname = string.Empty; - /// - /// 昵称 - /// - [Display(Name="昵称")] - public string Nickname { - get => _nickname == null ? string.Empty : _nickname.Trim(); - set => _nickname=value; - } - /// - /// 余额 - /// - [Display(Name="余额")] - public decimal? Balance { get; set; } - /// - /// 性别 - /// - [Display(Name="性别")] - public int? Gender { get; set; } - - private string _tel = string.Empty; - /// - /// 联系电话 - /// - [Display(Name="联系电话")] - public string Tel { - get => _tel == null ? string.Empty : _tel.Trim(); - set => _tel=value; - } - - private string _mobile = string.Empty; - /// - /// 手机号 - /// - [Display(Name="手机号")] - public string Mobile { - get => _mobile == null ? string.Empty : _mobile.Trim(); - set => _mobile=value; - } - - private string _email = string.Empty; - /// - /// 电子邮件 - /// - [Display(Name="电子邮件")] - public string Email { - get => _email == null ? string.Empty : _email.Trim(); - set => _email=value; - } - /// - /// 起始创建时间 - /// - [Display( Name = "起始创建时间" )] - public DateTime? BeginCreationTime { get; set; } - /// - /// 结束创建时间 - /// - [Display( Name = "结束创建时间" )] - public DateTime? EndCreationTime { get; set; } - /// - /// 创建人 - /// - [Display(Name="创建人")] - public Guid? CreatorId { get; set; } - /// - /// 起始最后修改时间 - /// - [Display( Name = "起始最后修改时间" )] - public DateTime? BeginLastModificationTime { get; set; } - /// - /// 结束最后修改时间 - /// - [Display( Name = "结束最后修改时间" )] - public DateTime? EndLastModificationTime { get; set; } - /// - /// 最后修改人 - /// - [Display(Name="最后修改人")] - public Guid? LastModifierId { get; set; } - - /// - /// 添加描述 - /// - protected override void AddDescriptions() { - base.AddDescriptions(); - AddDescription( "客户编号", CustomerId ); - AddDescription( "客户名称", Name ); - AddDescription( "昵称", Nickname ); - AddDescription( "余额", Balance ); - AddDescription( "性别", Gender ); - AddDescription( "联系电话", Tel ); - AddDescription( "手机号", Mobile ); - AddDescription( "电子邮件", Email ); - AddDescription( "起始创建时间", BeginCreationTime ); - AddDescription( "结束创建时间", EndCreationTime ); - AddDescription( "创建人", CreatorId ); - AddDescription( "起始最后修改时间", BeginLastModificationTime ); - AddDescription( "结束最后修改时间", EndLastModificationTime ); - AddDescription( "最后修改人", LastModifierId ); - } - } -} diff --git a/sample/Util.Samples.Webs/Startup.cs b/sample/Util.Samples.Webs/Startup.cs deleted file mode 100644 index 1cb8dea30..000000000 --- a/sample/Util.Samples.Webs/Startup.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.SpaServices.Webpack; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Util.Datas.Ef; -using Util.Datas.Tests.Samples.Datas.SqlServer.UnitOfWorks; -using Util.Events.Default; -using Util.Logs.Extensions; -using Util.Webs.Extensions; - -namespace Util.Samples.Webs { - /// - /// 启动配置 - /// - public class Startup { - /// - /// 初始化启动配置 - /// - /// 配置 - public Startup( IConfiguration configuration ) { - Configuration = configuration; - } - - /// - /// 配置 - /// - public IConfiguration Configuration { get; } - - /// - /// 配置服务 - /// - public IServiceProvider ConfigureServices( IServiceCollection services ) { - //添加Mvc服务 - services.AddMvc().AddControllersAsServices(); - - //添加NLog日志操作 - services.AddNLog(); - - //添加事件总线服务 - services.AddEventBus(); - - services.AddUnitOfWork( Configuration.GetConnectionString( "DefaultConnection" ) ); - - //添加Util基础设施服务 - return services.AddUtil(); - } - - /// - /// 配置请求管道 - /// - public void Configure( IApplicationBuilder app, IHostingEnvironment env ) { - if( env.IsDevelopment() == false ) { - ProductionConfig( app ); - return; - } - DevelopmentConfig( app ); - } - - /// - /// 生产环境配置 - /// - private void ProductionConfig( IApplicationBuilder app ) { - app.UseExceptionHandler( "/Home/Error" ); - app.UseAuthentication(); - CommonConfig( app ); - } - - /// - /// 公共配置 - /// - private void CommonConfig( IApplicationBuilder app ) { - app.UseErrorLog(); - app.UseStaticFiles(); - ConfigRoute( app ); - } - - /// - /// 路由配置,支持区域 - /// - private void ConfigRoute( IApplicationBuilder app ) { - app.UseMvc( routes => { - routes.MapRoute( "areaRoute", "{area:exists}/{controller}/{action=Index}/{id?}" ); - routes.MapRoute( "default", "{controller=Home}/{action=Index}/{id?}" ); - routes.MapSpaFallbackRoute( "spa-fallback", new { controller = "Home", action = "Index" } ); - } ); - } - - /// - /// 开发环境配置 - /// - private void DevelopmentConfig( IApplicationBuilder app ) { - app.UseBrowserLink(); - app.UseDeveloperExceptionPage(); - app.UseWebpackDevMiddleware( new WebpackDevMiddlewareOptions { - HotModuleReplacement = true - } ); - CommonConfig( app ); - } - } -} diff --git a/sample/Util.Samples.Webs/Typings/app/app.component.ts b/sample/Util.Samples.Webs/Typings/app/app.component.ts deleted file mode 100644 index 7cf122a53..000000000 --- a/sample/Util.Samples.Webs/Typings/app/app.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Component } from "@angular/core" -import {util} from "../util"; - -/** - * 根组件 - */ -@Component({ - selector: 'app', - templateUrl: '/home/main' -}) -export class AppComponent { -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/app/app.module.ts b/sample/Util.Samples.Webs/Typings/app/app.module.ts deleted file mode 100644 index fe9c142a8..000000000 --- a/sample/Util.Samples.Webs/Typings/app/app.module.ts +++ /dev/null @@ -1,35 +0,0 @@ -//Angular模块 -import { NgModule, Injector } from '@angular/core'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; - -//框架模块 -import { FrameworkModule } from './framework.module'; -import { util } from '../util'; - -//根组件 -import { AppComponent } from './app.component'; - -//路由模块 -import { AppRoutingModule } from './app.routing.module'; - -/** - * 应用根模块 - */ -@NgModule({ - declarations: [ - AppComponent - ], - imports: [ - BrowserAnimationsModule,FrameworkModule, AppRoutingModule - ], - bootstrap: [AppComponent] -}) -export class AppModule { - /** - * 初始化应用根模块 - * @param injector 注入器 - */ - constructor(injector: Injector) { - util.ioc.injector = injector; - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/app/app.routing.module.ts b/sample/Util.Samples.Webs/Typings/app/app.routing.module.ts deleted file mode 100644 index ad5e03644..000000000 --- a/sample/Util.Samples.Webs/Typings/app/app.routing.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core' -import { RouterModule, Routes } from '@angular/router' - -//路由配置 -const routes: Routes = [ - { path: '', redirectTo: 'demo', pathMatch: 'full' }, - { path: 'demo', loadChildren: "./demo/demo.module#DemoModule" }, - { path: '**', redirectTo: '/' } -]; - -/** - * 路由配置模块 - */ -@NgModule({ - imports: [RouterModule.forRoot(routes)] -}) -export class AppRoutingModule { } \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/app/demo/demo.component.ts b/sample/Util.Samples.Webs/Typings/app/demo/demo.component.ts deleted file mode 100644 index 4e5bac5e8..000000000 --- a/sample/Util.Samples.Webs/Typings/app/demo/demo.component.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Component, ViewChild, OnInit, Injector } from "@angular/core" -import { NgForm } from "@angular/forms" -import { ComponentBase, ViewModel, QueryParameter, TableWrapperComponent, util } from "../../util"; -@Component({ - selector: 'demo', - templateUrl: '/Home/Demo' -}) -export class DemoComponent extends ComponentBase implements OnInit { - queryParam: CustomerQueryModel; - - @ViewChild('grid') grid: TableWrapperComponent; - - model: CustomerViewModel; - id:string; - - delete() { - this.grid.delete(); - } - - constructor(injector: Injector) { - super(injector); - this.queryParam = new CustomerQueryModel(); - this.model = new CustomerViewModel(); - } - - query() { - this.grid.query(); - } - - onChange(form: NgForm, event) { - this.util.message.error("a"); - this.util.form.submit({ - form: form, - url: '/api/customers', - data: this.model, - }); - } - - ngOnInit() { - this.model.isGender = true; - } - - show() { - util.message.error("aa"); - } -} - - - - -class CustomerQueryModel extends QueryParameter { - public name: string; -} - -class CustomerViewModel extends ViewModel { - name: string; - value: string; - nation; - hide: boolean; - num: number; - date: Date; - creationTime:Date; - isGender:boolean; -} - - -@Component({ - selector: 'ao', - template: 'This is the routed body of the sunny tab.1111111111', -}) -export class A1 { } - -@Component({ - selector: 'bo', - template: 'This is the routed body of the sunny tab.2222222222', -}) -export class B1 { } -@Component({ - selector: 'co', - template: 'This is the routed body of the sunny tab.333333333333', -}) -export class C1 { } - -@Component({ - selector: 'do', - template: 'This is the routed body of the sunny tab.444444444444', -}) -export class D1 { } \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/app/demo/demo.module.ts b/sample/Util.Samples.Webs/Typings/app/demo/demo.module.ts deleted file mode 100644 index 1fcb94624..000000000 --- a/sample/Util.Samples.Webs/Typings/app/demo/demo.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule } from '@angular/core'; -import { FrameworkModule } from "../framework.module"; -import { DemoRoutingModule } from "./demo.routing.module"; -import { DemoComponent, A1, B1, C1, D1 } from "./demo.component"; - -@NgModule({ - declarations: [ - DemoComponent, A1, B1, C1, D1 - ], - imports: [ - FrameworkModule,DemoRoutingModule - ], - exports: [ - DemoComponent, A1, B1, C1, D1 - ] -}) -export class DemoModule { -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/app/demo/demo.routing.module.ts b/sample/Util.Samples.Webs/Typings/app/demo/demo.routing.module.ts deleted file mode 100644 index 0750a0939..000000000 --- a/sample/Util.Samples.Webs/Typings/app/demo/demo.routing.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { NgModule } from '@angular/core' -import { RouterModule, Routes } from '@angular/router' -import { DemoComponent, A1, B1,C1,D1 } from "./demo.component"; - -//路由配置 -const routes: Routes = [ - { path: '', component: DemoComponent, children: [{ path: 'a', component: A1 }, { path: 'b', component: B1 }, { path: 'c', component: C1 }, { path: 'd', component: D1 }] } -]; - -/** - * 路由配置模块 - */ -@NgModule({ - imports: [RouterModule.forChild(routes)] -}) -export class DemoRoutingModule { } \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/app/framework.module.ts b/sample/Util.Samples.Webs/Typings/app/framework.module.ts deleted file mode 100644 index c90ab4e5a..000000000 --- a/sample/Util.Samples.Webs/Typings/app/framework.module.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { NgModule } from '@angular/core'; -//Util模块 -import { UtilModule } from '../util'; -//Material模块 -import { - MatButtonToggleModule, - MatChipsModule, - MatDialogModule, - MatListModule, - MatSliderModule, - MatStepperModule -} from '@angular/material'; -@NgModule({ - exports: [ - UtilModule, - MatButtonToggleModule, - MatChipsModule, - MatDialogModule, - MatListModule, - MatSliderModule, - MatStepperModule - ] -}) -export class FrameworkModule { -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/main.ts b/sample/Util.Samples.Webs/Typings/main.ts deleted file mode 100644 index 05ea8fb35..000000000 --- a/sample/Util.Samples.Webs/Typings/main.ts +++ /dev/null @@ -1,14 +0,0 @@ -import 'reflect-metadata'; -import 'zone.js'; -import 'es6-shim'; -import 'hammerjs'; -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { AppModule } from "./app/app.module"; - -if (module.hot) { - module.hot.accept(); -} else { - enableProdMode(); -} -platformBrowserDynamic().bootstrapModule(AppModule).catch(ex => console.log(ex)); \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/test/karma-main.ts b/sample/Util.Samples.Webs/Typings/test/karma-main.ts deleted file mode 100644 index f5e37a4c0..000000000 --- a/sample/Util.Samples.Webs/Typings/test/karma-main.ts +++ /dev/null @@ -1,25 +0,0 @@ -import 'babel-polyfill'; -import 'reflect-metadata'; -import 'zone.js'; -import 'zone.js/dist/long-stack-trace-zone'; -import 'zone.js/dist/proxy.js'; -import 'zone.js/dist/sync-test'; -import 'zone.js/dist/jasmine-patch'; -import 'zone.js/dist/async-test'; -import 'zone.js/dist/fake-async-test'; -import * as testing from '@angular/core/testing'; -import * as testingBrowser from '@angular/platform-browser-dynamic/testing'; - -declare var __karma__: any; -declare var require: any; - -__karma__.loaded = function () {}; - -testing.getTestBed().initTestEnvironment( - testingBrowser.BrowserDynamicTestingModule, - testingBrowser.platformBrowserDynamicTesting() -); - -const context = require.context('../', true, /\.test\.ts$/); -context.keys().map(context); -__karma__.start(); \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/test/karma.conf.js b/sample/Util.Samples.Webs/Typings/test/karma.conf.js deleted file mode 100644 index d463f06e9..000000000 --- a/sample/Util.Samples.Webs/Typings/test/karma.conf.js +++ /dev/null @@ -1,47 +0,0 @@ -const webpack = require('webpack'); - -module.exports = function (config) { - config.set({ - basePath: '.', - frameworks: ['jasmine'], - files: [ - '../../wwwroot/dist/polyfills.js', - '../../wwwroot/dist/vendor.js', - '../../wwwroot/dist/util.js', - './karma-main.ts' - ], - preprocessors: { - './karma-main.ts':['webpack'] - }, - reporters: ['progress'], - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['PhantomJS'], - mime: { 'application/javascript': ['ts'] }, - singleRun: false, - webpack: { - resolve: { - extensions: ['.js', '.ts'] - }, - module: { - rules: [ - { test: /\.ts$/, include: /Typings/, use: ['awesome-typescript-loader?silent=true'] } - ] - }, - plugins: [ - new webpack.DllReferencePlugin({ - manifest: require('../../wwwroot/dist/polyfills-manifest.json') - }), - new webpack.DllReferencePlugin({ - manifest: require('../../wwwroot/dist/vendor-manifest.json') - }), - new webpack.DllReferencePlugin({ - manifest: require('../../wwwroot/dist/util-manifest.json') - }) - ] - }, - webpackMiddleware: { stats: 'errors-only' } - }); -} diff --git a/sample/Util.Samples.Webs/Typings/test/util/common/helper.test.ts b/sample/Util.Samples.Webs/Typings/test/util/common/helper.test.ts deleted file mode 100644 index 4d9ab7d91..000000000 --- a/sample/Util.Samples.Webs/Typings/test/util/common/helper.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -//============== Util公共操作测试================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { util } from "../../../util" - -describe("util.helper", () => { - it("isEmpty", () => { - expect(util.helper.isEmpty(undefined)).toBeTruthy("undefined"); - expect(util.helper.isEmpty(null)).toBeTruthy("null"); - expect(util.helper.isEmpty("")).toBeTruthy("''"); - expect(util.helper.isEmpty(" ")).toBeTruthy("' '"); - expect(util.helper.isEmpty(0)).toBeFalsy("0"); - expect(util.helper.isEmpty("0")).toBeFalsy("'0'"); - expect(util.helper.isEmpty("00000000-0000-0000-0000-000000000000")).toBeTruthy("00000000-0000-0000-0000-000000000000"); - expect(util.helper.isEmpty("4ABCA27E-EAFC-4DEE-B809-8DD2ABDFDA1C")).toBeFalsy("4ABCA27E-EAFC-4DEE-B809-8DD2ABDFDA1C"); - expect(util.helper.isEmpty("6")).toBeFalsy("'6'"); - expect(util.helper.isEmpty(6)).toBeFalsy("6"); - expect(util.helper.isEmpty("a6")).toBeFalsy("a6"); - }); - it("isNumber", () => { - expect(util.helper.isNumber(1)).toBeTruthy("1"); - expect(util.helper.isNumber("1")).toBeTruthy("'1'"); - expect(util.helper.isNumber("")).toBeFalsy("''"); - expect(util.helper.isNumber("a")).toBeFalsy("'a'"); - }); - it("toNumber", () => { - expect(util.helper.toNumber("a")).toEqual(0, "a"); - expect(util.helper.toNumber("0")).toEqual(0, "0"); - expect(util.helper.toNumber("1")).toEqual(1, "1"); - expect(util.helper.toNumber("1.5")).toEqual(1.5, "1.5"); - expect(util.helper.toNumber("1.5", 0)).toEqual(2, "1.5,0"); - expect(util.helper.toNumber("1.5", 0, true)).toEqual(1, "1.5,0,true"); - expect(util.helper.toNumber("8.99999999999999999", 0)).toEqual(9); - expect(util.helper.isNumber(util.helper.toNumber("8.99999999999999999", 0))).toBeTruthy(); - expect(util.helper.toNumber("8.99999999999999999", 2, true)).toEqual(8.99); - expect(util.helper.toNumber(1.567, 1, true)).toEqual(1.5); - expect(util.helper.isNumber(util.helper.toNumber("8.99999999999999999", 2, true))).toBeTruthy(); - }); - it("isEmptyArray", () => { - expect(util.helper.isEmptyArray(undefined)).toBeFalsy(); - expect(util.helper.isEmptyArray(null)).toBeFalsy(); - expect(util.helper.isEmptyArray([])).toBeTruthy(); - expect(util.helper.isEmptyArray([1])).toBeFalsy(); - }); - it("isValidDate", () => { - expect(util.helper.isValidDate("1999-09-09")).toBeTruthy(); - expect(util.helper.isValidDate("1999-9-9")).toBeTruthy(); - }); - it("toDate", () => { - expect(util.helper.isValidDate(util.helper.toDate("1999-09-09"))).toBeTruthy(); - expect(util.helper.toDate("1999-09-09").getFullYear()).toBe(1999); - expect(util.helper.toDate("1999-09-09").getMonth()).toBe(8); - expect(util.helper.toDate("1999-09-09").getDate()).toBe(9); - expect(util.helper.isValidDate(util.helper.toDate("1999-9-9"))).toBeTruthy(); - expect(util.helper.toDate("1999-9-9 1:2:3").getFullYear()).toBe(1999); - expect(util.helper.toDate("1999-9-9 1:2:3").getMonth()).toBe(8); - expect(util.helper.toDate("1999-9-9 1:2:3").getDate()).toBe(9); - expect(util.helper.toDate("1999-9-9 1:2:3").getHours()).toBe(1); - expect(util.helper.toDate("1999-9-9 1:2:3").getMinutes()).toBe(2); - expect(util.helper.toDate("1999-9-9 1:2:3").getSeconds()).toBe(3); - }); - it("formatDate", () => { - var date = new Date(2014, 11, 30, 1, 20, 15, 285); - expect(util.helper.formatDate(date, "YYYY-MM-DD HH:mm:ss:SSS")).toBe("2014-12-30 01:20:15:285"); - expect(util.helper.formatDate(date, "YYYY年MM月DD日 HH:mm:ss")).toBe("2014年12月30日 01:20:15"); - - expect(util.helper.formatDate("1999-09-09", "YYYY年MM月DD日")).toBe("1999年09月09日"); - expect(util.helper.formatDate("1999-9-9", "YYYY年MM月DD日")).toBe("1999年09月09日"); - }); - it("getValidDate", () => { - expect(util.helper.getValidDate("1999-09-09")).toBe("1999-09-09"); - expect(util.helper.getValidDate("1999-9-9")).toBe("1999-09-09"); - expect(util.helper.getValidDate("1999-9-9 1:2")).toBe("1999-09-09 01:02"); - expect(util.helper.getValidDate("1999-9-9 1:2:3")).toBe("1999-09-09 01:02:03"); - }); -}); diff --git a/sample/Util.Samples.Webs/Typings/test/util/core/select.test.ts b/sample/Util.Samples.Webs/Typings/test/util/core/select.test.ts deleted file mode 100644 index 701b9bb0d..000000000 --- a/sample/Util.Samples.Webs/Typings/test/util/core/select.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -//============== Util列表操作测试================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import {Select,SelectItem} from '../../../util/core/select'; - -describe("select", () => { - it("toOptions_1", () => { - let data: SelectItem[] = [{text:"a",value:"1"}]; - let select = new Select(data); - let result = select.toOptions(); - expect(result.length).toBe(1); - expect(result[0].text).toBe("a"); - expect(result[0].value).toBe("1"); - }); - it("toOptions_2", () => { - let data: SelectItem[] = [{ text: "a", value: "1" }, { text: "b", value: "2",disabled:true }]; - let select = new Select(data); - let result = select.toOptions(); - expect(result.length).toBe(2); - expect(result[0].text).toBe("a"); - expect(result[0].value).toBe("1"); - expect(result[0].disabled).toBeFalsy(); - expect(result[1].text).toBe("b"); - expect(result[1].value).toBe("2"); - expect(result[1].disabled).toBeTruthy(); - }); - it("toGroups_1", () => { - let data: SelectItem[] = [{ text: "a", value: "1", group: "group" }, { text: "b", value: "2", disabled: true, group: "group"}]; - let select = new Select(data); - let result = select.toGroups(); - expect(result.length).toBe(1); - expect(result[0].text).toBe("group"); - let value = result[0].value; - expect(value && value[0].text).toBe("a"); - expect(value && value[0].value).toBe("1"); - expect(value && value[1].text).toBe("b"); - expect(value && value[1].value).toBe("2"); - }); - it("toGroups_2", () => { - let data: SelectItem[] = [{ text: "a", value: "1", group: "group", sortId: 3 }, - { text: "b", value: "2", group: "group", sortId: 1 }, - { text: "c", value: "3", group: "group", sortId: 2 }]; - let select = new Select(data); - let result = select.toGroups(); - expect(result.length).toBe(1); - expect(result[0].text).toBe("group"); - let value = result[0].value; - expect(value && value[0].text).toBe("b"); - expect(value && value[0].value).toBe("2"); - expect(value && value[1].text).toBe("c"); - expect(value && value[1].value).toBe("3"); - expect(value && value[2].text).toBe("a"); - expect(value && value[2].value).toBe("1"); - }); - it("toGroups_3", () => { - let data: SelectItem[] = [{ text: "a", value: "1", group: "group", sortId: 3 }, - { text: "b", value: "2", group: "group", sortId: 2 }, - { text: "c", value: "3", group: "group2", sortId: 4 }, - { text: "d", value: "4", group: "group2", sortId: 1 }]; - let select = new Select(data); - let result = select.toGroups(); - expect(result.length).toBe(2); - expect(result[0].text).toBe("group2"); - expect(result[1].text).toBe("group"); - let group1 = result[0].value; - expect(group1 && group1[0].text).toBe("d"); - expect(group1 && group1[0].value).toBe("4"); - expect(group1 && group1[1].text).toBe("c"); - expect(group1 && group1[1].value).toBe("3"); - let group2 = result[1].value; - expect(group2 && group2[0].text).toBe("b"); - expect(group2 && group2[0].value).toBe("2"); - expect(group2 && group2[1].text).toBe("a"); - expect(group2 && group2[1].value).toBe("1"); - }); - it("isGroup_1", () => { - let data: SelectItem[] = [{ text: "a", value: "1" }, { text: "b", value: "2", disabled: true }]; - let select = new Select(data); - expect(select.isGroup()).toBeFalsy(); - }); - it("isGroup_2", () => { - let data: SelectItem[] = [{ text: "a", value: "1",group:"a" }, { text: "b", value: "2", disabled: true }]; - let select = new Select(data); - expect(select.isGroup()).toBeFalsy(); - }); - it("isGroup_3", () => { - let data: SelectItem[] = [{ text: "a", value: "1", group: "a" }, { text: "b", value: "2", disabled: true, group: "a" }]; - let select = new Select(data); - expect(select.isGroup()).toBeTruthy(); - }); -}); \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/angular/event-helper.ts b/sample/Util.Samples.Webs/Typings/util/angular/event-helper.ts deleted file mode 100644 index 14bb6432f..000000000 --- a/sample/Util.Samples.Webs/Typings/util/angular/event-helper.ts +++ /dev/null @@ -1,19 +0,0 @@ -//============== 事件操作========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ - -/** - * 事件操作 - */ -export class EventHelper { - /** - * 获取事件传递的值 - * @param event 事件 - */ - static getValue(event): TResult { - if (event && event.target ) - return event.target.value; - return event; - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/angular/http-helper.ts b/sample/Util.Samples.Webs/Typings/util/angular/http-helper.ts deleted file mode 100644 index a24ed5ef6..000000000 --- a/sample/Util.Samples.Webs/Typings/util/angular/http-helper.ts +++ /dev/null @@ -1,231 +0,0 @@ -//============== Http操作========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { HttpClient, HttpHeaders, HttpParams, HttpErrorResponse } from '@angular/common/http'; -import { IocHelper as ioc } from './ioc-helper'; -import { Observable } from 'rxjs/Observable'; - -/** - * Http操作 - */ -export class HttpHelper { - /** - * 发送请求 - * @param url 请求地址 - * @param httpMethod http方法 - * @param data 数据 - */ - static send(url: string, httpMethod: HttpMethod, data?): HttpRequest { - switch (httpMethod) { - case HttpMethod.Get: - return this.get(url).param(data); - case HttpMethod.Post: - return this.post(url, data); - case HttpMethod.Put: - return this.put(url, data); - case HttpMethod.Delete: - return this.delete(url).param(data); - default: - return this.get(url).param(data); - } - } - - /** - * get请求 - * @param url 请求地址 - */ - static get(url: string): HttpRequest { - return new HttpRequest(HttpMethod.Get, url); - } - - /** - * post请求 - * @param url 请求地址 - * @param body Http主体 - */ - static post(url: string, body?): HttpRequest { - return new HttpRequest(HttpMethod.Post, url, body); - } - - /** - * put请求 - * @param url 请求地址 - * @param body Http主体 - */ - static put(url: string, body?): HttpRequest { - return new HttpRequest(HttpMethod.Put, url, body); - } - - /** - * delete请求 - * @param url 请求地址 - */ - static delete(url: string): HttpRequest { - return new HttpRequest(HttpMethod.Delete, url); - } -} - -/** - * Http请求操作 - */ -export class HttpRequest { - /** - * Http头集合 - */ - private headers: HttpHeaders; - /** - * 内容类型 - */ - private httpContentType: HttpContentType; - /** - * Http参数集合 - */ - private parameters: HttpParams; - - /** - * 初始化Http请求操作 - * @param httpMethod Http方法 - * @param url 请求地址 - * @param body Http主体 - */ - constructor(private httpMethod: HttpMethod, private url: string, private body?) { - this.headers = new HttpHeaders(); - this.parameters = new HttpParams(); - } - - /** - * 添加Http头 - * @param name 名称 - * @param value 值 - */ - header(name: string, value): HttpRequest { - let stringValue = ""; - if (value !== undefined && value !== null) - stringValue = String(value); - this.headers = this.headers.append(name, stringValue ); - return this; - } - - /** - * 设置内容类型 - * @param contentType 内容类型 - */ - contentType(contentType: HttpContentType): HttpRequest { - this.httpContentType = contentType; - return this; - } - - /** - * 添加Http参数,添加到url查询字符串 - * @param data 参数对象 - */ - param(data): HttpRequest; - /** - * 添加Http参数,添加到url查询字符串 - * @param name 名称 - * @param value 值 - */ - param(name: string, value: string): HttpRequest; - param(data, value?: string): HttpRequest { - if (typeof data === "object") { - for (let key in data) { - if (data.hasOwnProperty(key)) - this.parameters = this.parameters.append(key, data[key]); - } - return this; - } - if (typeof data === "string" && value) - this.parameters = this.parameters.append(data, value); - return this; - } - - /** - * 处理响应 - * @param handler 响应处理函数 - * @param errorHandler 错误处理函数 - * @param beforeHandler 发送前处理函数,返回false则取消发送 - * @param completeHandler 请求完成处理函数 - */ - handle(handler: (value: T) => void, errorHandler?: (error: HttpErrorResponse) => void, beforeHandler?: () => boolean, completeHandler?: () => void) { - if (beforeHandler && beforeHandler() === false) - return; - this.request().subscribe(handler, errorHandler, completeHandler); - } - - /** - * 发送请求 - */ - private request(): Observable { - this.setContentType(); - let httpClient = ioc.get(HttpClient); - let options = { headers: this.headers, params: this.parameters }; - switch (this.httpMethod) { - case HttpMethod.Get: - return httpClient.get(this.url, options); - case HttpMethod.Post: - return httpClient.post(this.url, this.getBody(), options); - case HttpMethod.Put: - return httpClient.put(this.url, this.getBody(), options); - case HttpMethod.Delete: - return httpClient.delete(this.url, options); - default: - return httpClient.get(this.url, options); - } - } - - /** - * 获取body - */ - private getBody() { - if (typeof this.body === "string") - return JSON.stringify(this.body); - return this.body; - } - - /** - * 设置内容类型 - */ - private setContentType() { - return this.header("Content-Type", this.getContentType(this.httpContentType)); - } - - /** - * 获取内容类型 - * @param contentType - */ - private getContentType(contentType: HttpContentType) { - switch (contentType) { - case HttpContentType.FormUrlEncoded: - return "application/x-www-form-urlencoded"; - case HttpContentType.Json: - return "application/json"; - default: - return "application/json"; - } - } -} - -/** - * Http方法 - */ -export enum HttpMethod { - Get, - Post, - Put, - Delete -} - -/** - * Http内容类型 - */ -export enum HttpContentType { - /** - * application/x-www-form-urlencoded - */ - FormUrlEncoded, - /** - * application/json - */ - Json -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/angular/ioc-helper.ts b/sample/Util.Samples.Webs/Typings/util/angular/ioc-helper.ts deleted file mode 100644 index 294e62181..000000000 --- a/sample/Util.Samples.Webs/Typings/util/angular/ioc-helper.ts +++ /dev/null @@ -1,35 +0,0 @@ -//============== Ioc操作========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Injector, Type, InjectionToken } from '@angular/core'; - -/** - * Ioc操作 - */ -export class IocHelper { - /** - * 全局注入器 - */ - static injector: Injector; - /** - * 当前组件注入器 - */ - static componentInjector: Injector; - - /** - * 获取实例,从全局注入器中获取 - * @param token 实例标记,一般为类或接口名称,范例:util.ioc.get(Http) - */ - static get(token: Type | InjectionToken): T { - return IocHelper.injector.get(token); - } - - /** - * 获取实例,从当前组件注入器中获取 - * @param token 实例标记,一般为类或接口名称,范例:util.ioc.getByComponent(Http) - */ - static getByComponent(token: Type | InjectionToken): T { - return IocHelper.componentInjector.get(token); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/angular/router-helper.ts b/sample/Util.Samples.Webs/Typings/util/angular/router-helper.ts deleted file mode 100644 index fe520e80c..000000000 --- a/sample/Util.Samples.Webs/Typings/util/angular/router-helper.ts +++ /dev/null @@ -1,48 +0,0 @@ -//============== 路由操作========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Router, ActivatedRoute, NavigationExtras } from '@angular/router'; -import { Location } from '@angular/common'; -import { IocHelper as ioc } from './ioc-helper'; - -/** - * 路由操作 - */ -export class RouterHelper { - /** - * 返回上一次视图 - */ - static back(): void { - let location: Location = ioc.get(Location); - location.back(); - } - - /** - * 导航 - * @param commands 导航参数,范例: ['team', 33, 'user', 11],表示 /team/33/user/11 - * @param extras 附加参数,范例: {queryParams: {id:'1'}},表示 ?id=1 - */ - static navigate(commands: any[], extras?: NavigationExtras): Promise { - let router = ioc.get(Router); - return router.navigate(commands, extras); - } - - /** - * 获取当前路由参数值,从路由快照中获取参数 - * @param paramName 参数名 - */ - static getParam(paramName: string): string | null { - let route = ioc.getByComponent(ActivatedRoute); - return route.snapshot.paramMap.get(paramName); - } - - /** - * 获取当前路由参数值,从路由快照中的查询字符串获取参数 - * @param paramName 参数名 - */ - static getQueryParam(paramName: string): string | null { - let route = ioc.getByComponent(ActivatedRoute); - return route.snapshot.queryParamMap.get(paramName); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/common/form.ts b/sample/Util.Samples.Webs/Typings/util/common/form.ts deleted file mode 100644 index 1f74a7f5d..000000000 --- a/sample/Util.Samples.Webs/Typings/util/common/form.ts +++ /dev/null @@ -1,183 +0,0 @@ -//============== 表单操作 ======================== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { NgForm } from '@angular/forms'; -import { FailResult } from '../core/result'; -import { ViewModel } from '../core/view-model'; -import { HttpMethod } from '../angular/http-helper'; -import { WebApi } from './webapi'; -import { RouterHelper } from '../angular/router-helper'; -import { Message } from './message'; -import { MessageConfig } from '../config/message-config'; - -/** - * 表单操作 - */ -export class Form { - /** - * 提交表单 - * @param options 表单提交参数 - */ - submit(options: IFormSubmitOptions): void { - this.initSubmit(options); - if (!this.validateSubmit(options)) { - options["fnComplete"](); - return; - } - if (!this.submitBefore(options)) { - options["fnComplete"](); - return; - } - if (!options.confirm) { - this.submitForm(options); - return; - } - Message.confirm({ - title: options.confirmTitle, - message: options.confirm, - ok: () => this.submitForm(options), - cancel: options["fnComplete"] - }); - } - - /** - * 提交表单初始化 - */ - private initSubmit(options: IFormSubmitOptions) { - if (!options) - return; - options["fnComplete"] = () => { - if (options.form) - (options.form as { submitted: boolean }).submitted = false; - options.completeHandler && options.completeHandler(); - }; - } - - /** - * 提交表单验证 - */ - private validateSubmit(options: IFormSubmitOptions) { - if (!options) { - Message.error("表单参数[options: FormSubmitOptions]未设置"); - return false; - } - if (!options.url) { - Message.error("表单url未设置"); - return false; - } - if (!options.form) { - Message.error("表单ngForm未设置"); - return false; - } - if (!options.data) { - Message.error("表单数据未设置"); - return false; - } - return true; - } - - /** - * 提交前操作 - */ - private submitBefore(options: IFormSubmitOptions) { - if (!options.beforeHandler) - return true; - return options.beforeHandler(); - } - - /** - * 提交表单 - */ - private submitForm(options: IFormSubmitOptions) { - if (!options.httpMethod) { - options.httpMethod = options.data.id ? HttpMethod.Put : HttpMethod.Post; - } - WebApi.send(options.url, options.httpMethod, options.data).header(options.header).handle({ - handler: result => { - this.submitHandler(options, result); - }, - failHandler: options.failHandler, - completeHandler: options["fnComplete"] - }); - } - - /** - * 提交表单成功处理函数 - */ - private submitHandler(options: IFormSubmitOptions, result) { - options.handler && options.handler(result); - if (options.showMessage !== false) - Message.snack(MessageConfig.successed); - if (options.reset) - options.form.resetForm(); - if (options.back) - RouterHelper.back(); - } -} - -/** - * 表单提交参数 - */ -export interface IFormSubmitOptions { - /** - * 表单 - */ - form: NgForm; - /** - * 请求地址 - */ - url: string; - /** - * 提交数据 - */ - data: ViewModel; - /** - * Http头 - */ - header?: { name: string, value }[]; - /** - * Http方法 - */ - httpMethod?: HttpMethod; - /** - * 确认消息,设置该项则提交前需要确认 - */ - confirm?: string; - /** - * 确认标题 - */ - confirmTitle?: string; - /** - * 提交成功后是否显示成功提示,默认为true - */ - showMessage?: boolean; - /** - * 提交成功后是否返回上一个视图,默认为false - */ - back?: boolean; - /** - * 提交成功后是否关闭弹出层,当在弹出层中编辑时使用,默认为false - */ - closeDialog?: boolean; - /** - * 提交成功后是否重置表单,默认为false - */ - reset?: boolean; - /** - * 提交前处理函数,返回false则取消提交 - */ - beforeHandler?: () => boolean; - /** - * 提交成功处理函数 - */ - handler?: (result) => void; - /** - * 提交失败处理函数 - */ - failHandler?: (result: FailResult) => void; - /** - * 操作完成处理函数,注意:该函数在任意情况下都会执行 - */ - completeHandler?: () => void; -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/common/helper.ts b/sample/Util.Samples.Webs/Typings/util/common/helper.ts deleted file mode 100644 index 57852f2e0..000000000 --- a/sample/Util.Samples.Webs/Typings/util/common/helper.ts +++ /dev/null @@ -1,172 +0,0 @@ -//============== 公共操作========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { UUID } from './internal/uuid'; -import * as moment from 'moment'; - -/** - * 是否未定义 - * @param value 值 - */ -export let isUndefined = (value): boolean => { - return typeof value === 'undefined'; -} - -/** - * 是否字符串 - * @param value 值 - */ -export let isString = (value): boolean => { - return typeof value === 'string'; -} - -/** - * 是否空值,当值为undefined、null、空字符串、空Guid时返回true,其余返回false - * @param value 值 - */ -export let isEmpty = (value): boolean => { - if (isUndefined(value)) - return true; - if (value === null) - return true; - if (!isString(value)) - return false; - if (value && value.trim) - value = value.trim(); - if (!value) - return true; - if (value === "00000000-0000-0000-0000-000000000000") - return true; - return false; -} - -/** - * 是否数字,字符串"1"返回true - * @param value 值 - */ -export let isNumber = (value): boolean => { - return !isNaN(parseFloat(value)) && isFinite(value); -} - -/** - * 转换为数值 - * @param value 输入值 - * @param precision 数值精度,即小数位数,可选值为0-20 - * @param isTruncate 是否截断,传入true,则按精度截断,否则四舍五入 - */ -export let toNumber = (value, precision?, isTruncate?: boolean) => { - if (!isNumber(value)) - return 0; - value = value.toString(); - if (isEmpty(precision)) - return parseFloat(value); - if (isTruncate) - return parseFloat(value.substring(0, value.indexOf(".") + parseInt(precision) + 1)); - return parseFloat(parseFloat(value).toFixed(precision)); -} - -/** - * 是否数组 - * @param value 值 - */ -export let isArray = (value): boolean => { - return Array.isArray(value); -} - -/** - * 是否空数组,undefined和null返回false,[]返回true - * @param value 值 - */ -export let isEmptyArray = (value): boolean => { - return isArray(value) && value.length === 0; -} - -/** - * 转换为json字符串 - * @param value 值 - */ -export let toJson = (value): string => { - return JSON.stringify(value); -} - -/** - * 创建唯一标识 - */ -export let uuid = (): string => { - return UUID.UUID(); -} - -/** - * 是否有效日期 - * @param date 日期 - */ -export let isValidDate = (date): boolean => { - return moment(getValidDate(date)).isValid(); -} - -/** - * *获取有效的日期字符串,对无效日期补全前导0,不支持毫秒, - * 范例:2000-1-1 1:2:3,返回2000-01-01 01:02:03 - * @param date 日期 - */ -export let getValidDate = (date) => { - if (!date) - return date; - if (typeof date !== "string") - return date; - if (date.indexOf("-") <= 0) - return date; - let regex = /(\d{4})-(\d{1,2})-(\d{1,2})(?:(?:\s+)(\d{1,2}):(\d{1,2}):?(\d{1,2})?)?/; - if (!regex.test(date)) - return date; - let dateSegment = date.match(regex); - if (!dateSegment) - return date; - let year = dateSegment[1]; - let month = dateSegment[2]; - let day = dateSegment[3]; - let hour = dateSegment[4]; - let minute = dateSegment[5]; - let second = dateSegment[6]; - month = month.length === 1 ? `0${month}` : month; - day = day.length === 1 ? `0${day}` : day; - let result = `${year}-${month}-${day}`; - if (hour && minute) { - hour = hour.length === 1 ? `0${hour}` : hour; - minute = minute.length === 1 ? `0${minute}` : minute; - result += ` ${hour}:${minute}`; - } - if (second) { - second = second.length === 1 ? `0${second}` : second; - result += `:${second}`; - } - return result; -} - -/** - * 转换为日期 - * @param date 日期,字符串日期范例:2001-01-01 - */ -export let toDate = (date): Date => { - return moment(getValidDate(date)).toDate(); -} - -/** - * 格式化日期 - * @param datetime 日期 - * @param format 格式化字符串,范例:YYYY-MM-DD,可选值:(注意:区分大小写) - * (1) 年: YYYY - * (2) 月: MM - * (3) 日: DD - * (4) 时: HH - * (5) 分: mm - * (6) 秒: ss - * (7) 毫秒: SSS - */ -export let formatDate = (datetime, format: string): string => { - let date = moment(getValidDate(datetime)); - if (!date.isValid()) - return ""; - return date.format(format); -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/common/internal/uuid.ts b/sample/Util.Samples.Webs/Typings/util/common/internal/uuid.ts deleted file mode 100644 index 3b8fa218e..000000000 --- a/sample/Util.Samples.Webs/Typings/util/common/internal/uuid.ts +++ /dev/null @@ -1,36 +0,0 @@ -//Դhttps://github.com/wulfsolter/angular2-uuid/blob/master/src/uuid.ts -"use strict"; - -export class UUID { - - public static UUID(): string { - if (typeof (window) !== "undefined" && typeof (window.crypto) !== "undefined" && typeof (window.crypto.getRandomValues) !== "undefined") { - // If we have a cryptographically secure PRNG, use that - // http://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript - let buf: Uint16Array = new Uint16Array(8); - window.crypto.getRandomValues(buf); - return (this.pad4(buf[0]) + this.pad4(buf[1]) + "-" + this.pad4(buf[2]) + "-" + this.pad4(buf[3]) + "-" + this.pad4(buf[4]) + "-" + this.pad4(buf[5]) + this.pad4(buf[6]) + this.pad4(buf[7])); - } else { - // Otherwise, just use Math.random - // https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript - // https://stackoverflow.com/questions/11605068/why-does-jshint-argue-against-bitwise-operators-how-should-i-express-this-code - return this.random4() + this.random4() + "-" + this.random4() + "-" + this.random4() + "-" + - this.random4() + "-" + this.random4() + this.random4() + this.random4(); - } - } - - private static pad4(num: number): string { - let ret: string = num.toString(16); - while (ret.length < 4) { - ret = "0" + ret; - } - return ret; - } - - private static random4(): string { - return Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1); - } - -} diff --git a/sample/Util.Samples.Webs/Typings/util/common/message.ts b/sample/Util.Samples.Webs/Typings/util/common/message.ts deleted file mode 100644 index 1e08e68e9..000000000 --- a/sample/Util.Samples.Webs/Typings/util/common/message.ts +++ /dev/null @@ -1,152 +0,0 @@ -//============== 消息操作========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { MatSnackBar } from '@angular/material'; -import { MessageService } from 'primeng/components/common/messageservice'; -import { ConfirmationService } from 'primeng/primeng'; -import { IocHelper as ioc } from '../angular/ioc-helper'; - -/** - * 消息操作 - */ -export class Message { - /** - * 成功消息 - * @param message 消息 - * @param title 标题 - */ - static success(message: string, title?: string): void { - var service = ioc.get(MessageService); - service.add({ severity: 'success', summary: title || "成功", detail: message }); - } - - /** - * 信息消息 - * @param message 消息 - * @param title 标题 - */ - static info(message: string, title?: string): void { - var service = ioc.get(MessageService); - service.add({ severity: 'info', summary: title || "信息", detail: message }); - } - - /** - * 警告消息 - * @param message 消息 - * @param title 标题 - */ - static warn(message: string, title?: string): void { - var service = ioc.get(MessageService); - service.add({ severity: 'warn', summary: title || "警告", detail: message }); - } - - /** - * 错误消息 - * @param message 消息 - * @param title 标题 - */ - static error(message: string, title?: string): void { - var service = ioc.get(MessageService); - service.add({ severity: 'error', summary: title || "错误", detail: message }); - } - - /** - * 确认 - * @param options 配置 - */ - static confirm(options: { - /** - * 消息 - */ - message: string, - /** - * 确认回调函数 - */ - ok: () => void, - /** - * 取消回调函数 - */ - cancel?: () => void, - /** - * 标题 - */ - title?: string; - }): void; - /** - * 确认 - * @param message 消息 - * @param ok 确认回调函数 - */ - static confirm(message: string, ok?: () => void): void; - static confirm(options, ok?): void { - let service = ioc.get(ConfirmationService); - let message = ""; - let title = ""; - let cancel = () => { }; - if (typeof options === "object") { - message = options["message"]; - title = options["title"]; - ok = options["ok"]; - cancel = options["cancel"]; - } - else if (typeof options === "string") { - message = options; - } - service.confirm({ - message: message, - accept: ok, - reject: cancel, - header: title || "确认" - }); - } - - /** - * 小提示 - * @param options - */ - static snack(options: { - /** - * 消息 - */ - message: string; - /** - * 持续时间,单位:毫秒,默认值:2000 - */ - duration?: number; - /** - * 操作文本 - */ - actionLabel?: string; - /** - * 操作 - */ - action?: () => void; - }); - /** - * 小提示 - * @param message 消息 - */ - static snack(message: string); - static snack(options) { - let bar = ioc.get(MatSnackBar); - let message = ""; - let actionLabel = ""; - let action; - let duration; - if (typeof options === "object") { - message = options["message"]; - actionLabel = options["actionLabel"]; - action = options["action"]; - duration = options["duration"]; - } - else if (typeof options === "string") { - message = options; - } - let ref = bar.open(message, actionLabel || "关闭", { - duration: duration || 2000 - }); - if (action) - ref.onAction().subscribe(action); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/common/webapi.ts b/sample/Util.Samples.Webs/Typings/util/common/webapi.ts deleted file mode 100644 index 39c224368..000000000 --- a/sample/Util.Samples.Webs/Typings/util/common/webapi.ts +++ /dev/null @@ -1,239 +0,0 @@ -//============== WebApi操作========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { HttpErrorResponse } from '@angular/common/http'; -import { Result, FailResult, StateCode } from '../core/result'; -import { HttpHelper, HttpRequest, HttpContentType,HttpMethod } from '../angular/http-helper'; -import { Message } from './message'; - -/** - * WebApi操作,与服务端返回的标准result对象交互 - */ -export class WebApi { - /** - * 发送请求 - * @param url 请求地址 - * @param httpMethod http方法 - * @param data 数据 - */ - static send(url: string, httpMethod: HttpMethod, data?): WebApiRequest { - switch (httpMethod) { - case HttpMethod.Get: - return this.get(url).param(data); - case HttpMethod.Post: - return this.post(url, data); - case HttpMethod.Put: - return this.put(url, data); - case HttpMethod.Delete: - return this.delete(url).param(data); - default: - return this.get(url).param(data); - } - } - - /** - * get请求 - * @param url 请求地址 - */ - static get(url: string): WebApiRequest { - return new WebApiRequest(HttpHelper.get>(url)); - } - - /** - * post请求 - * @param url 请求地址 - * @param body Http主体 - */ - static post(url: string, body?): WebApiRequest { - return new WebApiRequest(HttpHelper.post>(url, body)); - } - - /** - * put请求 - * @param url 请求地址 - * @param body Http主体 - */ - static put(url: string, body?): WebApiRequest { - return new WebApiRequest(HttpHelper.put>(url, body)); - } - - /** - * delete请求 - * @param url 请求地址 - */ - static delete(url: string): WebApiRequest { - return new WebApiRequest(HttpHelper.delete>(url)); - } -} - -/** - * WebApi请求操作 - */ -export class WebApiRequest { - /** - * 初始化WebApi请求操作 - * @param request Http请求操作 - */ - constructor(private request: HttpRequest>) { - } - - /** - * 添加Http头 - * @param headers Http头集合 - */ - header(headers?: { name: string, value }[]): WebApiRequest; - /** - * 添加Http头 - * @param name 名称 - * @param value 值 - */ - header(name: string, value): WebApiRequest; - header(name, value?): WebApiRequest { - if (typeof name === "object") - this.addHeaders(name); - else if (typeof name === "string") - this.request.header(name, value); - return this; - } - - /** - * 添加Http头 - */ - private addHeaders(param) { - let headers = param as { name: string, value }[]; - if (!headers) - return; - headers.forEach(item => { - this.request.header(item.name, item.value); - }); - } - - /** - * 设置内容类型 - * @param contentType 内容类型 - */ - contentType(contentType: HttpContentType): WebApiRequest { - this.request.contentType(contentType); - return this; - } - - /** - * 添加Http参数,添加到url查询字符串 - * @param data 参数对象 - */ - param(data): WebApiRequest; - /** - * 添加Http参数,添加到url查询字符串 - * @param name 名称 - * @param value 值 - */ - param(name: string, value: string): WebApiRequest; - param(data, value?: string): WebApiRequest { - if (typeof data === "object") { - this.request.param(data); - return this; - } - if (typeof data === "string" && value) - this.request.param(data, value); - return this; - } - - /** - * 处理响应 - * @param options 响应处理器配置 - */ - handle(options: WebApiHandleOptions) { - if (!options) - return; - this.request.handle( - (result: Result) => this.handleOk(options, result), - (error: HttpErrorResponse) => this.handleFail(options, undefined, error), - options.beforeHandler, - options.completeHandler - ); - } - - /** - * 处理成功响应 - */ - private handleOk(options: WebApiHandleOptions, result: Result) { - if (!result) - return; - if (result.code === StateCode.Ok) { - options.handler && options.handler(result.data); - return; - } - this.handleFail(options, result); - } - - /** - * 处理失败响应 - */ - private handleFail(options: WebApiHandleOptions, result?: Result, errorResponse?: HttpErrorResponse) { - let failResult = new FailResult(result, errorResponse); - if (options.failHandler) { - options.failHandler(failResult); - return; - } - if (result) { - this.handleBusinessException(result); - return; - } - this.handleHttpException(options, failResult); - } - - /** - * 处理业务异常 - */ - private handleBusinessException(result: Result) { - if (result.code === StateCode.Fail) { - Message.error(result.message); - console.log(`业务异常:\n${result.message}` ); - } - } - - /** - * 处理Http异常 - */ - private handleHttpException(options: WebApiHandleOptions, failResult: FailResult) { - if (failResult.errorResponse) - console.log(this.getHttpExceptionMessage(failResult)); - if (options.completeHandler) - options.completeHandler(); - } - - /** - * 获取Http异常消息 - */ - private getHttpExceptionMessage(failResult: FailResult) { - if (!failResult.errorResponse) - return ""; - let error = failResult.errorResponse; - return `Http请求异常:\nUrl:${error.url}\n状态码:${error.status},${error.statusText}\n` - + `错误消息:${error.message}\n错误响应:\n ${error.error.text}\n`; - } -} - -/** - * WebApi响应处理器 - */ -export class WebApiHandleOptions { - /** - * 发送前处理函数,返回false则取消发送 - */ - beforeHandler?: () => boolean; - /** - * 成功处理函数 - */ - handler: (value: T) => void; - /** - * 失败处理函数 - */ - failHandler?: (result: FailResult) => void; - /** - * 请求完成处理函数 - */ - completeHandler?: () => void; -} - diff --git a/sample/Util.Samples.Webs/Typings/util/config/message-config.ts b/sample/Util.Samples.Webs/Typings/util/config/message-config.ts deleted file mode 100644 index 9e947d541..000000000 --- a/sample/Util.Samples.Webs/Typings/util/config/message-config.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * 提示消息配置 - */ -export class MessageConfig { - /** - * 清除 - */ - static clear = "清除"; - /** - * 取消 - */ - static cancel = "取消"; - /** - * 上传 - */ - static upload = "上传"; - /** - * 选择文件 - */ - static chooseFile = "选择文件"; - /** - * 重 置 - */ - static reset = "重 置"; - /** - * 提 交 - */ - static submit = "提 交"; - /** - * 重置项默认文本 - */ - static resetOptionText = "-- 请选择 --"; - /** - * 必填项默认验证消息 - */ - static requiredMessage = "该项必须填写"; - /** - * 最小长度默认验证消息 - */ - static minLengthMessage = "输入内容的长度必须大于{0}位"; - /** - * 电子邮件默认验证消息 - */ - static emailMessage = "请输入有效的电子邮件"; - /** - * 请选择待删除的记录 - */ - static deleteNotSelected = "请选择待删除的记录"; - /** - * 操作成功 - */ - static successed = "操作成功"; - /** - * 删除成功 - */ - static deleteSuccessed = "删除成功"; - /** - * 您确定删除选中的记录吗? - */ - static deleteConfirm = "您确定删除选中的记录吗?"; -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/core/component-base.ts b/sample/Util.Samples.Webs/Typings/util/core/component-base.ts deleted file mode 100644 index e1263ffb7..000000000 --- a/sample/Util.Samples.Webs/Typings/util/core/component-base.ts +++ /dev/null @@ -1,33 +0,0 @@ -//============== 组件基类========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Injector } from '@angular/core'; -import { IocHelper as ioc } from '../angular/ioc-helper'; -import { RouterHelper as router } from "../angular/router-helper"; -import { Util } from '../util'; - -/** - * 组件 - */ -export class ComponentBase { - /** - * 初始化组件 - * @param injector 注入器 - */ - constructor(injector: Injector) { - ioc.componentInjector = injector; - } - - /** - * 操作库 - */ - protected util = Util; - - /** - * 返回上一次视图 - */ - back(): void { - router.back(); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/core/file-info.ts b/sample/Util.Samples.Webs/Typings/util/core/file-info.ts deleted file mode 100644 index 84ed85612..000000000 --- a/sample/Util.Samples.Webs/Typings/util/core/file-info.ts +++ /dev/null @@ -1,43 +0,0 @@ -//============== 文件信息========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -/** - * 文件信息 - */ -export class FileInfo { - /** - * 标识 - */ - id: string; - /** - * 文件地址 - */ - url: string; - /** - * 文件名 - */ - fileName: string; - /** - * 扩展名 - */ - extension: string; - /** - * 文件类型 - */ - type: FileType; -} - -/** - * 文件类型 - */ -export enum FileType { - /** - * 图片 - */ - Image = 1, - /** - * 其它 - */ - Other = 2 -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/core/pager-list.ts b/sample/Util.Samples.Webs/Typings/util/core/pager-list.ts deleted file mode 100644 index 732056a1c..000000000 --- a/sample/Util.Samples.Webs/Typings/util/core/pager-list.ts +++ /dev/null @@ -1,58 +0,0 @@ -//============== 分页集合========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -/** - * 分页集合 - */ -export class PagerList { - /** - * 初始化分页集合 - * @param list 分页集合 - */ - constructor(list?: PagerList) { - if (!list) - return; - this.page = list.page; - this.pageSize = list.pageSize; - this.totalCount = list.totalCount; - this.pageCount = list.pageCount; - this.order = list.order; - this.data = list.data; - } - - /** - * 页索引,即第几页 - */ - page: number; - /** - * 每页显示行数 - */ - pageSize: number; - /** - * 总行数 - */ - totalCount: number; - /** - * 总页数 - */ - pageCount: number; - /** - * 排序条件 - */ - order: string; - /** - * 数据 - */ - data: T[]; - - /** - * 初始化行号 - */ - initLineNumbers(): void { - for (let i = 0; i < this.data.length; i++) { - let line = (this.page - 1) * this.pageSize + i + 1; - this.data[i]["lineNumber"] = line; - } - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/core/query-parameter.ts b/sample/Util.Samples.Webs/Typings/util/core/query-parameter.ts deleted file mode 100644 index 2957ade92..000000000 --- a/sample/Util.Samples.Webs/Typings/util/core/query-parameter.ts +++ /dev/null @@ -1,25 +0,0 @@ -//============== 查询参数========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -/** - * 查询参数 - */ -export class QueryParameter { - /** - * 页索引,即第几页 - */ - page: number; - /** - * 每页显示行数 - */ - pageSize: number; - /** - * 排序条件 - */ - order: string; - /** - * 搜索关键字 - */ - keyword:string; -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/core/result.ts b/sample/Util.Samples.Webs/Typings/util/core/result.ts deleted file mode 100644 index cd7578b9e..000000000 --- a/sample/Util.Samples.Webs/Typings/util/core/result.ts +++ /dev/null @@ -1,62 +0,0 @@ -//============== 服务端结果约定格式=============== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { HttpErrorResponse } from '@angular/common/http'; - -/** - * 服务端返回的标准结果 - */ -export class Result { - /** - * 状态码 - */ - code: StateCode; - /** - * 消息 - */ - message: string; - /** - * 数据 - */ - data: T; -} - -/** - * 错误结果 - */ -export class FailResult { - /** - * - * @param result 结果 - * @param errorResponse Http错误响应 - */ - constructor(result?: Result, public errorResponse?: HttpErrorResponse) { - if (result) { - this.code = result.code; - this.message = result.message; - } - } - /** - * 状态码 - */ - code: StateCode; - /** - * 消息 - */ - message: string; -} - -/** - * 状态码 - */ -export enum StateCode { - /** - * 成功 - */ - Ok = 1, - /** - * 失败 - */ - Fail = 2 -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/core/select.ts b/sample/Util.Samples.Webs/Typings/util/core/select.ts deleted file mode 100644 index 6f8027d8e..000000000 --- a/sample/Util.Samples.Webs/Typings/util/core/select.ts +++ /dev/null @@ -1,124 +0,0 @@ -//============== 列表============================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { ISort, sort } from '../core/sort'; - -/** - * 列表 - */ -export class Select { - /** - * 初始化列表 - * @param items 列表项集合 - */ - constructor(private items: SelectItem[]) { - } - - /** - * 转换为下拉列表项集合 - */ - toOptions(): SelectOption[] { - return this.getSortedItems().map(value => new SelectOption(value)); - } - - /** - * 获取已排序的列表项集合 - */ - private getSortedItems() { - return sort(this.items); - } - - /** - * 转换为下拉列表组集合 - */ - toGroups(): SelectOptionGroup[] { - let result: SelectOptionGroup[] = new Array(); - this.getSortedItems().forEach(item => { - if (!item.group) - return; - let group = result.find(group => group.text === item.group); - if (group) { - group.value.push(new SelectOption(item)); - return; - } - result.push(new SelectOptionGroup(item.group, [new SelectOption(item)], false)); - }); - return result; - } - - /** - * 是否列表组 - */ - isGroup(): boolean { - return this.items.every(value => !!value.group); - } -} - -/** - * 列表项 - */ -export class SelectItem implements ISort { - /** - * 文本 - */ - text: string; - /** - * 值 - */ - value; - /** - * 禁用 - */ - disabled?: boolean; - /** - * 排序号 - */ - sortId?: number; - /** - * 组 - */ - group?: string; -} - -/** - * 下拉列表项 - */ -export class SelectOption { - /** - * 文本 - */ - text: string; - /** - * 值 - */ - value; - /** - * 禁用 - */ - disabled?: boolean; - - /** - * 初始化下拉列表项 - * @param item 列表项 - */ - constructor(item: SelectItem) { - this.text = item.text; - this.value = item.value; - this.disabled = item.disabled; - } -} - -/** - * 下拉列表组 - */ -export class SelectOptionGroup { - /** - * 初始化下拉列表组 - * @param text 文本 - * @param value 值 - * @param disabled 禁用 - */ - constructor(public text: string, public value: SelectOption[], public disabled?: boolean) { - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/core/sort.ts b/sample/Util.Samples.Webs/Typings/util/core/sort.ts deleted file mode 100644 index 4ef763bfa..000000000 --- a/sample/Util.Samples.Webs/Typings/util/core/sort.ts +++ /dev/null @@ -1,22 +0,0 @@ -//============== 排序 ============================ -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ - -/** - * 排序 - */ -export interface ISort { - /** - * 排序号 - */ - sortId?: number; -} - -/** - * 排序 - * @param array 数组 - */ -export function sort(array: T[]): T[] { - return array.sort((a, b) => (a.sortId === undefined || b.sortId === undefined) ? 0 : a.sortId - b.sortId); -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/core/tree-node.ts b/sample/Util.Samples.Webs/Typings/util/core/tree-node.ts deleted file mode 100644 index 2c0760bbf..000000000 --- a/sample/Util.Samples.Webs/Typings/util/core/tree-node.ts +++ /dev/null @@ -1,27 +0,0 @@ -//============== 树节点 ========================== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { ISort } from '../core/sort'; - -/** - * 树节点 - */ -export class TreeNode implements ISort{ - /** - * 标识 - */ - id?: string; - /** - * 父标识 - */ - parentId?: string; - /** - * 文本 - */ - text: string; - /** - * 排序号 - */ - sortId?: number; -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/core/view-model.ts b/sample/Util.Samples.Webs/Typings/util/core/view-model.ts deleted file mode 100644 index 8d5e68af1..000000000 --- a/sample/Util.Samples.Webs/Typings/util/core/view-model.ts +++ /dev/null @@ -1,13 +0,0 @@ -//============== 视图模型========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -/** - * 视图模型 - */ -export class ViewModel { - /** - * 标识 - */ - id: string; -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/index.ts b/sample/Util.Samples.Webs/Typings/util/index.ts deleted file mode 100644 index aeca9bc06..000000000 --- a/sample/Util.Samples.Webs/Typings/util/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -//============== util操作========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -export { Util as util } from './util'; -export { UtilModule } from './util.module'; -export { HttpContentType } from "./angular/http-helper"; -export { ComponentBase } from './core/component-base'; -export { ViewModel } from './core/view-model'; -export { PagerList } from './core/pager-list'; -export { QueryParameter } from './core/query-parameter'; -export { Result, FailResult, StateCode } from './core/result'; -export { SelectItem } from './core/select'; -export { TableWrapperComponent } from './material/table-wrapper.component'; -export { SelectWrapperComponent } from './material/select-wrapper.component'; -export { TextBoxWrapperComponent } from './material/textbox-wrapper.component'; -export { TextareaWrapperComponent } from './material/textarea-wrapper.component'; -export { DatePickerWrapperComponent } from './material/datepicker-wrapper.component'; -export { ButtonWrapperComponent } from './material/button-wrapper.component'; -export { RadioWrapperComponent } from './material/radio-wrapper.component'; \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/material/base/form-control-wrapper-base.ts b/sample/Util.Samples.Webs/Typings/util/material/base/form-control-wrapper-base.ts deleted file mode 100644 index 046647a4c..000000000 --- a/sample/Util.Samples.Webs/Typings/util/material/base/form-control-wrapper-base.ts +++ /dev/null @@ -1,163 +0,0 @@ -//============== 表单控件包装器=========================== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Input, Output, EventEmitter, ViewChild, Optional, Host, AfterViewInit } from '@angular/core'; -import { NgModel, NgForm } from '@angular/forms'; -import { MessageConfig } from '../../config/message-config'; - -/** - * 表单控件包装器 - */ -export class FormControlWrapperBase implements AfterViewInit{ - /** - * 名称 - */ - @Input() name: string; - /** - * 禁用 - */ - @Input() disabled: boolean; - /** - * 占位提示符 - */ - @Input() placeholder: string; - /** - * 占位提示符浮动位置,可选值:auto,never,always - */ - @Input() floatPlaceholder: string; - /** - * 起始提示,显示在控件左下方 - */ - @Input() startHint: string; - /** - * 结束提示,显示在控件右下方 - */ - @Input() endHint: string; - /** - * 前缀文本 - */ - @Input() prefixText: string; - /** - * 后缀文本 - */ - @Input() suffixText: string; - /** - * 后缀FontAwesome图标 - */ - @Input() suffixFontAwesomeIcon: string; - /** - * 后缀Material图标 - */ - @Input() suffixMaterialIcon: string; - /** - * 必填项 - */ - @Input() required: boolean; - /** - * 必填项验证消息 - */ - @Input() requiredMessage: string; - /** - * 后缀图标单击事件 - */ - @Output() onSuffixIconClick = new EventEmitter(); - /** - * 模型,用于双向绑定 - */ - @Input() model; - /** - * 模型变更事件,用于双向绑定 - */ - @Output() modelChange = new EventEmitter(); - /** - * 变更事件 - */ - @Output() onChange = new EventEmitter(); - /** - * 获得焦点事件 - */ - @Output() onFocus = new EventEmitter(); - /** - * 失去焦点事件 - */ - @Output() onBlur = new EventEmitter(); - /** - * 键盘按键事件 - */ - @Output() onKeyup = new EventEmitter(); - /** - * 键盘按下事件 - */ - @Output() onKeydown = new EventEmitter(); - /** - * 控件模型 - */ - @ViewChild('controlModel') controlModel: NgModel; - - /** - * 表单控件包装器 - * @param form 表单 - */ - constructor( @Optional() @Host() private form: NgForm) { - this.floatPlaceholder = "auto"; - this.requiredMessage = MessageConfig.requiredMessage; - } - - /** - * 视图加载完成 - */ - ngAfterViewInit(): void { - this.form && this.form.addControl(this.controlModel); - } - - /** - * 获取值 - */ - get value() { - return this.controlModel.value; - } - - /** - * 模型变更事件处理 - */ - protected onModelChange(value) { - this.modelChange.emit(value); - this.onChange.emit(value); - } - - /** - * 后缀图标单击事件 - */ - protected suffixIconClick() { - this.onSuffixIconClick.emit(); - } - - /** - * 获得焦点事件 - */ - protected focus(event: FocusEvent) { - this.onFocus.emit(event); - } - - /** - * 失去焦点事件 - */ - protected blur(event: FocusEvent) { - this.onBlur.emit(event); - } - - /** - * 键盘按键事件 - */ - protected keyup(event: KeyboardEvent) { - this.onKeyup.emit(event); - } - - /** - * 键盘按下事件 - */ - protected keydown(event: KeyboardEvent) { - this.onKeydown.emit(event); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/material/button-wrapper.component.ts b/sample/Util.Samples.Webs/Typings/util/material/button-wrapper.component.ts deleted file mode 100644 index 798d63919..000000000 --- a/sample/Util.Samples.Webs/Typings/util/material/button-wrapper.component.ts +++ /dev/null @@ -1,116 +0,0 @@ -//============== 按钮包装器===================== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Component, Input, Output, EventEmitter, Host, Optional, ContentChild, TemplateRef} from '@angular/core'; -import { NgForm } from '@angular/forms'; -import { MessageConfig } from '../config/message-config'; - -/** - * Mat按钮包装器 - */ -@Component({ - selector: 'mat-button-wrapper', - template:` - - - {{getText()}} - - - - {{getText()}} - - - - {{getText()}} - - - - {{getText()}} - - - - {{getText()}} - - - - ` -}) -export class ButtonWrapperComponent { - /** - * 文本 - */ - @Input() text: string; - /** - * 类型,可选值:button,reset,submit - */ - @Input() type: string; - /** - * Mat按钮样式,可选值:mat-button,mat-raised-button,mat-icon-button,mat-fab,mat-mini-fab - */ - @Input() style: string; - /** - * 颜色,可选值:primary,accent,warn - */ - @Input() color: string; - /** - * 禁用 - */ - @Input() disabled: boolean; - /** - * 提示 - */ - @Input() tooltip: string; - /** - * 单击事件 - */ - @Output() onClick = new EventEmitter(); - /** - * 模板,用来支持图标 - */ - @ContentChild(TemplateRef) template: TemplateRef; - - /** - * 初始化Mat按钮包装器 - * @param form 表单 - */ - constructor(@Optional() @Host() private form: NgForm) { - this.type = "button"; - } - - /** - * 是否禁用 - */ - private isDisabled() { - if (this.disabled !== undefined) - return this.disabled; - return this.type === 'submit' && this.form && (!this.form.valid || this.form.submitted); - } - - /** - * 获取文本 - */ - private getText() { - if (this.text !== undefined) - return this.text; - if (this.template) - return null; - if (this.type === 'reset') - return MessageConfig.reset; - if (this.type === 'submit') - return MessageConfig.submit; - return null; - } - - /** - * 单击事件 - */ - private click(event) { - this.onClick.emit(event); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/material/datepicker-wrapper.component.ts b/sample/Util.Samples.Webs/Typings/util/material/datepicker-wrapper.component.ts deleted file mode 100644 index 86099e53c..000000000 --- a/sample/Util.Samples.Webs/Typings/util/material/datepicker-wrapper.component.ts +++ /dev/null @@ -1,107 +0,0 @@ -//============== 日期选择包装器===================== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Component, Input, Host, Optional } from '@angular/core'; -import { NgForm } from '@angular/forms'; -import { FormControlWrapperBase } from './base/form-control-wrapper-base'; -import { MessageConfig } from '../config/message-config'; -import { toDate } from '../common/helper'; - -/** - * Mat日期选择包装器 - */ -@Component({ - selector: 'mat-datepicker-wrapper', - template: ` - - - - {{startHint}} - {{endHint}} - {{prefixText}} - - close - - - {{suffixMaterialIcon}} - - {{suffixText}} - {{requiredMessage}} - - `, - host: { - 'class': 'util-form-field', - } -}) -export class DatePickerWrapperComponent extends FormControlWrapperBase { - /** - * 清除按钮提示 - */ - private clearButtonTooltip: string; - /** - * 是否显示清除按钮 - */ - @Input() showClearButton: boolean; - /** - * 只读 - */ - @Input() readonly: boolean; - /** - * 起始视图,可选值:year,month - */ - @Input() startView: string; - /** - * 触摸模式 - */ - @Input() touchUi: boolean; - /** - * 宽度 - */ - @Input() width: number|undefined; - /** - * 最小日期 - */ - private min: string | Date; - /** - * 最小日期 - */ - @Input() - get minDate(): string | Date { - return this.min; - } - set minDate(value: string | Date) { - this.min = toDate(value); - } - /** - * 最大日期 - */ - private max: string | Date; - /** - * 最大日期 - */ - @Input() - get maxDate(): string | Date { - return this.max; - } - set maxDate(value: string | Date) { - this.max = toDate(value); - } - - /** - * 初始化Mat日期选择包装器 - * @param form 表单 - */ - constructor( @Optional() @Host() form: NgForm) { - super(form); - this.startView = 'month'; - this.readonly = true; - this.clearButtonTooltip = MessageConfig.clear; - this.showClearButton = true; - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/material/local/date-adapter.ts b/sample/Util.Samples.Webs/Typings/util/material/local/date-adapter.ts deleted file mode 100644 index f89ef23d4..000000000 --- a/sample/Util.Samples.Webs/Typings/util/material/local/date-adapter.ts +++ /dev/null @@ -1,252 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * 汉化:何镇汐 - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import { Inject, Injectable, Optional } from '@angular/core'; -import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material'; -import { formatDate, toDate } from "../../common/helper" - -/** The default month names to use if Intl API is not available. */ -const DEFAULT_MONTH_NAMES = { - 'long': [ - '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', - '十月', '十一月', '十二月' - ], - 'short': ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], - 'narrow': ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'] -}; - - -/** The default date names to use if Intl API is not available. */ -const DEFAULT_DATE_NAMES = range(31, i => String(i + 1)); - - -/** The default day of the week names to use if Intl API is not available. */ -const DEFAULT_DAY_OF_WEEK_NAMES = { - 'long': ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], - 'short': ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], - 'narrow': ['日', '一', '二', '三', '四', '五', '六'] -}; - - -/** - * Matches strings that have the form of a valid RFC 3339 string - * (https://tools.ietf.org/html/rfc3339). Note that the string may not actually be a valid date - * because the regex will match strings an with out of bounds month, date, etc. - */ -const ISO_8601_REGEX = - /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|(?:(?:\+|-)\d{2}:\d{2}))?)?$/; - - -/** Creates an array and fills it with values. */ -function range(length: number, valueFunction: (index: number) => T): T[] { - const valuesArray = Array(length); - for (let i = 0; i < length; i++) { - valuesArray[i] = valueFunction(i); - } - return valuesArray; -} - -/** Adapts the native JS Date for use with cdk-based components that work with dates. */ -@Injectable() -export class UtilDateAdapter extends DateAdapter { - /** - * Whether to use `timeZone: 'utc'` with `Intl.DateTimeFormat` when formatting dates. - * Without this `Intl.DateTimeFormat` sometimes chooses the wrong timeZone, which can throw off - * the result. (e.g. in the en-US locale `new Date(1800, 7, 14).toLocaleDateString()` - * will produce `'8/13/1800'`. - */ - useUtcForDisplay: boolean; - - constructor( @Optional() @Inject(MAT_DATE_LOCALE) matDateLocale: string) { - super(); - super.setLocale(matDateLocale); - - // IE does its own time zone correction, so we disable this on IE. - // TODO(mmalerba): replace with !platform.TRIDENT, logic currently duplicated to avoid breaking - // change from injecting the Platform. - this.useUtcForDisplay = !(typeof document === 'object' && !!document && - /(msie|trident)/i.test(navigator.userAgent)); - } - - getYear(date: Date): number { - return date.getFullYear(); - } - - getMonth(date: Date): number { - return date.getMonth(); - } - - getDate(date: Date): number { - return date.getDate(); - } - - getDayOfWeek(date: Date): number { - return date.getDay(); - } - - getMonthNames(style: 'long' | 'short' | 'narrow'): string[] { - return DEFAULT_MONTH_NAMES[style]; - } - - getDateNames(): string[] { - return DEFAULT_DATE_NAMES; - } - - getDayOfWeekNames(style: 'long' | 'short' | 'narrow'): string[] { - return DEFAULT_DAY_OF_WEEK_NAMES[style]; - } - - getYearName(date: Date): string { - return `${this.getYear(date)}年`; - } - - getFirstDayOfWeek(): number { - // We can't tell using native JS Date what the first day of the week is, we default to Sunday. - return 0; - } - - getNumDaysInMonth(date: Date): number { - return this.getDate(this._createDateWithOverflow( - this.getYear(date), this.getMonth(date) + 1, 0)); - } - - clone(date: Date): Date { - return this.createDate(this.getYear(date), this.getMonth(date), this.getDate(date)); - } - - createDate(year: number, month: number, date: number): Date { - // Check for invalid month and date (except upper bound on date which we have to check after - // creating the Date). - if (month < 0 || month > 11) { - throw Error(`Invalid month index "${month}". Month index has to be between 0 and 11.`); - } - - if (date < 1) { - throw Error(`Invalid date "${date}". Date has to be greater than 0.`); - } - - let result = this._createDateWithOverflow(year, month, date); - - // Check that the date wasn't above the upper bound for the month, causing the month to overflow - if (result.getMonth() != month) { - throw Error(`Invalid date "${date}" for month with index "${month}".`); - } - - return result; - } - - today(): Date { - return new Date(); - } - - parse(value: any): Date | null { - return toDate(value); - } - - format(date: Date, displayFormat: Object): string { - return this._stripDirectionalityCharacters(formatDate(date, "YYYY-MM-DD")); - } - - addCalendarYears(date: Date, years: number): Date { - return this.addCalendarMonths(date, years * 12); - } - - addCalendarMonths(date: Date, months: number): Date { - let newDate = this._createDateWithOverflow( - this.getYear(date), this.getMonth(date) + months, this.getDate(date)); - - // It's possible to wind up in the wrong month if the original month has more days than the new - // month. In this case we want to go to the last day of the desired month. - // Note: the additional + 12 % 12 ensures we end up with a positive number, since JS % doesn't - // guarantee this. - if (this.getMonth(newDate) != ((this.getMonth(date) + months) % 12 + 12) % 12) { - newDate = this._createDateWithOverflow(this.getYear(newDate), this.getMonth(newDate), 0); - } - - return newDate; - } - - addCalendarDays(date: Date, days: number): Date { - return this._createDateWithOverflow( - this.getYear(date), this.getMonth(date), this.getDate(date) + days); - } - - toIso8601(date: Date): string { - return [ - date.getUTCFullYear(), - this._2digit(date.getUTCMonth() + 1), - this._2digit(date.getUTCDate()) - ].join('-'); - } - - /** - * Returns the given value if given a valid Date or null. Deserializes valid ISO 8601 strings - * (https://www.ietf.org/rfc/rfc3339.txt) into valid Dates and empty string into null. Returns an - * invalid date for all other values. - */ - deserialize(value: any): Date | null { - if (typeof value === 'string') { - if (!value) { - return null; - } - // The `Date` constructor accepts formats other than ISO 8601, so we need to make sure the - // string is the right format first. - if (ISO_8601_REGEX.test(value)) { - let date = new Date(value); - if (this.isValid(date)) { - return date; - } - } - } - return super.deserialize(value); - } - - isDateInstance(obj: any) { - return obj instanceof Date; - } - - isValid(date: Date) { - return !isNaN(date.getTime()); - } - - invalid(): Date { - return new Date(NaN); - } - - /** Creates a date but allows the month and date to overflow. */ - private _createDateWithOverflow(year: number, month: number, date: number) { - let result = new Date(year, month, date); - - // We need to correct for the fact that JS native Date treats years in range [0, 99] as - // abbreviations for 19xx. - if (year >= 0 && year < 100) { - result.setFullYear(this.getYear(result) - 1900); - } - return result; - } - - /** - * Pads a number to make it two digits. - * @param n The number to pad. - * @returns The padded number. - */ - private _2digit(n: number) { - return ('00' + n).slice(-2); - } - - /** - * Strip out unicode LTR and RTL characters. Edge and IE insert these into formatted dates while - * other browsers do not. We remove them to make output consistent and because they interfere with - * date parsing. - * @param str The string to strip direction characters from. - * @returns The stripped string. - */ - private _stripDirectionalityCharacters(str: string) { - return str.replace(/[\u200e\u200f]/g, ''); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/material/radio-wrapper.component.ts b/sample/Util.Samples.Webs/Typings/util/material/radio-wrapper.component.ts deleted file mode 100644 index b2d338ed1..000000000 --- a/sample/Util.Samples.Webs/Typings/util/material/radio-wrapper.component.ts +++ /dev/null @@ -1,174 +0,0 @@ -//============== 单选按钮包装器=================== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Component, Input, Output, EventEmitter, OnInit, Host, Optional, ViewChild, AfterViewInit, ViewEncapsulation } from '@angular/core'; -import { NgModel,NgForm } from '@angular/forms'; -import { Select, SelectItem, SelectOption } from '../core/select'; -import { WebApi as webapi } from '../common/webapi'; - -/** - * Mat单选按钮包装器 - */ -@Component({ - selector: 'mat-radio-wrapper', - template:` - - {{label}} - - * - - - - - {{ item.text }} - - - - `, - host: { - 'class': 'util-form-field', - }, - styles: [` - .radio-layout-vertical { - display: inline-flex; - flex-direction: column; - } - .radio-label{ - margin-bottom: 8px; - color:rgba(0,0,0,.54); - } - .radio-required{ - color: red; - } - .radio-button-horizontal { - margin-right: 12px; - } - .radio-button-vertical { - margin-bottom: 5px; - } - `] -}) -export class RadioWrapperComponent implements OnInit, AfterViewInit { - /** - * 名称 - */ - @Input() name: string; - /** - * 是否垂直布局 - */ - @Input() vertical: boolean; - /** - * 是否显示标签 - */ - @Input() showLabel: boolean; - /** - * 标签文本 - */ - @Input() label: string; - /** - * 标签文本位置,可选值:'before', 'after' - */ - @Input() labelPosition: string; - /** - * 禁用 - */ - @Input() disabled: boolean; - /** - * 必填项 - */ - @Input() required: boolean; - /** - * 数据源 - */ - @Input() dataSource: SelectOption[]; - /** - * 请求地址 - */ - @Input() url: string; - /** - * 模型,用于双向绑定 - */ - @Input() model; - /** - * 模型变更事件,用于双向绑定 - */ - @Output() modelChange = new EventEmitter(); - /** - * 变更事件 - */ - @Output() onChange = new EventEmitter(); - /** - * 控件模型 - */ - @ViewChild('controlModel') controlModel: NgModel; - - /** - * 初始化Mat单选按钮包装器 - */ - constructor( @Optional() @Host() private form: NgForm) { - this.showLabel = true; - } - - /** - * 组件初始化 - */ - ngOnInit() { - if (this.dataSource) - return; - this.loadUrl(); - } - - /** - * 加载数据 - * @param data 列表项集合 - */ - loadData(data?: SelectItem[]) { - if (!data) - return; - let select = new Select(data); - this.dataSource = select.toOptions(); - } - - /** - * 从服务器加载 - * @param url 请求地址 - */ - loadUrl(url?: string) { - url = url || this.url; - if (!url) { - console.log("请设置单选按钮Url"); - return; - } - webapi.get(url).handle({ - handler: result => { - this.loadData(result); - } - }); - } - - /** - * 视图加载完成 - */ - ngAfterViewInit(): void { - this.form && this.form.addControl(this.controlModel); - } - - /** - * 获取值 - */ - get value() { - return this.controlModel.value; - } - - /** - * 模型变更事件处理 - */ - protected onModelChange(value) { - this.modelChange.emit(value); - this.onChange.emit(value); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/material/select-wrapper.component.ts b/sample/Util.Samples.Webs/Typings/util/material/select-wrapper.component.ts deleted file mode 100644 index 416929202..000000000 --- a/sample/Util.Samples.Webs/Typings/util/material/select-wrapper.component.ts +++ /dev/null @@ -1,147 +0,0 @@ -//============== 下拉列表包装器=================== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Component, Input, OnInit, Host, Optional } from '@angular/core'; -import { NgForm } from '@angular/forms'; -import { FormControlWrapperBase } from './base/form-control-wrapper-base'; -import { Select, SelectItem, SelectOption, SelectOptionGroup } from '../core/select'; -import { WebApi as webapi } from '../common/webapi'; -import { MessageConfig } from '../config/message-config'; - -/** - * Mat下拉列表包装器 - */ -@Component({ - selector: 'mat-select-wrapper', - template: ` - - - {{getTemplate(control.triggerValue)}} - {{resetOptionText }} - - - {{ item.text }} - - - - - - {{ item.text }} - - - - - {{startHint}} - {{endHint}} - {{prefixText}} - {{suffixMaterialIcon}} - - {{suffixText}} - {{requiredMessage}} - - `, - host: { - 'class': 'util-form-field', - } -}) -export class SelectWrapperComponent extends FormControlWrapperBase implements OnInit { - /** - * 按组显示 - */ - private isGroup: boolean; - /** - * 列表项集合 - */ - private options: SelectOption[]; - /** - * 列表组集合 - */ - private optionGroups: SelectOptionGroup[]; - /** - * 数据源 - */ - @Input() dataSource: SelectItem[]; - /** - * 请求地址 - */ - @Input() url: string; - /** - * 多选 - */ - @Input() multiple: boolean; - /** - * 启用重置项 - */ - @Input() enableResetOption: boolean; - /** - * 重置项文本 - */ - @Input() resetOptionText: string; - /** - * 显示模板,值用{0}表示,范例:当前选中:{0} ,显示为 当前选中:1,2,3 - */ - @Input() template: string; - - /** - * 初始化Mat下拉列表包装器 - */ - constructor( @Optional() @Host() form: NgForm ) { - super(form); - this.enableResetOption = true; - this.resetOptionText = MessageConfig.resetOptionText; - } - - /** - * 组件初始化 - */ - ngOnInit() { - this.loadData(); - if (this.dataSource) - return; - this.loadUrl(); - } - - /** - * 加载数据 - * @param data 列表项集合 - */ - loadData(data?: SelectItem[]) { - data = data || this.dataSource; - if (!data) - return; - let select = new Select(data); - if (select.isGroup()) { - this.isGroup = true; - this.optionGroups = select.toGroups(); - return; - } - this.options = select.toOptions(); - } - - /** - * 从服务器加载 - * @param url 请求地址 - */ - loadUrl(url?: string) { - url = url || this.url; - if (!url) { - console.log("请设置下拉列表Url"); - return; - } - webapi.get(url).handle({ - handler: result => { - this.loadData(result); - } - }); - } - - /** - * 获取模板 - */ - private getTemplate(value) { - return this.template.replace(/\{0\}/g, value); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/material/table-wrapper.component.ts b/sample/Util.Samples.Webs/Typings/util/material/table-wrapper.component.ts deleted file mode 100644 index 49feb769b..000000000 --- a/sample/Util.Samples.Webs/Typings/util/material/table-wrapper.component.ts +++ /dev/null @@ -1,317 +0,0 @@ -//============== 表格包装器======================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Component, Input, ViewChild, OnInit, ContentChild } from '@angular/core'; -import { MatTableDataSource, MatPaginator, MatPaginatorIntl, MatSort } from '@angular/material'; -import { SelectionModel } from '@angular/cdk/collections'; -import { WebApi as webapi } from '../common/webapi'; -import { Message as message } from '../common/message'; -import { PagerList } from '../core/pager-list'; -import { ViewModel } from '../core/view-model'; -import { QueryParameter } from '../core/query-parameter'; -import { MessageConfig as config } from '../config/message-config'; - -/** - * 创建分页本地化提示 - */ -function createMatPaginatorIntl() { - let result = new MatPaginatorIntl(); - result.itemsPerPageLabel = "每页"; - result.nextPageLabel = "下一页"; - result.previousPageLabel = "上一页"; - result.getRangeLabel = (page: number, pageSize: number, length: number) => { - if (length == 0 || pageSize == 0) { return `0`; } - length = Math.max(length, 0); - const startIndex = page * pageSize; - const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize; - return `当前:${startIndex + 1} - ${endIndex},共: ${length}`; - }; - return result; -} - -/** - * Mat表格包装器 - */ -@Component({ - selector: 'table-wrapper', - providers: [{ provide: MatPaginatorIntl, useFactory: createMatPaginatorIntl }], - template: ` - - - - - - - - `, - styles: [` - .table-container { - display: flex; - flex-direction: column; - position: relative; - } - .table-loading-shade { - position: absolute; - top: 0; - left: 0; - bottom: 56px; - right: 0; - background: rgba(0, 0, 0, 0.15); - z-index: 1; - display: flex; - align-items: center; - justify-content: center; - } - ::ng-deep .mat-table { - overflow: auto; - } - ::ng-deep .table-header { - min-height: 64px; - padding: 8px 24px 0; - z-index: 100; - } - ::ng-deep .mat-form-field { - width: 100%; - } - `] -}) -export class TableWrapperComponent implements OnInit { - /** - * 显示进度条 - */ - private loading: boolean; - /** - * 总行数 - */ - private totalCount = 0; - /** - * 数据源 - */ - dataSource: MatTableDataSource; - /** - * 是否自动加载,默认在初始化时自动加载数据,设置成false则手工加载 - */ - @Input() autoLoad: boolean; - /** - * 最大高度 - */ - @Input() maxHeight: number; - /** - * 最小高度 - */ - @Input() minHeight: number; - /** - * 最小宽度 - */ - @Input() minWidth: number; - /** - * 宽度 - */ - @Input() width: number; - /** - * 分页长度列表 - */ - @Input() pageSizeItems: number[]; - /** - * 基地址,基于该地址构建请求和删除地址,范例:传入test,则请求地址为/api/test,删除地址为/api/test/delete - */ - @Input() baseUrl: string; - /** - * 请求地址,如果设置了基地址baseUrl,则可以省略该参数 - */ - @Input() url: string; - /** - * 查询参数 - */ - @Input() queryParam: QueryParameter; - /** - * 排序组件 - */ - @ContentChild(MatSort) sort: MatSort; - /** - * 分页组件 - */ - @ViewChild(MatPaginator) paginator: MatPaginator; - /** - * 选中列表 - */ - selection = new SelectionModel(true, []); - - /** - * 初始化Mat表格包装器 - */ - constructor() { - this.maxHeight = 500; - this.minHeight = 300; - this.minWidth = 300; - this.pageSizeItems = [20, 50, 100, 200]; - this.dataSource = new MatTableDataSource(); - this.loading = false; - this.autoLoad = true; - } - - /** - * 组件初始化 - */ - ngOnInit() { - this.initPaginator(); - this.initSort(); - if (this.autoLoad) - this.init(); - } - - /** - * 初始化分页组件 - */ - private initPaginator() { - this.paginator.page.subscribe(() => { - this.queryParam.page = this.paginator.pageIndex + 1; - this.queryParam.pageSize = this.paginator.pageSize; - this.query(); - }); - } - - /** - * 初始化排序组件 - */ - private initSort() { - this.sort.sortChange.subscribe(() => { - this.queryParam.order = `${this.sort.active} ${this.sort.direction}`; - this.query(); - }); - } - - /** - * 初始化 - */ - init() { - this.queryParam.page = 1; - if (this.pageSizeItems && this.pageSizeItems.length > 0) - this.queryParam.pageSize = this.pageSizeItems[0]; - this.query(); - } - - /** - * 发送查询请求 - */ - query() { - let url = this.url || (this.baseUrl && `/api/${this.baseUrl}`); - if (!url) { - console.log("表格url未设置"); - return; - } - webapi.get>(url).param(this.queryParam).handle({ - beforeHandler: () => { this.loading = true; return true; }, - handler: result => { - result = new PagerList(result); - result.initLineNumbers(); - this.dataSource.data = result.data; - this.paginator.pageIndex = result.page - 1; - this.totalCount = result.totalCount; - this.selection.clear(); - }, - completeHandler: () => this.loading = false - }); - } - - /** - * 刷新表格 - */ - refresh() { - this.query(); - } - - /** - * 获取样式 - */ - private getStyle() { - return { - 'max-height': `${this.maxHeight}px`, - 'min-width': `${this.minWidth}px`, - 'width': this.width ? `${this.width}px` : null - }; - } - - /** - * 表头主复选框切换选中状态 - */ - masterToggle() { - if (this.isMasterChecked()) { - this.selection.clear(); - return; - } - this.dataSource.data.forEach(data => this.selection.select(data)); - } - - /** - * 表头主复选框的选中状态 - */ - isMasterChecked() { - return this.selection.hasValue() && - this.isAllSelected() && - this.selection.selected.length >= this.dataSource.data.length; - } - - /** - * 是否所有行复选框被选中 - */ - private isAllSelected() { - return this.dataSource.data.every(data => this.selection.isSelected(data)); - } - - /** - * 表头主复选框的确定状态 - */ - isMasterIndeterminate() { - return this.selection.hasValue() && (!this.isAllSelected() || !this.dataSource.data.length); - } - - /** - * 获取被选中实体列表 - */ - getSelected(): T[] { - return this.dataSource.data.filter(data => this.selection.isSelected(data)); - } - - /** - * 获取被选中实体Id列表 - */ - getSelectedIds(): string { - return this.getSelected().map((value) => value.id).join(","); - } - - /** - * 批量删除被选中实体 - * @param ids 待删除的Id列表,多个Id用逗号分隔,范例:1,2,3 - * @param handler 删除成功回调函数 - * @param deleteUrl 服务端删除Api地址,如果设置了基地址baseUrl,则可以省略该参数 - */ - delete(ids?: string, handler?: () => {}, deleteUrl?: string) { - ids = ids || this.getSelectedIds(); - if (!ids) { - message.warn(config.deleteNotSelected); - return; - } - message.confirm(config.deleteConfirm, () => { - this.deleteRequest(ids, handler, deleteUrl); - }); - } - - /** - * 发送删除请求 - */ - private deleteRequest(ids?: string, handler?: () => {}, deleteUrl?: string) { - deleteUrl = deleteUrl || `/api/${this.baseUrl}/delete`; - webapi.post(deleteUrl, ids).handle({ - handler: () => { - if (handler) { - handler(); - return; - } - message.success(config.deleteSuccessed); - this.refresh(); - } - }); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/material/textarea-wrapper.component.ts b/sample/Util.Samples.Webs/Typings/util/material/textarea-wrapper.component.ts deleted file mode 100644 index 5dbc56e2d..000000000 --- a/sample/Util.Samples.Webs/Typings/util/material/textarea-wrapper.component.ts +++ /dev/null @@ -1,91 +0,0 @@ -//============== 多行文本框包装器================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Component, Input, Host, Optional } from '@angular/core'; -import { NgForm } from '@angular/forms'; -import { FormControlWrapperBase } from './base/form-control-wrapper-base'; -import { MessageConfig } from '../config/message-config'; - -/** - * Mat多行文本框包装器 - */ -@Component({ - selector: 'mat-textarea-wrapper', - template:` - - - {{startHint}} - {{endHint}} - {{prefixText}} - - close - - {{suffixMaterialIcon}} - - {{suffixText}} - {{getErrorMessage()}} - - `, - host: { - 'class': 'util-form-field', - } -}) -export class TextareaWrapperComponent extends FormControlWrapperBase { - /** - * 是否显示清除按钮 - */ - @Input() showClearButton: boolean; - /** - * 最小行数 - */ - @Input() minRows: number; - /** - * 最大行数 - */ - @Input() maxRows: number; - /** - * 只读 - */ - @Input() readonly: boolean; - /** - * 最小长度 - */ - @Input() minLength: number; - /** - * 最小长度验证消息 - */ - @Input() minLengthMessage: string; - /** - * 最大长度 - */ - @Input() maxLength: number; - - /** - * 初始化Mat多行文本框包装器 - * @param form 表单 - */ - constructor( @Optional() @Host() form: NgForm ) { - super(form); - this.showClearButton = true; - this.minRows = 1; - this.maxRows = 8; - } - - /** - * 获取错误消息 - */ - private getErrorMessage(): string { - if (!this.controlModel) - return ""; - if (this.controlModel.hasError('required')) - return this.requiredMessage; - if (this.controlModel.hasError('minlength')) - return this.minLengthMessage || MessageConfig.minLengthMessage.replace(/\{0\}/, String(this.minLength)); - return ""; - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/material/textbox-wrapper.component.ts b/sample/Util.Samples.Webs/Typings/util/material/textbox-wrapper.component.ts deleted file mode 100644 index 4197df2b5..000000000 --- a/sample/Util.Samples.Webs/Typings/util/material/textbox-wrapper.component.ts +++ /dev/null @@ -1,141 +0,0 @@ -//============== 文本框包装器===================== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Component, Input, OnInit, Host, Optional } from '@angular/core'; -import { NgForm } from '@angular/forms'; -import { FormControlWrapperBase } from './base/form-control-wrapper-base'; -import { MessageConfig } from '../config/message-config'; - -/** - * Mat文本框包装器 - */ -@Component({ - selector: 'mat-textbox-wrapper', - template: ` - - - {{startHint}} - {{endHint}} - {{prefixText}} - - close - - {{suffixMaterialIcon}} - - {{suffixText}} - {{getErrorMessage()}} - - `, - host: { - 'class': 'util-form-field', - } -}) -export class TextBoxWrapperComponent extends FormControlWrapperBase implements OnInit { - /** - * 是否密码框 - */ - private isPassword: boolean; - /** - * 密码显示隐藏开关 - */ - private hide: boolean; - /** - * 清除按钮提示 - */ - private clearButtonTooltip: string; - /** - * 是否显示清除按钮 - */ - @Input() showClearButton: boolean; - /** - * 文本框类型,可选值:text,password,number,email,date - */ - @Input() type: string; - /** - * 只读 - */ - @Input() readonly: boolean; - /** - * 最小长度 - */ - @Input() minLength: number; - /** - * 最小长度验证消息 - */ - @Input() minLengthMessage: string; - /** - * 最大长度 - */ - @Input() maxLength: number; - /** - * 电子邮件验证消息 - */ - @Input() emailMessage: string; - - /** - * 初始化Mat文本框包装器 - * @param form 表单 - */ - constructor(@Optional() @Host() form: NgForm) { - super(form); - this.clearButtonTooltip = MessageConfig.clear; - this.showClearButton = true; - } - - /** - * 组件初始化 - */ - ngOnInit() { - this.initPassword(); - } - - /** - * 初始化密码框 - */ - private initPassword() { - if (this.type !== "password") - return; - this.isPassword = true; - this.hide = true; - this.togglePassword(); - } - - /** - * 切换密码显示状态 - */ - private togglePassword() { - this.suffixMaterialIcon = this.hide ? 'visibility' : 'visibility_off'; - this.type = this.hide ? 'password' : 'text'; - this.hide = !this.hide; - } - - /** - * 后缀图标单击事件 - */ - protected suffixIconClick() { - super.suffixIconClick(); - if (this.isPassword) - this.togglePassword(); - } - - /** - * 获取错误消息 - */ - private getErrorMessage(): string { - if (!this.controlModel) - return ""; - if (this.controlModel.hasError('required')) - return this.requiredMessage; - if (this.controlModel.hasError('minlength')) - return this.minLengthMessage || MessageConfig.minLengthMessage.replace(/\{0\}/, String(this.minLength)); - if (this.controlModel.hasError('email')) - return this.emailMessage || MessageConfig.emailMessage; - return ""; - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/prime/file-upload.component.ts b/sample/Util.Samples.Webs/Typings/util/prime/file-upload.component.ts deleted file mode 100644 index 0783f68d1..000000000 --- a/sample/Util.Samples.Webs/Typings/util/prime/file-upload.component.ts +++ /dev/null @@ -1,92 +0,0 @@ -//============== 文件上传========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Component, NgZone, ElementRef } from '@angular/core'; -import { DomSanitizer } from '@angular/platform-browser'; -import { FileUpload, DomHandler } from 'primeng/primeng'; -import { MessageConfig } from '../config/message-config'; - -/** - * 文件上传,基于Prime文件上传组件 - */ -@Component({ - selector: 'prime-file-upload', - template:` - - - - add - - - - - cloud_upload - - - clear - - - - - - - - - - - - - - {{file.name}} - {{formatSize(file.size)}} - - - clear - - - - - - - - - - - - - cloud_upload - - - `, - styles: [` - .mat-progress-bar{ - height:2px; - } - `], - providers: [DomHandler] -}) -export class FileUploadComponent extends FileUpload { - /** - * 初始化文件上传 - */ - constructor(el: ElementRef, domHandler: DomHandler, sanitizer: DomSanitizer, zone: NgZone) { - super(el, domHandler, sanitizer, zone); - this.chooseLabel = MessageConfig.chooseFile; - this.uploadLabel = MessageConfig.upload; - this.cancelLabel = MessageConfig.cancel; - } - - /** - * 获取进度条样式 - */ - private getProgressStyles() { - return { - 'position': 'absolute', - 'top': '0px', - 'left': '0px' - }; - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/prime/single-file-upload.component.ts b/sample/Util.Samples.Webs/Typings/util/prime/single-file-upload.component.ts deleted file mode 100644 index 166b8c559..000000000 --- a/sample/Util.Samples.Webs/Typings/util/prime/single-file-upload.component.ts +++ /dev/null @@ -1,43 +0,0 @@ -//============== 单文件上传====================== -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { Component, EventEmitter, Input } from '@angular/core'; -import { MessageConfig } from '../config/message-config'; -import { FileInfo,FileType } from '../core/file-info'; - -/** - * 单文件上传 - */ -@Component({ - selector: 'single-file-upload', - template:` - - - - 下载 - - - ` -}) -export class SingleFileUploadComponent { - /** - * 上传地址 - */ - @Input() url: string; - - private images: any[]; - - private file:FileInfo; - - constructor() { - this.images = new Array(); - } - - upload(result) { - this.file = JSON.parse(result.xhr.responseText); - this.file.type = FileType.Image; - this.images = new Array(); - this.images.push({ source: `${this.file.url}`, thumbnail: `${this.file.url}`, title: this.file.fileName }); - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/util.module.ts b/sample/Util.Samples.Webs/Typings/util/util.module.ts deleted file mode 100644 index 4f20a9920..000000000 --- a/sample/Util.Samples.Webs/Typings/util/util.module.ts +++ /dev/null @@ -1,78 +0,0 @@ -//============== util模块========================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import { NgModule } from '@angular/core'; -//Angular模块 -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; -import { RouterModule } from '@angular/router'; -import { HttpClientModule } from "@angular/common/http"; -//Material模块 -import { - MatCommonModule, MatRippleModule, MatSortModule, - MatFormFieldModule, MatSelectModule, MatInputModule, MatDatepickerModule, MatAutocompleteModule, - MatCheckboxModule, MatSlideToggleModule, MatRadioModule, - MatSnackBarModule, MatProgressBarModule, MatMenuModule, MatTableModule, MatTabsModule, - MatSidenavModule, MatToolbarModule, MatCardModule, MatExpansionModule, MatGridListModule, - MatProgressSpinnerModule, MatPaginatorModule, MatIconModule, MatButtonModule, MatTooltipModule, - DateAdapter, MAT_DATE_LOCALE_PROVIDER, MAT_DATE_FORMATS, MAT_NATIVE_DATE_FORMATS, MAT_DATE_LOCALE -} from '@angular/material'; -//PrimeNg模块 -import { - ButtonModule, GrowlModule, MessageModule, MessagesModule, ConfirmDialogModule, ConfirmationService, - FileUploadModule, LightboxModule -} from 'primeng/primeng'; -//Util组件 -import { UtilDateAdapter } from './material/local/date-adapter'; -import { MessageService } from 'primeng/components/common/messageservice'; -import { TableWrapperComponent } from './material/table-wrapper.component'; -import { SelectWrapperComponent } from './material/select-wrapper.component'; -import { TextBoxWrapperComponent } from './material/textbox-wrapper.component'; -import { TextareaWrapperComponent } from './material/textarea-wrapper.component'; -import { DatePickerWrapperComponent } from './material/datepicker-wrapper.component'; -import { ButtonWrapperComponent } from './material/button-wrapper.component'; -import { RadioWrapperComponent } from './material/radio-wrapper.component'; -import { FileUploadComponent } from './prime/file-upload.component'; -import { SingleFileUploadComponent } from "./prime/single-file-upload.component"; -/** - * Util模块 - */ -@NgModule({ - imports: [ - CommonModule, FormsModule, RouterModule, HttpClientModule, - MatCommonModule, MatRippleModule, MatSortModule, - MatFormFieldModule, MatSelectModule, MatInputModule, MatDatepickerModule, MatAutocompleteModule, - MatCheckboxModule, MatSlideToggleModule, MatRadioModule, - MatSnackBarModule, MatProgressBarModule, MatMenuModule, MatTableModule, MatTabsModule, - MatSidenavModule, MatToolbarModule, MatCardModule, MatExpansionModule, MatGridListModule, - MatProgressSpinnerModule, MatPaginatorModule, MatIconModule, MatButtonModule, MatTooltipModule, - ButtonModule, GrowlModule, MessageModule, MessagesModule, ConfirmDialogModule, FileUploadModule, LightboxModule - ], - declarations: [ - TableWrapperComponent, SelectWrapperComponent, TextBoxWrapperComponent, TextareaWrapperComponent, - DatePickerWrapperComponent, ButtonWrapperComponent, RadioWrapperComponent, - FileUploadComponent, SingleFileUploadComponent - ], - exports: [ - CommonModule, FormsModule, RouterModule, HttpClientModule, - MatCommonModule, MatRippleModule, MatSortModule, - MatFormFieldModule, MatSelectModule, MatInputModule, MatDatepickerModule, MatAutocompleteModule, - MatCheckboxModule, MatSlideToggleModule, MatRadioModule, - MatSnackBarModule, MatProgressBarModule, MatMenuModule, MatTableModule, MatTabsModule, - MatSidenavModule, MatToolbarModule, MatCardModule, MatExpansionModule, MatGridListModule, - MatProgressSpinnerModule, MatPaginatorModule, MatIconModule, MatButtonModule, MatTooltipModule, - ButtonModule, GrowlModule, MessageModule, MessagesModule, ConfirmDialogModule, FileUploadModule, LightboxModule, - TableWrapperComponent, SelectWrapperComponent, TextBoxWrapperComponent, TextareaWrapperComponent, - DatePickerWrapperComponent, ButtonWrapperComponent, RadioWrapperComponent, - FileUploadComponent, SingleFileUploadComponent - ], - providers: [ - MessageService, ConfirmationService, MAT_DATE_LOCALE_PROVIDER, - { provide: MAT_DATE_LOCALE, useValue: 'zh-cn' }, - { provide: DateAdapter, useClass: UtilDateAdapter }, - { provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS } - ] -}) -export class UtilModule { -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Typings/util/util.ts b/sample/Util.Samples.Webs/Typings/util/util.ts deleted file mode 100644 index 30c5024af..000000000 --- a/sample/Util.Samples.Webs/Typings/util/util.ts +++ /dev/null @@ -1,50 +0,0 @@ -//============== util操作库======================= -//Copyright 2018 何镇汐 -//Licensed under the MIT license -//================================================ -import * as helper from './common/helper'; -import { IocHelper } from './angular/ioc-helper'; -import { HttpHelper } from './angular/http-helper'; -import { RouterHelper } from './angular/router-helper'; -import { EventHelper } from "./angular/event-helper"; -import { WebApi } from './common/webapi'; -import { Message } from './common/message'; -import { Form } from './common/form'; - -/** - * 操作库 - */ -export class Util { - /** - * 公共操作 - */ - static helper = helper; - /** - * Ioc操作 - */ - static ioc = IocHelper; - /** - * Http操作 - */ - static http = HttpHelper; - /** - * 事件操作 - */ - static event = EventHelper; - /** - * WebApi操作,与服务端返回的标准result对象交互 - */ - static webapi = WebApi; - /** - * 路由操作 - */ - static router = RouterHelper; - /** - * 消息操作 - */ - static message = Message; - /** - * 表单操作 - */ - static form = new Form(); -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Util.Samples.Webs.csproj b/sample/Util.Samples.Webs/Util.Samples.Webs.csproj deleted file mode 100644 index f5cf315e0..000000000 --- a/sample/Util.Samples.Webs/Util.Samples.Webs.csproj +++ /dev/null @@ -1,82 +0,0 @@ - - - - netcoreapp2.0 - aspnet-Util.Samples.Webs-D0551EBC-0589-40AD-ADC2-A88CA4609632 - 何镇汐 - 何镇汐 - - - Util应用框架Web示例项目 - - true - Latest - - - - portable - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Always - - - - - - - - - - - - - - - - - diff --git a/sample/Util.Samples.Webs/Util.Samples.Webs.csproj.user b/sample/Util.Samples.Webs/Util.Samples.Webs.csproj.user deleted file mode 100644 index 3bdb03739..000000000 --- a/sample/Util.Samples.Webs/Util.Samples.Webs.csproj.user +++ /dev/null @@ -1,16 +0,0 @@ - - - - false - 0.0 - IIS Express - FolderProfile - 600 - - - ProjectDebugger - - - ProjectDebugger - - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Views/Home/Demo.cshtml b/sample/Util.Samples.Webs/Views/Home/Demo.cshtml deleted file mode 100644 index 94c165ef3..000000000 --- a/sample/Util.Samples.Webs/Views/Home/Demo.cshtml +++ /dev/null @@ -1,127 +0,0 @@ -@model Donau.Services.Dtos.Customers.CustomersDto -@{ - var x = Html.Ui(); -} - - - - 工具栏 - - - - - - 标题 - 子标题 - - - - - - - @x.TextBox( t => t.Name ) - - - - - - - - - - - - - - - - @x.Select( t => t.Nation ) - - - - - @*表头*@ - - - - - - - - - - - ID - - - - 姓名 - - - - 昵称 - - - - 电话 - - - - @*数据*@ - - - - - - - - - - - - - - - ID - {{ row.lineNumber }} - - - - 姓名 - {{ row.name }} - - - - 昵称 - {{ row.nickname }} - - - - 电话 - {{ row.mobile }} - - - - - - - - - - - @x.Button().Reset() - @x.Button().Submit() - - - - - diff --git a/sample/Util.Samples.Webs/Views/Home/Index.cshtml b/sample/Util.Samples.Webs/Views/Home/Index.cshtml deleted file mode 100644 index 4b902d70a..000000000 --- a/sample/Util.Samples.Webs/Views/Home/Index.cshtml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Views/Home/Main.cshtml b/sample/Util.Samples.Webs/Views/Home/Main.cshtml deleted file mode 100644 index 53320b733..000000000 --- a/sample/Util.Samples.Webs/Views/Home/Main.cshtml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - 哈哈 - - - - 哈哈 - - - - - - - - 哈哈 - - - 哈哈 - - - - - - - - - - - - - - - - - -@*消息提示*@ - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Views/Shared/_Layout.cshtml b/sample/Util.Samples.Webs/Views/Shared/_Layout.cshtml deleted file mode 100644 index b542f5d1a..000000000 --- a/sample/Util.Samples.Webs/Views/Shared/_Layout.cshtml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - @ViewBag.Title - - - - - - - @RenderBody() - - - - - @RenderSection( "Scripts", required: false ) - - diff --git a/sample/Util.Samples.Webs/Views/_ViewImports.cshtml b/sample/Util.Samples.Webs/Views/_ViewImports.cshtml deleted file mode 100644 index 7f2816392..000000000 --- a/sample/Util.Samples.Webs/Views/_ViewImports.cshtml +++ /dev/null @@ -1,7 +0,0 @@ -@using Util.Ui.Services -@using Util.Ui.Extensions -@using Util.Ui.Material.Extensions -@using Util.Ui.Material.Enums -@using Util.Ui.Enums -@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers -@addTagHelper *,Util.Ui.Angular \ No newline at end of file diff --git a/sample/Util.Samples.Webs/Views/_ViewStart.cshtml b/sample/Util.Samples.Webs/Views/_ViewStart.cshtml deleted file mode 100644 index a5f10045d..000000000 --- a/sample/Util.Samples.Webs/Views/_ViewStart.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@{ - Layout = "_Layout"; -} diff --git a/sample/Util.Samples.Webs/appsettings.Development.json b/sample/Util.Samples.Webs/appsettings.Development.json deleted file mode 100644 index fa8ce71a9..000000000 --- a/sample/Util.Samples.Webs/appsettings.Development.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Microsoft": "Information" - } - } -} diff --git a/sample/Util.Samples.Webs/appsettings.json b/sample/Util.Samples.Webs/appsettings.json deleted file mode 100644 index 26057306c..000000000 --- a/sample/Util.Samples.Webs/appsettings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ConnectionStrings": { - "DefaultConnection": "Server=.\\sql2014;Database=UtilTest;uid=sa;pwd=sa;Trusted_Connection=True;MultipleActiveResultSets=true" - }, - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" - } - } -} diff --git a/sample/Util.Samples.Webs/nlog.config b/sample/Util.Samples.Webs/nlog.config deleted file mode 100644 index 9047de043..000000000 --- a/sample/Util.Samples.Webs/nlog.config +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/package.json b/sample/Util.Samples.Webs/package.json deleted file mode 100644 index e528dca3a..000000000 --- a/sample/Util.Samples.Webs/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "version": "1.0.0", - "name": "util", - "private": true, - "scripts": { - "vendor": "webpack --config webpack.config.vendor.js", - "app": "webpack --config webpack.config.util.js && webpack", - "dev": "npm run vendor && npm run app", - "prod": "webpack --config webpack.config.vendor.js --env.prod && webpack --config webpack.config.util.js --env.prod && webpack --env.prod", - "test": "karma start Typings/test/karma.conf.js" - }, - "dependencies": { - "@angular/animations": "6.0.0-beta.5", - "@angular/common": "6.0.0-beta.5", - "@angular/compiler": "6.0.0-beta.5", - "@angular/core": "6.0.0-beta.5", - "@angular/forms": "6.0.0-beta.5", - "@angular/platform-browser": "6.0.0-beta.5", - "@angular/platform-browser-dynamic": "6.0.0-beta.5", - "@angular/router": "6.0.0-beta.5", - "@angular/cdk": "6.0.0-beta.3", - "@angular/material": "6.0.0-beta.3", - "font-awesome": "4.7.0", - "hammerjs": "2.0.8", - "rxjs": "5.5.6", - "zone.js": "0.8.20", - "es6-shim": "0.35.3", - "es6-promise": "4.2.4", - "event-source-polyfill": "0.0.12", - "babel-polyfill": "6.26.0", - "material-design-icons": "3.0.1", - "primeng": "5.2.0", - "moment": "2.20.1" - }, - "devDependencies": { - "@angular/compiler-cli": "6.0.0-beta.5", - "@types/jasmine": "2.8.6", - "@types/webpack-env": "1.13.5", - "aspnet-webpack": "2.0.3", - "autoprefixer": "8.0.0", - "awesome-typescript-loader": "3.5.0", - "css-loader": "0.28.10", - "extract-text-webpack-plugin": "3.0.2", - "file-loader": "1.1.10", - "jasmine-core": "3.1.0", - "karma": "2.0.0", - "karma-phantomjs-launcher": "1.0.4", - "karma-jasmine": "1.1.1", - "karma-webpack": "2.0.13", - "node-sass": "4.7.2", - "postcss-loader": "2.1.1", - "sass-loader": "6.0.6", - "typescript": "2.7.2", - "url-loader": "0.6.2", - "webpack": "3.11.0", - "webpack-cli": "2.0.9", - "webpack-hot-middleware": "2.21.0", - "angular-router-loader": "0.8.2" - } -} diff --git a/sample/Util.Samples.Webs/tsconfig.json b/sample/Util.Samples.Webs/tsconfig.json deleted file mode 100644 index 28cc34f21..000000000 --- a/sample/Util.Samples.Webs/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compileOnSave": false, - "compilerOptions": { - "target": "es5", - "module": "es2015", - "moduleResolution": "node", - "noImplicitAny": false, - "noEmitOnError": true, - "removeComments": false, - "sourceMap": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "skipDefaultLibCheck": true, - "skipLibCheck": true, - "strictPropertyInitialization": false, - "strict": true, - "lib": [ "es6", "dom" ], - "types": [ "webpack-env", "jasmine" ] - }, - "exclude": [ "bin", "node_modules" ] -} diff --git a/sample/Util.Samples.Webs/webpack.config.js b/sample/Util.Samples.Webs/webpack.config.js deleted file mode 100644 index 12b2962e1..000000000 --- a/sample/Util.Samples.Webs/webpack.config.js +++ /dev/null @@ -1,87 +0,0 @@ -const pathPlugin = require('path'); -const webpack = require('webpack'); -var Extract = require("extract-text-webpack-plugin"); - -module.exports = (env) => { - //是否开发环境 - const isDev = !(env && env.prod); - - //将css提取到单独文件中 - const extractCss = new Extract("app.css"); - - //获取路径 - function getPath(path) { - return pathPlugin.join(__dirname, path); - } - - //打包js - let jsConfig = { - entry: { app: getPath("Typings/main.ts") }, - output: { - publicPath: 'dist/', - path: getPath("wwwroot/dist"), - filename: "[name].js" - }, - resolve: { - extensions: ['.js', '.ts'] - }, - devtool: "source-map", - module: { - rules: [ - { test: /\.ts$/, use: ['awesome-typescript-loader?silent=true', 'angular-router-loader'] } - ] - }, - plugins: [ - new webpack.DllReferencePlugin({ - manifest: require('./wwwroot/dist/polyfills-manifest.json') - }), - new webpack.DllReferencePlugin({ - manifest: require('./wwwroot/dist/vendor-manifest.json') - }), - new webpack.DllReferencePlugin({ - manifest: require('./wwwroot/dist/util-manifest.json') - }), - new webpack.optimize.ModuleConcatenationPlugin() - ].concat(isDev ? [] : [ - new webpack.optimize.UglifyJsPlugin() - ]) - } - - //打包css - let cssConfig = { - entry: { app: getPath("wwwroot/css/main.scss") }, - output: { - publicPath: './', - path: getPath("wwwroot/dist"), - filename: "[name].css" - }, - resolve: { - modules: ['wwwroot'] - }, - devtool: "source-map", - module: { - rules: [ - { - test: /\.scss$/, use: extractCss.extract({ - use: isDev ? ['css-loader', { loader: 'postcss-loader', options: { plugins: [require('autoprefixer')] } }, 'sass-loader'] - : ['css-loader?minimize', { loader: 'postcss-loader', options: { plugins: [require('autoprefixer')] } }, 'sass-loader'] - }) - }, - { - test: /\.(png|jpg|gif|woff|woff2|eot|ttf|svg)(\?|$)/, use: { - loader: 'url-loader', - options: { - limit: 20000, - name: "[name].[ext]", - outputPath: "images/" - } - } - } - ] - }, - plugins: [ - extractCss - ] - } - return [jsConfig, cssConfig]; -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/webpack.config.util.js b/sample/Util.Samples.Webs/webpack.config.util.js deleted file mode 100644 index 0bea06d0c..000000000 --- a/sample/Util.Samples.Webs/webpack.config.util.js +++ /dev/null @@ -1,48 +0,0 @@ -const pathPlugin = require('path'); -const webpack = require('webpack'); - -//env代表环境变量,如果传入env.production表示正式生产环境 -module.exports = (env) => { - //是否开发环境 - const isDev = !(env && env.prod); - - //获取路径 - function getPath(path) { - return pathPlugin.join(__dirname, path); - } - - //打包util脚本库 - return { - entry: { util: [getPath("Typings/util/index.ts")] }, - output: { - publicPath: 'dist/', - path: getPath("wwwroot/dist"), - filename: "[name].js", - library: '[name]' - }, - resolve: { - extensions: ['.js', '.ts'] - }, - devtool: "source-map", - module: { - rules: [ - { test: /\.ts$/, use: ['awesome-typescript-loader?silent=true'] } - ] - }, - plugins: [ - new webpack.DllReferencePlugin({ - manifest: require('./wwwroot/dist/polyfills-manifest.json') - }), - new webpack.DllReferencePlugin({ - manifest: require('./wwwroot/dist/vendor-manifest.json') - }), - new webpack.DllPlugin({ - path: getPath("wwwroot/dist/[name]-manifest.json"), - name: "[name]" - }), - new webpack.optimize.ModuleConcatenationPlugin() - ].concat(isDev ? [] : [ - new webpack.optimize.UglifyJsPlugin() - ]) - } -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/webpack.config.vendor.js b/sample/Util.Samples.Webs/webpack.config.vendor.js deleted file mode 100644 index 67d4daff6..000000000 --- a/sample/Util.Samples.Webs/webpack.config.vendor.js +++ /dev/null @@ -1,130 +0,0 @@ -const pathPlugin = require('path'); -const webpack = require('webpack'); -var Extract = require("extract-text-webpack-plugin"); - -//支持老浏览器的补丁 -const polyfillModules = [ - 'es6-shim', - 'es6-promise', - 'event-source-polyfill' -]; - -//第三方Js库 -const jsModules = [ - 'moment', - 'reflect-metadata', - 'zone.js', - '@angular/animations', - '@angular/common', - '@angular/common/http', - '@angular/compiler', - '@angular/core', - '@angular/forms', - '@angular/platform-browser', - '@angular/platform-browser/animations', - '@angular/platform-browser-dynamic', - '@angular/router', - 'hammerjs', - '@angular/cdk/esm5/collections.es5', - '@angular/material', - 'primeng/primeng' -]; - -//第三方Css库 -const cssModules = [ - '@angular/material/prebuilt-themes/indigo-pink.css', - 'material-design-icons/iconfont/material-icons.css', - 'font-awesome/css/font-awesome.css', - 'primeng/resources/primeng.css' -]; - -//env代表环境变量,如果传入env.production表示正式生产环境 -module.exports = (env) => { - //是否开发环境 - const isDev = !(env && env.prod); - - //将css提取到单独文件中 - const extractCss = new Extract("vendor.css"); - - //获取路径 - function getPath(path) { - return pathPlugin.join(__dirname, path); - } - - //打包补丁 - let polyfills = { - entry: { polyfills: polyfillModules }, - output: { - publicPath: 'dist/', - path: getPath("wwwroot/dist"), - filename: "[name].js", - library: '[name]' - }, - resolve: { - extensions: ['.js'] - }, - devtool: "source-map", - plugins: [ - new webpack.DllPlugin({ - path: getPath("wwwroot/dist/[name]-manifest.json"), - name: "[name]" - }), - new webpack.optimize.ModuleConcatenationPlugin() - ].concat(isDev ? [] : [new webpack.optimize.UglifyJsPlugin()]) - } - - //打包第三方Js库 - let vendorJs = { - entry: { vendor: jsModules }, - output: { - publicPath: 'dist/', - path: getPath("wwwroot/dist"), - filename: "[name].js", - library: '[name]' - }, - resolve: { - extensions: ['.js'] - }, - devtool: "source-map", - plugins: [ - new webpack.DllPlugin({ - path: getPath("wwwroot/dist/[name]-manifest.json"), - name: "[name]" - }), - new webpack.optimize.ModuleConcatenationPlugin(), - new webpack.ContextReplacementPlugin(/\@angular\b.*\b(bundles|linker)/, getPath('./Typings')), - new webpack.ContextReplacementPlugin(/angular(\\|\/)core(\\|\/)@angular/, getPath('./Typings')), - new webpack.IgnorePlugin(/^vertx$/) - ].concat(isDev ? [] : [new webpack.optimize.UglifyJsPlugin()]) - } - - //打包css - let vendorCss = { - entry: { vendor: cssModules }, - output: { - publicPath: './', - path: getPath("wwwroot/dist"), - filename: "[name].css" - }, - devtool: "source-map", - module: { - rules: [ - { test: /\.css$/, use: extractCss.extract({ use: isDev ? 'css-loader' : 'css-loader?minimize' }) }, - { - test: /\.(png|jpg|gif|woff|woff2|eot|ttf|svg)(\?|$)/, use: { - loader: 'url-loader', - options: { - limit: 20000, - name: "[name].[ext]", - outputPath: "images/" - } - } - } - ] - }, - plugins: [ - extractCss - ] - } - return [polyfills, vendorJs, vendorCss]; -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/css/app/_main.scss b/sample/Util.Samples.Webs/wwwroot/css/app/_main.scss deleted file mode 100644 index 5f282702b..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/app/_main.scss +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/css/common/_main.scss b/sample/Util.Samples.Webs/wwwroot/css/common/_main.scss deleted file mode 100644 index ed5c5c6a2..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/common/_main.scss +++ /dev/null @@ -1,16 +0,0 @@ -//导入变量 -@import "base/variables"; - -//导入基础样式 -@import "base/base"; - -//导入组件样式 -@import "base/component"; - -//导入primeNg组件样式 -@import "prime/theme"; - -//导入主界面布局样式 -@import 'layout/header'; -@import 'layout/navigation'; -@import 'layout/footer'; \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/css/common/base/_base.scss b/sample/Util.Samples.Webs/wwwroot/css/common/base/_base.scss deleted file mode 100644 index 5f282702b..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/common/base/_base.scss +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/css/common/base/_component.scss b/sample/Util.Samples.Webs/wwwroot/css/common/base/_component.scss deleted file mode 100644 index cc9603374..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/common/base/_component.scss +++ /dev/null @@ -1,49 +0,0 @@ -//mat表格复选框 -.mat-column-selectCheckbox { - max-width: 48px; - overflow: initial !important; -} -.mat-cell, .mat-header-cell { - overflow: initial !important; -} -//mat表格序号 -.mat-column-lineNumber { - max-width: 48px; - justify-content: flex-end; -} -//mat表格行滑过样式 -.mat-row-hover { - position: relative; - &:hover { - background: #f5f5f5; - } - &:active { - background: #eaeaea; - } -} -//mat菜单font-awesome图标 -.mat-menu-item .fa { - vertical-align: middle; - margin-right: 16px; - font-size: 24px; -} -//mat选项卡font-awesome图标 -.mat-tab-label .fa, .mat-tab-link .fa { - font-size: 24px; - margin-right: 3px; -} -//mat工具栏 -.mat-toolbar .mat-icon { - padding: 0 14px; -} -.toolbar-fill-remain { - flex: 1 1 auto; -} -//修复自定义表单组件宽度 -.util-form-field { - width: 100% -} -//重置栅格内容左对齐 -.mat-grid-tile .mat-figure { - justify-content:flex-start; -} \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/css/common/base/_variables.scss b/sample/Util.Samples.Webs/wwwroot/css/common/base/_variables.scss deleted file mode 100644 index 5f282702b..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/common/base/_variables.scss +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/css/common/layout/_footer.scss b/sample/Util.Samples.Webs/wwwroot/css/common/layout/_footer.scss deleted file mode 100644 index 5f282702b..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/common/layout/_footer.scss +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/css/common/layout/_header.scss b/sample/Util.Samples.Webs/wwwroot/css/common/layout/_header.scss deleted file mode 100644 index 5f282702b..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/common/layout/_header.scss +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/css/common/layout/_navigation.scss b/sample/Util.Samples.Webs/wwwroot/css/common/layout/_navigation.scss deleted file mode 100644 index 5f282702b..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/common/layout/_navigation.scss +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/css/common/prime/_base.scss b/sample/Util.Samples.Webs/wwwroot/css/common/prime/_base.scss deleted file mode 100644 index fd715d6aa..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/common/prime/_base.scss +++ /dev/null @@ -1,645 +0,0 @@ -@mixin hover-element() { - border-color: $stateHoverBorderColor; - background: $stateHoverBgColor; - color: $stateHoverTextColor; - - a { - color: $stateHoverTextColor; - } -} - -@mixin icon-override($icon) { - background: none !important; - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-indent: 0px !important; - text-align: center; - - &:before { - content: $icon; - } -} - -.ui-widget { - font-family: $fontFamily; - font-size: $fontSize; - - input, select, textarea, button { - font-family: $fontFamily; - font-size: $fontSize; - } - - :active { - outline: none; - } -} - -.ui-widget-content { - border: $contentBorderWidth solid $contentBorderColor; - background: $contentBgColor; - color: $contentTextColor; - - a { - color: $contentTextColor; - } -} - -.ui-widget-header { - border: $headerBorderWidth solid $headerBorderColor; - background: $headerBgColor; - color: $headerTextColor; - font-weight: $headerFontWeight; - - a { - color: $headerTextColor; - } -} - -.ui-widget-overlay { - background: #666666; - opacity: .50; - filter:Alpha(Opacity=50); -} - -.ui-state-default { - border: $stateDefaultBorderWidth solid $stateDefaultBorderColor; - background: $stateDefaultBgColor; - color: $stateDefaultTextColor; - - a { - color: $stateDefaultTextColor ; - } -} - -.ui-state-active { - border-color: $stateActiveBorderColor; - background: $stateActiveBgColor; - color: $stateActiveTextColor; - - a { - color: $stateActiveTextColor; - } -} - -.ui-state-highlight { - border-color: $stateHighlightBorderColor; - background: $stateHighlightBgColor; - color: $stateHighlightTextColor; - - a { - color: $stateHighlightTextColor; - } -} - -.ui-state-focus { - border-color: $stateFocusBorderColor; - background: $stateFocusBgColor; - color: $stateFocusTextColor; - - a { - color: $stateFocusTextColor; - } -} - -.ui-state-error { - border-color: $stateErrorBorderColor; - background: $stateErrorBgColor; - color: $stateErrorTextColor; - - a { - color: $stateErrorTextColor; - } -} - -.ui-state-disabled, -.ui-widget:disabled { - opacity: $disabledOpacity; - filter: Alpha(Opacity= $disabledOpacity * 100); - background-image: none; - cursor: default !important; - - * { - cursor: default !important; - } -} - -/* Forms */ -.ui-inputtext { - background: $inputBgColor; - color: $inputTextColor; -} - -.ui-inputtext:enabled:hover { - border-color: $stateHoverBorderColor; -} - -.ui-inputtext.ui-state-focus, -.ui-inputtext:focus { - outline: 0 none; - border-color: $stateFocusBorderColor; - -moz-box-shadow: 0px 0px 5px $stateFocusBorderColor; - -webkit-box-shadow: 0px 0px 5px $stateFocusBorderColor; - box-shadow: 0px 0px 5px $stateFocusBorderColor; -} - -.ui-inputgroup { - .ui-inputgroup-addon { - border-color: $stateDefaultBorderColor; - background-color: lighten($stateDefaultBorderColor, 10%); - color: $inputGroupTextColor; - - &:first-child { - border-top-left-radius: $borderRadius; - border-bottom-left-radius: $borderRadius; - } - - &:last-child { - border-top-right-radius: $borderRadius; - border-bottom-right-radius: $borderRadius; - } - } - - .ui-button { - &:first-child { - border-top-left-radius: $borderRadius; - border-bottom-left-radius: $borderRadius; - } - - &:last-child { - border-top-right-radius: $borderRadius; - border-bottom-right-radius: $borderRadius; - } - } -} - -.ui-float-label input.ng-dirty.ng-invalid ~ label { - color: $stateErrorTextColor; -} - -.ui-autocomplete { - .ui-autocomplete-multiple-container:not(.ui-state-disabled) { - &:hover { - border-color: $stateHoverBorderColor; - } - - &.ui-state-focus { - border-color: $stateFocusBorderColor; - - } - } -} - -.ui-chips { - > ul:not(.ui-state-disabled) { - &:hover { - border-color: $stateHoverBorderColor; - } - - &.ui-state-focus { - border-color: $stateFocusBorderColor; - } - } -} - -.ui-fileupload-buttonbar { - padding: 0; -} - -.ui-widget-header { - background: #fafafa !important; -} -.ui-widget-content{ - border-top:0; -} - -.ui-button:focus, -.ui-button:enabled:hover { - outline: 0 none; - @include hover-element(); -} - -.ui-button:enabled:active { - border-color: $stateActiveBorderColor; - background: $stateActiveBgColor; - color: $stateActiveTextColor; -} - -.ui-chkbox-box:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-radiobutton-box:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-dropdown:not(.ui-state-disabled):hover { - @include hover-element(); -} - -.ui-dropdown-panel .ui-dropdown-item:not(.ui-state-highlight):hover { - @include hover-element(); -} - -.ui-listbox { - .ui-listbox-header { - .ui-listbox-filter-container { - .fa { - color: $inputTextColor; - } - } - } - - &:not(.ui-state-disabled) { - .ui-listbox-item:not(.ui-state-highlight):hover { - @include hover-element(); - } - } - - &.ui-state-disabled { - .ui-chkbox-box:not(.ui-state-active):hover { - border-color: $stateDefaultBorderColor; - background: $stateDefaultBgColor; - color: $stateDefaultTextColor; - } - } -} - -.ui-multiselect:not(.ui-state-disabled):hover { - @include hover-element(); -} - -.ui-multiselect-panel .ui-multiselect-item:not(.ui-state-highlight):hover { - @include hover-element(); -} - -.ui-multiselect-panel .ui-multiselect-close { - color: $headerIconTextColor; -} - -.ui-multiselect-panel .ui-multiselect-filter-container .fa { - color: $inputTextColor; -} - -.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:hover { - @include hover-element(); -} - -.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:active { - border-color: $stateActiveBorderColor; - background: $stateActiveBgColor; - color: $stateActiveTextColor; -} - -.ui-selectbutton .ui-button:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-togglebutton:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-paginator a:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-paginator a { - color: $stateDefaultTextColor; -} - -.ui-datatable { - .ui-rowgroup-header a { - color: $headerTextColor; - } - - .ui-sortable-column:not(.ui-state-active):hover { - background: $stateHoverBgColor; - color: $stateHoverTextColor; - } - - .ui-row-toggler { - color: $contentTextColor; - } - - tbody.ui-datatable-hoverable-rows { - > tr.ui-widget-content:not(.ui-state-highlight):hover { - cursor: pointer; - background: $stateHoverBgColor; - color: $stateHoverTextColor; - } - } -} - -.ui-orderlist { - .ui-orderlist-item:not(.ui-state-highlight):hover { - @include hover-element(); - } -} - -.ui-picklist { - .ui-picklist-item:not(.ui-state-disabled):not(.ui-state-highlight):hover { - @include hover-element(); - } - - .ui-picklist-droppoint-highlight { - border-color: $stateHighlightBorderColor; - background: $stateHighlightBgColor; - color: darken($contentTextColor,1%); - - a { - color: darken($contentTextColor,1%); - } - } - - .ui-picklist-highlight { - border-color: $stateHighlightBorderColor; - color: darken($contentTextColor,1%); - - a { - color: darken($contentTextColor,1%); - } - } -} - -.ui-tree { - &.ui-treenode-dragover { - border-color: $stateHighlightBorderColor; - } - - .ui-treenode-content { - &.ui-treenode-selectable { - .ui-treenode-label:not(.ui-state-highlight):hover { - @include hover-element(); - } - } - - &.ui-treenode-dragover { - background: $stateActiveBgColor; - color: $stateActiveTextColor; - } - } - - &.ui-tree-horizontal { - .ui-treenode-content.ui-treenode-selectable { - .ui-treenode-label:not(.ui-state-highlight):hover { - background-color: inherit; - color: inherit; - } - - &:not(.ui-state-highlight):hover { - @include hover-element(); - } - } - } -} - -.ui-treetable { - .ui-treetable-row.ui-treetable-row-selectable:not(.ui-state-highlight):hover { - background: $stateHoverBgColor; - color: $stateHoverTextColor; - } -} - -.ui-organizationchart { - .ui-organizationchart-node-content { - &.ui-organizationchart-selectable-node:not(.ui-state-highlight):hover { - @include hover-element(); - } - } -} - -.ui-accordion { - .ui-accordion-header:not(.ui-state-active):not(.ui-state-disabled):hover { - @include hover-element(); - } -} - -.ui-fieldset { - &.ui-fieldset-toggleable { - .ui-fieldset-legend:hover { - @include hover-element(); - } - } -} - -.ui-panel { - .ui-panel-titlebar { - .ui-panel-titlebar-icon:hover { - @include hover-element(); - } - } -} - -.ui-tabview { - .ui-tabview-nav { - li { - &:not(.ui-state-active):not(.ui-state-disabled):hover { - @include hover-element(); - } - } - } -} - -.ui-dialog { - .ui-dialog-titlebar-icon { - color: $headerTextColor; - - &:hover { - @include hover-element(); - } - } -} - -.ui-sidebar { - .ui-sidebar-close { - color: $headerTextColor; - - &:hover { - @include hover-element(); - } - } -} - -.ui-overlaypanel { - .ui-overlaypanel-close:hover { - @include hover-element(); - } -} - -.ui-inplace { - .ui-inplace-display:hover { - @include hover-element(); - } -} - -.ui-breadcrumb { - a { - color: $headerTextColor; - } -} - -.ui-menu { - .ui-menuitem { - .ui-menuitem-link { - color: $contentTextColor; - - &:hover { - @include hover-element(); - border-color: transparent; - } - } - - &.ui-menuitem-active { - > .ui-menuitem-link { - @include hover-element(); - border-color: transparent; - } - } - } -} - -.ui-tabmenu { - .ui-tabmenu-nav { - li:not(.ui-state-active):hover { - @include hover-element(); - } - } -} - -.ui-steps { - .ui-steps-item:not(.ui-state-highlight):not(.ui-state-disabled):hover { - @include hover-element(); - } -} - -.ui-panelmenu { - .ui-panelmenu-header { - &:not(.ui-state-active):hover { - @include hover-element(); - border-color: $stateDefaultBorderColor; - - a { - color: $stateHoverTextColor; - } - } - - &.ui-state-active { - a { - color: $stateActiveTextColor; - } - } - } - - .ui-panelmenu-content { - .ui-menuitem-link { - color: $contentTextColor; - - &:hover { - @include hover-element(); - border-color: transparent; - } - } - } -} - -.ui-datepicker { - .ui-datepicker-header { - a { - color: $headerTextColor; - - &:hover { - @include hover-element(); - } - } - } - - .ui-datepicker-calendar { - td:not(.ui-state-disabled) { - a:hover { - @include hover-element(); - } - } - } -} - -.fc { - .fc-toolbar { - .fc-prev-button { - .ui-icon-circle-triangle-w { - margin-top: .3em; - @include icon_override("\f053"); - } - } - - .fc-next-button { - .ui-icon-circle-triangle-e { - margin-top: .3em; - @include icon_override("\f054"); - } - } - } -} - -.ui-rating { - a { - color: $inputTextColor; - } -} - -.ui-organizationchart { - .ui-organizationchart-line-down { - background-color: darken($contentBorderColor, 10%); - } - - .ui-organizationchart-line-left { - border-right: 1px solid darken($contentBorderColor, 10%); - } - - .ui-organizationchart-line-right { - - } - - .ui-organizationchart-line-top { - border-top: 1px solid darken($contentBorderColor, 10%); - } - - .ui-organizationchart-node-content { - border-color: darken($contentBorderColor, 10%); - } - - .ui-organizationchart-node-content .ui-node-toggler { - color: darken($contentBorderColor, 10%); - } -} - -/* Validation */ -.ui-inputtext.ng-dirty.ng-invalid, -p-dropdown.ng-dirty.ng-invalid > .ui-dropdown, -p-autocomplete.ng-dirty.ng-invalid > .ui-autocomplete > .ui-inputtext, -p-calendar.ng-dirty.ng-invalid > .ui-calendar > .ui-inputtext, -p-chips.ng-dirty.ng-invalid > .ui-inputtext, -p-inputmask.ng-dirty.ng-invalid > .ui-inputtext, -p-checkbox.ng-dirty.ng-invalid .ui-chkbox-box, -p-radiobutton.ng-dirty.ng-invalid .ui-radiobutton-box, -p-inputswitch.ng-dirty.ng-invalid .ui-inputswitch, -p-listbox.ng-dirty.ng-invalid .ui-inputtext, -p-multiselect.ng-dirty.ng-invalid > .ui-multiselect, -p-spinner.ng-dirty.ng-invalid > .ui-inputtext, -p-selectbutton.ng-dirty.ng-invalid .ui-button, -p-togglebutton.ng-dirty.ng-invalid .ui-button { - border-bottom-color: $invalidInputBorderColor; -} - -/* Cornering */ -.ui-corner-tl { -moz-border-radius-topleft: $borderRadius; -webkit-border-top-left-radius: $borderRadius; border-top-left-radius: $borderRadius; } -.ui-corner-tr { -moz-border-radius-topright: $borderRadius; -webkit-border-top-right-radius: $borderRadius; border-top-right-radius: $borderRadius; } -.ui-corner-bl { -moz-border-radius-bottomleft: $borderRadius; -webkit-border-bottom-left-radius: $borderRadius; border-bottom-left-radius: $borderRadius; } -.ui-corner-br { -moz-border-radius-bottomright: $borderRadius; -webkit-border-bottom-right-radius: $borderRadius; border-bottom-right-radius: $borderRadius; } -.ui-corner-top { -moz-border-radius-topleft: $borderRadius; -webkit-border-top-left-radius: $borderRadius; border-top-left-radius: $borderRadius; -moz-border-radius-topright: $borderRadius; -webkit-border-top-right-radius: $borderRadius; border-top-right-radius: $borderRadius; } -.ui-corner-bottom { -moz-border-radius-bottomleft: $borderRadius; -webkit-border-bottom-left-radius: $borderRadius; border-bottom-left-radius: $borderRadius; -moz-border-radius-bottomright: $borderRadius; -webkit-border-bottom-right-radius: $borderRadius; border-bottom-right-radius: $borderRadius; } -.ui-corner-right { -moz-border-radius-topright: $borderRadius; -webkit-border-top-right-radius: $borderRadius; border-top-right-radius: $borderRadius; -moz-border-radius-bottomright: $borderRadius; -webkit-border-bottom-right-radius: $borderRadius; border-bottom-right-radius: $borderRadius; } -.ui-corner-left { -moz-border-radius-topleft: $borderRadius; -webkit-border-top-left-radius: $borderRadius; border-top-left-radius: $borderRadius; -moz-border-radius-bottomleft: $borderRadius; -webkit-border-bottom-left-radius: $borderRadius; border-bottom-left-radius: $borderRadius; } -.ui-corner-all { -moz-border-radius: $borderRadius; -webkit-border-radius: $borderRadius; border-radius: $borderRadius; } diff --git a/sample/Util.Samples.Webs/wwwroot/css/common/prime/_theme.scss b/sample/Util.Samples.Webs/wwwroot/css/common/prime/_theme.scss deleted file mode 100644 index 9d2d374e7..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/common/prime/_theme.scss +++ /dev/null @@ -1,572 +0,0 @@ -$fontFamily: "Roboto", "Trebuchet MS", Arial, Helvetica, sans-serif; -$fontSize: 1em; -$borderRadius: 3px; -$disabledOpacity: 0.35; - -//Header -$headerBorderWidth: 1px; -$headerBorderColor: #d9d9d9; -$headerBgColor: #f6f7f9; -$headerTextColor: #1b1d1f; -$headerFontWeight: normal; -$headerIconTextColor: #1b1d1f; - -//Content -$contentBorderWidth: 1px; -$contentBorderColor: #D5D5D5; -$contentBgColor: #ffffff; -$contentTextColor: #222222; - -//Default State -$stateDefaultBorderWidth: 1px; -$stateDefaultBorderColor: #d6d6d6; -$stateDefaultBgColor: #ffffff; -$stateDefaultTextColor: #555555; - -//Active State -$stateActiveBorderColor: #bebebe; -$stateActiveBgColor: #d6d6d6; -$stateActiveTextColor: #212121; - -//Highlight State -$stateHighlightBorderColor: #156090; -$stateHighlightBgColor: #186ba0; -$stateHighlightTextColor: #FFFFFF; - -//Focus State -$stateFocusBorderColor: #c0c0c0; -$stateFocusBgColor: #eeeeee; -$stateFocusTextColor: #212121; - -//Error State -$stateErrorBorderColor: #f44336; -$stateErrorBgColor: #f5554a; -$stateErrorTextColor: #cd0a0a; - -//Hover State -$stateHoverBorderColor: #c0c0c0; -$stateHoverBgColor: #eeeeee; -$stateHoverTextColor: #212121; - -//Forms -$inputBgColor: #ffffff; -$inputTextColor: #222222; -$invalidInputBorderColor: #f44336; -$inputGroupTextColor: #222222; - -@import './base'; - -/* roboto-regular - latin */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: url('fonts/roboto-v15-latin-regular.eot'); /* IE9 Compat Modes */ - src: local('Roboto'), local('Roboto-Regular'), - url('fonts/roboto-v15-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('fonts/roboto-v15-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ - url('fonts/roboto-v15-latin-regular.woff') format('woff'), /* Modern Browsers */ - url('fonts/roboto-v15-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ - url('fonts/roboto-v15-latin-regular.svg#Roboto') format('svg'); /* Legacy iOS */ -} - -.ui-widget-header { - background: #f6f7f9 0 0 repeat-x; /* Old browsers */ - background: -moz-linear-gradient(top, #f6f7f9 0%, #ebedf0 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f6f7f9), color-stop(100%,#ebedf0)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* IE10+ */ - background: linear-gradient(to bottom, #f6f7f9 0%,#ebedf0 100%); /* W3C */ -} - -.ui-accordion { - .ui-accordion-header { - background: $headerBgColor; - border-top: 1px solid $headerBorderColor; - - a { - color: $headerTextColor; - } - - &:not(.ui-state-active):not(.ui-state-disabled):hover { - background: #ededf0; - } - - &.ui-state-active { - background: #ffffff; - border-left-color: transparent; - border-right-color: transparent; - border-bottom-color: transparent; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - } - } - - .ui-accordion-content { - border: 0 none; - } -} - -/* Tabview */ -.ui-tabview { - &.ui-widget-content { - border: 0 none; - } - - .ui-tabview-nav { - background: transparent; - - > li { - &.ui-state-default { - background: #f6f7f9; - } - - &.ui-state-active { - background: #ffffff; - font-weight: normal; - color: #555555; - } - - &:not(.ui-state-active):not(.ui-state-disabled):hover { - background: #ededf0; - } - } - } -} - -/* Spinner */ -.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:hover { - border: 1px solid #1f89ce; - background: #1f89ce; - outline: 0 none; - color: #ffffff; -} - -.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:active { - border: 1px solid #156090; - background: #186ba0; - color: #ffffff; -} - -.ui-slider { position: relative; text-align: left; background: #838688; border: none; -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;} -.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 17px !important; height: 21px !important; cursor: default; background: url("images/slider_handles.png") 0 0 no-repeat; outline: none; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; border: none; } -.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background: #14a4ff; -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } -.ui-slider .ui-slider-handle.ui-state-active { background-position: -17px 0; } - -.ui-slider-horizontal { height: 6px; } -.ui-slider-horizontal .ui-slider-handle { top: -2px !important; margin-left: -.6em; } -.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } -.ui-slider-horizontal .ui-slider-range-min { left: 0; } -.ui-slider-horizontal .ui-slider-range-max { right: 0; } - -.ui-slider-vertical { width: .8em; height: 100px; } -.ui-slider-vertical .ui-slider-handle { left: -.1em !important; margin-left: 0; margin-bottom: -.6em; } -.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } -.ui-slider-vertical .ui-slider-range-min { bottom: 0; } -.ui-slider-vertical .ui-slider-range-max { top: 0; } - -.ui-progressbar { - &.ui-progressbar-determinate { - .ui-progressbar-value { - border: 0 none; - background: #8ec5fc; - } - - .ui-progressbar .ui-progressbar-label { - color: #222222; - } - } - - &.ui-progressbar-indeterminate { - background: #8ec5fc; - - .ui-progressbar-value { - border: 0 none; - background-color: $stateHighlightBgColor; - } - } -} - - - -.ui-widget-header .ui-button, -.ui-widget-content .ui-button, -.ui-widget.ui-button, -.ui-button { - border: 1px solid #2399e5; - color: #FFFFFF; - background: #2399e5; - -webkit-transition: background-color .2s; - -moz-transition: background-color .2s; - transition: background-color .2s; - - &:enabled:hover, - &:focus { - border: 1px solid #1f89ce; - background: #1f89ce; - outline: 0 none; - color: #ffffff; - } - - &:enabled:active { - border: 1px solid #156090; - background: #186ba0; - color: #ffffff; - } -} - - -/* Checkbox and Radio */ -.ui-chkbox-box.ui-state-active, -.ui-radiobutton-box.ui-state-active { - border: 1px solid #156090; - background: #186ba0; - color: #FFFFFF; -} - -.ui-chkbox-box.ui-state-focus, -.ui-radiobutton-box.ui-state-focus { - -moz-box-shadow: 0px 0px 5px #1f89ce; - -webkit-box-shadow: 0px 0px 5px #1f89ce; - box-shadow: 0px 0px 5px #1f89ce; -} - -.ui-chkbox-box.ui-state-focus.ui-state-active { - background: #186ba0; -} - -/* Inputs */ -.ui-inputtext { - background: #ffffff; - color: #222222; - -webkit-transition: .2s; - -moz-transition: .2s; - transition: .2s; -} - -.ui-inputtext.ui-state-focus, -.ui-inputtext:focus { - -moz-box-shadow: 0px 0px 5px #1f89ce; - -webkit-box-shadow: 0px 0px 5px #1f89ce; - box-shadow: 0px 0px 5px #1f89ce; -} - -/* InputSwitch */ -.ui-inputswitch-on { - background: #186ba0 !important; - color: #ffffff !important; -} - -.ui-paginator .ui-paginator-page.ui-state-active { - background: #186ba0; - color: #ffffff; - border-color: #156090; -} - -/* DataTable */ -.ui-datatable { - th { - &.ui-state-default { - background: #ebedf0; - border-color: #d9d9d9; - } - - &.ui-sortable-column:not(.ui-state-active):hover { - background: #d3d5d8; - border-color: #d9d9d9; - } - - &.ui-state-active { - background: #186ba0; - color: #ffffff; - } - } - - tbody { - > tr.ui-widget-content { - border-color: #d9d9d9; - - &.ui-datatable-odd { - background-color: #fafafb; - } - - &.ui-state-highlight { - background-color: $stateHighlightBgColor; - color: $stateHighlightTextColor; - } - } - } - - tfoot { - td { - &.ui-state-default { - background: #ebedf0; - border-color: #d9d9d9; - } - } - } -} - -/* Panel */ -.ui-panel.ui-widget { - padding: 0; - - .ui-panel-titlebar.ui-corner-all { - -moz-border-radius-bottom-left: 0; - -webkit-border-bottom-left-radius: 0; - border-bottom-left-radius: 0; - -moz-border-radius-bottom-right: 0; - -webkit-border-bottom-right-radius: 0; - border-bottom-right-radius: 0; - } - - .ui-panel-titlebar { - border-width: 0 0 1px 0; - } - - .ui-panel-titlebar-icon span { - position: relative; - top: 1px; - } - -} - -/* TreeTable */ -.ui-treetable { - th.ui-state-default { - background: #ebedf0; - border-color: #d9d9d9; - } -} - -/* ButtonSet */ -.ui-togglebutton.ui-button.ui-state-default, -.ui-selectbutton .ui-button.ui-state-default { - border: 1px solid #d6d6d6; - background: #ffffff; - font-weight: normal; - color: #555555; -} - -.ui-togglebutton.ui-button.ui-state-hover,.ui-togglebutton.ui-button.ui-state-focus, -.ui-selectbutton .ui-button.ui-state-hover,.ui-selectbutton .ui-button.ui-state-focus { - border: 1px solid #c0c0c0; - background: #eeeeee; - font-weight: normal; - color: #212121; -} - -.ui-togglebutton.ui-button.ui-state-focus, -.ui-selectbutton .ui-button.ui-state-focus.ui-state-active { - -moz-box-shadow: 0px 0px 5px #1f89ce; - -webkit-box-shadow: 0px 0px 5px #1f89ce; - box-shadow: 0px 0px 5px #1f89ce; -} - -.ui-togglebutton.ui-button.ui-state-active, -.ui-selectbutton .ui-button.ui-state-active { - border: 1px solid #156090; - background: #186ba0; - color: #FFFFFF; -} - -.ui-multiselect { - .ui-multiselect-label { - background-color: #ffffff; - } -} - -.ui-dropdown.ui-state-focus, .ui-multiselect.ui-state-focus { - -moz-box-shadow: 0px 0px 5px #1f89ce; - -webkit-box-shadow: 0px 0px 5px #1f89ce; - box-shadow: 0px 0px 5px #1f89ce; -} - -/* Growl */ -.ui-growl-item-container.ui-state-highlight { - &.ui-growl-message-info { - background-color: #2196f3; - border-color :#2196f3; - } - - &.ui-growl-message-error { - background-color: #f44336; - border-color :#f44336; - } - - &.ui-growl-message-warn { - background-color: #FFB300; - border-color :#FFB300; - } - - &.ui-growl-message-success { - background-color: #4CAF50; - border-color :#4CAF50; - } -} - -/* TabMenu */ -.ui-tabmenu { - border: 0 none; - - .ui-tabmenu-nav { - background: none; - - > li { - &.ui-state-default { - background: #f6f7f9; - } - - &.ui-state-active { - background: #ffffff; - font-weight: normal; - color: #555555; - } - - &:not(.ui-state-active):not(.ui-state-disabled):hover { - background: #ededf0; - } - } - } -} - -/* Menus */ -.ui-menu, -.ui-menu .ui-menu-child { - border: 1px solid #d9d9d9; - color: #1b1d1f; - background: #f6f7f9 0 0 repeat-x; /* Old browsers */ - background: -moz-linear-gradient(top, #f6f7f9 0%, #ebedf0 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f6f7f9), color-stop(100%,#ebedf0)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* IE10+ */ - background: linear-gradient(to bottom, #f6f7f9 0%,#ebedf0 100%); /* W3C */ -} - -.ui-menu { - .ui-menuitem { - .ui-menuitem-link { - &:hover { - background-color: #a6a6a6; - color: #ffffff; - } - } - - &.ui-menuitem-active { - > .ui-menuitem-link { - background-color: #a6a6a6; - color: #ffffff; - } - } - } -} - -/* PanelMenu */ -.ui-panelmenu .ui-panelmenu-header.ui-state-active, -.ui-panelmenu .ui-panelmenu-header.ui-state-active a { - border-color: #156090; - background: #186ba0; - color: #FFFFFF; -} - -/* DatePicker */ -.ui-datepicker.ui-widget { - padding: 0; - - .ui-datepicker-header { - -webkit-border-radius: 0px; - -moz-border-radius: 0px; - border-radius: 0px; - border-top: 0 none; - border-left: 0 none; - border-right: 0 none; - - a { - &:hover { - border-width: 1px; - } - } - } - - .ui-datepicker-calendar { - margin: 0; - - thead th { - background-color: #f6f8fa; - padding: 8px; - } - - td { - border-bottom: 1px solid rgba(213, 213, 213, 0.5); - padding: 0; - - a { - border: 0 none; - text-align: center; - padding: 8px; - - &.ui-state-highlight { - background-color: #d6d6d6; - color: #212121; - } - - &.ui-state-active { - background-color: #186ba0; - color: #ffffff; - } - } - } - - tr:last-child td { - border-bottom: 0 none; - } - } - - .ui-timepicker { - border-bottom: 0 none; - border-left: 0 none; - border-right: 0 none; - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; - } - - &.ui-datepicker-timeonly { - .ui-timepicker { - border-top: 0 none; - } - } -} - -/* Steps */ -.ui-steps .ui-steps-item.ui-state-highlight .ui-menuitem-link { - color: #ffffff; -} - -/* Dialog */ -.ui-dialog.ui-widget .ui-dialog-titlebar { - padding: 1em 1.5em; -} - -.ui-dialog.ui-widget .ui-dialog-titlebar .ui-dialog-title { - font-size: 1.25em; -} - -.ui-dialog.ui-widget .ui-dialog-content { - padding: 1em 1.5em; -} - -/* Schedule */ -.fc { - .fc-button-group { - .ui-state-active { - border: 1px solid #156090; - background: #186ba0; - color: #ffffff; - } - } -} - diff --git a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.eot b/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.eot deleted file mode 100644 index d26bc8f51..000000000 Binary files a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.eot and /dev/null differ diff --git a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.svg b/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.svg deleted file mode 100644 index ed55c105d..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.svg +++ /dev/null @@ -1,308 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.ttf b/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.ttf deleted file mode 100644 index 7b25f3ce9..000000000 Binary files a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.ttf and /dev/null differ diff --git a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.woff b/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.woff deleted file mode 100644 index 941dfa4ba..000000000 Binary files a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.woff and /dev/null differ diff --git a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.woff2 b/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.woff2 deleted file mode 100644 index 120796bb7..000000000 Binary files a/sample/Util.Samples.Webs/wwwroot/css/fonts/roboto-v15-latin-regular.woff2 and /dev/null differ diff --git a/sample/Util.Samples.Webs/wwwroot/css/images/slider_handles.png b/sample/Util.Samples.Webs/wwwroot/css/images/slider_handles.png deleted file mode 100644 index 0fddde5fe..000000000 Binary files a/sample/Util.Samples.Webs/wwwroot/css/images/slider_handles.png and /dev/null differ diff --git a/sample/Util.Samples.Webs/wwwroot/css/images/slider_handles@2x.png b/sample/Util.Samples.Webs/wwwroot/css/images/slider_handles@2x.png deleted file mode 100644 index d8c901ec8..000000000 Binary files a/sample/Util.Samples.Webs/wwwroot/css/images/slider_handles@2x.png and /dev/null differ diff --git a/sample/Util.Samples.Webs/wwwroot/css/main.scss b/sample/Util.Samples.Webs/wwwroot/css/main.scss deleted file mode 100644 index fd2e3476e..000000000 --- a/sample/Util.Samples.Webs/wwwroot/css/main.scss +++ /dev/null @@ -1,8 +0,0 @@ -//字符编码 -@charset 'utf-8'; - -//导入公共样式 -@import "common/main"; - -//导入项目样式 -@import "app/main"; \ No newline at end of file diff --git a/sample/Util.Samples.Webs/wwwroot/favicon.ico b/sample/Util.Samples.Webs/wwwroot/favicon.ico deleted file mode 100644 index a3a799985..000000000 Binary files a/sample/Util.Samples.Webs/wwwroot/favicon.ico and /dev/null differ diff --git a/src/Util.Aop.AspectCore/03-Util.Aop.AspectCore.csproj b/src/Util.Aop.AspectCore/03-Util.Aop.AspectCore.csproj new file mode 100644 index 000000000..1d8d5c920 --- /dev/null +++ b/src/Util.Aop.AspectCore/03-Util.Aop.AspectCore.csproj @@ -0,0 +1,39 @@ + + + + $(NetTargetFramework) + icon.jpg + Util.Aop.AspectCore + Util.Aop + Util.Aop.AspectCore是Util应用框架基于 AspectCore 实现AOP拦截功能的库 + + + + + .\obj\Debug\$(NetTargetFramework)\Util.Aop.AspectCore.xml + + + + + .\obj\Release\$(NetTargetFramework)\Util.Aop.AspectCore.xml + + + + + True + False + + + + + + + + + + + + + + + diff --git a/src/Util.Aop.AspectCore/AopOptions.cs b/src/Util.Aop.AspectCore/AopOptions.cs new file mode 100644 index 000000000..6e56f1701 --- /dev/null +++ b/src/Util.Aop.AspectCore/AopOptions.cs @@ -0,0 +1,15 @@ +namespace Util.Aop; + +/// +/// Aop配置 +/// +public class AopOptions { + /// + /// 是否启用IAopProxy接口标记 + /// + public bool IsEnableIAopProxy { get; set; } + /// + /// 是否启用参数拦截器,默认值: true + /// + public bool IsEnableParameterAspect { get; set; } = true; +} \ No newline at end of file diff --git a/src/Util.Aop.AspectCore/AppBuilderExtensions.cs b/src/Util.Aop.AspectCore/AppBuilderExtensions.cs new file mode 100644 index 000000000..6c52982c2 --- /dev/null +++ b/src/Util.Aop.AspectCore/AppBuilderExtensions.cs @@ -0,0 +1,105 @@ +using Util.Configs; + +namespace Util.Aop; + +/// +/// Aop配置扩展 +/// +public static class AppBuilderExtensions { + /// + /// 启用AspectCore拦截器 + /// + /// 应用生成器 + public static IAppBuilder AddAop( this IAppBuilder builder ) { + return builder.AddAop( false ); + } + + /// + /// 启用AspectCore拦截器 + /// + /// 应用生成器 + /// 是否启用IAopProxy接口标记 + public static IAppBuilder AddAop( this IAppBuilder builder,bool isEnableIAopProxy ) { + return builder.AddAop( null, isEnableIAopProxy ); + } + + /// + /// 启用AspectCore拦截器 + /// + /// 应用生成器 + /// AspectCore拦截器配置操作 + public static IAppBuilder AddAop( this IAppBuilder builder, Action setupAction ) { + return builder.AddAop( setupAction, false ); + } + + /// + /// 启用AspectCore拦截器 + /// + /// 应用生成器 + /// AspectCore拦截器配置操作 + /// 是否启用IAopProxy接口标记 + private static IAppBuilder AddAop( this IAppBuilder builder, Action setupAction, bool isEnableIAopProxy ) { + return builder.AddAop( setupAction, t => t.IsEnableIAopProxy = isEnableIAopProxy ); + } + + /// + /// 启用AspectCore拦截器 + /// + /// 应用生成器 + /// AspectCore拦截器配置操作 + /// 配置操作 + private static IAppBuilder AddAop( this IAppBuilder builder, Action setupAction, Action action ) { + builder.CheckNull( nameof( builder ) ); + builder.Host.UseServiceProviderFactory( new DynamicProxyServiceProviderFactory() ); + builder.Host.ConfigureServices( ( context, services ) => { + var options = new AopOptions(); + action?.Invoke( options ); + ConfigureDynamicProxy( services, setupAction, options.IsEnableParameterAspect,options.IsEnableIAopProxy ); + RegisterAspectScoped( services ); + } ); + return builder; + } + + /// + /// 配置拦截器 + /// + private static void ConfigureDynamicProxy( IServiceCollection services, Action setupAction,bool isEnableParameterAspect, bool isEnableIAopProxy ) { + services.ConfigureDynamicProxy( config => { + if ( setupAction == null ) { + config.NonAspectPredicates.Add( t => !IsProxy( t.DeclaringType, isEnableIAopProxy ) ); + if( isEnableParameterAspect ) + config.EnableParameterAspect(); + return; + } + setupAction.Invoke( config ); + } ); + } + + /// + /// 是否创建代理 + /// + private static bool IsProxy( Type type, bool isEnableIAopProxy ) { + if ( type == null ) + return false; + if ( isEnableIAopProxy == false ) { + return type.SafeString().Contains( "Xunit.DependencyInjection.ITestOutputHelperAccessor" ) == false; + } + var interfaces = type.GetInterfaces(); + if ( interfaces == null || interfaces.Length == 0 ) + return false; + foreach ( var item in interfaces ) { + if ( item == typeof( IAopProxy ) ) + return true; + } + return false; + } + + /// + /// 注册拦截器服务 + /// + private static void RegisterAspectScoped( IServiceCollection services ) { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + } +} \ No newline at end of file diff --git a/src/Util.Aop.AspectCore/ExceptionExtensions.cs b/src/Util.Aop.AspectCore/ExceptionExtensions.cs new file mode 100644 index 000000000..4b6b14016 --- /dev/null +++ b/src/Util.Aop.AspectCore/ExceptionExtensions.cs @@ -0,0 +1,21 @@ +namespace Util.Aop; + +/// +/// 异常扩展 +/// +public static class ExceptionExtensions { + /// + /// 获取原始异常 + /// + /// 异常 + public static Exception GetRawException( this Exception exception ) { + if( exception == null ) + return null; + if( exception is AspectCore.DynamicProxy.AspectInvocationException aspectInvocationException ) { + if( aspectInvocationException.InnerException == null ) + return aspectInvocationException; + return GetRawException( aspectInvocationException.InnerException ); + } + return exception; + } +} \ No newline at end of file diff --git a/src/Util.Aop.AspectCore/IAopProxy.cs b/src/Util.Aop.AspectCore/IAopProxy.cs new file mode 100644 index 000000000..7a2bd1a04 --- /dev/null +++ b/src/Util.Aop.AspectCore/IAopProxy.cs @@ -0,0 +1,7 @@ +namespace Util.Aop; + +/// +/// Aop代理标记 +/// +public interface IAopProxy { +} \ No newline at end of file diff --git a/src/Util.Aop.AspectCore/IgnoreAttribute.cs b/src/Util.Aop.AspectCore/IgnoreAttribute.cs new file mode 100644 index 000000000..0032d80e7 --- /dev/null +++ b/src/Util.Aop.AspectCore/IgnoreAttribute.cs @@ -0,0 +1,7 @@ +namespace Util.Aop; + +/// +/// 忽略拦截 +/// +public class IgnoreAttribute : NonAspectAttribute { +} \ No newline at end of file diff --git a/src/Util.Aop.AspectCore/InterceptorBase.cs b/src/Util.Aop.AspectCore/InterceptorBase.cs new file mode 100644 index 000000000..e246baf72 --- /dev/null +++ b/src/Util.Aop.AspectCore/InterceptorBase.cs @@ -0,0 +1,7 @@ +namespace Util.Aop; + +/// +/// 拦截器基类 +/// +public abstract class InterceptorBase : AbstractInterceptorAttribute { +} \ No newline at end of file diff --git a/src/Util.Aop.AspectCore/NotEmptyAttribute.cs b/src/Util.Aop.AspectCore/NotEmptyAttribute.cs new file mode 100644 index 000000000..5e5bfc10b --- /dev/null +++ b/src/Util.Aop.AspectCore/NotEmptyAttribute.cs @@ -0,0 +1,15 @@ +namespace Util.Aop; + +/// +/// 验证参数不能为空 +/// +public class NotEmptyAttribute : ParameterInterceptorBase { + /// + /// 执行 + /// + public override Task Invoke( ParameterAspectContext context, ParameterAspectDelegate next ) { + if( string.IsNullOrWhiteSpace( context.Parameter.Value.SafeString() ) ) + throw new ArgumentNullException( context.Parameter.Name ); + return next( context ); + } +} \ No newline at end of file diff --git a/src/Util.Aop.AspectCore/NotNullAttribute.cs b/src/Util.Aop.AspectCore/NotNullAttribute.cs new file mode 100644 index 000000000..f20dd221e --- /dev/null +++ b/src/Util.Aop.AspectCore/NotNullAttribute.cs @@ -0,0 +1,15 @@ +namespace Util.Aop; + +/// +/// 验证参数不能为null +/// +public class NotNullAttribute : ParameterInterceptorBase { + /// + /// 执行 + /// + public override Task Invoke( ParameterAspectContext context, ParameterAspectDelegate next ) { + if( context.Parameter.Value == null ) + throw new ArgumentNullException( context.Parameter.Name ); + return next( context ); + } +} \ No newline at end of file diff --git a/src/Util.Aop.AspectCore/ParameterInterceptorBase.cs b/src/Util.Aop.AspectCore/ParameterInterceptorBase.cs new file mode 100644 index 000000000..802cb6fd5 --- /dev/null +++ b/src/Util.Aop.AspectCore/ParameterInterceptorBase.cs @@ -0,0 +1,7 @@ +namespace Util.Aop; + +/// +/// 参数拦截器基类 +/// +public abstract class ParameterInterceptorBase : ParameterInterceptorAttribute { +} \ No newline at end of file diff --git a/src/Util.Aop.AspectCore/Usings.cs b/src/Util.Aop.AspectCore/Usings.cs new file mode 100644 index 000000000..059e6cc71 --- /dev/null +++ b/src/Util.Aop.AspectCore/Usings.cs @@ -0,0 +1,8 @@ +global using System; +global using System.Threading.Tasks; +global using Microsoft.Extensions.DependencyInjection; +global using AspectCore.Configuration; +global using AspectCore.DynamicProxy; +global using AspectCore.DynamicProxy.Parameters; +global using AspectCore.Extensions.AspectScope; +global using AspectCore.Extensions.DependencyInjection; \ No newline at end of file diff --git a/src/Util.Application.EntityFrameworkCore/02-Util.Application.EntityFrameworkCore.csproj b/src/Util.Application.EntityFrameworkCore/02-Util.Application.EntityFrameworkCore.csproj new file mode 100644 index 000000000..1a9c8eb95 --- /dev/null +++ b/src/Util.Application.EntityFrameworkCore/02-Util.Application.EntityFrameworkCore.csproj @@ -0,0 +1,34 @@ + + + + $(NetTargetFramework) + Util.Applications + icon.jpg + Util.Application.EntityFrameworkCore是Util应用框架基于EntityFrameworkCore数据访问的应用层类库 + Util.Application.EntityFrameworkCore + + + + + .\obj\Debug\$(NetTargetFramework)\Util.Application.EntityFrameworkCore.xml + + + + + .\obj\Release\$(NetTargetFramework)\Util.Application.EntityFrameworkCore.xml + + + + + True + False + + + + + + + + + + diff --git a/src/Util.Application.EntityFrameworkCore/CrudServiceBase.cs b/src/Util.Application.EntityFrameworkCore/CrudServiceBase.cs new file mode 100644 index 000000000..ce7bf7ecf --- /dev/null +++ b/src/Util.Application.EntityFrameworkCore/CrudServiceBase.cs @@ -0,0 +1,466 @@ +using Util.Applications.Dtos; +using Util.Data; +using Util.Data.Queries; +using Util.Domain.Compare; +using Util.Domain.Entities; +using Util.Domain.Repositories; +using Util.Helpers; +using Util.Properties; + +namespace Util.Applications; + +/// +/// 增删改查服务 +/// +/// 实体类型 +/// 数据传输对象类型 +/// 查询参数类型 +public abstract class CrudServiceBase : CrudServiceBase + where TEntity : class, IAggregateRoot, new() + where TDto : class, IDto, new() + where TQuery : IPage { + /// + /// 初始化增删改查服务 + /// + /// 服务提供器 + /// 工作单元 + /// 仓储 + protected CrudServiceBase( IServiceProvider serviceProvider, IUnitOfWork unitOfWork, IRepository repository ) : base( serviceProvider, unitOfWork, repository ) { + } +} + +/// +/// 增删改查服务 +/// +/// 实体类型 +/// 数据传输对象类型 +/// 查询参数类型 +/// 实体标识类型 +public abstract class CrudServiceBase + : CrudServiceBase, ICrudService + where TEntity : class, IAggregateRoot, new() + where TDto : class, IDto, new() + where TQuery : IPage { + /// + /// 初始化增删改查服务 + /// + /// 服务提供器 + /// 工作单元 + /// 仓储 + protected CrudServiceBase( IServiceProvider serviceProvider, IUnitOfWork unitOfWork, IRepository repository ) : base( serviceProvider, unitOfWork, repository ) { + } +} + +/// +/// 增删改查服务 +/// +/// 实体类型 +/// 数据传输对象类型 +/// 创建参数类型 +/// 修改参数类型 +/// 查询参数类型 +public abstract class CrudServiceBase + : CrudServiceBase + where TEntity : class, IAggregateRoot, new() + where TDto : class, IDto, new() + where TCreateRequest : class, IRequest, new() + where TUpdateRequest : class, IDto, new() + where TQuery : IPage { + /// + /// 初始化增删改查服务 + /// + /// 服务提供器 + /// 工作单元 + /// 仓储 + protected CrudServiceBase( IServiceProvider serviceProvider, IUnitOfWork unitOfWork, IRepository repository ) : base( serviceProvider, unitOfWork, repository ) { + } +} + +/// +/// 增删改查服务 +/// +/// 实体类型 +/// 数据传输对象类型 +/// 创建参数类型 +/// 修改参数类型 +/// 查询参数类型 +/// 实体标识类型 +public abstract class CrudServiceBase + : QueryServiceBase, ICrudService + where TEntity : class, IAggregateRoot, new() + where TDto : class,IDto, new() + where TCreateRequest : class, IRequest, new() + where TUpdateRequest : class, IDto, new() + where TQuery : IPage { + + #region 字段 + + /// + /// 仓储 + /// + private readonly IRepository _repository; + + #endregion + + #region 构造方法 + + /// + /// 初始化增删改查服务 + /// + /// 服务提供器 + /// 工作单元 + /// 仓储 + protected CrudServiceBase( IServiceProvider serviceProvider, IUnitOfWork unitOfWork, IRepository repository ) : base( serviceProvider, repository ) { + UnitOfWork = unitOfWork ?? throw new ArgumentNullException( nameof( unitOfWork ) ); + _repository = repository ?? throw new ArgumentNullException( nameof( repository ) ); + EntityDescription = Reflection.GetDisplayNameOrDescription(); + } + + #endregion + + #region 属性 + + /// + /// 工作单元 + /// + protected IUnitOfWork UnitOfWork { get; } + + /// + /// 实体描述 + /// + protected string EntityDescription { get; } + + #endregion + + #region CreateAsync(创建) + + /// + public virtual async Task CreateAsync( TCreateRequest request ) { + request.CheckNull( nameof(request) ); + request.Validate(); + var entity = ToEntity( request ); + entity.CheckNull( nameof( entity ) ); + await CreateAsync( entity ); + await CommitAsync(); + await CreateCommitAfterAsync( entity ); + return entity.Id.ToString(); + } + + /// + /// 转换为实体 + /// + /// 创建参数 + protected virtual TEntity ToEntity( TCreateRequest request ) { + return request.MapTo(); + } + + /// + /// 创建实体 + /// + private async Task CreateAsync( TEntity entity ) { + await CreateBeforeAsync( entity ); + entity.Init(); + await _repository.AddAsync( entity ); + await CreateAfterAsync( entity ); + } + + /// + /// 创建前操作 + /// + /// 实体 + protected virtual Task CreateBeforeAsync( TEntity entity ) { + return Task.CompletedTask; + } + + /// + /// 创建后操作 + /// + /// 实体 + protected virtual Task CreateAfterAsync( TEntity entity ) { + return Task.CompletedTask; + } + + /// + /// 提交工作单元 + /// + protected virtual async Task CommitAsync() { + await UnitOfWork.CommitAsync(); + } + + /// + /// 创建提交后操作 + /// + /// 实体 + protected virtual Task CreateCommitAfterAsync( TEntity entity ) { + return Task.CompletedTask; + } + + #endregion + + #region UpdateAsync(修改) + + /// + public virtual async Task UpdateAsync( TUpdateRequest request ) { + request.CheckNull( nameof(request) ); + request.Validate(); + if ( request.Id.IsEmpty() ) + throw new InvalidOperationException( R.IdIsEmpty ); + var oldEntity = await FindOldEntityAsync( request.Id ); + oldEntity.CheckNull( nameof( oldEntity ) ); + var entity = ToEntity( oldEntity.Clone(), request ); + entity.CheckNull( nameof( entity ) ); + var changes = oldEntity.GetChanges( entity ); + await UpdateAsync( entity ); + await CommitAsync(); + await UpdateCommitAfterAsync( entity, changes ); + } + + /// + /// 查找旧实体 + /// + /// 标识 + private async Task FindOldEntityAsync( object id ) { + return await _repository.FindByIdAsync( id ); + } + + /// + /// 转换为实体 + /// + /// 旧实体 + /// 修改参数 + protected virtual TEntity ToEntity( TEntity oldEntity, TUpdateRequest request ) { + return request.MapTo( oldEntity ); + } + + /// + /// 修改实体 + /// + /// 实体 + private async Task UpdateAsync( TEntity entity ) { + await UpdateBeforeAsync( entity ); + await _repository.UpdateAsync( entity ); + await UpdateAfterAsync( entity ); + } + + /// + /// 修改前操作 + /// + /// 实体 + protected virtual Task UpdateBeforeAsync( TEntity entity ) { + return Task.CompletedTask; + } + + /// + /// 修改后操作 + /// + /// 实体 + protected virtual Task UpdateAfterAsync( TEntity entity ) { + return Task.CompletedTask; + } + + /// + /// 修改提交后操作 + /// + /// 实体 + /// 变更值集合 + protected virtual Task UpdateCommitAfterAsync( TEntity entity,ChangeValueCollection changeValues ) { + return Task.CompletedTask; + } + + #endregion + + #region DeleteAsync(删除) + + /// + public virtual async Task DeleteAsync( string ids ) { + if ( ids.IsEmpty() ) + return; + var entities = await _repository.FindByIdsAsync( ids ); + if ( entities?.Count == 0 ) + return; + await DeleteBeforeAsync( entities ); + await _repository.RemoveAsync( entities ); + await DeleteAfterAsync( entities ); + await CommitAsync(); + await DeleteCommitAfterAsync( entities ); + } + + /// + /// 删除前操作 + /// + /// 实体列表 + protected virtual Task DeleteBeforeAsync( List entities ) { + return Task.CompletedTask; + } + + /// + /// 删除后操作 + /// + /// 实体集合 + protected virtual Task DeleteAfterAsync( List entities ) { + return Task.CompletedTask; + } + + /// + /// 删除提交后操作 + /// + /// 实体集合 + protected virtual Task DeleteCommitAfterAsync( List entities ) { + return Task.CompletedTask; + } + + #endregion + + #region SaveAsync(批量保存) + + /// + /// 批量保存 + /// + /// 新增列表 + /// 修改列表 + /// 删除列表 + public virtual async Task> SaveAsync( List creationList, List updateList, List deleteList ) { + if ( creationList == null && updateList == null && deleteList == null ) + return new List(); + creationList ??= new List(); + updateList ??= new List(); + deleteList ??= new List(); + FilterList( creationList, updateList, deleteList ); + var addEntities = ToEntities( creationList ); + var updateEntities = ToEntities( updateList ); + var deleteEntities = ToEntities( deleteList ); + await SaveBeforeAsync( addEntities, updateEntities, deleteEntities ); + await AddListAsync( addEntities ); + var changeValues = await UpdateListAsync( updateEntities ); + await DeleteListAsync( deleteEntities ); + await SaveAfterAsync( addEntities, updateEntities, deleteEntities ); + await CommitAsync(); + await SaveCommitAfterAsync( addEntities, updateEntities, deleteEntities, changeValues ); + return GetResult( addEntities, updateEntities ); + } + + /// + /// 过滤列表 + /// + private void FilterList( List creationList, List updateList, List deleteList ) { + FilterByDeleteList( creationList, deleteList ); + FilterByDeleteList( updateList, deleteList ); + } + + /// + /// 过滤需要删除的项 + /// + private void FilterByDeleteList( List list, List deleteList ) { + for ( int i = 0; i < list.Count; i++ ) { + var item = list[i]; + if ( deleteList.Any( d => d.Id == item.Id ) ) + list.Remove( item ); + } + } + + /// + /// 转换为实体集合 + /// + private List ToEntities( List dtos ) { + return dtos.Select( ToEntity ).Distinct().ToList(); + } + + /// + /// 转换为实体 + /// + /// 参数 + protected virtual TEntity ToEntity( TDto request ) { + return request.MapTo(); + } + + /// + /// 保存前操作 + /// + /// 新增列表 + /// 修改列表 + /// 删除列表 + protected virtual Task SaveBeforeAsync( List creationList, List updateList, List deleteList ) { + return Task.CompletedTask; + } + + /// + /// 添加实体列表 + /// + private async Task AddListAsync( List list ) { + if ( list.Count == 0 ) + return; + foreach ( var entity in list ) + await CreateAsync( entity ); + } + + /// + /// 更新实体列表 + /// + private async Task>> UpdateListAsync( List list ) { + var result = new List>(); + if ( list.Count == 0 ) + return result; + var oldEntities = await FindOldEntities( list ); + foreach ( var entity in list ) { + var oldEntity = oldEntities.Find( t => t.Id.Equals( entity.Id ) ); + if ( oldEntity != null ) + result.Add( new Tuple( entity, oldEntity.GetChanges( entity ) ) ); + await UpdateAsync( entity ); + } + return result; + } + + /// + /// 查找旧实体集合 + /// + private async Task> FindOldEntities( List list ) { + return await _repository.FindAllAsync( item => list.Select( t => t.Id ).Contains( item.Id ) ); + } + + /// + /// 删除实体列表 + /// + private async Task DeleteListAsync( List list ) { + if ( list.Count == 0 ) + return; + foreach ( var entity in list ) + await DeleteChildrenAsync( entity ); + } + + /// + /// 删除子节点集合 + /// + protected virtual async Task DeleteChildrenAsync( TEntity parent ) { + await _repository.RemoveAsync( parent.Id ); + } + + /// + /// 保存后操作 + /// + /// 新增列表 + /// 修改列表 + /// 删除列表 + protected virtual Task SaveAfterAsync( List creationList, List updateList, List deleteList ) { + return Task.CompletedTask; + } + + /// + /// 保存提交后操作 + /// + /// 新增列表 + /// 修改列表 + /// 删除列表 + /// 变更值集合 + protected virtual Task SaveCommitAfterAsync( List creationList, List updateList, List deleteList, List> changeValues ) { + return Task.CompletedTask; + } + + /// + /// 获取结果 + /// + protected virtual List GetResult( List creationList, List updateList ) { + return creationList.Concat( updateList ).Select( ToDto ).ToList(); + } + + #endregion +} \ No newline at end of file diff --git a/src/Util.Application.EntityFrameworkCore/QueryServiceBase.cs b/src/Util.Application.EntityFrameworkCore/QueryServiceBase.cs new file mode 100644 index 000000000..4c125140c --- /dev/null +++ b/src/Util.Application.EntityFrameworkCore/QueryServiceBase.cs @@ -0,0 +1,178 @@ +using Microsoft.EntityFrameworkCore; +using Util.Data; +using Util.Data.EntityFrameworkCore; +using Util.Data.Queries; +using Util.Data.Stores; +using Util.Domain; + +namespace Util.Applications; + +/// +/// 查询服务 +/// +/// 实体类型 +/// 数据传输对象类型 +/// 查询参数类型 +public abstract class QueryServiceBase : QueryServiceBase + where TEntity : class, IKey + where TDto : new() + where TQuery : IPage { + /// + /// 初始化查询服务 + /// + /// 服务提供器 + /// 查询存储器 + protected QueryServiceBase( IServiceProvider serviceProvider, IQueryStore store ) : base( serviceProvider,store ) { + } +} + +/// +/// 查询服务 +/// +/// 实体类型 +/// 数据传输对象类型 +/// 查询参数类型 +/// 实体标识类型 +public abstract class QueryServiceBase : ServiceBase, IQueryService + where TEntity : class, IKey + where TDto : new() + where TQuery : IPage { + + #region 字段 + + /// + /// 查询存储器 + /// + private readonly IQueryStore _store; + + #endregion + + #region 构造方法 + + /// + /// 初始化查询服务 + /// + /// 服务提供器 + /// 查询存储器 + protected QueryServiceBase( IServiceProvider serviceProvider,IQueryStore store ) : base( serviceProvider ) { + _store = store ?? throw new ArgumentNullException( nameof( store ) ); + } + + #endregion + + #region 属性 + + /// + /// 查询时是否跟踪实体 + /// + protected virtual bool IsTracking => false; + + #endregion + + #region ToDto(转换) + + /// + /// 转换为数据传输对象 + /// + /// 实体 + protected virtual TDto ToDto( TEntity entity ) { + return entity.MapTo(); + } + + #endregion + + #region GetAllAsync(获取全部实体) + + /// + public virtual async Task> GetAllAsync() { + var entities = await GetStore().FindAllAsync(); + return entities.Select( ToDto ).ToList(); + } + + /// + /// 获取查询存储器 + /// + private IQueryStore GetStore() { + if( IsTracking ) + return _store; + return _store.NoTracking(); + } + + #endregion + + #region GetByIdAsync(通过标识获取实体) + + /// + public virtual async Task GetByIdAsync( object id ) { + var key = Util.Helpers.Convert.To( id ); + return ToDto( await GetStore().FindByIdAsync( key ) ); + } + + #endregion + + #region GetByIdsAsync(通过标识列表获取实体列表) + + /// + public virtual async Task> GetByIdsAsync( string ids ) { + var entities = await GetStore().FindByIdsAsync( ids ); + return entities.Select( ToDto ).ToList(); + } + + #endregion + + #region QueryAsync(查询) + + /// + public virtual async Task> QueryAsync( TQuery param ) { + if( param == null ) + return new List(); + var queryable = GetStore().Find(); + queryable = AddConditions( queryable, param ); + queryable = Filter( queryable, param ); + var result = await queryable.OrderBy( param ).ToListAsync(); + return result.Select( ToDto ).ToList(); + } + + /// + /// 添加条件列表 + /// + private IQueryable AddConditions( IQueryable queryable, TQuery param ) { + var conditions = GetConditions( param ); + if ( conditions == null ) + return queryable; + foreach ( var condition in conditions ) + queryable = queryable.Where( condition ); + return queryable; + } + + /// + /// 获取条件列表 + /// + protected virtual IEnumerable> GetConditions( TQuery param ) { + return null; + } + + /// + /// 过滤 + /// + protected virtual IQueryable Filter( IQueryable queryable, TQuery param ) { + return queryable; + } + + #endregion + + #region PageQueryAsync(分页查询) + + /// + public virtual async Task> PageQueryAsync( TQuery param ) { + if( param == null ) + return new PageList(); + var queryable = GetStore().Find(); + queryable = AddConditions( queryable, param ); + queryable = Filter( queryable, param ); + var result = await queryable.ToPageListAsync( param ); + return result.Convert( ToDto ); + } + + #endregion +} \ No newline at end of file diff --git a/src/Util.Application.EntityFrameworkCore/Trees/TreeQueryServiceBase.cs b/src/Util.Application.EntityFrameworkCore/Trees/TreeQueryServiceBase.cs new file mode 100644 index 000000000..e1f784951 --- /dev/null +++ b/src/Util.Application.EntityFrameworkCore/Trees/TreeQueryServiceBase.cs @@ -0,0 +1,70 @@ +using Util.Data; +using Util.Data.Trees; +using Util.Domain.Trees; + +namespace Util.Applications.Trees; + +/// +/// 树形查询服务 +/// +/// 实体类型 +/// 数据传输对象类型 +/// 查询参数类型 +public abstract class TreeQueryServiceBase + : TreeQueryServiceBase + where TEntity : class, ITreeEntity, new() + where TDto : class, ITreeNode, new() + where TQuery : class, ITreeQueryParameter { + /// + /// 初始化树形查询服务 + /// + /// 服务提供器 + /// 树形仓储 + protected TreeQueryServiceBase( IServiceProvider serviceProvider, ITreeRepository repository ) : base( serviceProvider, repository ) { + } +} + +/// +/// 树形查询服务 +/// +/// 实体类型 +/// 数据传输对象类型 +/// 查询参数类型 +/// 实体标识类型 +/// 父标识类型 +public abstract class TreeQueryServiceBase + : QueryServiceBase, ITreeQueryService + where TEntity : class, ITreeEntity, new() + where TDto : class, ITreeNode, new() + where TQuery : class, ITreeQueryParameter { + /// + /// 树形仓储 + /// + private readonly ITreeRepository _repository; + + /// + /// 初始化树形查询服务 + /// + /// 服务提供器 + /// 树形仓储 + protected TreeQueryServiceBase( IServiceProvider serviceProvider, ITreeRepository repository ) : base( serviceProvider, repository ) { + _repository = repository; + } + + ///