From eaabdc3593cc4da6f9b0537a2af106fc52f8cb9b Mon Sep 17 00:00:00 2001 From: cli <377476583@qq.com> Date: Tue, 11 Mar 2025 10:24:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 3 + .gitignore | 271 +++ Delete-BIN-OBJ-Folders.bat | 20 + Directory.Build.Lion.targets | 41 + Directory.Build.Microsoft.targets | 26 + Directory.Build.Volo.targets | 94 + Directory.Build.targets | 103 + Dockerfile | 46 + JiShe.IOT.sln | 147 ++ NuGet.Config | 7 + .../Controllers/HomeController.cs | 10 + .../AutoDeleteAfterSuccessAttributer.cs | 21 + .../Extensions/Hangfire/CronType.cs | 78 + .../Hangfire/CustomHangfireAuthorizeFilter.cs | 11 + .../Extensions/Hangfire/JobRetryLastFilter.cs | 24 + .../Hangfire/RecurringJobsExtensions.cs | 15 + host/JiShe.IOT.HttpApi.Host/GlobalUsings.cs | 65 + .../IOTHttpApiHostConst.cs | 40 + .../IOTHttpApiHostModule.cs | 290 +++ .../JiShe.IOT.HttpApi.Host.csproj | 65 + .../JiShe.IOT.HttpApi.Host/Pages/Login.cshtml | 158 ++ .../Pages/Login.cshtml.cs | 69 + .../Pages/Monitor.cshtml | 171 ++ .../Pages/Monitor.cshtml.cs | 12 + host/JiShe.IOT.HttpApi.Host/Program.cs | 25 + .../Properties/launchSettings.json | 12 + host/JiShe.IOT.HttpApi.Host/Startup.cs | 16 + .../appsettings.Production.json | 3 + host/JiShe.IOT.HttpApi.Host/appsettings.json | 61 + host/JiShe.IOT.HttpApi.Host/tempkey.jwk | 1 + host/JiShe.IOT.HttpApi.Host/tempkey.rsa | 1 + .../wwwroot/images/cap.png | Bin 0 -> 11113 bytes .../wwwroot/images/hangfire.png | Bin 0 -> 36278 bytes .../wwwroot/images/miniprofiler.png | Bin 0 -> 22147 bytes .../wwwroot/images/more.png | Bin 0 -> 20558 bytes .../wwwroot/images/swagger.png | Bin 0 -> 38571 bytes .../libs/bootstrap/css/bootstrap.min.css | 6 + .../AbpProWebGatewayModule.cs | 53 + host/JiShe.IOT.WebGateway/Dockerfile | 22 + host/JiShe.IOT.WebGateway/GlobalUsings.cs | 21 + .../JiShe.IOT.WebGateway.csproj | 10 + host/JiShe.IOT.WebGateway/Program.cs | 16 + .../Properties/launchSettings.json | 14 + .../appsettings.Consul.json | 48 + .../appsettings.Production.json | 52 + host/JiShe.IOT.WebGateway/appsettings.json | 52 + .../GlobalUsings.cs | 16 + .../IOTApplicationContractsModule.cs | 18 + .../IOTDtoExtensions.cs | 25 + .../JiShe.IOT.Application.Contracts.csproj | 23 + .../Jobs/IRecurringJob.cs | 11 + .../IOTPermissionDefinitionProvider.cs | 17 + .../Permissions/IOTPermissions.cs | 7 + src/JiShe.IOT.Application/GlobalUsings.cs | 20 + src/JiShe.IOT.Application/IOTAppService.cs | 12 + .../IOTApplicationAutoMapperProfile.cs | 10 + .../IOTApplicationModule.cs | 23 + .../JiShe.IOT.Application.csproj | 26 + src/JiShe.IOT.Application/Jobs/TestJob.cs | 11 + .../Properties/AssemblyInfo.cs | 2 + .../DbMigratorHostedService.cs | 42 + src/JiShe.IOT.DbMigrator/Dockerfile | 19 + src/JiShe.IOT.DbMigrator/GlobalUsings.cs | 18 + .../IOTDbMigratorModule.cs | 42 + .../JiShe.IOT.DbMigrator.csproj | 33 + src/JiShe.IOT.DbMigrator/Program.cs | 45 + src/JiShe.IOT.DbMigrator/appsettings.json | 5 + src/JiShe.IOT.DbMigrator/tempkey.rsa | 13 + src/JiShe.IOT.Domain.Shared/GlobalUsings.cs | 39 + .../IOTDomainErrorCodes.cs | 7 + .../IOTDomainSharedConsts.cs | 9 + .../IOTDomainSharedModule.cs | 44 + .../IOTGlobalFeatureConfigurator.cs | 21 + .../IOTModuleExtensionConfigurator.cs | 67 + .../JiShe.IOT.Domain.Shared.csproj | 22 + .../Localization/IOT/ar.json | 8 + .../Localization/IOT/cs.json | 8 + .../Localization/IOT/de-DE.json | 8 + .../Localization/IOT/en-GB.json | 8 + .../Localization/IOT/en.json | 29 + .../Localization/IOT/es.json | 8 + .../Localization/IOT/fr.json | 8 + .../Localization/IOT/hu.json | 8 + .../Localization/IOT/nl.json | 8 + .../Localization/IOT/pl-PL.json | 8 + .../Localization/IOT/pt-BR.json | 8 + .../Localization/IOT/ru.json | 8 + .../Localization/IOT/sl.json | 8 + .../Localization/IOT/tr.json | 8 + .../Localization/IOT/vi.json | 8 + .../Localization/IOT/zh-Hans.json | 30 + .../Localization/IOT/zh-Hant.json | 14 + .../Localization/IOTResource.cs | 8 + .../MultiTenancy/MultiTenancyConsts.cs | 11 + .../Users/Dto/UserOutput.cs | 7 + .../Data/IIOTDbSchemaMigrator.cs | 7 + .../Data/IOTDbMigrationService.cs | 205 ++ .../Data/NullIOTDbSchemaMigrator.cs | 13 + src/JiShe.IOT.Domain/GlobalUsings.cs | 32 + src/JiShe.IOT.Domain/IOTDbProperties.cs | 9 + src/JiShe.IOT.Domain/IOTDomainModule.cs | 18 + src/JiShe.IOT.Domain/IOTDomainService.cs | 36 + src/JiShe.IOT.Domain/JiShe.IOT.Domain.csproj | 18 + .../Properties/AssemblyInfo.cs | 3 + .../Settings/IOTSettingDefinitionProvider.cs | 25 + src/JiShe.IOT.Domain/Settings/IOTSettings.cs | 7 + .../EntityFrameworkCoreIOTDbSchemaMigrator.cs | 27 + .../EntityFrameworkCore/IIOTDbContext.cs | 8 + .../EntityFrameworkCore/IOTDbContext.cs | 61 + .../IOTDbContextModelCreatingExtensions.cs | 11 + .../IOTEfCoreEntityExtensionMappings.cs | 40 + .../IOTEntityFrameworkCoreModule.cs | 41 + .../IOTMigrationsDbContextFactory.cs | 39 + .../GlobalUsings.cs | 40 + .../JiShe.IOT.EntityFrameworkCore.csproj | 25 + .../20250219005605_Init.Designer.cs | 2089 +++++++++++++++++ .../Migrations/20250219005605_Init.cs | 1378 +++++++++++ .../Migrations/IOTDbContextModelSnapshot.cs | 2086 ++++++++++++++++ .../Properties/AssemblyInfo.cs | 2 + .../FreeSqlBasicRepository.cs | 14 + .../GlobalUsings.cs | 7 + .../IOTFreeSqlModule.cs | 15 + .../JiShe.IOT.FreeSqlRepository.csproj | 17 + src/JiShe.IOT.HttpApi.Client/GlobalUsings.cs | 10 + .../IOTHttpApiClientModule.cs | 27 + .../JiShe.IOT.HttpApi.Client.csproj | 18 + .../Controllers/IOTController.cs | 12 + src/JiShe.IOT.HttpApi/GlobalUsings.cs | 11 + src/JiShe.IOT.HttpApi/IOTHttpApiModule.cs | 32 + .../JiShe.IOT.HttpApi.csproj | 23 + .../GlobalUsings.cs | 6 + .../IOTApplicationTestBase.cs | 7 + .../IOTApplicationTestModule.cs | 13 + .../JiShe.IOT.Application.Tests.csproj | 17 + .../Samples/SampleAppServiceTests.cs | 28 + test/JiShe.IOT.Domain.Tests/GlobalUsings.cs | 13 + .../IOTDomainTestBase.cs | 10 + .../IOTDomainTestModule.cs | 10 + .../JiShe.IOT.Domain.Tests.csproj | 16 + .../Localizations/LocalizationHelper_Tests.cs | 40 + .../Localizations/TestType.cs | 9 + .../Samples/SampleDomainTests.cs | 40 + .../IOTEntityFrameworkCoreTestBase.cs | 7 + .../IOTEntityFrameworkCoreTestModule.cs | 52 + .../GlobalUsings.cs | 11 + ...JiShe.IOT.EntityFrameworkCore.Tests.csproj | 18 + .../IOTFreeSqlRepositoryTestBase.cs | 18 + .../IOTFreeSqlRepositoryTestModule.cs | 30 + .../JiShe.IOT.FreeSqlReppsitory.Tests.csproj | 12 + .../Users/UserFreeSqlBasicRepository_Tests.cs | 29 + .../ClientDemoService.cs | 21 + .../ConsoleTestAppHostedService.cs | 20 + .../GlobalUsings.cs | 14 + .../IOTConsoleApiClientModule.cs | 22 + ...e.IOT.HttpApi.Client.ConsoleTestApp.csproj | 29 + .../Program.cs | 17 + .../appsettings.json | 18 + .../appsettings.secrets.json | 2 + test/JiShe.IOT.TestBase/GlobalUsings.cs | 22 + test/JiShe.IOT.TestBase/IOTTestBase.cs | 53 + test/JiShe.IOT.TestBase/IOTTestBaseModule.cs | 41 + .../IOTTestDataSeedContributor.cs | 12 + .../JiShe.IOT.TestBase.csproj | 32 + .../Security/FakeCurrentPrincipalAccessor.cs | 38 + test/JiShe.IOT.TestBase/appsettings.json | 5 + 165 files changed, 10196 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 Delete-BIN-OBJ-Folders.bat create mode 100644 Directory.Build.Lion.targets create mode 100644 Directory.Build.Microsoft.targets create mode 100644 Directory.Build.Volo.targets create mode 100644 Directory.Build.targets create mode 100644 Dockerfile create mode 100644 JiShe.IOT.sln create mode 100644 NuGet.Config create mode 100644 host/JiShe.IOT.HttpApi.Host/Controllers/HomeController.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/AutoDeleteAfterSuccessAttributer.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/CronType.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/CustomHangfireAuthorizeFilter.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/JobRetryLastFilter.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/RecurringJobsExtensions.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/GlobalUsings.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/IOTHttpApiHostConst.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/IOTHttpApiHostModule.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/JiShe.IOT.HttpApi.Host.csproj create mode 100644 host/JiShe.IOT.HttpApi.Host/Pages/Login.cshtml create mode 100644 host/JiShe.IOT.HttpApi.Host/Pages/Login.cshtml.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/Pages/Monitor.cshtml create mode 100644 host/JiShe.IOT.HttpApi.Host/Pages/Monitor.cshtml.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/Program.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/Properties/launchSettings.json create mode 100644 host/JiShe.IOT.HttpApi.Host/Startup.cs create mode 100644 host/JiShe.IOT.HttpApi.Host/appsettings.Production.json create mode 100644 host/JiShe.IOT.HttpApi.Host/appsettings.json create mode 100644 host/JiShe.IOT.HttpApi.Host/tempkey.jwk create mode 100644 host/JiShe.IOT.HttpApi.Host/tempkey.rsa create mode 100644 host/JiShe.IOT.HttpApi.Host/wwwroot/images/cap.png create mode 100644 host/JiShe.IOT.HttpApi.Host/wwwroot/images/hangfire.png create mode 100644 host/JiShe.IOT.HttpApi.Host/wwwroot/images/miniprofiler.png create mode 100644 host/JiShe.IOT.HttpApi.Host/wwwroot/images/more.png create mode 100644 host/JiShe.IOT.HttpApi.Host/wwwroot/images/swagger.png create mode 100644 host/JiShe.IOT.HttpApi.Host/wwwroot/libs/bootstrap/css/bootstrap.min.css create mode 100644 host/JiShe.IOT.WebGateway/AbpProWebGatewayModule.cs create mode 100644 host/JiShe.IOT.WebGateway/Dockerfile create mode 100644 host/JiShe.IOT.WebGateway/GlobalUsings.cs create mode 100644 host/JiShe.IOT.WebGateway/JiShe.IOT.WebGateway.csproj create mode 100644 host/JiShe.IOT.WebGateway/Program.cs create mode 100644 host/JiShe.IOT.WebGateway/Properties/launchSettings.json create mode 100644 host/JiShe.IOT.WebGateway/appsettings.Consul.json create mode 100644 host/JiShe.IOT.WebGateway/appsettings.Production.json create mode 100644 host/JiShe.IOT.WebGateway/appsettings.json create mode 100644 src/JiShe.IOT.Application.Contracts/GlobalUsings.cs create mode 100644 src/JiShe.IOT.Application.Contracts/IOTApplicationContractsModule.cs create mode 100644 src/JiShe.IOT.Application.Contracts/IOTDtoExtensions.cs create mode 100644 src/JiShe.IOT.Application.Contracts/JiShe.IOT.Application.Contracts.csproj create mode 100644 src/JiShe.IOT.Application.Contracts/Jobs/IRecurringJob.cs create mode 100644 src/JiShe.IOT.Application.Contracts/Permissions/IOTPermissionDefinitionProvider.cs create mode 100644 src/JiShe.IOT.Application.Contracts/Permissions/IOTPermissions.cs create mode 100644 src/JiShe.IOT.Application/GlobalUsings.cs create mode 100644 src/JiShe.IOT.Application/IOTAppService.cs create mode 100644 src/JiShe.IOT.Application/IOTApplicationAutoMapperProfile.cs create mode 100644 src/JiShe.IOT.Application/IOTApplicationModule.cs create mode 100644 src/JiShe.IOT.Application/JiShe.IOT.Application.csproj create mode 100644 src/JiShe.IOT.Application/Jobs/TestJob.cs create mode 100644 src/JiShe.IOT.Application/Properties/AssemblyInfo.cs create mode 100644 src/JiShe.IOT.DbMigrator/DbMigratorHostedService.cs create mode 100644 src/JiShe.IOT.DbMigrator/Dockerfile create mode 100644 src/JiShe.IOT.DbMigrator/GlobalUsings.cs create mode 100644 src/JiShe.IOT.DbMigrator/IOTDbMigratorModule.cs create mode 100644 src/JiShe.IOT.DbMigrator/JiShe.IOT.DbMigrator.csproj create mode 100644 src/JiShe.IOT.DbMigrator/Program.cs create mode 100644 src/JiShe.IOT.DbMigrator/appsettings.json create mode 100644 src/JiShe.IOT.DbMigrator/tempkey.rsa create mode 100644 src/JiShe.IOT.Domain.Shared/GlobalUsings.cs create mode 100644 src/JiShe.IOT.Domain.Shared/IOTDomainErrorCodes.cs create mode 100644 src/JiShe.IOT.Domain.Shared/IOTDomainSharedConsts.cs create mode 100644 src/JiShe.IOT.Domain.Shared/IOTDomainSharedModule.cs create mode 100644 src/JiShe.IOT.Domain.Shared/IOTGlobalFeatureConfigurator.cs create mode 100644 src/JiShe.IOT.Domain.Shared/IOTModuleExtensionConfigurator.cs create mode 100644 src/JiShe.IOT.Domain.Shared/JiShe.IOT.Domain.Shared.csproj create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/ar.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/cs.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/de-DE.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/en-GB.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/en.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/es.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/fr.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/hu.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/nl.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/pl-PL.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/pt-BR.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/ru.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/sl.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/tr.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/vi.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/zh-Hans.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOT/zh-Hant.json create mode 100644 src/JiShe.IOT.Domain.Shared/Localization/IOTResource.cs create mode 100644 src/JiShe.IOT.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs create mode 100644 src/JiShe.IOT.Domain.Shared/Users/Dto/UserOutput.cs create mode 100644 src/JiShe.IOT.Domain/Data/IIOTDbSchemaMigrator.cs create mode 100644 src/JiShe.IOT.Domain/Data/IOTDbMigrationService.cs create mode 100644 src/JiShe.IOT.Domain/Data/NullIOTDbSchemaMigrator.cs create mode 100644 src/JiShe.IOT.Domain/GlobalUsings.cs create mode 100644 src/JiShe.IOT.Domain/IOTDbProperties.cs create mode 100644 src/JiShe.IOT.Domain/IOTDomainModule.cs create mode 100644 src/JiShe.IOT.Domain/IOTDomainService.cs create mode 100644 src/JiShe.IOT.Domain/JiShe.IOT.Domain.csproj create mode 100644 src/JiShe.IOT.Domain/Properties/AssemblyInfo.cs create mode 100644 src/JiShe.IOT.Domain/Settings/IOTSettingDefinitionProvider.cs create mode 100644 src/JiShe.IOT.Domain/Settings/IOTSettings.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreIOTDbSchemaMigrator.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IIOTDbContext.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTDbContext.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTDbContextModelCreatingExtensions.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTEfCoreEntityExtensionMappings.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTEntityFrameworkCoreModule.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTMigrationsDbContextFactory.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/GlobalUsings.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/JiShe.IOT.EntityFrameworkCore.csproj create mode 100644 src/JiShe.IOT.EntityFrameworkCore/Migrations/20250219005605_Init.Designer.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/Migrations/20250219005605_Init.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/Migrations/IOTDbContextModelSnapshot.cs create mode 100644 src/JiShe.IOT.EntityFrameworkCore/Properties/AssemblyInfo.cs create mode 100644 src/JiShe.IOT.FreeSqlRepository/FreeSqlBasicRepository.cs create mode 100644 src/JiShe.IOT.FreeSqlRepository/GlobalUsings.cs create mode 100644 src/JiShe.IOT.FreeSqlRepository/IOTFreeSqlModule.cs create mode 100644 src/JiShe.IOT.FreeSqlRepository/JiShe.IOT.FreeSqlRepository.csproj create mode 100644 src/JiShe.IOT.HttpApi.Client/GlobalUsings.cs create mode 100644 src/JiShe.IOT.HttpApi.Client/IOTHttpApiClientModule.cs create mode 100644 src/JiShe.IOT.HttpApi.Client/JiShe.IOT.HttpApi.Client.csproj create mode 100644 src/JiShe.IOT.HttpApi/Controllers/IOTController.cs create mode 100644 src/JiShe.IOT.HttpApi/GlobalUsings.cs create mode 100644 src/JiShe.IOT.HttpApi/IOTHttpApiModule.cs create mode 100644 src/JiShe.IOT.HttpApi/JiShe.IOT.HttpApi.csproj create mode 100644 test/JiShe.IOT.Application.Tests/GlobalUsings.cs create mode 100644 test/JiShe.IOT.Application.Tests/IOTApplicationTestBase.cs create mode 100644 test/JiShe.IOT.Application.Tests/IOTApplicationTestModule.cs create mode 100644 test/JiShe.IOT.Application.Tests/JiShe.IOT.Application.Tests.csproj create mode 100644 test/JiShe.IOT.Application.Tests/Samples/SampleAppServiceTests.cs create mode 100644 test/JiShe.IOT.Domain.Tests/GlobalUsings.cs create mode 100644 test/JiShe.IOT.Domain.Tests/IOTDomainTestBase.cs create mode 100644 test/JiShe.IOT.Domain.Tests/IOTDomainTestModule.cs create mode 100644 test/JiShe.IOT.Domain.Tests/JiShe.IOT.Domain.Tests.csproj create mode 100644 test/JiShe.IOT.Domain.Tests/Localizations/LocalizationHelper_Tests.cs create mode 100644 test/JiShe.IOT.Domain.Tests/Localizations/TestType.cs create mode 100644 test/JiShe.IOT.Domain.Tests/Samples/SampleDomainTests.cs create mode 100644 test/JiShe.IOT.EntityFrameworkCore.Tests/EntityFrameworkCore/IOTEntityFrameworkCoreTestBase.cs create mode 100644 test/JiShe.IOT.EntityFrameworkCore.Tests/EntityFrameworkCore/IOTEntityFrameworkCoreTestModule.cs create mode 100644 test/JiShe.IOT.EntityFrameworkCore.Tests/GlobalUsings.cs create mode 100644 test/JiShe.IOT.EntityFrameworkCore.Tests/JiShe.IOT.EntityFrameworkCore.Tests.csproj create mode 100644 test/JiShe.IOT.FreeSqlReppsitory.Tests/IOTFreeSqlRepositoryTestBase.cs create mode 100644 test/JiShe.IOT.FreeSqlReppsitory.Tests/IOTFreeSqlRepositoryTestModule.cs create mode 100644 test/JiShe.IOT.FreeSqlReppsitory.Tests/JiShe.IOT.FreeSqlReppsitory.Tests.csproj create mode 100644 test/JiShe.IOT.FreeSqlReppsitory.Tests/Users/UserFreeSqlBasicRepository_Tests.cs create mode 100644 test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs create mode 100644 test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs create mode 100644 test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/GlobalUsings.cs create mode 100644 test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/IOTConsoleApiClientModule.cs create mode 100644 test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/JiShe.IOT.HttpApi.Client.ConsoleTestApp.csproj create mode 100644 test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/Program.cs create mode 100644 test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/appsettings.json create mode 100644 test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json create mode 100644 test/JiShe.IOT.TestBase/GlobalUsings.cs create mode 100644 test/JiShe.IOT.TestBase/IOTTestBase.cs create mode 100644 test/JiShe.IOT.TestBase/IOTTestBaseModule.cs create mode 100644 test/JiShe.IOT.TestBase/IOTTestDataSeedContributor.cs create mode 100644 test/JiShe.IOT.TestBase/JiShe.IOT.TestBase.csproj create mode 100644 test/JiShe.IOT.TestBase/Security/FakeCurrentPrincipalAccessor.cs create mode 100644 test/JiShe.IOT.TestBase/appsettings.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c90a992 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +**/bin +**/obj +**/logs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17d74f7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,271 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +.DS_Store +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/logs +/aspnet-core/services/host/Lion.AbpPro.IdentityServer/Logs +/aspnet-core/services/host/Lion.AbpPro.IdentityServer/Logs +/aspnet-core/gateways/Lion.AbpPro.WebGateway/appsettings.Production.json +/aspnet-core/services/host/Lion.AbpPro.IdentityServer/appsettings.Production.json +/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.Production.json +aspnet-core/services/host/Lion.AbpPro.Web.Blazor.Server/Logs/logs.txt +/nupkgs +/aspnet-core/Lion.AbpPro.sln.DotSettings +/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/logs +/docs/site +/aspnet-core/modules/LanguageManagement/host/Lion.AbpPro.LanguageManagement.HttpApi.Host/Logs +/aspnet-core/frameworks/test/Lion.AbpPro.EntityFrameworkCore.Mysql.Tests/Logs +/aspnet-core/frameworks/test/Lion.AbpPro.EntityFrameworkCore.Mysql.Tests/wwwroot/libs +/templates/abp-vnext-pro-nuget-all/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/logs +/templates/abp-vnext-pro-nuget-simplify/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/logs +/vben28/pnpm-lock.yaml +/host/JiShe.IOT.HttpApi.Host/logs diff --git a/Delete-BIN-OBJ-Folders.bat b/Delete-BIN-OBJ-Folders.bat new file mode 100644 index 0000000..02cfaa5 --- /dev/null +++ b/Delete-BIN-OBJ-Folders.bat @@ -0,0 +1,20 @@ +@ECHO off +cls + +ECHO Deleting all BIN and OBJ folders... +ECHO. + +FOR /d /r . %%d in (bin,obj) DO ( + IF EXIST "%%d" ( + ECHO %%d | FIND /I "\node_modules\" > Nul && ( + ECHO.Skipping: %%d + ) || ( + ECHO.Deleting: %%d + rd /s/q "%%d" + ) + ) +) + +ECHO. +ECHO.BIN and OBJ folders have been successfully deleted. Press any key to exit. +pause > nul \ No newline at end of file diff --git a/Directory.Build.Lion.targets b/Directory.Build.Lion.targets new file mode 100644 index 0000000..669d673 --- /dev/null +++ b/Directory.Build.Lion.targets @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.Microsoft.targets b/Directory.Build.Microsoft.targets new file mode 100644 index 0000000..0de58ec --- /dev/null +++ b/Directory.Build.Microsoft.targets @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.Volo.targets b/Directory.Build.Volo.targets new file mode 100644 index 0000000..d230a25 --- /dev/null +++ b/Directory.Build.Volo.targets @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000..d2e47f3 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,103 @@ + + + + + + + + latest + 1.0.0 + Abp vNext Pro + $(NoWarn);CS1591;CS0436;NU1504 + app + true + WangJunZzz + true + https://github.com/WangJunZzz/abp-vnext-pro + icon.png + bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..edf9081 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ +# FROM mcr.microsoft.com/dotnet/aspnet:8.0 + +# # 创建目录 +# RUN mkdir /app + +# COPY publish /app + + + +# # 设置工作目录 +# WORKDIR /app + +# # 暴露80端口 +# EXPOSE 80 +# # 设置时区 .net6 才有这个问题 +# ENV TZ=Asia/Shanghai + +# # 设置环境变量 +# ENV ASPNETCORE_ENVIRONMENT=Production + +# ENTRYPOINT ["dotnet", "JiShe.IOT.HttpApi.Host.dll"] + + + +FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 +ENV TZ=Asia/Shanghai +ENV ASPNETCORE_ENVIRONMENT=Production + +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +WORKDIR /src +COPY . . +WORKDIR "/src/host/JiShe.IOT.HttpApi.Host" +RUN dotnet build "JiShe.IOT.HttpApi.Host.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "JiShe.IOT.HttpApi.Host.csproj" -c Release -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "JiShe.IOT.HttpApi.Host.dll"] + + diff --git a/JiShe.IOT.sln b/JiShe.IOT.sln new file mode 100644 index 0000000..c363d87 --- /dev/null +++ b/JiShe.IOT.sln @@ -0,0 +1,147 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31410.414 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.Domain", "src\JiShe.IOT.Domain\JiShe.IOT.Domain.csproj", "{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.Application", "src\JiShe.IOT.Application\JiShe.IOT.Application.csproj", "{1A94A50E-06DC-43C1-80B5-B662820EC3EB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.EntityFrameworkCore", "src\JiShe.IOT.EntityFrameworkCore\JiShe.IOT.EntityFrameworkCore.csproj", "{C956DD76-69C8-4A9C-83EA-D17DF83340FD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CA9AC87F-097E-4F15-8393-4BC07735A5B0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{04DBDB01-70F4-4E06-B468-8F87850B22BE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.Application.Tests", "test\JiShe.IOT.Application.Tests\JiShe.IOT.Application.Tests.csproj", "{50B2631D-129C-47B3-A587-029CCD6099BC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.Domain.Shared", "src\JiShe.IOT.Domain.Shared\JiShe.IOT.Domain.Shared.csproj", "{42F719ED-8413-4895-B5B4-5AB56079BC66}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.Application.Contracts", "src\JiShe.IOT.Application.Contracts\JiShe.IOT.Application.Contracts.csproj", "{520659C8-C734-4298-A3DA-B539DB9DFC0B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.HttpApi", "src\JiShe.IOT.HttpApi\JiShe.IOT.HttpApi.csproj", "{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.HttpApi.Client", "src\JiShe.IOT.HttpApi.Client\JiShe.IOT.HttpApi.Client.csproj", "{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.EntityFrameworkCore.Tests", "test\JiShe.IOT.EntityFrameworkCore.Tests\JiShe.IOT.EntityFrameworkCore.Tests.csproj", "{1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.TestBase", "test\JiShe.IOT.TestBase\JiShe.IOT.TestBase.csproj", "{91853F21-9CD9-4132-BC29-A7D5D84FFFE7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.Domain.Tests", "test\JiShe.IOT.Domain.Tests\JiShe.IOT.Domain.Tests.csproj", "{E512F4D9-9375-480F-A2F6-A46509F9D824}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.HttpApi.Client.ConsoleTestApp", "test\JiShe.IOT.HttpApi.Client.ConsoleTestApp\JiShe.IOT.HttpApi.Client.ConsoleTestApp.csproj", "{EF480016-9127-4916-8735-D2466BDBC582}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.DbMigrator", "src\JiShe.IOT.DbMigrator\JiShe.IOT.DbMigrator.csproj", "{AA94D832-1CCC-4715-95A9-A483F23A1A5D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0.Solution Items", "0.Solution Items", "{2C4A6DB8-8D9E-42E6-B7C3-1EDB7B3DE22E}" + ProjectSection(SolutionItems) = preProject + NuGet.Config = NuGet.Config + Directory.Build.Microsoft.targets = Directory.Build.Microsoft.targets + Directory.Build.targets = Directory.Build.targets + Directory.Build.Volo.targets = Directory.Build.Volo.targets + Directory.Build.Lion.targets = Directory.Build.Lion.targets + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "host", "host", "{8C1B8C6C-C518-4290-B070-622CCA6004DA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.HttpApi.Host", "host\JiShe.IOT.HttpApi.Host\JiShe.IOT.HttpApi.Host.csproj", "{FB20372D-6C96-4733-9AAC-12522F15CAA6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.IOT.FreeSqlRepository", "src\JiShe.IOT.FreeSqlRepository\JiShe.IOT.FreeSqlRepository.csproj", "{27C7A0E6-4C2E-4AFF-9DE7-1F526DDC0D18}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.IOT.WebGateway", "host\JiShe.IOT.WebGateway\JiShe.IOT.WebGateway.csproj", "{9C009501-0ED2-4930-B020-C8D06FE28E44}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.Build.0 = Release|Any CPU + {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.Build.0 = Release|Any CPU + {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.Build.0 = Release|Any CPU + {50B2631D-129C-47B3-A587-029CCD6099BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50B2631D-129C-47B3-A587-029CCD6099BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50B2631D-129C-47B3-A587-029CCD6099BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50B2631D-129C-47B3-A587-029CCD6099BC}.Release|Any CPU.Build.0 = Release|Any CPU + {42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.Build.0 = Release|Any CPU + {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.Build.0 = Release|Any CPU + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.Build.0 = Release|Any CPU + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.Build.0 = Release|Any CPU + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Release|Any CPU.Build.0 = Release|Any CPU + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Release|Any CPU.Build.0 = Release|Any CPU + {E512F4D9-9375-480F-A2F6-A46509F9D824}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E512F4D9-9375-480F-A2F6-A46509F9D824}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E512F4D9-9375-480F-A2F6-A46509F9D824}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E512F4D9-9375-480F-A2F6-A46509F9D824}.Release|Any CPU.Build.0 = Release|Any CPU + {EF480016-9127-4916-8735-D2466BDBC582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF480016-9127-4916-8735-D2466BDBC582}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF480016-9127-4916-8735-D2466BDBC582}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF480016-9127-4916-8735-D2466BDBC582}.Release|Any CPU.Build.0 = Release|Any CPU + {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.Build.0 = Release|Any CPU + {FB20372D-6C96-4733-9AAC-12522F15CAA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB20372D-6C96-4733-9AAC-12522F15CAA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB20372D-6C96-4733-9AAC-12522F15CAA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB20372D-6C96-4733-9AAC-12522F15CAA6}.Release|Any CPU.Build.0 = Release|Any CPU + {27C7A0E6-4C2E-4AFF-9DE7-1F526DDC0D18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {27C7A0E6-4C2E-4AFF-9DE7-1F526DDC0D18}.Debug|Any CPU.Build.0 = Debug|Any CPU + {27C7A0E6-4C2E-4AFF-9DE7-1F526DDC0D18}.Release|Any CPU.ActiveCfg = Release|Any CPU + {27C7A0E6-4C2E-4AFF-9DE7-1F526DDC0D18}.Release|Any CPU.Build.0 = Release|Any CPU + {9C009501-0ED2-4930-B020-C8D06FE28E44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C009501-0ED2-4930-B020-C8D06FE28E44}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C009501-0ED2-4930-B020-C8D06FE28E44}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C009501-0ED2-4930-B020-C8D06FE28E44}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {554AD327-6DBA-4F8F-96F8-81CE7A0C863F} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {1A94A50E-06DC-43C1-80B5-B662820EC3EB} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {C956DD76-69C8-4A9C-83EA-D17DF83340FD} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {50B2631D-129C-47B3-A587-029CCD6099BC} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} + {42F719ED-8413-4895-B5B4-5AB56079BC66} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {520659C8-C734-4298-A3DA-B539DB9DFC0B} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {4164BDF7-F527-4E85-9CE6-E3C2D7426A27} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {3B5A0094-670D-4BB1-BFDD-61B88A8773DC} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} + {91853F21-9CD9-4132-BC29-A7D5D84FFFE7} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} + {E512F4D9-9375-480F-A2F6-A46509F9D824} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} + {EF480016-9127-4916-8735-D2466BDBC582} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} + {AA94D832-1CCC-4715-95A9-A483F23A1A5D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {FB20372D-6C96-4733-9AAC-12522F15CAA6} = {8C1B8C6C-C518-4290-B070-622CCA6004DA} + {27C7A0E6-4C2E-4AFF-9DE7-1F526DDC0D18} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {9C009501-0ED2-4930-B020-C8D06FE28E44} = {8C1B8C6C-C518-4290-B070-622CCA6004DA} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F} + EndGlobalSection +EndGlobal diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 0000000..44f8e7f --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/Controllers/HomeController.cs b/host/JiShe.IOT.HttpApi.Host/Controllers/HomeController.cs new file mode 100644 index 0000000..502cde6 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Controllers/HomeController.cs @@ -0,0 +1,10 @@ +namespace JiShe.IOT.Controllers +{ + public class HomeController : AbpController + { + public ActionResult Index() + { + return Redirect("/Login"); + } + } +} diff --git a/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/AutoDeleteAfterSuccessAttributer.cs b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/AutoDeleteAfterSuccessAttributer.cs new file mode 100644 index 0000000..d68a112 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/AutoDeleteAfterSuccessAttributer.cs @@ -0,0 +1,21 @@ +namespace JiShe.IOT.Extensions.Hangfire; + +public class AutoDeleteAfterSuccessAttributer : JobFilterAttribute, IApplyStateFilter +{ + private readonly TimeSpan _deleteAfter; + + public AutoDeleteAfterSuccessAttributer(TimeSpan timeSpan) + { + _deleteAfter = timeSpan; + } + + public void OnStateApplied(ApplyStateContext context, IWriteOnlyTransaction transaction) + { + context.JobExpirationTimeout = _deleteAfter; + } + + public void OnStateUnapplied(ApplyStateContext context, IWriteOnlyTransaction transaction) + { + + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/CronType.cs b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/CronType.cs new file mode 100644 index 0000000..6d180ce --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/CronType.cs @@ -0,0 +1,78 @@ +namespace JiShe.IOT.Extensions.Hangfire +{ + /// + /// Cron类型 + /// + public static class CronType + { + /// + /// 周期性为分钟的任务 + /// + /// 执行周期的间隔,默认为每分钟一次 + /// + public static string Minute(int interval = 1) + { + return "1 0/" + interval.ToString() + " * * * ? "; + } + + /// + /// 周期性为小时的任务 + /// + /// 第几分钟开始,默认为第一分钟 + /// 执行周期的间隔,默认为每小时一次 + /// + public static string Hour(int minute = 1, int interval = 1) + { + return "1 " + minute + " 0/" + interval.ToString() + " * * ? "; + } + + /// + /// 周期性为天的任务 + /// + /// 第几小时开始,默认从1点开始 + /// 第几分钟开始,默认从第1分钟开始 + /// 执行周期的间隔,默认为每天一次 + /// + public static string Day(int hour = 1, int minute = 1, int interval = 1) + { + return "1 " + minute.ToString() + " " + hour.ToString() + " 1/" + interval.ToString() + " * ? "; + } + + /// + /// 周期性为周的任务 + /// + /// 星期几开始,默认从星期一点开始 + /// 第几小时开始,默认从1点开始 + /// 第几分钟开始,默认从第1分钟开始 + /// + public static string Week(DayOfWeek dayOfWeek = DayOfWeek.Monday, int hour = 1, int minute = 1) + { + return Cron.Weekly(dayOfWeek, hour, minute); + } + + /// + /// 周期性为月的任务 + /// + /// 几号开始,默认从一号开始 + /// 第几小时开始,默认从1点开始 + /// 第几分钟开始,默认从第1分钟开始 + /// + public static string Month(int day = 1, int hour = 1, int minute = 1) + { + return Cron.Monthly(day, hour, minute); + } + + /// + /// 周期性为年的任务 + /// + /// 几月开始,默认从一月开始 + /// 几号开始,默认从一号开始 + /// 第几小时开始,默认从1点开始 + /// 第几分钟开始,默认从第1分钟开始 + /// + public static string Year(int month = 1, int day = 1, int hour = 1, int minute = 1) + { + return Cron.Yearly(month, day, hour, minute); + } + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/CustomHangfireAuthorizeFilter.cs b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/CustomHangfireAuthorizeFilter.cs new file mode 100644 index 0000000..41ed584 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/CustomHangfireAuthorizeFilter.cs @@ -0,0 +1,11 @@ +namespace JiShe.IOT.Extensions.Hangfire +{ + public class CustomHangfireAuthorizeFilter : IDashboardAuthorizationFilter + { + public bool Authorize(DashboardContext context) + { + var _currentUser = context.GetHttpContext().RequestServices.GetRequiredService(); + return _currentUser.IsAuthenticated; + } + } +} diff --git a/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/JobRetryLastFilter.cs b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/JobRetryLastFilter.cs new file mode 100644 index 0000000..a331569 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/JobRetryLastFilter.cs @@ -0,0 +1,24 @@ +namespace JiShe.IOT.Extensions.Hangfire; + +/// +/// 重试最后一次 +/// +public class JobRetryLastFilter : JobFilterAttribute, IElectStateFilter +{ + private int RetryCount { get; } + + public JobRetryLastFilter(int retryCount) + { + RetryCount = retryCount; + } + + + public void OnStateElection(ElectStateContext context) + { + var retryAttempt = context.GetJobParameter("RetryCount"); + if (RetryCount == retryAttempt) + { + Log.Error("最后一次重试"); + } + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/RecurringJobsExtensions.cs b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/RecurringJobsExtensions.cs new file mode 100644 index 0000000..ab2f67a --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Extensions/Hangfire/RecurringJobsExtensions.cs @@ -0,0 +1,15 @@ +using JiShe.IOT.Jobs; + +namespace JiShe.IOT.Extensions.Hangfire +{ + public static class RecurringJobsExtensions + { + public static void CreateRecurringJob(this ApplicationInitializationContext context) + { + RecurringJob.AddOrUpdate("测试Job", e => e.ExecuteAsync(), CronType.Minute(1), new RecurringJobOptions() + { + TimeZone = TimeZoneInfo.Local + }); + } + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/GlobalUsings.cs b/host/JiShe.IOT.HttpApi.Host/GlobalUsings.cs new file mode 100644 index 0000000..c1f3004 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/GlobalUsings.cs @@ -0,0 +1,65 @@ +// Global using directives + +global using System; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Text; +global using System.Text.RegularExpressions; +global using System.Threading.Tasks; +global using Hangfire; +global using Hangfire.Common; +global using Hangfire.Dashboard; +global using Hangfire.States; +global using Hangfire.Storage; +global using Lion.AbpPro; +global using JiShe.IOT.EntityFrameworkCore; +global using JiShe.IOT.Extensions; +global using JiShe.IOT.Extensions.Hangfire; +global using JiShe.IOT.MultiTenancy; +global using Microsoft.AspNetCore.Authentication.JwtBearer; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.DataProtection; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Identity; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore.Mvc.Abstractions; +global using Microsoft.AspNetCore.Mvc.Filters; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Localization; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Logging.Abstractions; +global using Microsoft.Extensions.Options; +global using Microsoft.IdentityModel.Tokens; +global using Microsoft.OpenApi.Models; +global using Serilog; +global using StackExchange.Redis; +global using Swagger; +global using Swashbuckle.AspNetCore.SwaggerUI; +global using Volo.Abp; +global using Volo.Abp.Account.Web; +global using Volo.Abp.AspNetCore.Auditing; +global using Volo.Abp.AspNetCore.Authentication.JwtBearer; +global using Volo.Abp.AspNetCore.ExceptionHandling; +global using Volo.Abp.AspNetCore.Mvc; +global using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy; +global using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; +global using Volo.Abp.AspNetCore.Serilog; +global using Volo.Abp.Auditing; +global using Volo.Abp.Authorization; +global using Volo.Abp.BackgroundJobs; +global using Volo.Abp.BackgroundJobs.Hangfire; +global using Volo.Abp.Caching; +global using Volo.Abp.Caching.StackExchangeRedis; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.Domain.Entities; +global using Volo.Abp.ExceptionHandling; +global using Volo.Abp.Http; +global using Volo.Abp.Json; +global using Volo.Abp.Modularity; +global using Volo.Abp.MultiTenancy; +global using Volo.Abp.Users; +global using Volo.Abp.Validation; \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/IOTHttpApiHostConst.cs b/host/JiShe.IOT.HttpApi.Host/IOTHttpApiHostConst.cs new file mode 100644 index 0000000..8c4319f --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/IOTHttpApiHostConst.cs @@ -0,0 +1,40 @@ +namespace JiShe.IOT +{ + public static class IOTHttpApiHostConst + { + /// + /// 跨域策略名 + /// + public const string DefaultCorsPolicyName = "Default"; + + /// + /// Cookies名称 + /// + public const string DefaultCookieName = "JiShe.IOT.Http.Api"; + + /// + /// SwaggerUi 端点 + /// + public const string SwaggerUiEndPoint = "/swagger"; + + /// + /// Hangfire 端点 + /// + public const string HangfireDashboardEndPoint = "/hangfire"; + + /// + /// CAP 端点 + /// + public const string CapDashboardEndPoint = "/cap"; + + + public const string MoreEndPoint = "https://doc.cncore.club/"; + + + /// + /// HMiniprofiler端点 + /// + public const string MiniprofilerEndPoint = "/profiler/results-index"; + + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/IOTHttpApiHostModule.cs b/host/JiShe.IOT.HttpApi.Host/IOTHttpApiHostModule.cs new file mode 100644 index 0000000..d7fa24b --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/IOTHttpApiHostModule.cs @@ -0,0 +1,290 @@ +namespace JiShe.IOT +{ + [DependsOn( + typeof(IOTHttpApiModule), + typeof(AbpProSharedHostingMicroserviceModule), + typeof(AbpAspNetCoreMvcUiMultiTenancyModule), + typeof(IOTEntityFrameworkCoreModule), + typeof(AbpAspNetCoreAuthenticationJwtBearerModule), + typeof(AbpAspNetCoreSerilogModule), + typeof(AbpAccountWebModule), + typeof(IOTApplicationModule), + typeof(AbpAspNetCoreMvcUiBasicThemeModule), + typeof(AbpCachingStackExchangeRedisModule) + )] + public class IOTHttpApiHostModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + ConfigureCache(context); + ConfigureSwaggerServices(context); + ConfigureJwtAuthentication(context, configuration); + ConfigureMiniProfiler(context); + ConfigureIdentity(context); + ConfigureAuditLog(context); + ConfigurationSignalR(context); + ConfigurationMultiTenancy(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + var configuration = context.GetConfiguration(); + + app.UseAbpProRequestLocalization(); + app.UseCorrelationId(); + app.UseStaticFiles(); + app.UseMiniProfiler(); + app.UseRouting(); + app.UseCors(IOTHttpApiHostConst.DefaultCorsPolicyName); + app.UseAuthentication(); + + if (MultiTenancyConsts.IsEnabled) + { + app.UseMultiTenancy(); + } + + app.UseAuthorization(); + app.UseSwagger(); + app.UseAbpSwaggerUI(options => + { + options.SwaggerEndpoint("/swagger/IOT/swagger.json", "IOT API"); + options.DocExpansion(DocExpansion.None); + options.DefaultModelsExpandDepth(-1); + }); + + app.UseAuditing(); + app.UseAbpSerilogEnrichers(); + + app.UseUnitOfWork(); + app.UseConfiguredEndpoints(endpoints => + { + endpoints.MapHealthChecks("/health"); + + // endpoints.MapHangfireDashboard("/hangfire", new DashboardOptions() + // { + // Authorization = new[] { new CustomHangfireAuthorizeFilter() }, + // IgnoreAntiforgeryToken = true + // }); + + }); + + + if (configuration.GetValue("Consul:Enabled", false)) + { + app.UseConsul(); + } + } + + private void ConfigurationSignalR(ServiceConfigurationContext context) + { + var redisConnection = context.Services.GetConfiguration().GetValue("Redis:Configuration"); + + if (redisConnection.IsNullOrWhiteSpace()) + { + throw new UserFriendlyException(message: "Redis连接字符串未配置."); + } + + context.Services.AddSignalR().AddStackExchangeRedis(redisConnection, options => { options.Configuration.ChannelPrefix = "Lion.AbpPro"; }); + } + + /// + /// 配置MiniProfiler + /// + private void ConfigureMiniProfiler(ServiceConfigurationContext context) + { + context.Services.AddMiniProfiler(options => options.RouteBasePath = "/profiler").AddEntityFramework(); + } + + /// + /// 配置JWT + /// + private void ConfigureJwtAuthentication(ServiceConfigurationContext context, + IConfiguration configuration) + { + context.Services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(options => + { + options.TokenValidationParameters = + new TokenValidationParameters() + { + // 是否开启签名认证 + ValidateIssuerSigningKey = true, + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + //ClockSkew = TimeSpan.Zero, + ValidIssuer = configuration["Jwt:Issuer"], + ValidAudience = configuration["Jwt:Audience"], + IssuerSigningKey = + new SymmetricSecurityKey( + Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"])) + }; + + options.Events = new JwtBearerEvents + { + OnMessageReceived = currentContext => + { + var path = currentContext.HttpContext.Request.Path; + if (path.StartsWithSegments("/login")) + { + return Task.CompletedTask; + } + + var accessToken = string.Empty; + if (currentContext.HttpContext.Request.Headers.ContainsKey("Authorization")) + { + accessToken = currentContext.HttpContext.Request.Headers["Authorization"]; + if (!string.IsNullOrWhiteSpace(accessToken)) + { + accessToken = accessToken.Split(" ").LastOrDefault(); + } + } + + if (accessToken.IsNullOrWhiteSpace()) + { + accessToken = currentContext.Request.Query["access_token"].FirstOrDefault(); + } + + if (accessToken.IsNullOrWhiteSpace()) + { + accessToken = currentContext.Request.Cookies[IOTHttpApiHostConst.DefaultCookieName]; + } + + currentContext.Token = accessToken; + currentContext.Request.Headers.Remove("Authorization"); + currentContext.Request.Headers.Add("Authorization", $"Bearer {accessToken}"); + + return Task.CompletedTask; + } + }; + }); + } + + + /// + /// Redis缓存 + /// + private void ConfigureCache(ServiceConfigurationContext context) + { + Configure( + options => { options.KeyPrefix = "IOT:"; }); + var configuration = context.Services.GetConfiguration(); + var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); + context.Services + .AddDataProtection() + .PersistKeysToStackExchangeRedis(redis, "IOT-Protection-Keys"); + } + + + /// + /// 配置Identity + /// + private void ConfigureIdentity(ServiceConfigurationContext context) + { + context.Services.Configure(options => { options.Lockout = new LockoutOptions() { AllowedForNewUsers = false }; }); + } + + private static void ConfigureSwaggerServices(ServiceConfigurationContext context) + { + context.Services.AddSwaggerGen( + options => + { + // 文件下载类型 + options.MapType(() => new OpenApiSchema() { Type = "file" }); + + options.SwaggerDoc("IOT", + new OpenApiInfo { Title = "JiSheIOT API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.EnableAnnotations(); // 启用注解 + options.DocumentFilter(); + options.SchemaFilter(); + // 加载所有xml注释,这里会导致swagger加载有点缓慢 + var xmlPaths = Directory.GetFiles(AppContext.BaseDirectory, "*.xml"); + foreach (var xml in xmlPaths) + { + options.IncludeXmlComments(xml, true); + } + + options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, + new OpenApiSecurityScheme() + { + Description = "直接在下框输入JWT生成的Token", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = JwtBearerDefaults.AuthenticationScheme, + BearerFormat = "JWT" + }); + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, Id = "Bearer" + } + }, + new List() + } + }); + + options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme() + { + Type = SecuritySchemeType.ApiKey, + In = ParameterLocation.Header, + Name = "Accept-Language", + Description = "多语言设置,系统预设语言有zh-Hans、en,默认为zh-Hans", + }); + + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { Type = ReferenceType.SecurityScheme, Id = "ApiKey" } + }, + Array.Empty() + } + }); + }); + } + + + /// + /// 审计日志 + /// + private void ConfigureAuditLog(ServiceConfigurationContext context) + { + Configure + ( + options => + { + options.IsEnabled = true; + options.EntityHistorySelectors.AddAllEntities(); + options.ApplicationName = "JiShe.IOT"; + } + ); + + Configure( + options => + { + options.IgnoredUrls.Add("/AuditLogs/page"); + options.IgnoredUrls.Add("/hangfire/stats"); + options.IgnoredUrls.Add("/cap"); + }); + } + + private void ConfigurationMultiTenancy() + { + Configure(options => { options.IsEnabled = MultiTenancyConsts.IsEnabled; }); + } + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/JiShe.IOT.HttpApi.Host.csproj b/host/JiShe.IOT.HttpApi.Host/JiShe.IOT.HttpApi.Host.csproj new file mode 100644 index 0000000..b78430c --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/JiShe.IOT.HttpApi.Host.csproj @@ -0,0 +1,65 @@ + + + + + net9.0 + JiShe.IOT + true + JiShe.IOT-4681b4fd-151f-4221-84a4-929d86723e4c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/host/JiShe.IOT.HttpApi.Host/Pages/Login.cshtml b/host/JiShe.IOT.HttpApi.Host/Pages/Login.cshtml new file mode 100644 index 0000000..54d729a --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Pages/Login.cshtml @@ -0,0 +1,158 @@ +@page +@model JiShe.IOT.Pages.Login + +@{ + Layout = null; +} + + + + + + 后台服务登录 + + + +
+
+
+
+ @Html.AntiForgeryToken() + 后台服务登录 +
+ +
+
+ +
+
+ +
+
+
+
+
+ + + \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/Pages/Login.cshtml.cs b/host/JiShe.IOT.HttpApi.Host/Pages/Login.cshtml.cs new file mode 100644 index 0000000..5c581de --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Pages/Login.cshtml.cs @@ -0,0 +1,69 @@ + +using Lion.AbpPro.BasicManagement.ConfigurationOptions; +using Lion.AbpPro.BasicManagement.Users; +using Lion.AbpPro.BasicManagement.Users.Dtos; +using Microsoft.AspNetCore.Mvc.RazorPages; + + +namespace JiShe.IOT.Pages +{ + public class Login : PageModel + { + private readonly IAccountAppService _accountAppService; + private readonly ILogger _logger; + private readonly IHostEnvironment _hostEnvironment; + private readonly JwtOptions _jwtOptions; + public Login(IAccountAppService accountAppService, + ILogger logger, + IHostEnvironment hostEnvironment, + IOptionsSnapshot jwtOptions) + { + _accountAppService = accountAppService; + _logger = logger; + _hostEnvironment = hostEnvironment; + _jwtOptions = jwtOptions.Value; + } + + public void OnGet() + { + } + + public async Task OnPost() + { + string userName = Request.Form["userName"]; + string password = Request.Form["password"]; + if (userName.IsNullOrWhiteSpace() || password.IsNullOrWhiteSpace()) + { + Response.Redirect("/Login"); + return; + } + + try + { + var options = new CookieOptions + { + Expires = DateTime.Now.AddHours(_jwtOptions.ExpirationTime), + SameSite = SameSiteMode.Unspecified, + }; + + + // 设置cookies domain + //options.Domain = "IOT.cn"; + + + var result = await _accountAppService.LoginAsync(new LoginInput() + { Name = userName, Password = password }); + Response.Cookies.Append(IOTHttpApiHostConst.DefaultCookieName, + result.Token, options); + } + catch (Exception e) + { + _logger.LogError($"登录失败:{e.Message}"); + Response.Redirect("/Login"); + return; + } + + Response.Redirect("/monitor"); + } + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/Pages/Monitor.cshtml b/host/JiShe.IOT.HttpApi.Host/Pages/Monitor.cshtml new file mode 100644 index 0000000..6e545f8 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Pages/Monitor.cshtml @@ -0,0 +1,171 @@ +@page +@using JiShe.IOT +@model JiShe.IOT.Pages.Monitor + + +@{ + Layout = null; +} + + + + + + + + + + 后端服务 + + + +
+ +
+
+
+ + + +
+

+ SwaggerUI +

+
+
+
+ + @*
*@ + @*
*@ + @* *@ + @* *@ + @* *@ + @*
*@ + @*

*@ + @* Hangfire面板 *@ + @*

*@ + @*
*@ + @*
*@ + @*
*@ +
+
+ + + +
+

+ Miniprofiler +

+
+
+
+
+
+ + + +
+

+ 了解更多... +

+
+
+
+
+
+ + + \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/Pages/Monitor.cshtml.cs b/host/JiShe.IOT.HttpApi.Host/Pages/Monitor.cshtml.cs new file mode 100644 index 0000000..adcedbc --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Pages/Monitor.cshtml.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace JiShe.IOT.Pages +{ + public class Monitor : PageModel + { + public void OnGet() + { + + } + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/Program.cs b/host/JiShe.IOT.HttpApi.Host/Program.cs new file mode 100644 index 0000000..8d49e8d --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Program.cs @@ -0,0 +1,25 @@ +namespace JiShe.IOT +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + + } + + private static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.ConfigureKestrel((context, options) => { options.Limits.MaxRequestBodySize = 1024 * 50; }); + webBuilder.UseStartup(); + }) + .UseSerilog((context, loggerConfiguration) => + { + SerilogToEsExtensions.SetSerilogConfiguration( + loggerConfiguration, + context.Configuration); + }).UseAutofac(); + } +} diff --git a/host/JiShe.IOT.HttpApi.Host/Properties/launchSettings.json b/host/JiShe.IOT.HttpApi.Host/Properties/launchSettings.json new file mode 100644 index 0000000..227cec9 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "JiShe.IOT.HttpApi.Host": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "http://localhost:44315", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/Startup.cs b/host/JiShe.IOT.HttpApi.Host/Startup.cs new file mode 100644 index 0000000..e5e7a10 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/Startup.cs @@ -0,0 +1,16 @@ +namespace JiShe.IOT +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddApplication(); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + { + app.InitializeApplication(); + + } + } +} diff --git a/host/JiShe.IOT.HttpApi.Host/appsettings.Production.json b/host/JiShe.IOT.HttpApi.Host/appsettings.Production.json new file mode 100644 index 0000000..0e0dcd2 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/appsettings.Production.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/appsettings.json b/host/JiShe.IOT.HttpApi.Host/appsettings.json new file mode 100644 index 0000000..adc9072 --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/appsettings.json @@ -0,0 +1,61 @@ +{ + "Serilog": { + "Using": [ + "Serilog.Sinks.Console", + "Serilog.Sinks.File" + ], + "MinimumLevel": { + "Default": "Debug", + "Override": { + "Microsoft": "Information", + "Volo.Abp": "Information", + "Hangfire": "Information", + "DotNetCore.CAP": "Information", + "Serilog.AspNetCore": "Information", + "Microsoft.EntityFrameworkCore": "Warning", + "Microsoft.AspNetCore": "Information" + } + }, + "WriteTo": [ + { + "Name": "Console" + }, + { + "Name": "File", + "Args": { + "path": "logs/logs-.txt", + "rollingInterval": "Day" + } + } + ] + }, + "App": { + "SelfUrl": "http://localhost:44315", + "CorsOrigins": "https://*.IOT.com,http://localhost:4200,http://localhost:3100,http://118.190.144.92:9111" + }, + "ConnectionStrings": { + "Default": "Data Source=118.190.144.92;Port=33306;Database=JiSheIOTDB;uid=root;pwd=admin123;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" + }, + "Redis": { + "Configuration": "118.190.144.92:6379,defaultdatabase=14" + }, + "Jwt": { + "Audience": "JiShe.IOT", + "SecurityKey": "dzehzRz9a8asdfasfdadfasdfasdfafsdadfasbasdf=", + "Issuer": "JiShe.IOT", + "ExpirationTime": 2 + }, + "ElasticSearch": { + "Enabled": "false", + "Url": "http://es.cn", + "IndexFormat": "JiShe.IOT.development.{0:yyyy.MM.dd}", + "UserName": "elastic", + "Password": "aVVhjQ95RP7nbwNy", + "SearchIndexFormat": "JiShe.IOT.development*" + }, + "Consul": { + "Enabled": false, + "Host": "http://localhost:8500", + "Service": "Project-Service" + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/tempkey.jwk b/host/JiShe.IOT.HttpApi.Host/tempkey.jwk new file mode 100644 index 0000000..b4f8b7d --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/tempkey.jwk @@ -0,0 +1 @@ +{"AdditionalData":{},"Alg":"RS256","Crv":null,"D":"eH-Ld45J684VguyI2jACQEEVGtTx79Nt7ElT20JeUi-pbVnhJxxAJwnAe68d9Q8skpv6BxZs5QuyIORwfGpJK-lKVuo8EtyUQTuUuPmP4o1YK4cv2FIi5xN18tddTltg2JmJi1sN2AD5z-zwm45YNvoFxdQYlnUlA9lJL8QfG0HQLMQX1sv2_lgND8RfRGQBCpVXC2kcap4GvkFVQpKaQ5xaUqvNdH6ftwkGMdFfMRlHGhyYyabIjs4T16HslofvXiHbOCAzk37HtBNNsBpeoQuZul1-G7tAndHe1XtuGvuE-k1fyqdm3YiCU8wK7FpvQU3x6JqvfqmWgMAPnWKOtQ","DP":"hd3I9Nc3LlaZDoPg20JZu48kpv9rMMQ0rLtcZ0UPB_HpZWBC_No-3t3t1HFRbD4iz0MCpCR6gb5q4UsL2N2xh3Q8OhQ1Zrl76UKDZrVKs3oE0VVr9K2VUU3s1sytE4OWSv7PAHYURygcx_MrunMn8Ryd4ZJBQ_g5M2GvpBj1o5M","DQ":"T3ibciK4KxGGHqau9dnWxE6l3fGtcNw1GcjV93Lxe0NKTbfrwPEIFVVAyPsFS8QdmRXEgyunkDFKLHyq2hXBi2fZCwXGoWkUqVUKAKMaNYZaDDd_XeJKOu7mwNY8rgxNETHCyMSnnNNPNabBf2iiXmrBnMwesle2L1kwky42yns","E":"AQAB","K":null,"KeyId":"0D94529E740F5FD50EC6B8A19FF460D6","Kid":"0D94529E740F5FD50EC6B8A19FF460D6","Kty":"RSA","N":"w2jhtWb6a3kH4VqAPfuuvdF5hBh7U6gwMRnddHAH7zaVL6aYwjpCzNW56RQy4W4Zabv1My4Yw9GZpjrOcyr3Bm669eZjn_JC0O00eRTNStNgmg2kB_6AB6ROkEW7br1JC0jKr_dXhOYPBMmR-KHvpwaZXA9R1xOqY02S3JD0KB-TGMSC9q1RlVydt81aMOHFzWVyruLsYGdmcKhRPKDtL6GXpU_DG1gzzOYbk795x_D_UUTOJYuhIDEj7aYi3o32yXLEBvh4Q7HPLjLcWzV-EzCn6Ossl-EVJ2TrR53Eln03R93Vmo63DzQbLIOi3yTcZD2a3O6mpGLiqyZjUducIQ","Oth":null,"P":"y84cEtE6IRBeU2sDJxjDYb50HB4nAF7-bfvbEq0haQL2sFBz-Q-uOUAeXhaS74Gh_IagmW1TzOKblVilijMHCsfOFTWlCljaDoNfdl31enh50HMFvUu8IFjcWiQ9fjR5no8n5-jDeRO5zVfgcWoRHfVTOq4Di7WlVHJRr8FB-R8","Q":"9XRZvvMIvoumlDAVxWZHkb7_an0_dFwBLqc8v74XBZhiK5SLuBqmsJICB5kwNTKzORH7yedx-RXOJWkchJLlEtmH_cQO_6WKQQAyc1PMnLPa0tYkhjotWo8VRE9bAdVmrR0cnJeudfSJ-6gDpUBQYy9g1m8cAfWbTAk3at2_gr8","QI":"xRLXLwhTdNbevlEzANlDDnU9lDeKZWV9-YrvUxHMJBBygBNVqkNFWiee7LNUi82YgTHRn46rpHY9TZf6oQbgk6xa86MyDYXGU2uGO8DHm5oh20Spp7A-RlzZ4JRXAJ3eAYMZHQIP45JApVvKbgHh_pUGjNaiqZKZ9IN6H_L9k1s","Use":null,"X":null,"X5t":null,"X5tS256":null,"X5u":null,"Y":null,"KeySize":2048,"HasPrivateKey":true,"CryptoProviderFactory":{"CryptoProviderCache":{},"CustomCryptoProvider":null,"CacheSignatureProviders":true}} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/tempkey.rsa b/host/JiShe.IOT.HttpApi.Host/tempkey.rsa new file mode 100644 index 0000000..ed0defa --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/tempkey.rsa @@ -0,0 +1 @@ +{"KeyId":"600caa200caf5d805eba9f06ace9e236","Parameters":{"D":"KCNDHA96eimN+UqchSKocgYITGflaAIwxzCS5KqSTkYAFliPthQx7LySuLor4F1+uLvwnh3ZocyI3y43GZu+eVHD256sxdV8/UsQz1HC23RRFqcUiAZjze8K5VMVStrBOxaa/Ds1U9/bpuNE7jZdcgFIEHsdZtCACqwtlE4nlIs1/GLiokqjBOESgxJMy9WUeDbWcvoo+YdwgKf5jt6AZHOYSS+TokLL+Y7TEfGMXe3jZD9VtSMkBSM8wGB89zNGR0FZB9maCG/BCoRJqxdYRyeb4FFXJclQtK3DexyDVqlNZQaNKVHu0tVAnVNKKcd7Iex8gA+5DNqqucUA7C/F6Q==","DP":"fr9iaNb1W4YZ/NJ56+N3SCeDQYuKobq1qeaQWmHlQsOHKoHhNZJQZ5x0M9PQilou16AwVlNGCJncMwxsSUxXn6itG0LcBnvfMeo2v3xKcij1BtFR9qfXecwEn2nnhI3mpXtZxyCdP3NIYUp9qViLJUjGJqrbQk+OIAGRQd2rRe0=","DQ":"o1umLkDodtwvpCsDguQYSjd3iob+WHNmfe/9HyjADmUehP8b9SpUgcrb+QF301J8YmQMnYZKWW5rEwKOtwsWNswgXfMnXeWerlZmz0tj9y38YczS70liU0vETsRefhrRCaXHraMvneqYNNedhsrCNalWK+DNwcixi4L59vA8ofs=","Exponent":"AQAB","InverseQ":"btd1nwwxl/E3ryfDi2bN12TuVDvv7yoPvryIlLgu+FiLpe4vaA1omDLliQBcl7oeyA563HBUop4D5oE7si+jD64N8XgFz37dD3KqUokeQ4lrTSSOePT1K+nWIl30sqDd7YE4auz4CvSjm2wXmN31+CXW1hp3YWN2972yrUt+R5U=","Modulus":"uwMB6reAVtm/Cq0BRPZ0ozBq6g3wDh2kzqFKBf8I7u8d9p7i5ExLSrOWPupHwPr/IW1VUn2TKHrJ8OnyYhznKIRxqlxj0U3D2GXijz5kfFOoHK+mlfKaDMqweRoS0UzEz58kMlgwUoDraUj6dTHTPCVPo3TqA2ImRw50j6D+jobFrY5321EFvlirZViMPDAgB8Ca7wGCqNBcCxvIPYw1O6WZmcVmjG7umelD3XjcUIQlEbIyAmi/3gXAo7NdPmgOamla6bnSWsy429HfsNpXyCfPBzV3QS3ubpTekWPoPcOVZbWwVPYtFQbhRh8PmWATRx0cV6oePZNZGxGeJl8WYQ==","P":"wplelBfVmiOPmr6iUxtOgIzuvwSqvP6Rqmh8dhaGDiJjU8OqZ0tZhuh0G+xnMLPIHb2fMeg0dqZMJZ5iXaIi1QycYn/JKz1i4cUonJ6IIQeKKf67tvzn/BY0V0N8rJw8hVfzou+/5sRBCbiHtJ2KIN1YJQuWGFFfrZJOJzc95ss=","Q":"9gTGKoDiOdrY8kqIXJ2nMhoeNryAH4q3EUrROJ7simqc28oYlGx24Sco/wOoeB2xxrdcF5JYOlyJ7H2YY/huLvJISaw/wHLPskiKiYQ78tuNwW0ip+5ceB1dSToHcEe3sR30+OeTh0Z4ZKoqthKziFGIt3EhEgiGq1gjZuWB5gM="}} \ No newline at end of file diff --git a/host/JiShe.IOT.HttpApi.Host/wwwroot/images/cap.png b/host/JiShe.IOT.HttpApi.Host/wwwroot/images/cap.png new file mode 100644 index 0000000000000000000000000000000000000000..76c667e0525b3368071af5abc103685afcb1894d GIT binary patch literal 11113 zcmdUV=R2HV)UJde`slq3gQ!uWmxR$GTJ+u`dM7#&Z4iVg(PK!2=)Lz&FnaWEM2$A0 zo@ajV^`3v=d^#T(<9eQ5*1Ffd?zQ%g)>Ky_#G}Q-z`!6>QHH+8z<9_D{5^n+4g6-i zM>qf<4?JHh$zha@((eLauxwwby}-bzOu)afd<1-d?51q!iGe}XjsAJi@A~5n1_sxi z3iO4Jui3#;l#kAAEB`U-z9rMc)7T|oZ@J`pnKz!nM4w(WPO{5qSY)%FO&F8(rj=BiXIUfi}|(CB*4H269s z6b6G0U{M>PKgjJIJX@y5J9Ss)Cy5UbZ<7uAT z$S?+F#Br>(Q{K1kdOa@j$?04Yf=kE2INuTQLb2MHFl}c^uDItB?z_9`Dk4lM{&qa4zE^YzUjO)`&qnr_QeLWR@UnwJQBsW09y?`nS}eX~7wbEYizp$hL- z#eAqP6Z1GY)*qELHW3RE1k-J6J|8+C16Eyi~6TJ$4IPu&j>S7QEgZGci z35SM%U}+42^4%uaba=Ef#&O_nImK|j>Z$ILN&Eg;VV(m5j$uR($=nqqORtw@rMG3q zN*lkdgt#HM@ueDfKcTWgxFrFGy@GC1U-DS>eC_~AmBPron)~*NgN-h*!b(>r`Awqgba9Y4+t+tJT2ib+eadu38ng>3jQsz^Y+?}4YJBHq6rj%tf?<}~~Ao&Hiycm0ia zLrNbjLIp{|NM^q}8At+FImzr|rQ)mxnADMbW$8@j!*6PuvDA!k23 z74C@hLm>j$z0lTP>@*u{#>`sZV-`SzaP5S3pPMZ@|4+-uQCOEWqfCTO<34YW1r5qKkz5AKSA z(ChRJLO|cCU&A;P1!_ooqh06X;#)X;&+O|2m3#7`nnkx4O(s{M>(|(hO(bVHHGuz; z=Kz?kKX-aXp~}DE9rei|rg&NReVr$*U^5?hsT!0>1^5}t-jHO`67H|iy53T0PKQ*eSTT?x9(R0YDN96y8paB`!hargd{)O=+;5hH zmJ41qa&!hw6In1}YyCXr6cy;~Y9Gn10Cb`hB7c-S)C)XtOG>Tu#Md>vq)*M~KPVX4z zJgWt=Jm@iT+7*trYmsJxJ184d5vn>hM~j7sH9y5Wo*nst0k)L57pRGFE%squeJ)5{d21ZWvbp6UtVV`DWKMg;zRZ*-G z8gJiGHAov(m`z@xd7Wy=^wsrRk)SY#04M$WSVV+bOpIBcv>PAPiU(l$qr|D>@$u(V zz#LHN--!tzkU^jCE0niX)a`4Lt9LF6sP*5-j0=&b@9M836TZBZ(v}LilB@{->Do`( z5Oc(etZ>W?hbhMa;e*}ALIvcYkA^>k-Q}wrSR^)?njtJZrH;t^ZB+w(J}9cizG5Ws zUg3x4qj&+%;Stn$s~fhHu}r7(49%s)Lal}(^sFDf$#L&mqOG6(+py}nsq34-M}YvJ zh-_eGt2eyFL$te!mT*&c2-*rZeedJ{@ncAE!_kvw)xck47e&P4waECJ6KxfSd%3ObT<_l+##TL@BEm@fLyVRlYmq6T>?hzn^~R#h+C~ zK=4?1?J1;dxZ|#TwIzToST&8n6nb_AB%lcvCgC3y;e!b4go$+PL z%+�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 literal 0 HcmV?d00001 diff --git a/host/JiShe.IOT.HttpApi.Host/wwwroot/images/hangfire.png b/host/JiShe.IOT.HttpApi.Host/wwwroot/images/hangfire.png new file mode 100644 index 0000000000000000000000000000000000000000..5cdeb40f0157e93361de3ca004454f7e840639f8 GIT binary patch literal 36278 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 literal 0 HcmV?d00001 diff --git a/host/JiShe.IOT.HttpApi.Host/wwwroot/images/miniprofiler.png b/host/JiShe.IOT.HttpApi.Host/wwwroot/images/miniprofiler.png new file mode 100644 index 0000000000000000000000000000000000000000..244c7029ac13d24d9f11101d0d4ff550cf233dfd GIT binary patch literal 22147 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 P1AKI~4YbPcScm-=eWKC$ literal 0 HcmV?d00001 diff --git a/host/JiShe.IOT.HttpApi.Host/wwwroot/libs/bootstrap/css/bootstrap.min.css b/host/JiShe.IOT.HttpApi.Host/wwwroot/libs/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000..ed3905e --- /dev/null +++ b/host/JiShe.IOT.HttpApi.Host/wwwroot/libs/bootstrap/css/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/host/JiShe.IOT.WebGateway/AbpProWebGatewayModule.cs b/host/JiShe.IOT.WebGateway/AbpProWebGatewayModule.cs new file mode 100644 index 0000000..e400532 --- /dev/null +++ b/host/JiShe.IOT.WebGateway/AbpProWebGatewayModule.cs @@ -0,0 +1,53 @@ +namespace Lion.AbpPro.WebGateway +{ + [DependsOn( + typeof(AbpProSharedHostingGatewayModule))] + public class AbpProWebGatewayModule : AbpModule + { + private const string DefaultCorsPolicyName = "Default"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureCors(context); + + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + app.UseCorrelationId(); + app.UseCors(DefaultCorsPolicyName); + app.UseRouting(); + app.UseConfiguredEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); }); + app.UseWebSockets(); + app.UseOcelot().Wait(); + } + + /// + /// 配置跨域 + /// + private void ConfigureCors(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + context.Services.AddCors(options => + { + options.AddPolicy(DefaultCorsPolicyName, builder => + { + builder + .WithOrigins( + configuration["App:CorsOrigins"] + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.WebGateway/Dockerfile b/host/JiShe.IOT.WebGateway/Dockerfile new file mode 100644 index 0000000..2331f10 --- /dev/null +++ b/host/JiShe.IOT.WebGateway/Dockerfile @@ -0,0 +1,22 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 + +# 创建目录 +RUN mkdir /app + +COPY publish /app + +# 设置工作目录 +WORKDIR /app + +# 暴露80端口 +EXPOSE 80 + +# 设置时区 .net6 才有这个问题 +ENV TZ=Asia/Shanghai + +# 设置环境变量 +ENV ASPNETCORE_ENVIRONMENT=Production + +ENTRYPOINT ["dotnet", "JiShe.IOT.WebGateway.dll"] + + diff --git a/host/JiShe.IOT.WebGateway/GlobalUsings.cs b/host/JiShe.IOT.WebGateway/GlobalUsings.cs new file mode 100644 index 0000000..89d3c21 --- /dev/null +++ b/host/JiShe.IOT.WebGateway/GlobalUsings.cs @@ -0,0 +1,21 @@ +// Global using directives + +global using System; +global using System.Collections.Generic; +global using System.Linq; +global using System.Threading.Tasks; +global using Lion.AbpPro; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Cors; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.HttpsPolicy; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Microsoft.OpenApi.Models; +global using Ocelot.Middleware; +global using Swashbuckle.AspNetCore.SwaggerUI; +global using Volo.Abp; +global using Volo.Abp.Modularity; \ No newline at end of file diff --git a/host/JiShe.IOT.WebGateway/JiShe.IOT.WebGateway.csproj b/host/JiShe.IOT.WebGateway/JiShe.IOT.WebGateway.csproj new file mode 100644 index 0000000..a5351bd --- /dev/null +++ b/host/JiShe.IOT.WebGateway/JiShe.IOT.WebGateway.csproj @@ -0,0 +1,10 @@ + + + + net9.0 + + + + + + \ No newline at end of file diff --git a/host/JiShe.IOT.WebGateway/Program.cs b/host/JiShe.IOT.WebGateway/Program.cs new file mode 100644 index 0000000..3c1a240 --- /dev/null +++ b/host/JiShe.IOT.WebGateway/Program.cs @@ -0,0 +1,16 @@ +namespace Lion.AbpPro.WebGateway +{ + public class Program + { + public static async Task Main(string[] args) + { + var builder = WebApplication.CreateBuilder(args); + builder.Host + .UseAutofac(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); + } + } +} \ No newline at end of file diff --git a/host/JiShe.IOT.WebGateway/Properties/launchSettings.json b/host/JiShe.IOT.WebGateway/Properties/launchSettings.json new file mode 100644 index 0000000..a57d879 --- /dev/null +++ b/host/JiShe.IOT.WebGateway/Properties/launchSettings.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "JiShe.IOT.WebGateway": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:44314", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/host/JiShe.IOT.WebGateway/appsettings.Consul.json b/host/JiShe.IOT.WebGateway/appsettings.Consul.json new file mode 100644 index 0000000..e7d26dc --- /dev/null +++ b/host/JiShe.IOT.WebGateway/appsettings.Consul.json @@ -0,0 +1,48 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*", + "App": { + "SelfUrl": "http://120.24.194.14:8014", + "CorsOrigins": "http://localhost:4200,http://120.24.194.14:8012,http://120.24.194.14:8011,http://120.24.194.14:8013" + }, + "GlobalConfiguration": { + }, + "Routes": [ + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "http", + "ServiceName": "IOT-Service", + "LoadBalancerOptions": { + "Type": "LeastConnection" + }, + "UpstreamPathTemplate": "/gateway/{url}", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + }, + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "ws", + "ServiceName": "IOT-Service", + "LoadBalancerOptions": { + "Type": "LeastConnection" + }, + "UpstreamPathTemplate": "/ws/{url}", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + } + ] +} diff --git a/host/JiShe.IOT.WebGateway/appsettings.Production.json b/host/JiShe.IOT.WebGateway/appsettings.Production.json new file mode 100644 index 0000000..8d40287 --- /dev/null +++ b/host/JiShe.IOT.WebGateway/appsettings.Production.json @@ -0,0 +1,52 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*", + "App": { + "SelfUrl": "http://localhost:44314", + "CorsOrigins": "http://*:*,https://*,http://*,http://localhost" + }, + "GlobalConfiguration": { + }, + "Routes": [ + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "lion.abp.pro", + "Port": 8080 + } + ], + "UpstreamPathTemplate": "/gateway/{url}", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + }, + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "ws", + "DownstreamHostAndPorts": [ + { + "Host": "lion.abp.pro", + "Port": 8080 + } + ], + "UpstreamPathTemplate": "/ws/{url}", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + } + ] +} \ No newline at end of file diff --git a/host/JiShe.IOT.WebGateway/appsettings.json b/host/JiShe.IOT.WebGateway/appsettings.json new file mode 100644 index 0000000..11ae9e2 --- /dev/null +++ b/host/JiShe.IOT.WebGateway/appsettings.json @@ -0,0 +1,52 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*", + "App": { + "SelfUrl": "http://localhost:44314", + "CorsOrigins": "http://localhost:4200" + }, + "GlobalConfiguration": { + }, + "Routes": [ + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44315 + } + ], + "UpstreamPathTemplate": "/gateway/{url}", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + }, + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "ws", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44315 + } + ], + "UpstreamPathTemplate": "/ws/{url}", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + } + ] +} diff --git a/src/JiShe.IOT.Application.Contracts/GlobalUsings.cs b/src/JiShe.IOT.Application.Contracts/GlobalUsings.cs new file mode 100644 index 0000000..dc76af9 --- /dev/null +++ b/src/JiShe.IOT.Application.Contracts/GlobalUsings.cs @@ -0,0 +1,16 @@ +// Global using directives + +global using System; +global using System.Threading.Tasks; +global using Lion.AbpPro.BasicManagement; +global using Lion.AbpPro.DataDictionaryManagement; +global using Lion.AbpPro.LanguageManagement; +global using Lion.AbpPro.NotificationManagement; +global using Volo.Abp.Application.Services; +global using Volo.Abp.Authorization.Permissions; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.Identity; +global using Volo.Abp.Localization; +global using Volo.Abp.Modularity; +global using Volo.Abp.ObjectExtending; +global using Volo.Abp.Threading; \ No newline at end of file diff --git a/src/JiShe.IOT.Application.Contracts/IOTApplicationContractsModule.cs b/src/JiShe.IOT.Application.Contracts/IOTApplicationContractsModule.cs new file mode 100644 index 0000000..c7b2d7f --- /dev/null +++ b/src/JiShe.IOT.Application.Contracts/IOTApplicationContractsModule.cs @@ -0,0 +1,18 @@ +namespace JiShe.IOT +{ + [DependsOn( + typeof(IOTDomainSharedModule), + typeof(AbpObjectExtendingModule), + typeof(BasicManagementApplicationContractsModule), + typeof(NotificationManagementApplicationContractsModule), + typeof(DataDictionaryManagementApplicationContractsModule), + typeof(LanguageManagementApplicationContractsModule) + )] + public class IOTApplicationContractsModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + IOTDtoExtensions.Configure(); + } + } +} diff --git a/src/JiShe.IOT.Application.Contracts/IOTDtoExtensions.cs b/src/JiShe.IOT.Application.Contracts/IOTDtoExtensions.cs new file mode 100644 index 0000000..54be01b --- /dev/null +++ b/src/JiShe.IOT.Application.Contracts/IOTDtoExtensions.cs @@ -0,0 +1,25 @@ +namespace JiShe.IOT +{ + public static class IOTDtoExtensions + { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can add extension properties to DTOs + * defined in the depended modules. + * + * Example: + * + * ObjectExtensionManager.Instance + * .AddOrUpdateProperty("Title"); + * + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Object-Extensions + */ + }); + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Application.Contracts/JiShe.IOT.Application.Contracts.csproj b/src/JiShe.IOT.Application.Contracts/JiShe.IOT.Application.Contracts.csproj new file mode 100644 index 0000000..23a3880 --- /dev/null +++ b/src/JiShe.IOT.Application.Contracts/JiShe.IOT.Application.Contracts.csproj @@ -0,0 +1,23 @@ + + + + net9.0 + JiShe.IOT + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/JiShe.IOT.Application.Contracts/Jobs/IRecurringJob.cs b/src/JiShe.IOT.Application.Contracts/Jobs/IRecurringJob.cs new file mode 100644 index 0000000..4d00fe7 --- /dev/null +++ b/src/JiShe.IOT.Application.Contracts/Jobs/IRecurringJob.cs @@ -0,0 +1,11 @@ +namespace JiShe.IOT.Jobs +{ + public interface IRecurringJob : ITransientDependency + { + /// + /// 执行任务 + /// + /// + Task ExecuteAsync(); + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Application.Contracts/Permissions/IOTPermissionDefinitionProvider.cs b/src/JiShe.IOT.Application.Contracts/Permissions/IOTPermissionDefinitionProvider.cs new file mode 100644 index 0000000..e53d02b --- /dev/null +++ b/src/JiShe.IOT.Application.Contracts/Permissions/IOTPermissionDefinitionProvider.cs @@ -0,0 +1,17 @@ +namespace JiShe.IOT.Permissions +{ + public class IOTPermissionDefinitionProvider : PermissionDefinitionProvider + { + public override void Define(IPermissionDefinitionContext context) + { + + + + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Application.Contracts/Permissions/IOTPermissions.cs b/src/JiShe.IOT.Application.Contracts/Permissions/IOTPermissions.cs new file mode 100644 index 0000000..c203afa --- /dev/null +++ b/src/JiShe.IOT.Application.Contracts/Permissions/IOTPermissions.cs @@ -0,0 +1,7 @@ +namespace JiShe.IOT.Permissions +{ + public static class IOTPermissions + { + + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Application/GlobalUsings.cs b/src/JiShe.IOT.Application/GlobalUsings.cs new file mode 100644 index 0000000..0833ddc --- /dev/null +++ b/src/JiShe.IOT.Application/GlobalUsings.cs @@ -0,0 +1,20 @@ +// Global using directives + +global using System; +global using System.Collections.Generic; +global using System.Linq; +global using System.Threading.Tasks; +global using Lion.AbpPro.BasicManagement; +global using Lion.AbpPro.DataDictionaryManagement; +global using Lion.AbpPro.LanguageManagement; +global using Lion.AbpPro.NotificationManagement; +global using JiShe.IOT.FreeSqlRepository; +global using JiShe.IOT.Permissions; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.Extensions.Configuration; +global using Volo.Abp.Application.Services; +global using Volo.Abp.AutoMapper; +global using Volo.Abp.BackgroundJobs.Hangfire; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.Modularity; +global using Profile = AutoMapper.Profile; \ No newline at end of file diff --git a/src/JiShe.IOT.Application/IOTAppService.cs b/src/JiShe.IOT.Application/IOTAppService.cs new file mode 100644 index 0000000..e4af0a6 --- /dev/null +++ b/src/JiShe.IOT.Application/IOTAppService.cs @@ -0,0 +1,12 @@ +namespace JiShe.IOT +{ + /* Inherit your application services from this class. + */ + public abstract class IOTAppService : ApplicationService + { + protected IOTAppService() + { + LocalizationResource = typeof(IOTResource); + } + } +} diff --git a/src/JiShe.IOT.Application/IOTApplicationAutoMapperProfile.cs b/src/JiShe.IOT.Application/IOTApplicationAutoMapperProfile.cs new file mode 100644 index 0000000..580a1d1 --- /dev/null +++ b/src/JiShe.IOT.Application/IOTApplicationAutoMapperProfile.cs @@ -0,0 +1,10 @@ +namespace JiShe.IOT +{ + public class IOTApplicationAutoMapperProfile : Profile + { + public IOTApplicationAutoMapperProfile() + { + + } + } +} diff --git a/src/JiShe.IOT.Application/IOTApplicationModule.cs b/src/JiShe.IOT.Application/IOTApplicationModule.cs new file mode 100644 index 0000000..a379d59 --- /dev/null +++ b/src/JiShe.IOT.Application/IOTApplicationModule.cs @@ -0,0 +1,23 @@ +namespace JiShe.IOT +{ + [DependsOn( + typeof(IOTDomainModule), + typeof(IOTApplicationContractsModule), + typeof(BasicManagementApplicationModule), + typeof(NotificationManagementApplicationModule), + typeof(DataDictionaryManagementApplicationModule), + typeof(LanguageManagementApplicationModule), + typeof(IOTFreeSqlModule) + )] + public class IOTApplicationModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.AddMaps(); + }); + + } + } +} diff --git a/src/JiShe.IOT.Application/JiShe.IOT.Application.csproj b/src/JiShe.IOT.Application/JiShe.IOT.Application.csproj new file mode 100644 index 0000000..d7047d9 --- /dev/null +++ b/src/JiShe.IOT.Application/JiShe.IOT.Application.csproj @@ -0,0 +1,26 @@ + + + + + net9.0 + JiShe.IOT + + + + + + + + + + + + + + + + + + + + diff --git a/src/JiShe.IOT.Application/Jobs/TestJob.cs b/src/JiShe.IOT.Application/Jobs/TestJob.cs new file mode 100644 index 0000000..bb7464b --- /dev/null +++ b/src/JiShe.IOT.Application/Jobs/TestJob.cs @@ -0,0 +1,11 @@ +namespace JiShe.IOT.Jobs +{ + public class TestJob : IRecurringJob + { + public Task ExecuteAsync() + { + Console.WriteLine($"job 测试- {DateTime.Now}"); + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Application/Properties/AssemblyInfo.cs b/src/JiShe.IOT.Application/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d7b2e67 --- /dev/null +++ b/src/JiShe.IOT.Application/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("JiShe.IOT.Application.Tests")] diff --git a/src/JiShe.IOT.DbMigrator/DbMigratorHostedService.cs b/src/JiShe.IOT.DbMigrator/DbMigratorHostedService.cs new file mode 100644 index 0000000..9350c31 --- /dev/null +++ b/src/JiShe.IOT.DbMigrator/DbMigratorHostedService.cs @@ -0,0 +1,42 @@ +using Volo.Abp.Data; + +namespace JiShe.IOT.DbMigrator +{ + public class DbMigratorHostedService : IHostedService + { + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly IConfiguration _configuration; + public DbMigratorHostedService(IHostApplicationLifetime hostApplicationLifetime, + IConfiguration configuration) + { + _hostApplicationLifetime = hostApplicationLifetime; + _configuration = configuration; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = await AbpApplicationFactory.CreateAsync(options => + { + options.Services.ReplaceConfiguration(_configuration); + options.UseAutofac(); + options.Services.AddLogging(c => c.AddSerilog()); + // https://github.com/abpframework/abp/pull/15208 + options.AddDataMigrationEnvironment(); + })) + { + await application.InitializeAsync(); + + await application + .ServiceProvider + .GetRequiredService() + .MigrateAsync(); + + await application.ShutdownAsync(); + + _hostApplicationLifetime.StopApplication(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + } +} diff --git a/src/JiShe.IOT.DbMigrator/Dockerfile b/src/JiShe.IOT.DbMigrator/Dockerfile new file mode 100644 index 0000000..9000a5d --- /dev/null +++ b/src/JiShe.IOT.DbMigrator/Dockerfile @@ -0,0 +1,19 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 + +# 创建目录 +RUN mkdir /app + +COPY publish /app + +# 设置工作目录 +WORKDIR /app + +# 设置时区 .net6 才有这个问题 +ENV TZ=Asia/Shanghai + +# 设置环境变量 +ENV ASPNETCORE_ENVIRONMENT=Production + +ENTRYPOINT ["dotnet", "JiShe.IOT.DbMigrator.dll"] + + diff --git a/src/JiShe.IOT.DbMigrator/GlobalUsings.cs b/src/JiShe.IOT.DbMigrator/GlobalUsings.cs new file mode 100644 index 0000000..b7a433b --- /dev/null +++ b/src/JiShe.IOT.DbMigrator/GlobalUsings.cs @@ -0,0 +1,18 @@ +// Global using directives + +global using System; +global using System.IO; +global using System.Threading; +global using System.Threading.Tasks; +global using JiShe.IOT.Data; +global using JiShe.IOT.EntityFrameworkCore; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Serilog; +global using Serilog.Events; +global using Volo.Abp; +global using Volo.Abp.Autofac; +global using Volo.Abp.BackgroundJobs; +global using Volo.Abp.Modularity; \ No newline at end of file diff --git a/src/JiShe.IOT.DbMigrator/IOTDbMigratorModule.cs b/src/JiShe.IOT.DbMigrator/IOTDbMigratorModule.cs new file mode 100644 index 0000000..acaee2a --- /dev/null +++ b/src/JiShe.IOT.DbMigrator/IOTDbMigratorModule.cs @@ -0,0 +1,42 @@ +using Volo.Abp.Localization; + +namespace JiShe.IOT.DbMigrator +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(IOTEntityFrameworkCoreModule), + typeof(IOTApplicationContractsModule) + )] + public class IOTDbMigratorModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => options.IsJobExecutionEnabled = false); + + ConfigureLocalization(); + } + + /// + /// 多语言配置 + /// + private void ConfigureLocalization() + { + Configure(options => + { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); + options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); + options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); + options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); + options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); + }); + } + } +} diff --git a/src/JiShe.IOT.DbMigrator/JiShe.IOT.DbMigrator.csproj b/src/JiShe.IOT.DbMigrator/JiShe.IOT.DbMigrator.csproj new file mode 100644 index 0000000..b07f793 --- /dev/null +++ b/src/JiShe.IOT.DbMigrator/JiShe.IOT.DbMigrator.csproj @@ -0,0 +1,33 @@ + + + + Exe + net9.0 + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + diff --git a/src/JiShe.IOT.DbMigrator/Program.cs b/src/JiShe.IOT.DbMigrator/Program.cs new file mode 100644 index 0000000..fd81e90 --- /dev/null +++ b/src/JiShe.IOT.DbMigrator/Program.cs @@ -0,0 +1,45 @@ +namespace JiShe.IOT.DbMigrator +{ + class Program + { + static async Task Main(string[] args) + { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Information() + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning) +#if DEBUG + .MinimumLevel.Override("JiShe.IOT", LogEventLevel.Debug) +#else + .MinimumLevel.Override("JiShe.IOT", LogEventLevel.Information) +#endif + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) + .WriteTo.Async(c => c.Console()) + .CreateLogger(); + + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureLogging((context, logging) => logging.ClearProviders()) + .ConfigureAppConfiguration + ( + otpions => + { + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); + + var appSettingFileName = "appsettings.json"; + if (!environment.IsNullOrWhiteSpace()) + appSettingFileName = $"appsettings.{environment}.json"; + + otpions.AddJsonFile(appSettingFileName, optional: true); + } + ) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + } +} diff --git a/src/JiShe.IOT.DbMigrator/appsettings.json b/src/JiShe.IOT.DbMigrator/appsettings.json new file mode 100644 index 0000000..0443719 --- /dev/null +++ b/src/JiShe.IOT.DbMigrator/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Data Source=118.190.144.92;Port=33306;Database=JiSheIOTDB;uid=root;pwd=admin123;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.DbMigrator/tempkey.rsa b/src/JiShe.IOT.DbMigrator/tempkey.rsa new file mode 100644 index 0000000..494c201 --- /dev/null +++ b/src/JiShe.IOT.DbMigrator/tempkey.rsa @@ -0,0 +1,13 @@ +{ + "KeyId": "f788zGVUZh9H-HbWL1S-Mg", + "Parameters": { + "D": "F19hbC5PLO872DszGiJnVoU55ee7XGXmNf0KEKndJ/uGBv5lWklXA0QF80h1ytWXde0jV5isQPB1t7mPhRQlDoDTkywLi1CeOgBPbxzHEfLjZZ5c4olfeX0IJX9BDqgUntY0H1a/+Om/eDu4OZUz3EIJFFZBgz46YZSyTT6ZDvAEdpC/o66sNJmxvJIp+8zVoVDSqBUzxmc+oEamXLg7r2jdymxJMxau1kQFxEGLOrJnNxGsEe8UrYA3qSsm8m/Xg4uOh7RYgnuEEt88+KTvRq+CAMWhN3YNLtOJ3NmXowwE7e1Ma+jih9+UVfxZn14P5+SOJbQ2bYV2sCV+2vBiCQ==", + "DP": "oPiGO/qdOQfFEAS9fMInQnsrNylIZVpDYEVoDJ6/jQfE/IpuwxGcmsaGvCob3SKxZiJRLCWpwJYo1hCh/JOSVGWMkVyELky56nbbkkV5ymKLSGZ4JoetdQs+GchnPdR+k2P9Ij1Kjk13ylubN3htzNhcBASJpOfSEv5pPVzGKX0=", + "DQ": "z6imxLABHkyftbfUUtpeOlPanEHgpuIjmUdp3T1Ju1jziE63UEhuj0GPAXOF17uYxixwYE8JhOJ7+TyIK9oZeI3zH2OzJqQh8f5PCQ/E+0ULXZDeNV/ShDLCTufu3Fis9Rt64uTp/H/l21oMQ79jc0ysa8DTz1ReJLRc5qjL41U=", + "Exponent": "AQAB", + "InverseQ": "ieZcvSt5XYukKJKhXpv5Dm/1RD7iH88cZnhLSTEVTMoOUHoYWmApY5pNLGahbfjA9bxnkBWDYex/i7wE9uNNY5CsA6ovUaQLVJDt3kHvR9W+9QtN8D6jjG2TuRbbOdEg4RqhfjUaDfDIgTJX2Wxc8U98FOvOyGw1HzwUPFZKecM=", + "Modulus": "vk4z1Bmtmbo+gxITcY+FIlXzcO2wTOGlOXK5GMYj/6PUMFt7lbqkc72AkPsrAo5/JE8LYLhWj7fzSKbjvtowHCz5m2t+FlUYmuiKpvvnJsTqvQrckNlbZ1nm071q5PhP3Dar/OksfBhPtAX+c3+NjDnM/w53ccJJNaBDO/s9JYoN7vH5n6ed1pMSK71hmg4MPsxChcnc1f1PpnG2mqyJ253+GEUbj/kRyeBSmCCr9aadov2ZzxIKVaFNagJEHOzanQmorSLpP25GfOHCuy27Zkef94V/qU9elzjbH4uIKslVGx5T6H99TYh0sUGu11NytYJa5WNAZWow95CzurC2vw==", + "P": "4GMCQy+XTNzR5TsgFcdAZv2K6TcQR13fHVvPoxQp/b32V5YUJOBFEUAtqociy5ro4+KzpXP5WPSk1ZtznGKuNZyLq8gTnhpB3rwd0sdo4zxKnQ5nu+n1UhlhWNxg5A9V5TaciUAyPrHWJfLoYTQWygNTgJELQH5zZXi2ihC2uiU=", + "Q": "2R36pamnLAJggkPJxiW5qH6HizZ+bkQVg0BBftMLzkAM8Y9CwTW75GRUzGEJFpMckkw0GZSYb1Uwl3DVUpkcQ8LZ91IPYdPpDlYUshhIxl184M55pnO14besKxJtMZ64zhHKVAR2pBMO0n6W4/1iBXkkQqyPViJxdfvXPJMBbhM=" + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/GlobalUsings.cs b/src/JiShe.IOT.Domain.Shared/GlobalUsings.cs new file mode 100644 index 0000000..4146a61 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/GlobalUsings.cs @@ -0,0 +1,39 @@ +// Global using directives + +global using System; +global using System.Collections.Generic; +global using System.ComponentModel.DataAnnotations; +global using System.Linq; +global using System.Reflection; +global using System.Text; +global using System.Threading.Tasks; +global using Lion.AbpPro.BasicManagement; +global using Lion.AbpPro.BasicManagement.Localization; +global using Lion.AbpPro.Core; +global using Lion.AbpPro.DataDictionaryManagement; +global using Lion.AbpPro.LanguageManagement; +global using Lion.AbpPro.NotificationManagement; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Localization; +global using Volo.Abp; +global using Volo.Abp.AuditLogging; +global using Volo.Abp.BackgroundJobs; +global using Volo.Abp.Data; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.FeatureManagement; +global using Volo.Abp.Identity; +global using Volo.Abp.Identity.Localization; +global using Volo.Abp.Localization; +global using Volo.Abp.Localization.ExceptionHandling; +global using Volo.Abp.Localization.Resources.AbpLocalization; +global using Volo.Abp.Modularity; +global using Volo.Abp.ObjectExtending; +global using Volo.Abp.PermissionManagement; +global using Volo.Abp.SettingManagement; +global using Volo.Abp.SettingManagement.Localization; +global using Volo.Abp.TenantManagement; +global using Volo.Abp.Threading; +global using Volo.Abp.Timing.Localization.Resources.AbpTiming; +global using Volo.Abp.Validation; +global using Volo.Abp.Validation.Localization; +global using Volo.Abp.VirtualFileSystem; \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/IOTDomainErrorCodes.cs b/src/JiShe.IOT.Domain.Shared/IOTDomainErrorCodes.cs new file mode 100644 index 0000000..3892a82 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/IOTDomainErrorCodes.cs @@ -0,0 +1,7 @@ +namespace JiShe.IOT +{ + public static class IOTDomainErrorCodes + { + + } +} diff --git a/src/JiShe.IOT.Domain.Shared/IOTDomainSharedConsts.cs b/src/JiShe.IOT.Domain.Shared/IOTDomainSharedConsts.cs new file mode 100644 index 0000000..199f438 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/IOTDomainSharedConsts.cs @@ -0,0 +1,9 @@ +namespace JiShe.IOT; + +public class IOTDomainSharedConsts +{ + /// 名称空间 + public const string NameSpace = "JiShe.IOT"; + /// 默认语言 + public const string DefaultCultureName = "zh-Hans"; +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/IOTDomainSharedModule.cs b/src/JiShe.IOT.Domain.Shared/IOTDomainSharedModule.cs new file mode 100644 index 0000000..9426db1 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/IOTDomainSharedModule.cs @@ -0,0 +1,44 @@ +namespace JiShe.IOT +{ + [DependsOn( + typeof(BasicManagementDomainSharedModule), + typeof(NotificationManagementDomainSharedModule), + typeof(DataDictionaryManagementDomainSharedModule), + typeof(LanguageManagementDomainSharedModule), + typeof(AbpProCoreModule) + )] + public class IOTDomainSharedModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + IOTGlobalFeatureConfigurator.Configure(); + IOTModuleExtensionConfigurator.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(IOTDomainSharedConsts.NameSpace); + }); + + Configure(options => + { + options.Resources + .Add(IOTDomainSharedConsts.DefaultCultureName) + .AddVirtualJson("/Localization/IOT") + .AddBaseTypes(typeof(BasicManagementResource)) + .AddBaseTypes(typeof(AbpTimingResource)); + + options.DefaultResourceType = typeof(IOTResource); + }); + + Configure(options => + { + options.MapCodeNamespace(IOTDomainSharedConsts.NameSpace, typeof(IOTResource)); + }); + } + + + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/IOTGlobalFeatureConfigurator.cs b/src/JiShe.IOT.Domain.Shared/IOTGlobalFeatureConfigurator.cs new file mode 100644 index 0000000..e89fc0a --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/IOTGlobalFeatureConfigurator.cs @@ -0,0 +1,21 @@ +namespace JiShe.IOT +{ + public static class IOTGlobalFeatureConfigurator + { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + /* You can configure (enable/disable) global features of the used modules here. + * + * YOU CAN SAFELY DELETE THIS CLASS AND REMOVE ITS USAGES IF YOU DON'T NEED TO IT! + * + * Please refer to the documentation to lear more about the Global Features System: + * https://docs.abp.io/en/abp/latest/Global-Features + */ + }); + } + } +} diff --git a/src/JiShe.IOT.Domain.Shared/IOTModuleExtensionConfigurator.cs b/src/JiShe.IOT.Domain.Shared/IOTModuleExtensionConfigurator.cs new file mode 100644 index 0000000..402738b --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/IOTModuleExtensionConfigurator.cs @@ -0,0 +1,67 @@ +namespace JiShe.IOT +{ + public static class IOTModuleExtensionConfigurator + { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + OneTimeRunner.Run(() => + { + ConfigureExistingProperties(); + ConfigureExtraProperties(); + }); + } + + private static void ConfigureExistingProperties() + { + /* You can change max lengths for properties of the + * entities defined in the modules used by your application. + * + * Example: Change user and role name max lengths + + IdentityUserConsts.MaxNameLength = 99; + IdentityRoleConsts.MaxNameLength = 99; + + * Notice: It is not suggested to change property lengths + * unless you really need it. Go with the standard values wherever possible. + * + * If you are using EF Core, you will need to run the add-migration command after your changes. + */ + } + + private static void ConfigureExtraProperties() + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to define these extra properties + * with a high level, easy to use API. + * + * Example: Add a new property to the user entity of the identity module + + ObjectExtensionManager.Instance.Modules() + .ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( //property type: string + "SocialSecurityNumber", //property name + property => + { + //validation rules + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4}); + + //...other configurations for this property + } + ); + }); + }); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Module-Entity-Extensions + */ + } + } +} diff --git a/src/JiShe.IOT.Domain.Shared/JiShe.IOT.Domain.Shared.csproj b/src/JiShe.IOT.Domain.Shared/JiShe.IOT.Domain.Shared.csproj new file mode 100644 index 0000000..870ba01 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/JiShe.IOT.Domain.Shared.csproj @@ -0,0 +1,22 @@ + + + net9.0 + JiShe.IOT + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/ar.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/ar.json new file mode 100644 index 0000000..3e5227a --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/ar.json @@ -0,0 +1,8 @@ +{ + "culture": "ar", + "texts": { + "Menu:Home": "الرئيسية", + "Welcome": "مرحبا", + "LongWelcomeMessage": "مرحبا بكم في التطبيق. هذا مشروع بدء تشغيل يعتمد على إطار عمل ABP. لمزيد من المعلومات ، يرجى زيارة abp.io." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/cs.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/cs.json new file mode 100644 index 0000000..5a0bbf6 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/cs.json @@ -0,0 +1,8 @@ +{ + "culture": "cs", + "texts": { + "Menu:Home": "Úvod", + "Welcome": "Vítejte", + "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io." + } +} diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/de-DE.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/de-DE.json new file mode 100644 index 0000000..aca4528 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/de-DE.json @@ -0,0 +1,8 @@ +{ + "culture": "de-DE", + "texts": { + "Menu:Home": "Home", + "Welcome": "Willkommen", + "LongWelcomeMessage": "Willkommen bei der Anwendung. Dies ist ein Startup-Projekt, das auf dem ABP-Framework basiert. Weitere Informationen finden Sie unter abp.io." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/en-GB.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/en-GB.json new file mode 100644 index 0000000..d2ca079 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/en-GB.json @@ -0,0 +1,8 @@ +{ + "culture": "en-GB", + "texts": { + "Menu:Home": "Home", + "Welcome": "Welcome", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/en.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/en.json new file mode 100644 index 0000000..9a176ff --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/en.json @@ -0,0 +1,29 @@ +{ + "culture": "en", + "texts": { + "Menu:Home": "Home", + "Welcome": "Welcome", + "Test": "Test", + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.", + "Permission:Query": "Query", + "Permission:Create": "Create", + "Permission:Update": "Update", + "Permission:Delete": "Delete", + "Permission:Export": "Export", + "Permission:Enable": "Enable|Disable", + "Permission:SystemManagement": "SystemManagement", + "Permission:AuditLogManagement": "AuditLog", + "Permission:HangfireManagement": "BackgroundTask", + "Permission:CapManagement": "IntegratedEvent", + "Permission:ESManagement": "ESManagement", + "Permission:SettingManagement": "SettingManagement", + "Permission:OrganizationUnitManagement": "OrganizationUnitManagement", + "Setting.Group.System": "System", + "Setting.Group.Other": "Other", + "DisplayName:Setting.Group.Other.Github": "Github", + "Description:Setting.Group.Other.Github": "Github", + "Enum:TestType:Created:1":"Created", + "Enum:TestType:Cancel:1":"Cancel", + "Enum:TestType:Delete:1":"Delete" + } +} diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/es.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/es.json new file mode 100644 index 0000000..31b4b59 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/es.json @@ -0,0 +1,8 @@ +{ + "culture": "es", + "texts": { + "Menu:Home": "Inicio", + "Welcome": "Bienvenido", + "LongWelcomeMessage": "Bienvenido a la aplicación, este es un proyecto base basado en el framework ABP. Para más información, visita abp.io." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/fr.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/fr.json new file mode 100644 index 0000000..e76eac0 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/fr.json @@ -0,0 +1,8 @@ +{ + "culture": "fr", + "texts": { + "Menu:Home": "Accueil", + "Welcome": "Bienvenue", + "LongWelcomeMessage": "Bienvenue dans l'application. Il s'agit d'un projet de démarrage basé sur le framework ABP. Pour plus d'informations, visitez abp.io." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/hu.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/hu.json new file mode 100644 index 0000000..c7b6a33 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/hu.json @@ -0,0 +1,8 @@ +{ + "culture": "hu", + "texts": { + "Menu:Home": "Kezdőlap", + "Welcome": "Üdvözlöm", + "LongWelcomeMessage": "Üdvözöljük az alkalmazásban. Ez egy ABP keretrendszeren alapuló startup projekt. További információkért látogasson el az abp.io oldalra." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/nl.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/nl.json new file mode 100644 index 0000000..9ba8da4 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/nl.json @@ -0,0 +1,8 @@ +{ + "culture": "nl", + "texts": { + "Menu:Home": "Home", + "Welcome": "Welkom", + "LongWelcomeMessage": "Welkom bij de applicatie. Dit is een startup-project gebaseerd op het ABP-framework. Bezoek abp.io voor meer informatie." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/pl-PL.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/pl-PL.json new file mode 100644 index 0000000..33412f3 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/pl-PL.json @@ -0,0 +1,8 @@ +{ + "culture": "pl-PL", + "texts": { + "Menu:Home": "Home", + "Welcome": "Witaj", + "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/pt-BR.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/pt-BR.json new file mode 100644 index 0000000..8c818a0 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/pt-BR.json @@ -0,0 +1,8 @@ +{ + "culture": "pt-BR", + "texts": { + "Menu:Home": "Principal", + "Welcome": "Seja bem-vindo!", + "LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/ru.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/ru.json new file mode 100644 index 0000000..8464e44 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/ru.json @@ -0,0 +1,8 @@ +{ + "culture": "ru", + "texts": { + "Menu:Home": "Главная", + "Welcome": "Добро пожаловать", + "LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io." + } +} diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/sl.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/sl.json new file mode 100644 index 0000000..a066ef2 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/sl.json @@ -0,0 +1,8 @@ +{ + "culture": "sl", + "texts": { + "Menu:Home": "Domov", + "Welcome": "Dobrodošli", + "LongWelcomeMessage": "Dobrodošli v aplikaciji. To je začetni projekt na osnovi okolja ABP. Za več informacij obiščite abp.io." + } +} diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/tr.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/tr.json new file mode 100644 index 0000000..2cc911e --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/tr.json @@ -0,0 +1,8 @@ +{ + "culture": "tr", + "texts": { + "Menu:Home": "Ana sayfa", + "Welcome": "Hoşgeldiniz", + "LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz." + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/vi.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/vi.json new file mode 100644 index 0000000..c115a35 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/vi.json @@ -0,0 +1,8 @@ +{ + "culture": "vi", + "texts": { + "Menu:Home": "Trang chủ", + "Welcome": "Chào mừng bạn", + "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io." + } +} diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/zh-Hans.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/zh-Hans.json new file mode 100644 index 0000000..497f63e --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/zh-Hans.json @@ -0,0 +1,30 @@ +{ + "culture": "zh-Hans", + "texts": { + "Menu:Home": "首页", + "Welcome": "欢迎", + "Test": "测试", + "LongWelcomeMessage": "欢迎来到该应用程序. 这是一个基于ABP框架的启动项目. 有关更多信息, 请访问 abp.io.", + "Permission:Query": "查询", + "Permission:Create": "创建", + "Permission:Update": "编辑", + "Permission:Delete": "删除", + "Permission:Export": "导出", + "Permission:Enable": "启用|禁用", + "Permission:AuditLogManagement": "审计日志", + "Permission:SystemManagement": "系统管理", + "Permission:HangfireManagement": "后台任务", + "Permission:CapManagement": "集成事件", + "Permission:ESManagement": "ES日志", + "Permission:SettingManagement": "设置管理", + "Permission:OrganizationUnitManagement": "组织结构管理", + + "Setting.Group.System": "系统", + "Setting.Group.Other": "其它", + "DisplayName:Setting.Group.Other.Github": "Github", + "Description:Setting.Group.Other.Github": "Github", + "Enum:TestType:Created:1":"创建", + "Enum:TestType:Cancel:1":"取消", + "Enum:TestType:Delete:1":"删除" + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOT/zh-Hant.json b/src/JiShe.IOT.Domain.Shared/Localization/IOT/zh-Hant.json new file mode 100644 index 0000000..7622bcf --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOT/zh-Hant.json @@ -0,0 +1,14 @@ +{ + "culture": "zh-Hant", + "texts": { + "Menu:Home": "首頁", + "Welcome": "歡迎", + "LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io.", + "Permissions:Query": "查询", + "Permissions:Create": "创建", + "Permissions:Update": "更新", + "Permissions:Delete": "删除", + "Permissions:Enable": "启用|禁用", + "Permissions:AuditLogManagement": "审计日志" + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/Localization/IOTResource.cs b/src/JiShe.IOT.Domain.Shared/Localization/IOTResource.cs new file mode 100644 index 0000000..e7c1432 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Localization/IOTResource.cs @@ -0,0 +1,8 @@ +namespace JiShe.IOT +{ + [LocalizationResourceName("IOT")] + public class IOTResource + { + + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs b/src/JiShe.IOT.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs new file mode 100644 index 0000000..b2f5cd8 --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs @@ -0,0 +1,11 @@ +namespace JiShe.IOT.MultiTenancy +{ + public static class MultiTenancyConsts + { + /* Enable/disable multi-tenancy easily in a single point. + * If you will never need to multi-tenancy, you can remove + * related modules and code parts, including this file. + */ + public const bool IsEnabled = true; + } +} diff --git a/src/JiShe.IOT.Domain.Shared/Users/Dto/UserOutput.cs b/src/JiShe.IOT.Domain.Shared/Users/Dto/UserOutput.cs new file mode 100644 index 0000000..227cf5a --- /dev/null +++ b/src/JiShe.IOT.Domain.Shared/Users/Dto/UserOutput.cs @@ -0,0 +1,7 @@ +namespace JiShe.IOT.Users.Dto +{ + public class UserOutput + { + public Guid Id { get; set; } + } +} diff --git a/src/JiShe.IOT.Domain/Data/IIOTDbSchemaMigrator.cs b/src/JiShe.IOT.Domain/Data/IIOTDbSchemaMigrator.cs new file mode 100644 index 0000000..bfb883a --- /dev/null +++ b/src/JiShe.IOT.Domain/Data/IIOTDbSchemaMigrator.cs @@ -0,0 +1,7 @@ +namespace JiShe.IOT.Data +{ + public interface IIOTDbSchemaMigrator + { + Task MigrateAsync(); + } +} diff --git a/src/JiShe.IOT.Domain/Data/IOTDbMigrationService.cs b/src/JiShe.IOT.Domain/Data/IOTDbMigrationService.cs new file mode 100644 index 0000000..e9cab0b --- /dev/null +++ b/src/JiShe.IOT.Domain/Data/IOTDbMigrationService.cs @@ -0,0 +1,205 @@ +namespace JiShe.IOT.Data +{ + public class IOTDbMigrationService : ITransientDependency + { + public ILogger Logger { get; set; } + + private readonly IDataSeeder _dataSeeder; + private readonly IEnumerable _dbSchemaMigrators; + private readonly ITenantRepository _tenantRepository; + private readonly ICurrentTenant _currentTenant; + + public IOTDbMigrationService( + IDataSeeder dataSeeder, + IEnumerable dbSchemaMigrators, + ITenantRepository tenantRepository, + ICurrentTenant currentTenant) + { + _dataSeeder = dataSeeder; + _dbSchemaMigrators = dbSchemaMigrators; + _tenantRepository = tenantRepository; + _currentTenant = currentTenant; + + Logger = NullLogger.Instance; + } + + public async Task MigrateAsync() + { + var initialMigrationAdded = AddInitialMigrationIfNotExist(); + + if (initialMigrationAdded) + { + return; + } + + Logger.LogInformation("Started database migrations..."); + + await MigrateDatabaseSchemaAsync(); + await SeedDataAsync(); + + Logger.LogInformation($"Successfully completed host database migrations."); + + var tenants = await _tenantRepository.GetListAsync(includeDetails: true); + + var migratedDatabaseSchemas = new HashSet(); + foreach (var tenant in tenants) + { + using (_currentTenant.Change(tenant.Id)) + { + if (tenant.ConnectionStrings.Any()) + { + var tenantConnectionStrings = tenant.ConnectionStrings + .Select(x => x.Value) + .ToList(); + + if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) + { + await MigrateDatabaseSchemaAsync(tenant); + + migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); + } + } + + await SeedDataAsync(tenant); + } + + Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); + } + + Logger.LogInformation("Successfully completed all database migrations."); + Logger.LogInformation("You can safely end this process..."); + } + + private async Task MigrateDatabaseSchemaAsync(Tenant tenant = null) + { + Logger.LogInformation( + $"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database..."); + + foreach (var migrator in _dbSchemaMigrators) + { + await migrator.MigrateAsync(); + } + } + + private async Task SeedDataAsync(Tenant tenant = null) + { + Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); + + await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) + .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue) + .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue) + ); + } + + private bool AddInitialMigrationIfNotExist() + { + try + { + if (!DbMigrationsProjectExists()) + { + return false; + } + } + catch (Exception) + { + return false; + } + + try + { + if (!MigrationsFolderExists()) + { + AddInitialMigration(); + return true; + } + else + { + return false; + } + } + catch (Exception e) + { + Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message); + return false; + } + } + + private bool DbMigrationsProjectExists() + { + var dbMigrationsProjectFolder = GetDbMigrationsProjectFolderPath(); + + return dbMigrationsProjectFolder != null; + } + + private bool MigrationsFolderExists() + { + var dbMigrationsProjectFolder = GetDbMigrationsProjectFolderPath(); + + return Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "EntityFrameworkCore")); + } + + private void AddInitialMigration() + { + Logger.LogInformation("Creating initial migration..."); + + string argumentPrefix; + string fileName; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + argumentPrefix = "-c"; + fileName = "/bin/bash"; + } + else + { + argumentPrefix = "/C"; + fileName = "cmd.exe"; + } + + var procStartInfo = new ProcessStartInfo(fileName, + $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetDbMigrationsProjectFolderPath()}\"\"" + ); + + try + { + Process.Start(procStartInfo); + } + catch (Exception) + { + throw new Exception("Couldn't run ABP CLI..."); + } + } + + private string GetDbMigrationsProjectFolderPath() + { + var slnDirectoryPath = GetSolutionDirectoryPath(); + + if (slnDirectoryPath == null) + { + throw new Exception("Solution folder not found!"); + } + + var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src"); + + return Directory.GetDirectories(srcDirectoryPath) + .FirstOrDefault(d => d.EndsWith(".DbMigrations")); + } + + private string GetSolutionDirectoryPath() + { + var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory()); + + while (Directory.GetParent(currentDirectory.FullName) != null) + { + currentDirectory = Directory.GetParent(currentDirectory.FullName); + + if (Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null) + { + return currentDirectory.FullName; + } + } + + return null; + } + } +} diff --git a/src/JiShe.IOT.Domain/Data/NullIOTDbSchemaMigrator.cs b/src/JiShe.IOT.Domain/Data/NullIOTDbSchemaMigrator.cs new file mode 100644 index 0000000..aeba1f0 --- /dev/null +++ b/src/JiShe.IOT.Domain/Data/NullIOTDbSchemaMigrator.cs @@ -0,0 +1,13 @@ +namespace JiShe.IOT.Data +{ + /* This is used if database provider does't define + * IIOTDbSchemaMigrator implementation. + */ + public class NullIOTDbSchemaMigrator : IIOTDbSchemaMigrator, ITransientDependency + { + public Task MigrateAsync() + { + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain/GlobalUsings.cs b/src/JiShe.IOT.Domain/GlobalUsings.cs new file mode 100644 index 0000000..ab1cb1f --- /dev/null +++ b/src/JiShe.IOT.Domain/GlobalUsings.cs @@ -0,0 +1,32 @@ +// Global using directives + +global using System; +global using System.Collections.Generic; +global using System.Diagnostics; +global using System.IO; +global using System.Linq; +global using System.Runtime.InteropServices; +global using System.Threading.Tasks; +global using Lion.AbpPro.BasicManagement; +global using Lion.AbpPro.DataDictionaryManagement; +global using Lion.AbpPro.LanguageManagement; +global using Lion.AbpPro.NotificationManagement; +global using JiShe.IOT.MultiTenancy; +global using JiShe.IOT.Users.Dto; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Logging.Abstractions; +global using Volo.Abp.AutoMapper; +global using Volo.Abp.Data; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.Domain.Services; +global using Volo.Abp.EventBus.Distributed; +global using Volo.Abp.Identity; +global using Volo.Abp.Localization; +global using Volo.Abp.Modularity; +global using Volo.Abp.MultiTenancy; +global using Volo.Abp.ObjectMapping; +global using Volo.Abp.SettingManagement; +global using Volo.Abp.Settings; +global using Volo.Abp.TenantManagement; +global using Volo.Abp.Uow; \ No newline at end of file diff --git a/src/JiShe.IOT.Domain/IOTDbProperties.cs b/src/JiShe.IOT.Domain/IOTDbProperties.cs new file mode 100644 index 0000000..36f62c4 --- /dev/null +++ b/src/JiShe.IOT.Domain/IOTDbProperties.cs @@ -0,0 +1,9 @@ +namespace JiShe.IOT +{ + public static class IOTDbProperties + { + public const string DbTablePrefix = "Abp"; + + public const string DbSchema = null; + } +} diff --git a/src/JiShe.IOT.Domain/IOTDomainModule.cs b/src/JiShe.IOT.Domain/IOTDomainModule.cs new file mode 100644 index 0000000..d55367e --- /dev/null +++ b/src/JiShe.IOT.Domain/IOTDomainModule.cs @@ -0,0 +1,18 @@ +namespace JiShe.IOT +{ + [DependsOn( + typeof(IOTDomainSharedModule), + typeof(BasicManagementDomainModule), + typeof(NotificationManagementDomainModule), + typeof(DataDictionaryManagementDomainModule), + typeof(LanguageManagementDomainModule) + )] + public class IOTDomainModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => { options.IsEnabled = MultiTenancyConsts.IsEnabled; }); + Configure(options => { options.AddMaps(); }); + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain/IOTDomainService.cs b/src/JiShe.IOT.Domain/IOTDomainService.cs new file mode 100644 index 0000000..55ec0b5 --- /dev/null +++ b/src/JiShe.IOT.Domain/IOTDomainService.cs @@ -0,0 +1,36 @@ +using Volo.Abp.EventBus.Local; + +namespace JiShe.IOT +{ + public abstract class IOTDomainService : DomainService + { + protected Type ObjectMapperContext { get; set; } + + /// + /// 工作单元管理器 + /// + protected IUnitOfWorkManager UnitOfWorkManager => + LazyServiceProvider.LazyGetRequiredService(); + + /// + /// 领域事件总线 + /// + protected ILocalEventBus LocalEventBus => + LazyServiceProvider.LazyGetRequiredService(); + /// + /// 分布式事件总线 + /// + protected IDistributedEventBus DistributedEventBus => + LazyServiceProvider.LazyGetRequiredService(); + + /// + /// 对象映射器 + /// + protected IObjectMapper ObjectMapper => LazyServiceProvider.LazyGetService( + provider => + ObjectMapperContext == null + ? provider.GetRequiredService() + : (IObjectMapper)provider.GetRequiredService( + typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext))); + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain/JiShe.IOT.Domain.csproj b/src/JiShe.IOT.Domain/JiShe.IOT.Domain.csproj new file mode 100644 index 0000000..aff5292 --- /dev/null +++ b/src/JiShe.IOT.Domain/JiShe.IOT.Domain.csproj @@ -0,0 +1,18 @@ + + + net9.0 + JiShe.IOT + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/JiShe.IOT.Domain/Properties/AssemblyInfo.cs b/src/JiShe.IOT.Domain/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8d629ba --- /dev/null +++ b/src/JiShe.IOT.Domain/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("JiShe.IOT.Domain.Tests")] +[assembly:InternalsVisibleToAttribute("JiShe.IOT.TestBase")] diff --git a/src/JiShe.IOT.Domain/Settings/IOTSettingDefinitionProvider.cs b/src/JiShe.IOT.Domain/Settings/IOTSettingDefinitionProvider.cs new file mode 100644 index 0000000..427504d --- /dev/null +++ b/src/JiShe.IOT.Domain/Settings/IOTSettingDefinitionProvider.cs @@ -0,0 +1,25 @@ +namespace JiShe.IOT.Settings +{ + public class IOTSettingDefinitionProvider : SettingDefinitionProvider + { + public override void Define(ISettingDefinitionContext context) + { + //Define your own settings here. Example: + //context.Add(new SettingDefinition(IOTSettings.MySetting1)); + OverrideDefalutSettings(context); + } + + /// + /// 重写默认setting添加自定义属性 + /// + private static void OverrideDefalutSettings(ISettingDefinitionContext context) + { + + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.Domain/Settings/IOTSettings.cs b/src/JiShe.IOT.Domain/Settings/IOTSettings.cs new file mode 100644 index 0000000..d25c7e5 --- /dev/null +++ b/src/JiShe.IOT.Domain/Settings/IOTSettings.cs @@ -0,0 +1,7 @@ +namespace JiShe.IOT.Settings +{ + public static class IOTSettings + { + + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreIOTDbSchemaMigrator.cs b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreIOTDbSchemaMigrator.cs new file mode 100644 index 0000000..468633e --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreIOTDbSchemaMigrator.cs @@ -0,0 +1,27 @@ +namespace JiShe.IOT.EntityFrameworkCore +{ + public class EntityFrameworkCoreIOTDbSchemaMigrator + : IIOTDbSchemaMigrator, ITransientDependency + { + private readonly IServiceProvider _serviceProvider; + + public EntityFrameworkCoreIOTDbSchemaMigrator(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task MigrateAsync() + { + /* We intentionally resolving the IOTMigrationsDbContext + * from IServiceProvider (instead of directly injecting it) + * to properly get the connection string of the current tenant in the + * current scope. + */ + + await _serviceProvider + .GetRequiredService() + .Database + .MigrateAsync(); + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IIOTDbContext.cs b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IIOTDbContext.cs new file mode 100644 index 0000000..163b806 --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IIOTDbContext.cs @@ -0,0 +1,8 @@ +namespace JiShe.IOT.EntityFrameworkCore +{ + [ConnectionStringName("Default")] + public interface IIOTDbContext : IEfCoreDbContext + { + + } +} diff --git a/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTDbContext.cs b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTDbContext.cs new file mode 100644 index 0000000..73ac9ff --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTDbContext.cs @@ -0,0 +1,61 @@ +namespace JiShe.IOT.EntityFrameworkCore +{ + [ConnectionStringName("Default")] + public class IOTDbContext : AbpDbContext, IIOTDbContext, + IBasicManagementDbContext, + INotificationManagementDbContext, + IDataDictionaryManagementDbContext, + ILanguageManagementDbContext + { + public DbSet Users { get; set; } + public DbSet Roles { get; set; } + public DbSet ClaimTypes { get; set; } + public DbSet OrganizationUnits { get; set; } + public DbSet SecurityLogs { get; set; } + public DbSet LinkUsers { get; set; } + public DbSet UserDelegations { get; set; } + public DbSet Sessions { get; set; } + public DbSet FeatureGroups { get; set; } + public DbSet Features { get; set; } + public DbSet FeatureValues { get; set; } + public DbSet PermissionGroups { get; set; } + public DbSet Permissions { get; set; } + public DbSet PermissionGrants { get; set; } + public DbSet Settings { get; set; } + public DbSet SettingDefinitionRecords { get; set; } + public DbSet Tenants { get; set; } + public DbSet TenantConnectionStrings { get; set; } + public DbSet BackgroundJobs { get; set; } + public DbSet AuditLogs { get; set; } + public DbSet Notifications { get; set; } + public DbSet NotificationSubscriptions { get; set; } + public DbSet DataDictionaries { get; set; } + public DbSet Languages { get; set; } + public DbSet LanguageTexts { get; set; } + public IOTDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder builder) + { + + base.OnModelCreating(builder); + + builder.ConfigureIOT(); + + // 基础模块 + builder.ConfigureBasicManagement(); + + // 消息通知 + builder.ConfigureNotificationManagement(); + + //数据字典 + builder.ConfigureDataDictionaryManagement(); + + // 多语言 + builder.ConfigureLanguageManagement(); + } + + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTDbContextModelCreatingExtensions.cs b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTDbContextModelCreatingExtensions.cs new file mode 100644 index 0000000..4d0d498 --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTDbContextModelCreatingExtensions.cs @@ -0,0 +1,11 @@ +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace JiShe.IOT.EntityFrameworkCore; + +public static class IOTDbContextModelCreatingExtensions +{ + public static void ConfigureIOT(this ModelBuilder builder) + { + Check.NotNull(builder, nameof(builder)); + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTEfCoreEntityExtensionMappings.cs b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTEfCoreEntityExtensionMappings.cs new file mode 100644 index 0000000..5cd7e25 --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTEfCoreEntityExtensionMappings.cs @@ -0,0 +1,40 @@ +namespace JiShe.IOT.EntityFrameworkCore +{ + public static class IOTEfCoreEntityExtensionMappings + { + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + IOTGlobalFeatureConfigurator.Configure(); + IOTModuleExtensionConfigurator.Configure(); + + OneTimeRunner.Run(() => + { + /* You can configure extra properties for the + * entities defined in the modules used by your application. + * + * This class can be used to map these extra properties to table fields in the database. + * + * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING. + * USE IOTModuleExtensionConfigurator CLASS (in the Domain.Shared project) + * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES + * + * Example: Map a property to a table field: + + ObjectExtensionManager.Instance + .MapEfCoreProperty( + "MyProperty", + (entityBuilder, propertyBuilder) => + { + propertyBuilder.HasMaxLength(128); + } + ); + + * See the documentation for more: + * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities + */ + }); + } + } +} diff --git a/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTEntityFrameworkCoreModule.cs b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTEntityFrameworkCoreModule.cs new file mode 100644 index 0000000..d25e60b --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTEntityFrameworkCoreModule.cs @@ -0,0 +1,41 @@ +using Volo.Abp.Guids; + +namespace JiShe.IOT.EntityFrameworkCore +{ + [DependsOn( + typeof(IOTDomainModule), + typeof(AbpEntityFrameworkCoreMySQLModule), + typeof(BasicManagementEntityFrameworkCoreModule), + typeof(DataDictionaryManagementEntityFrameworkCoreModule), + typeof(NotificationManagementEntityFrameworkCoreModule), + typeof(LanguageManagementEntityFrameworkCoreModule) + )] + public class IOTEntityFrameworkCoreModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + IOTEfCoreEntityExtensionMappings.Configure(); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAbpDbContext(options => + { + /* Remove "includeAllEntities: true" to create + * default repositories only for aggregate roots */ + options.AddDefaultRepositories(includeAllEntities: true); + }); + Configure(options => + { + options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsString; + }); + Configure(options => + { + options.UseMySQL(builder => + { + builder.TranslateParameterizedCollectionsToConstants(); + }); + }); + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTMigrationsDbContextFactory.cs b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTMigrationsDbContextFactory.cs new file mode 100644 index 0000000..faac5ec --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/EntityFrameworkCore/IOTMigrationsDbContextFactory.cs @@ -0,0 +1,39 @@ +namespace JiShe.IOT.EntityFrameworkCore +{ + /* This class is needed for EF Core console commands + * (like Add-Migration and Update-Database commands) */ + public class IOTMigrationsDbContextFactory : IDesignTimeDbContextFactory + { + public IOTDbContext CreateDbContext(string[] args) + { + IOTEfCoreEntityExtensionMappings.Configure(); + + var configuration = BuildConfiguration(); + + var builder = new DbContextOptionsBuilder() + .UseMySql(configuration.GetConnectionString("Default"), MySqlServerVersion.LatestSupportedServerVersion); + + return new IOTDbContext(builder.Options); + } + + private static IConfigurationRoot BuildConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath + ( + Path.Combine + ( + Directory.GetCurrentDirectory(), + "../JiShe.IOT.DbMigrator/" + ) + ) + .AddJsonFile + ( + "appsettings.json", + false + ); + + return builder.Build(); + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.EntityFrameworkCore/GlobalUsings.cs b/src/JiShe.IOT.EntityFrameworkCore/GlobalUsings.cs new file mode 100644 index 0000000..3bffcdb --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/GlobalUsings.cs @@ -0,0 +1,40 @@ +// Global using directives + +global using System; +global using System.Collections.Generic; +global using System.IO; +global using System.Linq; +global using System.Text; +global using System.Threading.Tasks; +global using Lion.AbpPro.BasicManagement.EntityFrameworkCore; +global using Lion.AbpPro.DataDictionaryManagement; +global using Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates; +global using Lion.AbpPro.DataDictionaryManagement.EntityFrameworkCore; +global using Lion.AbpPro.LanguageManagement.EntityFrameworkCore; +global using Lion.AbpPro.LanguageManagement.Languages.Aggregates; +global using Lion.AbpPro.LanguageManagement.LanguageTexts.Aggregates; +global using Lion.AbpPro.NotificationManagement; +global using Lion.AbpPro.NotificationManagement.EntityFrameworkCore; +global using Lion.AbpPro.NotificationManagement.Notifications.Aggregates; +global using JiShe.IOT.Data; +global using JiShe.IOT.Users; +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.Design; +global using Microsoft.EntityFrameworkCore.Storage; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using MySqlConnector; +global using Volo.Abp; +global using Volo.Abp.AuditLogging; +global using Volo.Abp.BackgroundJobs; +global using Volo.Abp.Data; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.EntityFrameworkCore; +global using Volo.Abp.EntityFrameworkCore.MySQL; +global using Volo.Abp.FeatureManagement; +global using Volo.Abp.Identity; +global using Volo.Abp.Modularity; +global using Volo.Abp.PermissionManagement; +global using Volo.Abp.SettingManagement; +global using Volo.Abp.TenantManagement; +global using Volo.Abp.Threading; \ No newline at end of file diff --git a/src/JiShe.IOT.EntityFrameworkCore/JiShe.IOT.EntityFrameworkCore.csproj b/src/JiShe.IOT.EntityFrameworkCore/JiShe.IOT.EntityFrameworkCore.csproj new file mode 100644 index 0000000..cab7401 --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/JiShe.IOT.EntityFrameworkCore.csproj @@ -0,0 +1,25 @@ + + + net9.0 + JiShe.IOT + + + + + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers + compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native + + + \ No newline at end of file diff --git a/src/JiShe.IOT.EntityFrameworkCore/Migrations/20250219005605_Init.Designer.cs b/src/JiShe.IOT.EntityFrameworkCore/Migrations/20250219005605_Init.Designer.cs new file mode 100644 index 0000000..98f6186 --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/Migrations/20250219005605_Init.Designer.cs @@ -0,0 +1,2089 @@ +// +using System; +using JiShe.IOT.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace JiShe.IOT.Migrations +{ + [DbContext(typeof(IOTDbContext))] + [Migration("20250219005605_Init")] + partial class Init + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionary", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("DisplayText") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpDataDictionaries", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionaryDetail", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Code") + .HasColumnType("longtext"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DataDictionaryId") + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("DisplayText") + .HasColumnType("longtext"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DataDictionaryId"); + + b.ToTable("AbpDataDictionaryDetails", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.LanguageManagement.LanguageTexts.Aggregates.LanguageText", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("语言名称"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasComment("名称"); + + b.Property("ResourceName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("资源名称"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasComment("值"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ResourceName", "CultureName"); + + b.ToTable("AbpLanguageTexts", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.LanguageManagement.Languages.Aggregates.Language", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("语言名称"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("显示名称"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("FlagIcon") + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("图标"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("UiCultureName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("Ui语言名称"); + + b.HasKey("Id"); + + b.HasIndex("CultureName"); + + b.ToTable("AbpLanguages", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.NotificationManagement.Notifications.Aggregates.Notification", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("MessageLevel") + .HasColumnType("int"); + + b.Property("MessageType") + .HasColumnType("int"); + + b.Property("Read") + .HasColumnType("tinyint(1)"); + + b.Property("ReadTime") + .HasColumnType("datetime(6)"); + + b.Property("ReceiveUserId") + .HasColumnType("char(36)"); + + b.Property("ReceiveUserName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("SenderUserId") + .HasColumnType("char(36)"); + + b.Property("SenderUserName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.ToTable("AbpNotifications", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.NotificationManagement.Notifications.Aggregates.NotificationSubscription", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("NotificationId") + .HasColumnType("char(36)"); + + b.Property("Read") + .HasColumnType("tinyint(1)"); + + b.Property("ReadTime") + .HasColumnType("datetime(6)"); + + b.Property("ReceiveUserId") + .HasColumnType("char(36)"); + + b.Property("ReceiveUserName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NotificationId"); + + b.HasIndex("ReceiveUserId"); + + b.ToTable("AbpNotificationSubscriptions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("varchar(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("varchar(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("longtext"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("varchar(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("int") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("char(36)") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("char(36)") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("char(36)") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AuditLogId") + .HasColumnType("char(36)") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime(6)") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("varchar(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AuditLogId") + .HasColumnType("char(36)") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("datetime(6)") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("tinyint unsigned") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("char(36)"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("EntityChangeId") + .HasColumnType("char(36)"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("varchar(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("varchar(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("longtext"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("LastTryTime") + .HasColumnType("datetime(6)"); + + b.Property("NextTryTime") + .HasColumnType("datetime(6)"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint unsigned") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("tinyint(1)"); + + b.Property("IsVisibleToClients") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Required") + .HasColumnType("tinyint(1)"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("SourceTenantId") + .HasColumnType("char(36)"); + + b.Property("SourceUserId") + .HasColumnType("char(36)"); + + b.Property("TargetTenantId") + .HasColumnType("char(36)"); + + b.Property("TargetUserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("tinyint(1)") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("tinyint(1)") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("varchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("varchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("varchar(96)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("LastAccessed") + .HasColumnType("datetime(6)"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("SignedIn") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("varchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("tinyint(1)"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("EndTime") + .HasColumnType("datetime(6)"); + + b.Property("SourceUserId") + .HasColumnType("char(36)"); + + b.Property("StartTime") + .HasColumnType("datetime(6)"); + + b.Property("TargetUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("varchar(196)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("varchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("char(36)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint unsigned"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("tinyint(1)"); + + b.Property("IsInherited") + .HasColumnType("tinyint(1)"); + + b.Property("IsVisibleToClients") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionaryDetail", b => + { + b.HasOne("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionary", null) + .WithMany("Details") + .HasForeignKey("DataDictionaryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionary", b => + { + b.Navigation("Details"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/JiShe.IOT.EntityFrameworkCore/Migrations/20250219005605_Init.cs b/src/JiShe.IOT.EntityFrameworkCore/Migrations/20250219005605_Init.cs new file mode 100644 index 0000000..adb03e0 --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/Migrations/20250219005605_Init.cs @@ -0,0 +1,1378 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace JiShe.IOT.Migrations +{ + /// + public partial class Init : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpAuditLogs", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ApplicationName = table.Column(type: "varchar(96)", maxLength: 96, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + UserId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + UserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + TenantName = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ImpersonatorUserId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ImpersonatorUserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ImpersonatorTenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ImpersonatorTenantName = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ExecutionTime = table.Column(type: "datetime(6)", nullable: false), + ExecutionDuration = table.Column(type: "int", nullable: false), + ClientIpAddress = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ClientName = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ClientId = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + CorrelationId = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + BrowserInfo = table.Column(type: "varchar(512)", maxLength: 512, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + HttpMethod = table.Column(type: "varchar(16)", maxLength: 16, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Url = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Exceptions = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Comments = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + HttpStatusCode = table.Column(type: "int", nullable: true), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogs", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpBackgroundJobs", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + JobName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + JobArgs = table.Column(type: "longtext", maxLength: 1048576, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TryCount = table.Column(type: "smallint", nullable: false, defaultValue: (short)0), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + NextTryTime = table.Column(type: "datetime(6)", nullable: false), + LastTryTime = table.Column(type: "datetime(6)", nullable: true), + IsAbandoned = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + Priority = table.Column(type: "tinyint unsigned", nullable: false, defaultValue: (byte)15), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpBackgroundJobs", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Required = table.Column(type: "tinyint(1)", nullable: false), + IsStatic = table.Column(type: "tinyint(1)", nullable: false), + Regex = table.Column(type: "varchar(512)", maxLength: 512, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + RegexDescription = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ValueType = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpDataDictionaries", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Code = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayText = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + DeletionTime = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpDataDictionaries", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpFeatureGroups", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureGroups", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpFeatures", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + GroupName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ParentName = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + DefaultValue = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + IsVisibleToClients = table.Column(type: "tinyint(1)", nullable: false), + IsAvailableToHost = table.Column(type: "tinyint(1)", nullable: false), + AllowedProviders = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ValueType = table.Column(type: "varchar(2048)", maxLength: 2048, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatures", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpFeatureValues", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderName = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderKey = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpFeatureValues", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpLanguages", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + CultureName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false, comment: "语言名称") + .Annotation("MySql:CharSet", "utf8mb4"), + UiCultureName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false, comment: "Ui语言名称") + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false, comment: "显示名称") + .Annotation("MySql:CharSet", "utf8mb4"), + FlagIcon = table.Column(type: "varchar(128)", maxLength: 128, nullable: true, comment: "图标") + .Annotation("MySql:CharSet", "utf8mb4"), + IsEnabled = table.Column(type: "tinyint(1)", nullable: false), + IsDefault = table.Column(type: "tinyint(1)", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + DeletionTime = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLanguages", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpLanguageTexts", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + CultureName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false, comment: "语言名称") + .Annotation("MySql:CharSet", "utf8mb4"), + ResourceName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false, comment: "资源名称") + .Annotation("MySql:CharSet", "utf8mb4"), + Name = table.Column(type: "varchar(256)", maxLength: 256, nullable: false, comment: "名称") + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "varchar(256)", maxLength: 256, nullable: false, comment: "值") + .Annotation("MySql:CharSet", "utf8mb4"), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + DeletionTime = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLanguageTexts", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpLinkUsers", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + SourceUserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + SourceTenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + TargetUserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TargetTenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpLinkUsers", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpNotifications", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Title = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Content = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + MessageType = table.Column(type: "int", nullable: false), + MessageLevel = table.Column(type: "int", nullable: false), + SenderUserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + SenderUserName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ReceiveUserId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ReceiveUserName = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Read = table.Column(type: "tinyint(1)", nullable: false), + ReadTime = table.Column(type: "datetime(6)", nullable: true), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + DeletionTime = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpNotifications", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpNotificationSubscriptions", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + NotificationId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ReceiveUserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ReceiveUserName = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Read = table.Column(type: "tinyint(1)", nullable: false), + ReadTime = table.Column(type: "datetime(6)", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + DeletionTime = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpNotificationSubscriptions", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnits", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ParentId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Code = table.Column(type: "varchar(95)", maxLength: 95, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + EntityVersion = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + DeletionTime = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnits", x => x.Id); + table.ForeignKey( + name: "FK_AbpOrganizationUnits_AbpOrganizationUnits_ParentId", + column: x => x.ParentId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id"); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpPermissionGrants", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderName = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderKey = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGrants", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpPermissionGroups", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissionGroups", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpPermissions", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + GroupName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ParentName = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsEnabled = table.Column(type: "tinyint(1)", nullable: false), + MultiTenancySide = table.Column(type: "tinyint unsigned", nullable: false), + Providers = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + StateCheckers = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpPermissions", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpRoles", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + NormalizedName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsDefault = table.Column(type: "tinyint(1)", nullable: false), + IsStatic = table.Column(type: "tinyint(1)", nullable: false), + IsPublic = table.Column(type: "tinyint(1)", nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoles", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpSecurityLogs", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ApplicationName = table.Column(type: "varchar(96)", maxLength: 96, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Identity = table.Column(type: "varchar(96)", maxLength: 96, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Action = table.Column(type: "varchar(96)", maxLength: 96, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + UserId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + UserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + TenantName = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ClientId = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + CorrelationId = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ClientIpAddress = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + BrowserInfo = table.Column(type: "varchar(512)", maxLength: 512, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpSessions", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + SessionId = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Device = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DeviceInfo = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + UserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ClientId = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + IpAddresses = table.Column(type: "varchar(2048)", maxLength: 2048, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + SignedIn = table.Column(type: "datetime(6)", nullable: false), + LastAccessed = table.Column(type: "datetime(6)", nullable: true), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSessions", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpSettingDefinitions", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "varchar(512)", maxLength: 512, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + DefaultValue = table.Column(type: "varchar(2048)", maxLength: 2048, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + IsVisibleToClients = table.Column(type: "tinyint(1)", nullable: false), + Providers = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + IsInherited = table.Column(type: "tinyint(1)", nullable: false), + IsEncrypted = table.Column(type: "tinyint(1)", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettingDefinitions", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpSettings", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "varchar(2048)", maxLength: 2048, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderName = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderKey = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettings", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpTenants", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + NormalizedName = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + EntityVersion = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + DeletionTime = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenants", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpUserDelegations", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + SourceUserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TargetUserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + StartTime = table.Column(type: "datetime(6)", nullable: false), + EndTime = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserDelegations", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpUsers", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + UserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + NormalizedUserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Name = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Surname = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Email = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + NormalizedEmail = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + EmailConfirmed = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + PasswordHash = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + SecurityStamp = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsExternal = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + PhoneNumber = table.Column(type: "varchar(16)", maxLength: 16, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + PhoneNumberConfirmed = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + TwoFactorEnabled = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + LockoutEnd = table.Column(type: "datetime(6)", nullable: true), + LockoutEnabled = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + AccessFailedCount = table.Column(type: "int", nullable: false, defaultValue: 0), + ShouldChangePasswordOnNextLogin = table.Column(type: "tinyint(1)", nullable: false), + EntityVersion = table.Column(type: "int", nullable: false), + LastPasswordChangeTime = table.Column(type: "datetime(6)", nullable: true), + ExtraProperties = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + DeletionTime = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUsers", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpAuditLogActions", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + AuditLogId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ServiceName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + MethodName = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Parameters = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ExecutionTime = table.Column(type: "datetime(6)", nullable: false), + ExecutionDuration = table.Column(type: "int", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpAuditLogActions", x => x.Id); + table.ForeignKey( + name: "FK_AbpAuditLogActions_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpEntityChanges", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + AuditLogId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ChangeTime = table.Column(type: "datetime(6)", nullable: false), + ChangeType = table.Column(type: "tinyint unsigned", nullable: false), + EntityTenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + EntityId = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + EntityTypeFullName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityChanges_AbpAuditLogs_AuditLogId", + column: x => x.AuditLogId, + principalTable: "AbpAuditLogs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpDataDictionaryDetails", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + DataDictionaryId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Code = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Order = table.Column(type: "int", nullable: false), + DisplayText = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + IsEnabled = table.Column(type: "tinyint(1)", nullable: false), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpDataDictionaryDetails", x => x.Id); + table.ForeignKey( + name: "FK_AbpDataDictionaryDetails_AbpDataDictionaries_DataDictionaryId", + column: x => x.DataDictionaryId, + principalTable: "AbpDataDictionaries", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpOrganizationUnitRoles", + columns: table => new + { + RoleId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + OrganizationUnitId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpOrganizationUnitRoles", x => new { x.OrganizationUnitId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpOrganizationUnits_OrganizationUn~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpOrganizationUnitRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpRoleClaims", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + RoleId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ClaimType = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ClaimValue = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpRoleClaims_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpTenantConnectionStrings", + columns: table => new + { + TenantId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTenantConnectionStrings", x => new { x.TenantId, x.Name }); + table.ForeignKey( + name: "FK_AbpTenantConnectionStrings_AbpTenants_TenantId", + column: x => x.TenantId, + principalTable: "AbpTenants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpUserClaims", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + UserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ClaimType = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ClaimValue = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AbpUserClaims_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpUserLogins", + columns: table => new + { + UserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + LoginProvider = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ProviderKey = table.Column(type: "varchar(196)", maxLength: 196, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderDisplayName = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserLogins", x => new { x.UserId, x.LoginProvider }); + table.ForeignKey( + name: "FK_AbpUserLogins_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpUserOrganizationUnits", + columns: table => new + { + UserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + OrganizationUnitId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserOrganizationUnits", x => new { x.OrganizationUnitId, x.UserId }); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpOrganizationUnits_OrganizationUn~", + column: x => x.OrganizationUnitId, + principalTable: "AbpOrganizationUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserOrganizationUnits_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpUserRoles", + columns: table => new + { + UserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + RoleId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpRoles_RoleId", + column: x => x.RoleId, + principalTable: "AbpRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AbpUserRoles_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpUserTokens", + columns: table => new + { + UserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + LoginProvider = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Value = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AbpUserTokens_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AbpEntityPropertyChanges", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + TenantId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + EntityChangeId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + NewValue = table.Column(type: "varchar(512)", maxLength: 512, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + OriginalValue = table.Column(type: "varchar(512)", maxLength: 512, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + PropertyName = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + PropertyTypeFullName = table.Column(type: "varchar(64)", maxLength: 64, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpEntityPropertyChanges", x => x.Id); + table.ForeignKey( + name: "FK_AbpEntityPropertyChanges_AbpEntityChanges_EntityChangeId", + column: x => x.EntityChangeId, + principalTable: "AbpEntityChanges", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_AuditLogId", + table: "AbpAuditLogActions", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogActions_TenantId_ServiceName_MethodName_Execution~", + table: "AbpAuditLogActions", + columns: new[] { "TenantId", "ServiceName", "MethodName", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpAuditLogs_TenantId_UserId_ExecutionTime", + table: "AbpAuditLogs", + columns: new[] { "TenantId", "UserId", "ExecutionTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpBackgroundJobs_IsAbandoned_NextTryTime", + table: "AbpBackgroundJobs", + columns: new[] { "IsAbandoned", "NextTryTime" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpDataDictionaryDetails_DataDictionaryId", + table: "AbpDataDictionaryDetails", + column: "DataDictionaryId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_AuditLogId", + table: "AbpEntityChanges", + column: "AuditLogId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityChanges_TenantId_EntityTypeFullName_EntityId", + table: "AbpEntityChanges", + columns: new[] { "TenantId", "EntityTypeFullName", "EntityId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpEntityPropertyChanges_EntityChangeId", + table: "AbpEntityPropertyChanges", + column: "EntityChangeId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureGroups_Name", + table: "AbpFeatureGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_GroupName", + table: "AbpFeatures", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatures_Name", + table: "AbpFeatures", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpFeatureValues_Name_ProviderName_ProviderKey", + table: "AbpFeatureValues", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpLanguages_CultureName", + table: "AbpLanguages", + column: "CultureName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpLanguageTexts_TenantId_ResourceName_CultureName", + table: "AbpLanguageTexts", + columns: new[] { "TenantId", "ResourceName", "CultureName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_Target~", + table: "AbpLinkUsers", + columns: new[] { "SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpNotificationSubscriptions_NotificationId", + table: "AbpNotificationSubscriptions", + column: "NotificationId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpNotificationSubscriptions_ReceiveUserId", + table: "AbpNotificationSubscriptions", + column: "ReceiveUserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnitRoles_RoleId_OrganizationUnitId", + table: "AbpOrganizationUnitRoles", + columns: new[] { "RoleId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_Code", + table: "AbpOrganizationUnits", + column: "Code"); + + migrationBuilder.CreateIndex( + name: "IX_AbpOrganizationUnits_ParentId", + table: "AbpOrganizationUnits", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", + table: "AbpPermissionGrants", + columns: new[] { "TenantId", "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissionGroups_Name", + table: "AbpPermissionGroups", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_GroupName", + table: "AbpPermissions", + column: "GroupName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpPermissions_Name", + table: "AbpPermissions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoleClaims_RoleId", + table: "AbpRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpRoles_NormalizedName", + table: "AbpRoles", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Action", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Action" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_ApplicationName", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "ApplicationName" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_Identity", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "Identity" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSecurityLogs_TenantId_UserId", + table: "AbpSecurityLogs", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_Device", + table: "AbpSessions", + column: "Device"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_SessionId", + table: "AbpSessions", + column: "SessionId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpSessions_TenantId_UserId", + table: "AbpSessions", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettingDefinitions_Name", + table: "AbpSettingDefinitions", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettings_Name_ProviderName_ProviderKey", + table: "AbpSettings", + columns: new[] { "Name", "ProviderName", "ProviderKey" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_Name", + table: "AbpTenants", + column: "Name"); + + migrationBuilder.CreateIndex( + name: "IX_AbpTenants_NormalizedName", + table: "AbpTenants", + column: "NormalizedName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserClaims_UserId", + table: "AbpUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserLogins_LoginProvider_ProviderKey", + table: "AbpUserLogins", + columns: new[] { "LoginProvider", "ProviderKey" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserOrganizationUnits_UserId_OrganizationUnitId", + table: "AbpUserOrganizationUnits", + columns: new[] { "UserId", "OrganizationUnitId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUserRoles_RoleId_UserId", + table: "AbpUserRoles", + columns: new[] { "RoleId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_Email", + table: "AbpUsers", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedEmail", + table: "AbpUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_NormalizedUserName", + table: "AbpUsers", + column: "NormalizedUserName"); + + migrationBuilder.CreateIndex( + name: "IX_AbpUsers_UserName", + table: "AbpUsers", + column: "UserName"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpAuditLogActions"); + + migrationBuilder.DropTable( + name: "AbpBackgroundJobs"); + + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropTable( + name: "AbpDataDictionaryDetails"); + + migrationBuilder.DropTable( + name: "AbpEntityPropertyChanges"); + + migrationBuilder.DropTable( + name: "AbpFeatureGroups"); + + migrationBuilder.DropTable( + name: "AbpFeatures"); + + migrationBuilder.DropTable( + name: "AbpFeatureValues"); + + migrationBuilder.DropTable( + name: "AbpLanguages"); + + migrationBuilder.DropTable( + name: "AbpLanguageTexts"); + + migrationBuilder.DropTable( + name: "AbpLinkUsers"); + + migrationBuilder.DropTable( + name: "AbpNotifications"); + + migrationBuilder.DropTable( + name: "AbpNotificationSubscriptions"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnitRoles"); + + migrationBuilder.DropTable( + name: "AbpPermissionGrants"); + + migrationBuilder.DropTable( + name: "AbpPermissionGroups"); + + migrationBuilder.DropTable( + name: "AbpPermissions"); + + migrationBuilder.DropTable( + name: "AbpRoleClaims"); + + migrationBuilder.DropTable( + name: "AbpSecurityLogs"); + + migrationBuilder.DropTable( + name: "AbpSessions"); + + migrationBuilder.DropTable( + name: "AbpSettingDefinitions"); + + migrationBuilder.DropTable( + name: "AbpSettings"); + + migrationBuilder.DropTable( + name: "AbpTenantConnectionStrings"); + + migrationBuilder.DropTable( + name: "AbpUserClaims"); + + migrationBuilder.DropTable( + name: "AbpUserDelegations"); + + migrationBuilder.DropTable( + name: "AbpUserLogins"); + + migrationBuilder.DropTable( + name: "AbpUserOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpUserRoles"); + + migrationBuilder.DropTable( + name: "AbpUserTokens"); + + migrationBuilder.DropTable( + name: "AbpDataDictionaries"); + + migrationBuilder.DropTable( + name: "AbpEntityChanges"); + + migrationBuilder.DropTable( + name: "AbpTenants"); + + migrationBuilder.DropTable( + name: "AbpOrganizationUnits"); + + migrationBuilder.DropTable( + name: "AbpRoles"); + + migrationBuilder.DropTable( + name: "AbpUsers"); + + migrationBuilder.DropTable( + name: "AbpAuditLogs"); + } + } +} diff --git a/src/JiShe.IOT.EntityFrameworkCore/Migrations/IOTDbContextModelSnapshot.cs b/src/JiShe.IOT.EntityFrameworkCore/Migrations/IOTDbContextModelSnapshot.cs new file mode 100644 index 0000000..4b8cf31 --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/Migrations/IOTDbContextModelSnapshot.cs @@ -0,0 +1,2086 @@ +// +using System; +using JiShe.IOT.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace JiShe.IOT.Migrations +{ + [DbContext(typeof(IOTDbContext))] + partial class IOTDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionary", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("DisplayText") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpDataDictionaries", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionaryDetail", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Code") + .HasColumnType("longtext"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DataDictionaryId") + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("DisplayText") + .HasColumnType("longtext"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Order") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DataDictionaryId"); + + b.ToTable("AbpDataDictionaryDetails", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.LanguageManagement.LanguageTexts.Aggregates.LanguageText", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("语言名称"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasComment("名称"); + + b.Property("ResourceName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("资源名称"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasComment("值"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ResourceName", "CultureName"); + + b.ToTable("AbpLanguageTexts", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.LanguageManagement.Languages.Aggregates.Language", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("语言名称"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("显示名称"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("FlagIcon") + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("图标"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("UiCultureName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasComment("Ui语言名称"); + + b.HasKey("Id"); + + b.HasIndex("CultureName"); + + b.ToTable("AbpLanguages", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.NotificationManagement.Notifications.Aggregates.Notification", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("MessageLevel") + .HasColumnType("int"); + + b.Property("MessageType") + .HasColumnType("int"); + + b.Property("Read") + .HasColumnType("tinyint(1)"); + + b.Property("ReadTime") + .HasColumnType("datetime(6)"); + + b.Property("ReceiveUserId") + .HasColumnType("char(36)"); + + b.Property("ReceiveUserName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("SenderUserId") + .HasColumnType("char(36)"); + + b.Property("SenderUserName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.ToTable("AbpNotifications", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.NotificationManagement.Notifications.Aggregates.NotificationSubscription", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("NotificationId") + .HasColumnType("char(36)"); + + b.Property("Read") + .HasColumnType("tinyint(1)"); + + b.Property("ReadTime") + .HasColumnType("datetime(6)"); + + b.Property("ReceiveUserId") + .HasColumnType("char(36)"); + + b.Property("ReceiveUserName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NotificationId"); + + b.HasIndex("ReceiveUserId"); + + b.ToTable("AbpNotificationSubscriptions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("varchar(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("varchar(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("longtext"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("varchar(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("int") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("char(36)") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("char(36)") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("char(36)") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AuditLogId") + .HasColumnType("char(36)") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime(6)") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("varchar(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AuditLogId") + .HasColumnType("char(36)") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("datetime(6)") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("tinyint unsigned") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("char(36)"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("EntityChangeId") + .HasColumnType("char(36)"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("varchar(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("varchar(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("longtext"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("LastTryTime") + .HasColumnType("datetime(6)"); + + b.Property("NextTryTime") + .HasColumnType("datetime(6)"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint unsigned") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("tinyint(1)"); + + b.Property("IsVisibleToClients") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Required") + .HasColumnType("tinyint(1)"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("SourceTenantId") + .HasColumnType("char(36)"); + + b.Property("SourceUserId") + .HasColumnType("char(36)"); + + b.Property("TargetTenantId") + .HasColumnType("char(36)"); + + b.Property("TargetUserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("tinyint(1)") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("tinyint(1)") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("tinyint(1)") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("varchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("varchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("varchar(96)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("LastAccessed") + .HasColumnType("datetime(6)"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("SignedIn") + .HasColumnType("datetime(6)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("varchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("tinyint(1)"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("varchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("EndTime") + .HasColumnType("datetime(6)"); + + b.Property("SourceUserId") + .HasColumnType("char(36)"); + + b.Property("StartTime") + .HasColumnType("datetime(6)"); + + b.Property("TargetUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("varchar(196)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("char(36)"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("varchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("char(36)"); + + b.Property("RoleId") + .HasColumnType("char(36)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint unsigned"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("tinyint(1)"); + + b.Property("IsInherited") + .HasColumnType("tinyint(1)"); + + b.Property("IsVisibleToClients") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionaryDetail", b => + { + b.HasOne("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionary", null) + .WithMany("Details") + .HasForeignKey("DataDictionaryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Lion.AbpPro.DataDictionaryManagement.DataDictionaries.Aggregates.DataDictionary", b => + { + b.Navigation("Details"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/JiShe.IOT.EntityFrameworkCore/Properties/AssemblyInfo.cs b/src/JiShe.IOT.EntityFrameworkCore/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ef2f2b4 --- /dev/null +++ b/src/JiShe.IOT.EntityFrameworkCore/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using System.Runtime.CompilerServices; +[assembly:InternalsVisibleToAttribute("JiShe.IOT.EntityFrameworkCore.Tests")] diff --git a/src/JiShe.IOT.FreeSqlRepository/FreeSqlBasicRepository.cs b/src/JiShe.IOT.FreeSqlRepository/FreeSqlBasicRepository.cs new file mode 100644 index 0000000..5a1d47d --- /dev/null +++ b/src/JiShe.IOT.FreeSqlRepository/FreeSqlBasicRepository.cs @@ -0,0 +1,14 @@ +namespace JiShe.IOT.FreeSqlRepository; + +public abstract class FreeSqlBasicRepository : DomainService +{ + protected IFreeSql FreeSql => LazyServiceProvider.LazyGetRequiredService(); + + private ICancellationTokenProvider CancellationTokenProvider => + LazyServiceProvider.LazyGetService(NullCancellationTokenProvider.Instance); + + protected virtual CancellationToken GetCancellationToken(CancellationToken preferredValue = default) + { + return CancellationTokenProvider.FallbackToProvider(preferredValue); + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.FreeSqlRepository/GlobalUsings.cs b/src/JiShe.IOT.FreeSqlRepository/GlobalUsings.cs new file mode 100644 index 0000000..39a34c3 --- /dev/null +++ b/src/JiShe.IOT.FreeSqlRepository/GlobalUsings.cs @@ -0,0 +1,7 @@ +// Global using directives + +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Volo.Abp.Domain.Services; +global using Volo.Abp.Modularity; +global using Volo.Abp.Threading; \ No newline at end of file diff --git a/src/JiShe.IOT.FreeSqlRepository/IOTFreeSqlModule.cs b/src/JiShe.IOT.FreeSqlRepository/IOTFreeSqlModule.cs new file mode 100644 index 0000000..ea0de01 --- /dev/null +++ b/src/JiShe.IOT.FreeSqlRepository/IOTFreeSqlModule.cs @@ -0,0 +1,15 @@ +namespace JiShe.IOT.FreeSqlRepository; + +public class IOTFreeSqlModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + var connectionString = configuration.GetConnectionString("Default"); + var freeSql = new FreeSql.FreeSqlBuilder() + .UseConnectionString(FreeSql.DataType.MySql, connectionString) + .Build(); + + context.Services.AddSingleton(freeSql); + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.FreeSqlRepository/JiShe.IOT.FreeSqlRepository.csproj b/src/JiShe.IOT.FreeSqlRepository/JiShe.IOT.FreeSqlRepository.csproj new file mode 100644 index 0000000..957b6c8 --- /dev/null +++ b/src/JiShe.IOT.FreeSqlRepository/JiShe.IOT.FreeSqlRepository.csproj @@ -0,0 +1,17 @@ + + + + net9.0 + enable + + + + + + + + + + + + diff --git a/src/JiShe.IOT.HttpApi.Client/GlobalUsings.cs b/src/JiShe.IOT.HttpApi.Client/GlobalUsings.cs new file mode 100644 index 0000000..ab3acb4 --- /dev/null +++ b/src/JiShe.IOT.HttpApi.Client/GlobalUsings.cs @@ -0,0 +1,10 @@ +// Global using directives + +global using Microsoft.Extensions.DependencyInjection; +global using Volo.Abp.Account; +global using Volo.Abp.FeatureManagement; +global using Volo.Abp.Identity; +global using Volo.Abp.Modularity; +global using Volo.Abp.PermissionManagement; +global using Volo.Abp.SettingManagement; +global using Volo.Abp.TenantManagement; \ No newline at end of file diff --git a/src/JiShe.IOT.HttpApi.Client/IOTHttpApiClientModule.cs b/src/JiShe.IOT.HttpApi.Client/IOTHttpApiClientModule.cs new file mode 100644 index 0000000..dd437fc --- /dev/null +++ b/src/JiShe.IOT.HttpApi.Client/IOTHttpApiClientModule.cs @@ -0,0 +1,27 @@ +using Lion.AbpPro.BasicManagement; +using Lion.AbpPro.DataDictionaryManagement; +using Lion.AbpPro.LanguageManagement; +using Lion.AbpPro.NotificationManagement; + +namespace JiShe.IOT +{ + [DependsOn( + typeof(IOTApplicationContractsModule), + typeof(BasicManagementHttpApiClientModule), + typeof(NotificationManagementHttpApiClientModule), + typeof(DataDictionaryManagementHttpApiClientModule), + typeof(LanguageManagementHttpApiClientModule) + )] + public class IOTHttpApiClientModule : AbpModule + { + public const string RemoteServiceName = "Default"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHttpClientProxies( + typeof(IOTApplicationContractsModule).Assembly, + RemoteServiceName + ); + } + } +} diff --git a/src/JiShe.IOT.HttpApi.Client/JiShe.IOT.HttpApi.Client.csproj b/src/JiShe.IOT.HttpApi.Client/JiShe.IOT.HttpApi.Client.csproj new file mode 100644 index 0000000..08b5632 --- /dev/null +++ b/src/JiShe.IOT.HttpApi.Client/JiShe.IOT.HttpApi.Client.csproj @@ -0,0 +1,18 @@ + + + net9.0 + JiShe.IOT + + + + + + + + + + + + + + diff --git a/src/JiShe.IOT.HttpApi/Controllers/IOTController.cs b/src/JiShe.IOT.HttpApi/Controllers/IOTController.cs new file mode 100644 index 0000000..427901f --- /dev/null +++ b/src/JiShe.IOT.HttpApi/Controllers/IOTController.cs @@ -0,0 +1,12 @@ +namespace JiShe.IOT.Controllers +{ + /* Inherit your controllers from this class. + */ + public abstract class IOTController : AbpController + { + protected IOTController() + { + LocalizationResource = typeof(IOTResource); + } + } +} \ No newline at end of file diff --git a/src/JiShe.IOT.HttpApi/GlobalUsings.cs b/src/JiShe.IOT.HttpApi/GlobalUsings.cs new file mode 100644 index 0000000..c419edf --- /dev/null +++ b/src/JiShe.IOT.HttpApi/GlobalUsings.cs @@ -0,0 +1,11 @@ +// Global using directives + + +global using Lion.AbpPro.BasicManagement; +global using Lion.AbpPro.NotificationManagement; +global using Localization.Resources.AbpUi; +global using Microsoft.AspNetCore.Mvc; +global using Swashbuckle.AspNetCore.Annotations; +global using Volo.Abp.AspNetCore.Mvc; +global using Volo.Abp.Localization; +global using Volo.Abp.Modularity; \ No newline at end of file diff --git a/src/JiShe.IOT.HttpApi/IOTHttpApiModule.cs b/src/JiShe.IOT.HttpApi/IOTHttpApiModule.cs new file mode 100644 index 0000000..d6d17df --- /dev/null +++ b/src/JiShe.IOT.HttpApi/IOTHttpApiModule.cs @@ -0,0 +1,32 @@ +using Lion.AbpPro.DataDictionaryManagement; +using Lion.AbpPro.LanguageManagement; + +namespace JiShe.IOT +{ + [DependsOn( + typeof(IOTApplicationContractsModule), + typeof(BasicManagementHttpApiModule), + typeof(NotificationManagementHttpApiModule), + typeof(DataDictionaryManagementHttpApiModule), + typeof(LanguageManagementHttpApiModule) + )] + public class IOTHttpApiModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureLocalization(); + } + + private void ConfigureLocalization() + { + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes( + typeof(AbpUiResource) + ); + }); + } + } +} diff --git a/src/JiShe.IOT.HttpApi/JiShe.IOT.HttpApi.csproj b/src/JiShe.IOT.HttpApi/JiShe.IOT.HttpApi.csproj new file mode 100644 index 0000000..9a40466 --- /dev/null +++ b/src/JiShe.IOT.HttpApi/JiShe.IOT.HttpApi.csproj @@ -0,0 +1,23 @@ + + + + net9.0 + JiShe.IOT + + + + + + + + + + + + + + + + + + diff --git a/test/JiShe.IOT.Application.Tests/GlobalUsings.cs b/test/JiShe.IOT.Application.Tests/GlobalUsings.cs new file mode 100644 index 0000000..6832035 --- /dev/null +++ b/test/JiShe.IOT.Application.Tests/GlobalUsings.cs @@ -0,0 +1,6 @@ +// Global using directives + +global using System.Threading.Tasks; +global using Shouldly; +global using Volo.Abp.Identity; +global using Xunit; \ No newline at end of file diff --git a/test/JiShe.IOT.Application.Tests/IOTApplicationTestBase.cs b/test/JiShe.IOT.Application.Tests/IOTApplicationTestBase.cs new file mode 100644 index 0000000..5c2fe70 --- /dev/null +++ b/test/JiShe.IOT.Application.Tests/IOTApplicationTestBase.cs @@ -0,0 +1,7 @@ +namespace JiShe.IOT +{ + public abstract class IOTApplicationTestBase : IOTTestBase + { + + } +} diff --git a/test/JiShe.IOT.Application.Tests/IOTApplicationTestModule.cs b/test/JiShe.IOT.Application.Tests/IOTApplicationTestModule.cs new file mode 100644 index 0000000..ab9d589 --- /dev/null +++ b/test/JiShe.IOT.Application.Tests/IOTApplicationTestModule.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Modularity; + +namespace JiShe.IOT +{ + [DependsOn( + typeof(IOTApplicationModule), + typeof(IOTDomainTestModule) + )] + public class IOTApplicationTestModule : AbpModule + { + + } +} \ No newline at end of file diff --git a/test/JiShe.IOT.Application.Tests/JiShe.IOT.Application.Tests.csproj b/test/JiShe.IOT.Application.Tests/JiShe.IOT.Application.Tests.csproj new file mode 100644 index 0000000..e370cfa --- /dev/null +++ b/test/JiShe.IOT.Application.Tests/JiShe.IOT.Application.Tests.csproj @@ -0,0 +1,17 @@ + + + net9.0 + JiShe.IOT + false + + + + + + + + + + + + \ No newline at end of file diff --git a/test/JiShe.IOT.Application.Tests/Samples/SampleAppServiceTests.cs b/test/JiShe.IOT.Application.Tests/Samples/SampleAppServiceTests.cs new file mode 100644 index 0000000..ffde8b1 --- /dev/null +++ b/test/JiShe.IOT.Application.Tests/Samples/SampleAppServiceTests.cs @@ -0,0 +1,28 @@ +namespace JiShe.IOT.Samples +{ + /* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IIdentityUserAppService here). + * Only test your own application services. + */ + public class SampleAppServiceTests : IOTApplicationTestBase + { + private readonly IIdentityUserAppService _userAppService; + + public SampleAppServiceTests() + { + _userAppService = GetRequiredService(); + } + + [Fact] + public async Task Initial_Data_Should_Contain_Admin_User() + { + //Act + var result = await _userAppService.GetListAsync(new GetIdentityUsersInput()); + + //Assert + result.TotalCount.ShouldBeGreaterThan(0); + result.Items.ShouldContain(u => u.UserName == "admin"); + } + } +} diff --git a/test/JiShe.IOT.Domain.Tests/GlobalUsings.cs b/test/JiShe.IOT.Domain.Tests/GlobalUsings.cs new file mode 100644 index 0000000..af84c74 --- /dev/null +++ b/test/JiShe.IOT.Domain.Tests/GlobalUsings.cs @@ -0,0 +1,13 @@ +// Global using directives + +global using System; +global using System.Collections.Generic; +global using System.Linq; +global using System.Threading.Tasks; +global using JiShe.IOT.EntityFrameworkCore; +global using Shouldly; +global using Volo.Abp; +global using Volo.Abp.Identity; +global using Volo.Abp.Localization; +global using Volo.Abp.Modularity; +global using Xunit; \ No newline at end of file diff --git a/test/JiShe.IOT.Domain.Tests/IOTDomainTestBase.cs b/test/JiShe.IOT.Domain.Tests/IOTDomainTestBase.cs new file mode 100644 index 0000000..f8b9c00 --- /dev/null +++ b/test/JiShe.IOT.Domain.Tests/IOTDomainTestBase.cs @@ -0,0 +1,10 @@ +namespace JiShe.IOT +{ + public abstract class IOTDomainTestBase : IOTTestBase + { + public IOTDomainTestBase() + { + + } + } +} diff --git a/test/JiShe.IOT.Domain.Tests/IOTDomainTestModule.cs b/test/JiShe.IOT.Domain.Tests/IOTDomainTestModule.cs new file mode 100644 index 0000000..6b49a3e --- /dev/null +++ b/test/JiShe.IOT.Domain.Tests/IOTDomainTestModule.cs @@ -0,0 +1,10 @@ +namespace JiShe.IOT +{ + [DependsOn( + typeof(IOTEntityFrameworkCoreTestModule) + )] + public class IOTDomainTestModule : AbpModule + { + + } +} \ No newline at end of file diff --git a/test/JiShe.IOT.Domain.Tests/JiShe.IOT.Domain.Tests.csproj b/test/JiShe.IOT.Domain.Tests/JiShe.IOT.Domain.Tests.csproj new file mode 100644 index 0000000..23e97b3 --- /dev/null +++ b/test/JiShe.IOT.Domain.Tests/JiShe.IOT.Domain.Tests.csproj @@ -0,0 +1,16 @@ + + + net9.0 + JiShe.IOT + false + + + + + + + + + + + \ No newline at end of file diff --git a/test/JiShe.IOT.Domain.Tests/Localizations/LocalizationHelper_Tests.cs b/test/JiShe.IOT.Domain.Tests/Localizations/LocalizationHelper_Tests.cs new file mode 100644 index 0000000..e7f6892 --- /dev/null +++ b/test/JiShe.IOT.Domain.Tests/Localizations/LocalizationHelper_Tests.cs @@ -0,0 +1,40 @@ +// namespace JiShe.IOT.Localizations +// { +// public class LocalizationHelper_Tests:IOTDomainTestBase +// { +// [Fact] +// public void Test_LocalizationHelper_L_OK() +// { +// using (CultureHelper.Use("en")) +// { +// var enValue = LocalizationHelper.L["Welcome"]; +// enValue.Value.ShouldBe("Welcome"); +// } +// +// using (CultureHelper.Use("zh-Hans")) +// { +// +// var enValue = LocalizationHelper.L["Welcome"]; +// enValue.Value.ShouldBe("欢迎"); +// } +// } +// +// [Fact] +// public void Test_ToLocalicationDescription_L_OK() +// { +// var test = new {TestType=TestType.Cancel}; +// using (CultureHelper.Use("en")) +// { +// var enValue = test.TestType.ToLocalicationDescription(); +// enValue.ShouldBe("Cancel"); +// } +// +// using (CultureHelper.Use("zh-Hans")) +// { +// +// var enValue = test.TestType.ToLocalicationDescription(); +// enValue.ShouldBe("取消"); +// } +// } +// } +// } \ No newline at end of file diff --git a/test/JiShe.IOT.Domain.Tests/Localizations/TestType.cs b/test/JiShe.IOT.Domain.Tests/Localizations/TestType.cs new file mode 100644 index 0000000..1011407 --- /dev/null +++ b/test/JiShe.IOT.Domain.Tests/Localizations/TestType.cs @@ -0,0 +1,9 @@ +namespace JiShe.IOT.Localizations +{ + public enum TestType + { + Created, + Cancel, + Delete + } +} \ No newline at end of file diff --git a/test/JiShe.IOT.Domain.Tests/Samples/SampleDomainTests.cs b/test/JiShe.IOT.Domain.Tests/Samples/SampleDomainTests.cs new file mode 100644 index 0000000..70dd562 --- /dev/null +++ b/test/JiShe.IOT.Domain.Tests/Samples/SampleDomainTests.cs @@ -0,0 +1,40 @@ +namespace JiShe.IOT.Samples +{ + /* This is just an example test class. + * Normally, you don't test code of the modules you are using + * (like IdentityUserManager here). + * Only test your own domain services. + */ + public class SampleDomainTests : IOTDomainTestBase + { + private readonly IIdentityUserRepository _identityUserRepository; + private readonly IdentityUserManager _identityUserManager; + + public SampleDomainTests() + { + _identityUserRepository = GetRequiredService(); + _identityUserManager = GetRequiredService(); + } + + [Fact] + public async Task Should_Set_Email_Of_A_User() + { + IdentityUser adminUser; + + /* Need to manually start Unit Of Work because + * FirstOrDefaultAsync should be executed while db connection / context is available. + */ + await WithUnitOfWorkAsync(async () => + { + adminUser = await _identityUserRepository + .FindByNormalizedUserNameAsync("ADMIN"); + + await _identityUserManager.SetEmailAsync(adminUser, "newemail@abp.io"); + await _identityUserRepository.UpdateAsync(adminUser); + }); + + adminUser = await _identityUserRepository.FindByNormalizedUserNameAsync("ADMIN"); + adminUser.Email.ShouldBe("newemail@abp.io"); + } + } +} diff --git a/test/JiShe.IOT.EntityFrameworkCore.Tests/EntityFrameworkCore/IOTEntityFrameworkCoreTestBase.cs b/test/JiShe.IOT.EntityFrameworkCore.Tests/EntityFrameworkCore/IOTEntityFrameworkCoreTestBase.cs new file mode 100644 index 0000000..62ba988 --- /dev/null +++ b/test/JiShe.IOT.EntityFrameworkCore.Tests/EntityFrameworkCore/IOTEntityFrameworkCoreTestBase.cs @@ -0,0 +1,7 @@ +namespace JiShe.IOT.EntityFrameworkCore +{ + public abstract class IOTEntityFrameworkCoreTestBase : IOTTestBase + { + + } +} diff --git a/test/JiShe.IOT.EntityFrameworkCore.Tests/EntityFrameworkCore/IOTEntityFrameworkCoreTestModule.cs b/test/JiShe.IOT.EntityFrameworkCore.Tests/EntityFrameworkCore/IOTEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000..57f7b74 --- /dev/null +++ b/test/JiShe.IOT.EntityFrameworkCore.Tests/EntityFrameworkCore/IOTEntityFrameworkCoreTestModule.cs @@ -0,0 +1,52 @@ +namespace JiShe.IOT.EntityFrameworkCore +{ + [DependsOn( + typeof(IOTTestBaseModule), + typeof(IOTEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqliteModule) + )] + public class IOTEntityFrameworkCoreTestModule : AbpModule + { + private SqliteConnection _sqliteConnection; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureInMemorySqlite(context.Services); + } + + private void ConfigureInMemorySqlite(IServiceCollection services) + { + _sqliteConnection = CreateDatabaseAndGetConnection(); + + services.Configure(options => + { + options.Configure(context => + { + context.DbContextOptions.UseSqlite(_sqliteConnection); + }); + }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + _sqliteConnection.Dispose(); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new SqliteConnection("Data Source=:memory:"); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options; + + using (var context = new IOTDbContext(options)) + { + context.GetService().CreateTables(); + } + + return connection; + } + } +} diff --git a/test/JiShe.IOT.EntityFrameworkCore.Tests/GlobalUsings.cs b/test/JiShe.IOT.EntityFrameworkCore.Tests/GlobalUsings.cs new file mode 100644 index 0000000..9c9e9b2 --- /dev/null +++ b/test/JiShe.IOT.EntityFrameworkCore.Tests/GlobalUsings.cs @@ -0,0 +1,11 @@ +// Global using directives + +global using Microsoft.Data.Sqlite; +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.Infrastructure; +global using Microsoft.EntityFrameworkCore.Storage; +global using Microsoft.Extensions.DependencyInjection; +global using Volo.Abp; +global using Volo.Abp.EntityFrameworkCore; +global using Volo.Abp.EntityFrameworkCore.Sqlite; +global using Volo.Abp.Modularity; \ No newline at end of file diff --git a/test/JiShe.IOT.EntityFrameworkCore.Tests/JiShe.IOT.EntityFrameworkCore.Tests.csproj b/test/JiShe.IOT.EntityFrameworkCore.Tests/JiShe.IOT.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000..f6d2d4f --- /dev/null +++ b/test/JiShe.IOT.EntityFrameworkCore.Tests/JiShe.IOT.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,18 @@ + + + net9.0 + JiShe.IOT + false + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/JiShe.IOT.FreeSqlReppsitory.Tests/IOTFreeSqlRepositoryTestBase.cs b/test/JiShe.IOT.FreeSqlReppsitory.Tests/IOTFreeSqlRepositoryTestBase.cs new file mode 100644 index 0000000..6b8ca27 --- /dev/null +++ b/test/JiShe.IOT.FreeSqlReppsitory.Tests/IOTFreeSqlRepositoryTestBase.cs @@ -0,0 +1,18 @@ +using JiShe.IOT.FreeSqlReppsitory.Tests; +using JiShe.IOT.Localization; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.IOT +{ + public abstract class IOTFreeSqlRepositoryTestBase: IOTTestBase + { + public IOTFreeSqlRepositoryTestBase() + { + ServiceProvider.InitializeLocalization(); + } + } +} diff --git a/test/JiShe.IOT.FreeSqlReppsitory.Tests/IOTFreeSqlRepositoryTestModule.cs b/test/JiShe.IOT.FreeSqlReppsitory.Tests/IOTFreeSqlRepositoryTestModule.cs new file mode 100644 index 0000000..b8b5d6f --- /dev/null +++ b/test/JiShe.IOT.FreeSqlReppsitory.Tests/IOTFreeSqlRepositoryTestModule.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace JiShe.IOT.FreeSqlReppsitory.Tests; + +[DependsOn( + typeof(IOTTestBaseModule), + typeof(IOTFreeSqlModule) + )] + +public class IOTFreeSqlRepositoryTestModule: AbpModule +{ + + //public override void ConfigureServices(ServiceConfigurationContext context) + //{ + + + + // var configuration = context.Services.GetConfiguration(); + // var connectionString = configuration.GetConnectionString("Default"); + // var freeSql = new FreeSql.FreeSqlBuilder() + // .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10") + // .UseAutoSyncStructure(true) + // .Build(); + + // context.Services.AddSingleton(freeSql); + //} + +} \ No newline at end of file diff --git a/test/JiShe.IOT.FreeSqlReppsitory.Tests/JiShe.IOT.FreeSqlReppsitory.Tests.csproj b/test/JiShe.IOT.FreeSqlReppsitory.Tests/JiShe.IOT.FreeSqlReppsitory.Tests.csproj new file mode 100644 index 0000000..39cc0fd --- /dev/null +++ b/test/JiShe.IOT.FreeSqlReppsitory.Tests/JiShe.IOT.FreeSqlReppsitory.Tests.csproj @@ -0,0 +1,12 @@ + + + net7.0 + JiShe.IOT + false + + + + + + + diff --git a/test/JiShe.IOT.FreeSqlReppsitory.Tests/Users/UserFreeSqlBasicRepository_Tests.cs b/test/JiShe.IOT.FreeSqlReppsitory.Tests/Users/UserFreeSqlBasicRepository_Tests.cs new file mode 100644 index 0000000..77f57da --- /dev/null +++ b/test/JiShe.IOT.FreeSqlReppsitory.Tests/Users/UserFreeSqlBasicRepository_Tests.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace JiShe.IOT.Users +{ + + + public class UserFreeSqlBasicRepository_Tests: IOTFreeSqlRepositoryTestBase + { + //private readonly IUserFreeSqlBasicRepository _userFreeSqlBasicRepository; + //public UserFreeSqlBasicRepositoryTest() + //{ + // _userFreeSqlBasicRepository = GetRequiredService(); + //} + + [Fact] + public void Should_NotThrow_ListAsyncTest() + { + //var result = await _userFreeSqlBasicRepository.GetListAsync(); + var s = 1; + } + } + +} diff --git a/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs new file mode 100644 index 0000000..4e9a6c5 --- /dev/null +++ b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/ClientDemoService.cs @@ -0,0 +1,21 @@ +namespace JiShe.IOT.HttpApi.Client.ConsoleTestApp +{ + public class ClientDemoService : ITransientDependency + { + private readonly IProfileAppService _profileAppService; + + public ClientDemoService(IProfileAppService profileAppService) + { + _profileAppService = profileAppService; + } + + public async Task RunAsync() + { + var output = await _profileAppService.GetAsync(); + Console.WriteLine($"UserName : {output.UserName}"); + Console.WriteLine($"Email : {output.Email}"); + Console.WriteLine($"Name : {output.Name}"); + Console.WriteLine($"Surname : {output.Surname}"); + } + } +} \ No newline at end of file diff --git a/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs new file mode 100644 index 0000000..0c06f6f --- /dev/null +++ b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/ConsoleTestAppHostedService.cs @@ -0,0 +1,20 @@ +namespace JiShe.IOT.HttpApi.Client.ConsoleTestApp +{ + public class ConsoleTestAppHostedService : IHostedService + { + public async Task StartAsync(CancellationToken cancellationToken) + { + using (var application = AbpApplicationFactory.Create()) + { + application.Initialize(); + + var demo = application.ServiceProvider.GetRequiredService(); + await demo.RunAsync(); + + application.Shutdown(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + } +} diff --git a/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/GlobalUsings.cs b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/GlobalUsings.cs new file mode 100644 index 0000000..eaf034e --- /dev/null +++ b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/GlobalUsings.cs @@ -0,0 +1,14 @@ +// Global using directives + +global using System; +global using System.Threading; +global using System.Threading.Tasks; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Hosting; +global using Polly; +global using Volo.Abp; +global using Volo.Abp.Account; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.Http.Client; +global using Volo.Abp.Http.Client.IdentityModel; +global using Volo.Abp.Modularity; \ No newline at end of file diff --git a/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/IOTConsoleApiClientModule.cs b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/IOTConsoleApiClientModule.cs new file mode 100644 index 0000000..3951a6c --- /dev/null +++ b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/IOTConsoleApiClientModule.cs @@ -0,0 +1,22 @@ +namespace JiShe.IOT.HttpApi.Client.ConsoleTestApp +{ + [DependsOn( + typeof(IOTHttpApiClientModule), + typeof(AbpHttpClientIdentityModelModule) + )] + public class IOTConsoleApiClientModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.ProxyClientBuildActions.Add((remoteServiceName, clientBuilder) => + { + clientBuilder.AddTransientHttpErrorPolicy( + policyBuilder => policyBuilder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))) + ); + }); + }); + } + } +} diff --git a/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/JiShe.IOT.HttpApi.Client.ConsoleTestApp.csproj b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/JiShe.IOT.HttpApi.Client.ConsoleTestApp.csproj new file mode 100644 index 0000000..50bead6 --- /dev/null +++ b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/JiShe.IOT.HttpApi.Client.ConsoleTestApp.csproj @@ -0,0 +1,29 @@ + + + Exe + net9.0 + false + + + + + + + + + PreserveNewest + Always + + + + + + + + + + + + + + diff --git a/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/Program.cs b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/Program.cs new file mode 100644 index 0000000..6318742 --- /dev/null +++ b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/Program.cs @@ -0,0 +1,17 @@ +namespace JiShe.IOT.HttpApi.Client.ConsoleTestApp +{ + class Program + { + static async Task Main(string[] args) + { + await CreateHostBuilder(args).RunConsoleAsync(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + }); + } +} diff --git a/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/appsettings.json b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/appsettings.json new file mode 100644 index 0000000..664946d --- /dev/null +++ b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/appsettings.json @@ -0,0 +1,18 @@ +{ + "RemoteServices": { + "Default": { + "BaseUrl": "https://localhost:44315" + } + }, + "IdentityClients": { + "Default": { + "GrantType": "password", + "ClientId": "IOT_App", + "ClientSecret": "1q2w3e*", + "UserName": "admin", + "UserPassword": "1q2w3E*", + "Authority": "https://localhost:44354", + "Scope": "IOT" + } + } +} \ No newline at end of file diff --git a/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/test/JiShe.IOT.HttpApi.Client.ConsoleTestApp/appsettings.secrets.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/test/JiShe.IOT.TestBase/GlobalUsings.cs b/test/JiShe.IOT.TestBase/GlobalUsings.cs new file mode 100644 index 0000000..3af6751 --- /dev/null +++ b/test/JiShe.IOT.TestBase/GlobalUsings.cs @@ -0,0 +1,22 @@ +// Global using directives + +global using System; +global using System.Collections.Generic; +global using System.Security.Claims; +global using System.Threading.Tasks; +global using Microsoft.Extensions.DependencyInjection; +global using Volo.Abp; +global using Volo.Abp.Authorization; +global using Volo.Abp.Authorization.Permissions; +global using Volo.Abp.Autofac; +global using Volo.Abp.BackgroundJobs; +global using Volo.Abp.Data; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.Guids; +global using Volo.Abp.Modularity; +global using Volo.Abp.MultiTenancy; +global using Volo.Abp.PermissionManagement; +global using Volo.Abp.Security.Claims; +global using Volo.Abp.Testing; +global using Volo.Abp.Threading; +global using Volo.Abp.Uow; \ No newline at end of file diff --git a/test/JiShe.IOT.TestBase/IOTTestBase.cs b/test/JiShe.IOT.TestBase/IOTTestBase.cs new file mode 100644 index 0000000..8765232 --- /dev/null +++ b/test/JiShe.IOT.TestBase/IOTTestBase.cs @@ -0,0 +1,53 @@ +namespace JiShe.IOT +{ + /* All test classes are derived from this class, directly or indirectly. + */ + public abstract class IOTTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected virtual Task WithUnitOfWorkAsync(Func func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + await action(); + + await uow.CompleteAsync(); + } + } + } + + protected virtual Task WithUnitOfWorkAsync(Func> func) + { + return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); + } + + protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func) + { + using (var scope = ServiceProvider.CreateScope()) + { + var uowManager = scope.ServiceProvider.GetRequiredService(); + + using (var uow = uowManager.Begin(options)) + { + var result = await func(); + await uow.CompleteAsync(); + return result; + } + } + } + } +} diff --git a/test/JiShe.IOT.TestBase/IOTTestBaseModule.cs b/test/JiShe.IOT.TestBase/IOTTestBaseModule.cs new file mode 100644 index 0000000..8bf3faa --- /dev/null +++ b/test/JiShe.IOT.TestBase/IOTTestBaseModule.cs @@ -0,0 +1,41 @@ +namespace JiShe.IOT +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(IOTDomainModule) + )] + public class IOTTestBaseModule : AbpModule + { + + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + + context.Services.AddAlwaysAllowAuthorization(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); + } + } +} diff --git a/test/JiShe.IOT.TestBase/IOTTestDataSeedContributor.cs b/test/JiShe.IOT.TestBase/IOTTestDataSeedContributor.cs new file mode 100644 index 0000000..6577d45 --- /dev/null +++ b/test/JiShe.IOT.TestBase/IOTTestDataSeedContributor.cs @@ -0,0 +1,12 @@ +namespace JiShe.IOT +{ + public class IOTTestDataSeedContributor : IDataSeedContributor, ITransientDependency + { + public Task SeedAsync(DataSeedContext context) + { + /* Seed additional test data... */ + + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/test/JiShe.IOT.TestBase/JiShe.IOT.TestBase.csproj b/test/JiShe.IOT.TestBase/JiShe.IOT.TestBase.csproj new file mode 100644 index 0000000..533ef3f --- /dev/null +++ b/test/JiShe.IOT.TestBase/JiShe.IOT.TestBase.csproj @@ -0,0 +1,32 @@ + + + net9.0 + JiShe.IOT + false + + + + + + + + + + + + + + + + + + + + + true + PreserveNewest + PreserveNewest + + + + diff --git a/test/JiShe.IOT.TestBase/Security/FakeCurrentPrincipalAccessor.cs b/test/JiShe.IOT.TestBase/Security/FakeCurrentPrincipalAccessor.cs new file mode 100644 index 0000000..6656f24 --- /dev/null +++ b/test/JiShe.IOT.TestBase/Security/FakeCurrentPrincipalAccessor.cs @@ -0,0 +1,38 @@ +namespace JiShe.IOT.Security +{ + [Dependency(ReplaceServices = true)] + public class FakeCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor + { + protected override ClaimsPrincipal GetClaimsPrincipal() + { + return GetPrincipal(); + } + + private ClaimsPrincipal _principal; + + private ClaimsPrincipal GetPrincipal() + { + if (_principal == null) + { + lock (this) + { + if (_principal == null) + { + _principal = new ClaimsPrincipal( + new ClaimsIdentity( + new List + { + new Claim(AbpClaimTypes.UserId,"2e701e62-0953-4dd3-910b-dc6cc93ccb0d"), + new Claim(AbpClaimTypes.UserName,"admin"), + new Claim(AbpClaimTypes.Email,"admin@abp.io") + } + ) + ); + } + } + } + + return _principal; + } + } +} diff --git a/test/JiShe.IOT.TestBase/appsettings.json b/test/JiShe.IOT.TestBase/appsettings.json new file mode 100644 index 0000000..bd97896 --- /dev/null +++ b/test/JiShe.IOT.TestBase/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "Default": "Data Source=localhost;Database=JiSheIOTDB;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" + } +} \ No newline at end of file