From d8dc91f9c1fece5711e38edd1b1274cb9e579015 Mon Sep 17 00:00:00 2001 From: z8018 <1282578289@qq.com> Date: 星期四, 07 八月 2025 14:56:35 +0800 Subject: [PATCH] 激活部分以及后端管理 --- 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ApiAuthorizeFilter.cs | 117 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/MenuDTO.cs | 14 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/RepositoryBase.cs | 952 ++ 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/ModelValidate.cs | 229 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/UserPermissions.cs | 17 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/CustomAuthorizeFilter.cs | 20 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_DictionaryListService.cs | 14 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_RoleAuthService.cs | 14 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/AppSecret.cs | 29 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/MainDb.cs | 27 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ExportHelper.cs | 137 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IProductsService.cs | 19 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Role.tsv | 15 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Actions.cs | 16 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/PageDataOptions.cs | 65 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_RoleAuthService.cs | 19 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/MiddlewareHelpers.cs | 42 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/WIDESEA_Core.csproj | 35 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/anime.min.js | 33 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/HttpContextExtension.cs | 30 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/HostedService/SeedDataHostedService.cs | 71 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/CacheAttribute.cs | 20 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IRuntimeCodeService.cs | 17 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_RoleService.cs | 209 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ProductsService.cs | 137 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/CustomProfile.cs | 20 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/swg-login.html | 140 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_RoleController.cs | 64 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/QuartzLogger.cs | 117 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/ActivationCodeDTO.cs | 17 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/SqlSugarAop.cs | 126 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_User.cs | 84 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/ExceptionHandlerMiddleware.cs | 84 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/LoginInfo.cs | 15 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_LogService.cs | 14 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/ApiDoc/ByteHelper.cs | 24 代码管理/WIDESEA_ProductMgmtServer/.vs/TencentCopilotChatCurrentSession.json | 1 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/WIDESEA_IBasicInfoServices.csproj | 13 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ObjectExtension.cs | 89 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/style.css | 132 代码管理/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/config/applicationhost.config | 1021 ++ 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_DictionaryListController.cs | 17 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/IpLimitMiddleware.cs | 40 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/InitializationHostServiceSetup.cs | 28 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_TenantService.cs | 79 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Dictionary.tsv | 254 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/WIDESEA_ISystemServices.csproj | 14 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SwaggerSetup.cs | 132 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/TenantStatus.cs | 14 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Menu.tsv | 173 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/CorsSetup.cs | 56 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/HttpContextHelper.cs | 45 代码管理/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/CopilotIndices/17.14.734.62261/SemanticSymbols.db | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_TenantService.cs | 16 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/ActivationCodeController.cs | 32 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/VersionsService.cs | 20 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/RoleAuthor.cs | 14 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/Permissions.cs | 42 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/AllServicesMiddleware.cs | 72 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/HtmlElementType.cs | 32 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/InternalApp.cs | 47 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/DbSetup.cs | 32 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Common/WIDESEA_Common.csproj | 9 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IVersionsService.cs | 14 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/logo/favicon-32x32.png | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/EntityProperties.cs | 404 + 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/ServiceBase.cs | 852 ++ 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/CacheConst.cs | 94 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/site.js | 4 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/SequenceAttribute.cs | 30 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/IService.cs | 123 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/jquery-3.3.1.min.js | 2 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/WIDESEA_Model.csproj | 13 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/UnitOfWork.cs | 69 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/AppSettings.cs | 92 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_LogService.cs | 19 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/ApiLogMiddleware.cs | 144 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/ITenantEntity.cs | 21 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_DictionaryListService.cs | 19 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/VueDictionaryDTO.cs | 19 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_LogController.cs | 17 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/JwtTokenAuthMiddleware.cs | 94 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_RuntimeCode.cs | 59 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/WebResponseContent.cs | 64 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ConsoleHelper.cs | 57 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseIService.txt | 11 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseController.txt | 16 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/JwtHelper.cs | 127 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/HttpHelper.cs | 179 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_CharMapping.cs | 40 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ActivationCodeService.cs | 164 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/SqlDbTypeName.cs | 29 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/ServiceFunFilter.cs | 238 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/favicon.ico | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/BaseDBConfig.cs | 122 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/appsettings.json | 37 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SqlsugarSetup.cs | 160 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/AllOptionRegister.cs | 29 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/ActionDTO.cs | 16 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Properties/launchSettings.json | 31 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ExporterHeaderFilter.cs | 23 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/TenantUtil.cs | 127 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_Versions.cs | 65 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_UserController.cs | 174 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_RoleAuthController.cs | 17 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/AuthorizationSetup.cs | 88 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/DBContext.cs | 225 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_RoleAuth.tsv | 167 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/appsettings.Development.json | 8 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/logo.jpg.jpg | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/UseServiceDIAttribute.cs | 38 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/index.html | 188 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/MultiTenantAttribute.cs | 56 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/swaggerdoc.css | 109 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/LogLock.cs | 110 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/HttpRequestMiddleware.cs | 31 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/HttpContextSetup.cs | 30 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_DictionaryList.cs | 57 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/SecurityEncDecryptHelper.cs | 93 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_RoleService.cs | 23 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Role.cs | 54 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Log.cs | 80 代码管理/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/7c7e5e60-8670-43b4-ab23-b60ba11637cb.vsidx | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IActivationCodeService.cs | 16 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.csproj | 29 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/FrameSeed.cs | 582 + 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_User.tsv | 29 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/HttpContextUser/AspNetUser.cs | 282 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_MenuController.cs | 55 代码管理/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/a1a75bb8-01fc-457b-8a35-9aa191663ad9.vsidx | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseController/ApiBaseController.cs | 193 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/ModelValidateAttribute.cs | 72 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_Products.cs | 47 代码管理/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/9c3714cb-a523-4bd7-9919-13c7296da019.vsidx | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_TenantController.cs | 33 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/PageGridData.cs | 32 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_MenuService.cs | 32 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/ApiDoc/HtmlHelper.cs | 69 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/UtilConvert.cs | 559 + 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_DictionaryService.cs | 16 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/CodeGenerator/CodeGenertors.cs | 411 + 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseRepository.txt | 13 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/VuePage.txt | 50 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/IDependency.cs | 12 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/MD5Helper.cs | 101 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseService.txt | 16 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/MethodInfoExtensions.cs | 27 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Caches/MemoryCacheService.cs | 148 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/FileHelper.cs | 451 + 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/site.css | 71 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Tenant.cs | 57 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/ProductsController.cs | 43 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Dictionary.cs | 95 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/SwaggerMiddleware.cs | 61 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/DeviceInfoDTO.cs | 17 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/OperateTypeEnum.cs | 20 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_DictionaryList.tsv | 548 + 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/ApplicationSetup.cs | 35 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ActionExecuteFilter.cs | 37 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Program.cs | 144 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/UnitOfWorkManage.cs | 208 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/App.cs | 283 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/ActivationDTO.cs | 19 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Caches/ICacheService.cs | 64 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/TenantConst.cs | 13 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_RoleAuth.cs | 48 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/AutofacModuleRegister.cs | 86 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_ActivationCode.cs | 70 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/WIDESEA_BasicInfoServices.csproj | 13 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/DBSeed.cs | 354 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/Models/IBaseHistoryEntity.cs | 37 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/Logger.cs | 310 代码管理/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/CopilotIndices/17.14.734.62261/CodeChunks.db | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/LambdaExtensions.cs | 183 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/VierificationCode.cs | 122 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseIRepository.txt | 10 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/WebSocketSetup.cs | 29 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/AutofacPropertityModuleReg.cs | 17 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/SaveModel.cs | 30 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/HttpContextUser/IUser.cs | 80 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.http | 15 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/LinqExpressionType.cs | 21 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/RepositorySetting.cs | 53 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/RequestLogModel.cs | 13 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_UserService.cs | 22 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SwaggerContextExtension.cs | 116 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/http.html | 2337 ++++++ 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_DTO/WIDESEA_DTO.csproj | 13 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_UserService.cs | 186 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/AutoMapperSetup.cs | 20 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/IRepository.cs | 416 + 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Menu.cs | 81 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/IUnitOfWorkManage.cs | 54 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/RuntimeExtension.cs | 113 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/RouterInOutType.cs | 24 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/SwaggerAuthMiddleware.cs | 86 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/RuntimeCodeController.cs | 31 代码管理/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/1070cb09-ea00-48d7-aa5a-981caeb74f04.vsidx | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Department.cs | 57 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/EnumHelper.cs | 118 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.sln | 87 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_DictionaryController.cs | 119 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/MemoryCacheSetup.cs | 28 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/Models/BaseEntity.cs | 82 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_MenuService.cs | 361 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/CacheAOP.cs | 185 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/IpPolicyRateLimitSetup.cs | 43 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/swaggerdoc.js | 139 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_DictionaryService.cs | 126 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/UserPermissions.cs | 17 代码管理/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/bc990f7e-fcec-42af-9567-e682197ee62b.vsidx | 0 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/LogAOP.cs | 313 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/RuntimeCodeService.cs | 135 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/ConfigurableOptions.cs | 66 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/RoleNodes.cs | 15 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/MiniProfilerSetup.cs | 33 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/ErrorMsgConst.cs | 15 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/GlobalExceptionsFilter.cs | 101 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/WIDESEA_SystemServices.csproj | 13 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/AuthorizationResponse.cs | 57 代码管理/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/IConfigurableOptions.cs | 12 221 files changed, 22,701 insertions(+), 0 deletions(-) diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/TencentCopilotChatCurrentSession.json" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/TencentCopilotChatCurrentSession.json" new file mode 100644 index 0000000..ae1a96e --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/TencentCopilotChatCurrentSession.json" @@ -0,0 +1 @@ +{"_v":"v1","data":{"sessionId":"01987cf2b131711cb076a0b51206640b","sessionName":"","messages":[{"role":"user","content":"杩欓噷鐨勫簲鐢ㄤ綅缃亸绉荤畻娉曟湁闂锛屽鑷存暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀","isTips":null,"cost":0,"parser":{"nodes":[{"type":"line","content":"杩欓噷鐨勫簲鐢ㄤ綅缃亸绉荤畻娉曟湁闂锛屽鑷存暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀","contentId":1759870795,"children":[],"parent":null,"settled":false,"xmlData":{}}],"parserState":{"line":0,"column":32,"offset":33,"metadata":false,"buffer":"","closing":false,"currentParent":null,"moveCursor":true,"tagBuffer":"","isCollectingTag":false},"content":"杩欓噷鐨勫簲鐢ㄤ綅缃亸绉荤畻娉曟湁闂锛屽鑷存暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀","columns":[]},"source":null,"error":null,"id":null,"localReferences":[{"uri":{"scheme":"file","authority":"","path":"file:///E:/0.椤圭洰闆�/瀹芥捣/SMTFangCuoPDA/浠g爜绠$悊/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ActivationCodeService.cs","query":"","fragment":""},"range":[{"character":7,"line":21},{"character":8,"line":50}],"isRequestStage":true}],"references":null,"followup":null,"topic":"","score":null,"command":"","changeToOptimize":null,"button":null,"knowledge":null,"knowledgeReferences":null,"knowledgeStatus":null,"variables":[],"selectedRange":null,"actions":null,"selectedRanges":[],"createdAt":1754443019231},{"role":"assistant","content":"<think>\n鎴戜滑姝e湪鏌ョ湅鐨勪唬鐮佺墖娈垫槸GenerateActivationCode鏂规硶銆傜敤鎴锋寚鍑衡�滃簲鐢ㄤ綅缃亸绉荤畻娉曟湁闂锛屽鑷存暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濄�俓n 闂鍒嗘瀽锛歕n 褰撳墠浠g爜涓紝鎴戜滑鍒涘缓浜嗕竴涓粨鏋滄暟缁刞result`锛岄暱搴︿负`baseRandom.Length`銆傜劧鍚庨亶鍘哷baseRandom`鐨勬瘡涓瓧绗︼紙璺宠繃'-'锛夛紝鏍规嵁鏄犲皠瀛楀吀寰楀埌杈撳嚭瀛楃鍜屽亸绉婚噺銆俓n 鐒跺悗璁$畻鏂颁綅缃細`newPosition = (i + mapping.shift) % length`锛屽苟灏嗘槧灏勫悗鐨勫瓧绗︼紙鍙兘缁忚繃鐗规畩鍙樻崲锛夋斁鍏ョ粨鏋滄暟缁勭殑`newPosition`浣嶇疆銆俓n\n 闂鍦ㄤ簬锛氬鏋滀袱涓笉鍚岀殑瀛楃璁$畻鍑虹殑`newPosition`鐩稿悓锛岄偅涔堝悗鏀惧叆鐨勫瓧绗︿細瑕嗙洊鍓嶄竴涓瓧绗︺�傚悓鏃讹紝濡傛灉鏌愪釜浣嶇疆娌℃湁琚换浣曞瓧绗﹁祴鍊硷紝閭d箞璇ヤ綅缃皢淇濇寔鍒濆鍊硷紙鍗�'\\0'锛岀┖瀛楃锛夈�傝繖浼氬鑷存渶缁堢敓鎴愮殑瀛楃涓蹭腑鏈変簺浣嶇疆鏄┖瀛楃锛堝嵆娌℃湁琚浛鎹級锛屼粠鑰屼骇鐢熼敊璇�俓n\n 瑙e喅鏂规锛歕n 鎴戜滑闇�瑕佺‘淇濇瘡涓綅缃兘琚纭祴鍊硷紝骞朵笖涓嶈兘鏈夎鐩栵紙闄ら潪璁捐濡傛锛屼絾杩欓噷鏄剧劧涓嶆槸锛夈�備絾鏄紝鏍规嵁闂鎻忚堪锛屼技涔庢湁浜涗綅缃病鏈夎璧嬪�硷紝瀵艰嚧缁撴灉瀛楃涓蹭腑鏈夌┖瀛楃銆俓n\n 鍙︿竴绉嶆�濊矾锛氭垜浠笉搴旇鐩存帴鏍规嵁鍋忕Щ閲忓皢瀛楃鏀惧叆鏂颁綅缃紝鍥犱负杩欐牱浼氬鑷村啿绐佸拰鏈祴鍊肩殑浣嶇疆銆傛垜浠彲浠ュ厛瀵规瘡涓瓧绗﹁繘琛屾槧灏勶紙寰楀埌鏂扮殑瀛楃锛夛紝鐒跺悗鏍规嵁鍋忕Щ閲忚皟鏁翠綅缃紝浣嗚繖鏍疯皟鏁翠綅缃彲鑳戒細寰堝鏉傘�俓n\n 瀹為檯涓婏紝鍘熶唬鐮佺殑閫昏緫鏄細瀵逛簬杈撳叆瀛楃涓蹭腑鐨勬瘡涓瓧绗︼紙璺宠繃'-'锛夛紝鎴戜滑灏嗗叾鏄犲皠涓轰竴涓柊鐨勫瓧绗︼紝鐒跺悗鏍规嵁鍋忕Щ閲忓喅瀹氳繖涓柊瀛楃鍦ㄧ粨鏋滃瓧绗︿覆涓殑浣嶇疆銆備絾鏄紝鐢变簬杈撳叆瀛楃涓蹭腑姣忎釜瀛楃鐨勪綅缃甶鏄敮涓�鐨勶紙闄や簡璺宠繃'-'锛屼絾璺宠繃浼氬鑷磋緭鍏ュ瓧绗︿覆涓湁鏁堝瓧绗︽暟灏戜簬闀垮害锛岃�岀粨鏋滄暟缁勯暱搴﹀嵈鏄師濮嬪瓧绗︿覆闀垮害锛屽寘鎷偅浜涜璺宠繃鐨勪綅缃紵娉ㄦ剰锛岃繖閲岃烦杩囩殑瀛楃鏄�'-'锛屼絾寰幆涓亣鍒�'-'鏃朵娇鐢ㄤ簡continue锛屾墍浠ヤ笉浼氬鐞嗚瀛楃锛屼篃涓嶄細鍦ㄧ粨鏋滄暟缁勪腑鏀剧疆浠讳綍涓滆タ銆傝�屼笖锛屽師濮嬪瓧绗︿覆涓彲鑳藉寘鍚涓�'-'锛屼絾宸茬粡琚浛鎹负绌猴紝鎵�浠ュ疄闄呬笂baseRandom宸茬粡鍘婚櫎浜�'-'銆傛墍浠ワ紝鍦ㄥ惊鐜箣鍓嶏紝baseRandom宸茬粡绉婚櫎浜嗘墍鏈夌殑'-'锛屽洜姝ゅ惊鐜腑涓嶄細閬囧埌'-'銆傛墍浠ワ紝寰幆涓笉浼氳烦杩囦换浣曞瓧绗︺�傞偅涔堬紝姣忎釜瀛楃閮戒細琚鐞嗐�俓n\n 浣嗘槸锛岄棶棰樺嚭鍦ㄥ亸绉诲悗鐨勪綅缃彲鑳藉啿绐侊紝鎴栬�呭亸绉诲悗鏌愪簺浣嶇疆娌℃湁琚祴鍊硷紵瀹為檯涓婏紝鐢变簬鎴戜滑閬嶅巻姣忎釜浣嶇疆锛�0鍒發ength-1锛夛紝骞朵笖姣忎釜浣嶇疆閮戒細璁$畻涓�涓柊浣嶇疆锛坣ewPosition锛夛紝鐒跺悗璧嬪�笺�傜敱浜巌浠�0鍒發ength-1锛岃�宯ewPosition = (i + shift) % length锛岃繖涓�间篃鍦�0鍒發ength-1涔嬮棿銆備絾鏄紝涓嶅悓鐨刬鍙兘浼氬緱鍒扮浉鍚岀殑newPosition锛堝綋鍋忕Щ閲忎笉鍚屾椂锛屼絾鍚屼竴涓亸绉婚噺锛熸敞鎰忔瘡涓瓧绗︾殑鍋忕Щ閲忓彲鑳戒笉鍚岋紝鍥犱负mapping.shift鏄粠瀛楀吀涓彇鍑虹殑锛屾瘡涓瓧绗﹀搴旂殑shift鍙兘涓嶅悓锛夈�傚洜姝わ紝濡傛灉涓や釜涓嶅悓鐨刬璁$畻鍑虹殑newPosition鐩稿悓锛岄偅涔堝悗璧嬪�肩殑浼氳鐩栧墠闈㈢殑銆俓n\n 鍙﹀锛岀敱浜庢垜浠娇鐢ㄧ殑鏄悓涓�涓暟缁勶紝鍒濆鏃舵暟缁勭殑姣忎釜浣嶇疆閮芥槸'\\0'锛堢┖瀛楃锛夛紝濡傛灉鏌愪釜newPosition鍙璧嬪�间竴娆★紝閭d箞娌℃湁闂锛涘鏋滀竴娆¢兘娌℃湁琚祴鍊硷紝閭d箞璇ヤ綅缃氨鏄┖瀛楃锛堜絾鐞嗚涓婃瘡涓猧閮戒細璧嬪�间竴娆★紝鍥犱负姣忎釜i閮戒細璁$畻涓�涓猲ewPosition骞惰祴鍊硷紝鎵�浠ユ瘡涓綅缃嚦灏戜細琚祴鍊间竴娆★紵涓嶅锛屽洜涓簄ewPosition鐨勫彇鍊艰寖鍥存槸0鍒發ength-1锛屽苟涓旀瘡涓猧閮戒細璧嬪�间竴娆★紝鎵�浠ユ瘡涓綅缃兘浼氳璧嬪�硷紵浣嗘槸锛屽鏋滀袱涓猧鎸囧悜鍚屼竴涓猲ewPosition锛岄偅涔堝叾涓竴涓祴鍊间細琚鐩栵紝鑰屽彟涓�涓祴鍊间細淇濈暀锛岃繖鏍锋瘡涓綅缃繕鏄細琚祴鍊硷紙鍙笉杩囧彲鑳借澶氭璧嬪�硷紝鏈�鍚庝竴娆¤鐩栵級銆傛墍浠ワ紝姣忎釜浣嶇疆閮戒細鏈夊�硷紝涓嶄細鍑虹幇绌哄瓧绗︺�俓n\n 閭d箞涓轰粈涔堢敤鎴疯鈥滀笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濓紵鍙兘鏄寚缁撴灉瀛楃涓蹭腑鍑虹幇浜嗗師濮嬪瓧绗︼紵鎴栬�呭嚭鐜颁簡绌哄瓧绗︼紵\n\n 閲嶆柊瀹¤锛氬湪寰幆涓紝鎴戜滑璺宠繃浜�'-'锛屼絾鍓嶉潰宸茬粡灏哹aseRandom涓殑'-'绉婚櫎浜嗭紝鎵�浠ュ惊鐜腑涓嶄細閬囧埌'-'锛屽洜姝や笉浼氳烦杩囥�傛墍浠ユ瘡涓瓧绗﹂兘浼氳澶勭悊銆俓n\n 浣嗘槸锛屽鏋滃師濮嬪瓧绗︿覆涓笉鍖呭惈'-'锛岄偅涔坆aseRandom灏辨槸鍘熷瀛楃涓层�傚惊鐜腑姣忎釜瀛楃閮戒細琚鐞嗭紝姣忎釜浣嶇疆i閮戒細璁$畻涓�涓猲ewPosition锛岀劧鍚庤祴鍊笺�傛墍浠ョ粨鏋滄暟缁勭殑姣忎釜浣嶇疆閮戒細琚祴鍊硷紙鍥犱负newPosition瑕嗙洊浜�0鍒發ength-1锛夛紝鎵�浠ヤ笉浼氭湁绌哄瓧绗︺�俓n\n 閭d箞闂鍙兘鍑哄湪鍋忕Щ閲忓鑷寸殑浣嶇疆鍐茬獊锛熶緥濡傦紝涓や釜涓嶅悓鐨勫瓧绗﹁鏄犲皠鍒颁簡鍚屼竴涓綅缃紝閭d箞鍚庝竴涓瓧绗︿細瑕嗙洊鍓嶄竴涓紝瀵艰嚧鍓嶄竴涓瓧绗︿涪澶便�傝繖鏍凤紝缁撴灉瀛楃涓蹭腑灏变細涓㈠け涓�浜涘瓧绗︼紝鑰屽嚭鐜伴噸澶嶇殑瀛楃锛堝悗涓�涓鐩栧墠涓�涓紝浣嗗悗涓�涓瓧绗﹁姝g‘鏀剧疆锛屽墠涓�涓瑕嗙洊浜嗭級銆傝繖鏍凤紝缁撴灉瀛楃涓茬殑闀垮害铏界劧杩樻槸length锛屼絾鍙兘缂哄皯浜嗗師濮嬪瓧绗︿覆涓殑鏌愪簺瀛楃锛堣瑕嗙洊浜嗭級锛岃�屽鍑轰簡閲嶅鐨勫瓧绗︼紙瑕嗙洊鍒汉鐨勫瓧绗︼級銆俓n\n 鍥犳锛屾垜浠渶瑕侀伩鍏嶈鐩栥�傚浣曢伩鍏嶏紵鎴戜滑鍙互鍏堝垱寤轰竴涓拰鍘熷瀛楃涓茬瓑闀跨殑瀛楃鏁扮粍锛岀劧鍚庡垵濮嬪寲姣忎釜浣嶇疆涓轰竴涓粯璁ゅ�硷紙姣斿绌烘牸鎴栬�呬竴涓壒娈婂瓧绗︼級锛岀劧鍚庤祴鍊兼椂濡傛灉鍙戠幇鐩爣浣嶇疆宸茬粡琚崰鐢紝鍒欓噰鍙栨煇绉嶅啿绐佽В鍐崇瓥鐣ワ紙姣斿绾挎�ф帰娴嬶級锛熶絾鏄紝杩欐牱鍙兘浼氭敼鍙樺瓧绗︾殑椤哄簭锛岃�屼笖鍐茬獊瑙e喅绛栫暐鍙兘浼氬鏉傘�俓n\n 鎴栬�咃紝鎴戜滑鏀瑰彉鎬濊矾锛氭垜浠笉瀵瑰瓧绗﹁繘琛屼綅缃亸绉伙紝鑰屾槸鍏堝姣忎釜瀛楃杩涜鏄犲皠锛堝緱鍒颁竴涓柊鐨勫瓧绗︼級锛岀劧鍚庢牴鎹亸绉婚噺璋冩暣瀛楃鐨勯『搴忋�備篃灏辨槸璇达紝鎴戜滑鍙互鍏堝緱鍒颁竴涓瓧绗﹀簭鍒楋紙鏄犲皠鍚庣殑瀛楃搴忓垪锛夛紝鐒跺悗瀵硅繖涓簭鍒楄繘琛岄噸鎺掞紙鎸夌収鍋忕Щ瑙勫垯锛夈�俓n\n 鍏蜂綋姝ラ锛歕n 1. 鍒涘缓涓�涓垪琛紙鎴栨暟缁勶級鐢ㄤ簬瀛樻斁鏄犲皠鍚庣殑瀛楃锛堝寘鎷壒娈婂彉鎹級銆俓n 2. 閬嶅巻baseRandom鐨勬瘡涓瓧绗︼紝寰楀埌鏄犲皠鍚庣殑瀛楃锛堝彲鑳藉簲鐢ㄧ壒娈婂彉鎹級锛屽苟鏀惧叆涓�涓复鏃舵暟缁勶紙鎸夊師濮嬮『搴忥級銆俓n 3. 鐒跺悗锛屽垱寤轰竴涓柊鐨勭粨鏋滄暟缁勶紝闀垮害鍜屼复鏃舵暟缁勭浉鍚屻�俓n 4. 閬嶅巻涓存椂鏁扮粍锛屽浜庣i涓厓绱狅紝璁$畻瀹冨簲璇ユ斁缃殑浣嶇疆锛歯ewPosition = (i + shift) % length锛岀劧鍚庡皢璇ュ厓绱犳斁鍏ョ粨鏋滄暟缁勭殑newPosition浣嶇疆銆俓n\n 浣嗘槸锛岃繖鏍疯繕鏄細鏈夊啿绐侊紒鍥犱负鍚屼竴涓綅缃彲鑳借澶氫釜鍏冪礌瑕佹眰鏀惧叆銆俓n\n 鍙︿竴绉嶆柟娉曪細鎴戜滑涓嶆槸灏嗘瘡涓瓧绗︾嫭绔嬪湴鏀惧叆鏂颁綅缃紝鑰屾槸瀵规暣涓簭鍒楄繘琛岀Щ浣嶃�備絾鏄紝姣忎釜瀛楃鐨勭Щ浣嶉噺鍙兘涓嶅悓锛屾墍浠ヤ笉鑳界畝鍗曞湴鏁翠綋绉讳綅銆俓n\n 鍥犳锛屾垜浠渶瑕佷竴涓腑闂寸粨鏋勬潵璁板綍姣忎釜瀛楃鐨勫師濮嬩綅缃拰瀹冨簲璇ュ幓鐨勪綅缃紝鐒跺悗鎸夌収浣嶇疆璋冩暣椤哄簭銆備絾鏄紝鐢变簬姣忎釜瀛楃鐨勭Щ浣嶉噺涓嶅悓锛屾墍浠ユ瘡涓瓧绗︾殑鐩爣浣嶇疆鐙珛璁$畻銆俓n\n 涓轰簡閬垮厤鍐茬獊锛屾垜浠彲浠ヤ娇鐢ㄤ竴涓垪琛紙鎴栨暟缁勶級鏉ュ瓨鍌ㄦ瘡涓綅缃簲璇ユ斁缃殑瀛楃锛屼絾鏄厑璁镐竴涓綅缃湁澶氫釜瀛楃锛熶笉琛岋紝鍥犱负涓�涓綅缃彧鑳芥斁涓�涓瓧绗︺�俓n\n 鎵�浠ワ紝鎴戜滑鍙兘闇�瑕佹敼鍙樿璁★細浣嶇疆鍋忕Щ绠楁硶涓嶅簲璇ョ嫭绔嬪湴瀵规瘡涓瓧绗﹁繘琛岋紝鑰屽簲璇ュ熀浜庢暣涓瓧绗︿覆鐨勫彉鎹€�傛垨鑰咃紝鎴戜滑鏀惧純浣嶇疆鍋忕Щ锛岄噰鐢ㄥ叾浠栨柟寮忋�俓n\n 浣嗘槸锛岀敤鎴疯姹備慨澶嶉棶棰橈紝鑰屼笉鏄敼鍙樼畻娉曘�傛墍浠ワ紝鎴戜滑鍙兘闇�瑕佷竴涓啿绐佽В鍐虫満鍒躲�俓n\n 鐒惰�岋紝鍘熻璁℃剰鍥惧彲鑳芥槸锛氭瘡涓瓧绗︽牴鎹叾浣嶇疆鍜岃嚜韬殑shift鍊硷紝绉诲姩鍒版柊鐨勪綅缃�傚鏋滀袱涓瓧绗︾Щ鍔ㄥ埌鍚屼竴涓綅缃紝閭d箞鍚庡鐞嗙殑瀛楃浼氳鐩栧厛澶勭悊鐨勫瓧绗︼紙鍥犱负寰幆椤哄簭鏄粠0鍒發ength-1锛夈�傛墍浠ワ紝鍚庡鐞嗙殑瀛楃浼氳鐩栧厛澶勭悊鐨勫瓧绗︺�傝繖鍙兘鏄璁$己闄枫�俓n\n 濡備綍淇锛熸垜浠彲浠ヨ姣忎釜瀛楃鍦ㄧЩ鍔ㄦ椂锛屽鏋滅洰鏍囦綅缃凡缁忚鍗犵敤锛屽垯瀵绘壘涓嬩竴涓┖浣嶇疆锛堢嚎鎬ф帰娴嬶級銆備絾鏄紝杩欐牱鍙兘浼氭敼鍙樺瓧绗︾殑鐩稿椤哄簭锛岃�屼笖鍙兘浼氬鍔犺绠楅噺銆俓n\n 姝ラ锛歕n 1. 鍒濆鍖栫粨鏋滄暟缁勶紝姣忎釜浣嶇疆涓�'\\0'锛堣〃绀虹┖锛夈�俓n 2. 閬嶅巻姣忎釜瀛楃锛堟寜椤哄簭锛夛細\n 璁$畻newPosition = (i + mapping.shift) % length\n 濡傛灉缁撴灉鏁扮粍鐨刵ewPosition浣嶇疆涓虹┖锛屽垯鏀惧叆銆俓n 濡傛灉涓嶄负绌猴紝鍒欎粠newPosition寮�濮嬪悜鍚庡鎵撅紙寰幆锛夌洿鍒版壘鍒颁竴涓┖浣嶇疆锛堟敞鎰忓彇妯★級锛岀劧鍚庢斁鍏ャ�俓n 3. 杩欐牱锛屾瘡涓瓧绗﹂兘浼氳鏀惧叆锛屼笖涓嶄細瑕嗙洊銆俓n\n 浣嗘槸锛岃繖鏍峰彲鑳戒細瀵艰嚧鏌愪簺瀛楃琚斁鍦ㄨ窛绂荤洰鏍囦綅缃緝杩滅殑鍦版柟锛岃�屼笖椤哄簭鍙兘浼氳鎵撲贡锛堜絾鑷冲皯姣忎釜浣嶇疆閮芥湁瀛楃锛屼笖涓嶄細瑕嗙洊锛夈�俓n\n 浣嗘槸锛岃繖鏍蜂慨鏀瑰悗锛屽瓧绗︾殑浣嶇疆涓嶄粎鍙栧喅浜庡師濮嬩綅缃拰shift锛岃繕鍙栧喅浜庡啿绐佽В鍐崇殑鎯呭喌銆傝�屼笖锛屽鏋滄暟缁勬弧浜嗭紝鎴戜滑涓�瀹氳兘鎵惧埌绌轰綅鍚楋紵鐢变簬鎴戜滑閬嶅巻姣忎釜瀛楃锛屾瘡涓瓧绗﹂兘闇�瑕佹斁缃竴娆★紝鑰屾暟缁勯暱搴︽濂芥槸瀛楃涓暟锛屾墍浠ヤ竴瀹氬彲浠ユ壘鍒扮┖浣嶏紙鍥犱负鎬诲叡鏈塴ength涓綅缃紝鎴戜滑瑕佹斁length涓瓧绗︼紝涓斿啿绐佹椂鎴戜滑绾挎�ф帰娴嬬洿鍒版壘鍒扮┖浣嶏紝鎵�浠ユ渶缁堟瘡涓瓧绗﹂兘浼氳鏀剧疆锛屼笖涓嶄細瑕嗙洊锛夈�俓n\n 浣嗘槸锛岀嚎鎬ф帰娴嬪彲鑳戒細瀵艰嚧鎬ц兘闂锛堝鏋滃啿绐佸锛岄渶瑕侀亶鍘嗗緢澶氫綅缃級锛屼絾length涓嶄細澶ぇ锛堟縺娲荤爜涓�鑸笉浼氬お闀匡級锛屾墍浠ュ彲浠ユ帴鍙椼�俓n\n 淇敼浠g爜锛歕n\n 鎴戜滑淇敼寰幆閮ㄥ垎锛歕n\n 鍘熶唬鐮侊細\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n // 宸茬粡绉婚櫎浜�'-'锛屾墍浠ヤ笉闇�瑕佸垽鏂烦杩嘰n if (!mappingDict.TryGetValue(current, out var mapping))\n throw new InvalidOperationException($\"鏃犳晥瀛楃: {current}\");\n\n int newPosition = (i + mapping.shift) % length;\n char mappedChar = (i % 5 == 4) ? ApplySpecialTransform(mapping.output, i) : mapping.output;\n\n result[newPosition] = mappedChar;\n }\n\n 淇敼涓猴細\n\n // 鍒濆鍖栫粨鏋滄暟缁勶紝鐢�'\\0'琛ㄧず绌轰綅\n char[] result = new char[length];\n // 鎴戜滑涓嶉渶瑕佹樉寮忚祴鍊间负'\\0'锛屽洜涓簄ew char鏁扮粍榛樿灏辨槸'\\0'\n\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n if (!mappingDict.TryGetValue(current, out var mapping))\n throw new InvalidOperationException($\"鏃犳晥瀛楃: {current}\");\n\n char mappedChar = (i % 5 == 4) ? ApplySpecialTransform(mapping.output, i) : mapping.output;\n\n int newPosition = (i + mapping.shift) % length;\n\n // 濡傛灉鐩爣浣嶇疆宸茬粡琚崰鐢紝鍒欏鎵句笅涓�涓┖浣嶇疆锛堢嚎鎬ф帰娴嬶級\n while (result[newPosition] != '\\0')\n {\n newPosition = (newPosition + 1) % length; // 鍚戝悗绉诲姩涓�浣嶏紝濡傛灉鍒版湯灏惧垯鍥炲埌寮�澶碶n }\n result[newPosition] = mappedChar;\n }\n\n 杩欐牱锛屽鏋滆绠楀嚭鐨勪綅缃凡缁忚鍗犵敤锛屾垜浠氨鍚戝悗涓�涓竴涓壘锛岀洿鍒版壘鍒扮┖浣嶇疆銆俓n\n 浣嗘槸锛岃繖鏍蜂慨鏀瑰悗锛屽瓧绗︾殑浣嶇疆鍙兘浼氬洜涓哄啿绐佽�屾敼鍙橈紝浣嗚嚦灏戜繚璇佷簡姣忎釜浣嶇疆閮芥湁瀛楃锛屼笖涓嶄細瑕嗙洊銆俓n\n 浣嗘槸锛岀敤鎴风殑闂鎻忚堪鏄�滄暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濓紝鍙兘鏄寚缁撴灉鏁扮粍涓湁浣嶇疆娌℃湁琚祴鍊硷紙鍗宠繕鏄垵濮嬪��'\\0'锛夈�傛垜浠笂闈㈢殑淇敼淇濊瘉浜嗘瘡涓綅缃兘浼氳璧嬪�硷紙鍥犱负鎴戜滑鏀剧疆浜唋ength涓瓧绗︼紝涓旈�氳繃绾挎�ф帰娴嬮伩鍏嶄簡鍐茬獊锛屾墍浠ユ瘡涓綅缃兘浼氳璧嬪�间竴娆★級銆傛墍浠ワ紝杩欎釜淇敼搴旇鑳借В鍐抽棶棰樸�俓n\n 浣嗘槸锛屾垜浠篃瑕佹敞鎰忥紝绾挎�ф帰娴嬪彲鑳戒細瀵艰嚧瀛楃鐨勯『搴忎笌鍘熷璁捐鎰忓浘鏈夊亸宸紙鍥犱负鍐茬獊鏃跺瓧绗﹁鍚庣Щ浜嗭級銆傚師濮嬭璁℃剰鍥惧彲鑳芥槸姣忎釜瀛楃涓ユ牸鍦版斁鍦�(i+shift)%length鐨勪綅缃紝鍗充娇瑕嗙洊涔熶笉绠★紙浣嗚鐩栦細瀵艰嚧鏁版嵁涓㈠け锛夈�傜幇鍦紝鎴戜滑閫氳繃绾挎�ф帰娴嬮伩鍏嶄簡瑕嗙洊锛屼絾浣嶇疆鍙戠敓浜嗗彉鍖栥�俓n\n 鍙﹀锛屾垜浠繕闇�瑕佽�冭檻锛氬鏋滃師濮嬪瓧绗︿覆涓湁閲嶅瀛楃锛岄偅涔堟槧灏勫悗鐨勫瓧绗︿篃鍙兘閲嶅锛岃繖娌″叧绯伙紝鍥犱负姣忎釜瀛楃閮芥槸鐙珛澶勭悊鐨勩�俓n\n 鍥犳锛屾垜浠寜鐓т笂杩版�濊矾淇敼浠g爜銆俓n\n 娉ㄦ剰锛氱敱浜庢垜浠慨鏀逛簡浣嶇疆鍒嗛厤绠楁硶锛屽彲鑳戒細褰卞搷婵�娲荤爜鐨勭敓鎴愯鍒欍�備絾鐢ㄦ埛瑕佹眰淇瑕嗙洊鍜岀┖浣嶇殑闂锛屾墍浠ヨ繖鏄繀瑕佺殑銆俓n\n 淇敼鍚庣殑浠g爜锛歕n\n 鎴戜滑灏嗗惊鐜唴鐨勮祴鍊兼敼涓轰娇鐢ㄧ嚎鎬ф帰娴嬭В鍐冲啿绐併�俓n\n 浣嗘槸锛屾垜浠繕闇�瑕佹敞鎰忥細鍘熷浠g爜涓紝濡傛灉閬囧埌鐩稿悓鐨勪綅缃紝鍚庡鐞嗙殑瀛楃浼氳鐩栧厛澶勭悊鐨勫瓧绗︺�傜幇鍦紝鎴戜滑璁╁悗澶勭悊鐨勫瓧绗﹀悜鍚庡鎵剧┖浣嶏紝杩欐牱鍏堝鐞嗙殑瀛楃浼氬崰鎹畠璁$畻鐨勪綅缃紝鍚庡鐞嗙殑瀛楃濡傛灉鍐茬獊灏卞悗绉汇�傝繖鏍凤紝缁撴灉瀛楃涓蹭腑瀛楃鐨勯『搴忓彲鑳戒細涓庡師濮嬭璁℃湁杈冨ぇ涓嶅悓锛堢壒鍒槸褰撳啿绐佽緝澶氭椂锛夈�俓n\n 濡傛灉鐢ㄦ埛甯屾湜淇濇寔鍘熷璁捐鎰忓浘锛堝嵆姣忎釜瀛楃鐨勪綅缃敱(i+shift)%length鍞竴纭畾锛屼笉鍏佽鍐茬獊锛夛紝閭d箞鎴戜滑蹇呴』纭繚姣忎釜瀛楃鐨�(i+shift)%length閮芥槸鍞竴鐨勩�備絾杩欏緢闅句繚璇侊紝鍥犱负shift鏄瘡涓瓧绗﹁嚜宸卞喅瀹氱殑锛岃�宨鏄繛缁殑锛屾墍浠ュ綋涓や釜瀛楃鐨�(i1+shift1) % length 绛変簬 (i2+shift2) % length鏃讹紝鍐茬獊灏变細鍙戠敓銆俓n\n 鎵�浠ワ紝鎴戜滑鍙兘閫氳繃鍐茬獊瑙e喅鏈哄埗鏉ラ伩鍏嶈鐩栥�俓n\n 鍥犳锛屾垜浠噰鐢ㄧ嚎鎬ф帰娴嬨�俓n\n 淇敼鍚庣殑浠g爜锛歕n\n 娉ㄦ剰锛氭垜浠笉闇�瑕佹敼鍙樼壒娈婂彉鎹㈢殑閮ㄥ垎锛屽彧闇�瑕佹敼鍙樻斁缃瓧绗︾殑閫昏緫銆俓n\n 鎴戜滑杈撳嚭淇敼鍚庣殑鏁翠釜鏂规硶銆俓n\n 鍙﹀锛岀敤鎴疯姹備娇鐢ㄤ腑鏂囧洖绛旓紝浣嗕唬鐮侀儴鍒嗚繕鏄疌#浠g爜銆俓n\n 鎴戜滑閲嶅啓鏁翠釜鏂规硶锛屽彧淇敼鍐茬獊閮ㄥ垎銆俓n</think>\n\n鏍规嵁鎮ㄦ弿杩扮殑闂锛屼唬鐮佷腑鐨勪綅缃亸绉荤畻娉曠‘瀹炲瓨鍦ㄧ己闄枫�備富瑕侀棶棰樻槸褰撳涓瓧绗﹁绠楀嚭鐨勬柊浣嶇疆鐩稿悓鏃讹紝鍚庡啓鍏ョ殑瀛楃浼氳鐩栧墠涓�涓瓧绗︼紝瀵艰嚧閮ㄥ垎鏁版嵁涓㈠け銆備互涓嬫槸淇鍚庣殑浠g爜锛歕n\n```CSharp\npublic string GenerateActivationCode(string baseRandom)\n{\n baseRandom = baseRandom.Replace(\"-\", string.Empty);\n Dictionary<char, (char output, int shift)> mappingDict = _charMappingRepository.QueryData()\n .ToDictionary(x => x.InputChar[0], x => (x.OutputChar[0], x.ShiftFactor));\n\n char[] result = new char[baseRandom.Length];\n bool[] positionFilled = new bool[baseRandom.Length]; // 鏂板浣嶇疆鏍囪鏁扮粍\n int length = baseRandom.Length;\n\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n if (!mappingDict.TryGetValue(current, out var mapping))\n throw new InvalidOperationException($\"鏃犳晥瀛楃: {current}\");\n\n // 搴旂敤浣嶇疆鍋忕Щ绠楁硶\n int newPosition = (i + mapping.shift) % length;\n \n // 澶勭悊浣嶇疆鍐茬獊锛氭壘鍒颁笅涓�涓彲鐢ㄤ綅缃甛n while (positionFilled[newPosition]) \n {\n newPosition = (newPosition + 1) % length;\n }\n\n // 鐗规畩鍙樻崲\n char mappedChar = (i % 5 == 4) \n ? ApplySpecialTransform(mapping.output, i) \n : mapping.output;\n\n result[newPosition] = mappedChar;\n positionFilled[newPosition] = true; // 鏍囪浣嶇疆宸蹭娇鐢╘n }\n\n return FormatCode(new string(result));\n}\n```\n\n涓昏淇敼鐐癸細\n1. 娣诲姞浜哷positionFilled`鏁扮粍璺熻釜姣忎釜浣嶇疆鏄惁宸茶鍗犵敤\n2. 褰撹绠楀嚭鐨勬柊浣嶇疆宸茶鍗犵敤鏃讹紝浣跨敤寰幆鏌ユ壘涓嬩竴涓彲鐢ㄤ綅缃甛n3. 纭繚姣忎釜瀛楃閮借鍐欏叆涓斾笉浼氳鐩栧凡鏈夋暟鎹甛n4. 绉婚櫎浜嗗浣欑殑`-`瀛楃妫�鏌ワ紙宸插湪鍓嶇疆澶勭悊涓Щ闄わ級\n\n姝や慨鏀归�氳繃浣嶇疆鍐茬獊妫�娴嬫満鍒剁‘淇濈粨鏋滄暟缁勪腑鐨勬瘡涓綅缃兘浼氳姝g‘濉厖锛岃В鍐充簡鏁版嵁涓㈠け闂銆倁ndefined","isTips":null,"cost":124014,"parser":{"nodes":[{"type":"reasoning","content":"<think>\n鎴戜滑姝e湪鏌ョ湅鐨勪唬鐮佺墖娈垫槸GenerateActivationCode鏂规硶銆傜敤鎴锋寚鍑衡�滃簲鐢ㄤ綅缃亸绉荤畻娉曟湁闂锛屽鑷存暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濄�俓n 闂鍒嗘瀽锛歕n 褰撳墠浠g爜涓紝鎴戜滑鍒涘缓浜嗕竴涓粨鏋滄暟缁刞result`锛岄暱搴︿负`baseRandom.Length`銆傜劧鍚庨亶鍘哷baseRandom`鐨勬瘡涓瓧绗︼紙璺宠繃'-'锛夛紝鏍规嵁鏄犲皠瀛楀吀寰楀埌杈撳嚭瀛楃鍜屽亸绉婚噺銆俓n 鐒跺悗璁$畻鏂颁綅缃細`newPosition = (i + mapping.shift) % length`锛屽苟灏嗘槧灏勫悗鐨勫瓧绗︼紙鍙兘缁忚繃鐗规畩鍙樻崲锛夋斁鍏ョ粨鏋滄暟缁勭殑`newPosition`浣嶇疆銆俓n\n 闂鍦ㄤ簬锛氬鏋滀袱涓笉鍚岀殑瀛楃璁$畻鍑虹殑`newPosition`鐩稿悓锛岄偅涔堝悗鏀惧叆鐨勫瓧绗︿細瑕嗙洊鍓嶄竴涓瓧绗︺�傚悓鏃讹紝濡傛灉鏌愪釜浣嶇疆娌℃湁琚换浣曞瓧绗﹁祴鍊硷紝閭d箞璇ヤ綅缃皢淇濇寔鍒濆鍊硷紙鍗�'\\0'锛岀┖瀛楃锛夈�傝繖浼氬鑷存渶缁堢敓鎴愮殑瀛楃涓蹭腑鏈変簺浣嶇疆鏄┖瀛楃锛堝嵆娌℃湁琚浛鎹級锛屼粠鑰屼骇鐢熼敊璇�俓n\n 瑙e喅鏂规锛歕n 鎴戜滑闇�瑕佺‘淇濇瘡涓綅缃兘琚纭祴鍊硷紝骞朵笖涓嶈兘鏈夎鐩栵紙闄ら潪璁捐濡傛锛屼絾杩欓噷鏄剧劧涓嶆槸锛夈�備絾鏄紝鏍规嵁闂鎻忚堪锛屼技涔庢湁浜涗綅缃病鏈夎璧嬪�硷紝瀵艰嚧缁撴灉瀛楃涓蹭腑鏈夌┖瀛楃銆俓n\n 鍙︿竴绉嶆�濊矾锛氭垜浠笉搴旇鐩存帴鏍规嵁鍋忕Щ閲忓皢瀛楃鏀惧叆鏂颁綅缃紝鍥犱负杩欐牱浼氬鑷村啿绐佸拰鏈祴鍊肩殑浣嶇疆銆傛垜浠彲浠ュ厛瀵规瘡涓瓧绗﹁繘琛屾槧灏勶紙寰楀埌鏂扮殑瀛楃锛夛紝鐒跺悗鏍规嵁鍋忕Щ閲忚皟鏁翠綅缃紝浣嗚繖鏍疯皟鏁翠綅缃彲鑳戒細寰堝鏉傘�俓n\n 瀹為檯涓婏紝鍘熶唬鐮佺殑閫昏緫鏄細瀵逛簬杈撳叆瀛楃涓蹭腑鐨勬瘡涓瓧绗︼紙璺宠繃'-'锛夛紝鎴戜滑灏嗗叾鏄犲皠涓轰竴涓柊鐨勫瓧绗︼紝鐒跺悗鏍规嵁鍋忕Щ閲忓喅瀹氳繖涓柊瀛楃鍦ㄧ粨鏋滃瓧绗︿覆涓殑浣嶇疆銆備絾鏄紝鐢变簬杈撳叆瀛楃涓蹭腑姣忎釜瀛楃鐨勪綅缃甶鏄敮涓�鐨勶紙闄や簡璺宠繃'-'锛屼絾璺宠繃浼氬鑷磋緭鍏ュ瓧绗︿覆涓湁鏁堝瓧绗︽暟灏戜簬闀垮害锛岃�岀粨鏋滄暟缁勯暱搴﹀嵈鏄師濮嬪瓧绗︿覆闀垮害锛屽寘鎷偅浜涜璺宠繃鐨勪綅缃紵娉ㄦ剰锛岃繖閲岃烦杩囩殑瀛楃鏄�'-'锛屼絾寰幆涓亣鍒�'-'鏃朵娇鐢ㄤ簡continue锛屾墍浠ヤ笉浼氬鐞嗚瀛楃锛屼篃涓嶄細鍦ㄧ粨鏋滄暟缁勪腑鏀剧疆浠讳綍涓滆タ銆傝�屼笖锛屽師濮嬪瓧绗︿覆涓彲鑳藉寘鍚涓�'-'锛屼絾宸茬粡琚浛鎹负绌猴紝鎵�浠ュ疄闄呬笂baseRandom宸茬粡鍘婚櫎浜�'-'銆傛墍浠ワ紝鍦ㄥ惊鐜箣鍓嶏紝baseRandom宸茬粡绉婚櫎浜嗘墍鏈夌殑'-'锛屽洜姝ゅ惊鐜腑涓嶄細閬囧埌'-'銆傛墍浠ワ紝寰幆涓笉浼氳烦杩囦换浣曞瓧绗︺�傞偅涔堬紝姣忎釜瀛楃閮戒細琚鐞嗐�俓n\n 浣嗘槸锛岄棶棰樺嚭鍦ㄥ亸绉诲悗鐨勪綅缃彲鑳藉啿绐侊紝鎴栬�呭亸绉诲悗鏌愪簺浣嶇疆娌℃湁琚祴鍊硷紵瀹為檯涓婏紝鐢变簬鎴戜滑閬嶅巻姣忎釜浣嶇疆锛�0鍒發ength-1锛夛紝骞朵笖姣忎釜浣嶇疆閮戒細璁$畻涓�涓柊浣嶇疆锛坣ewPosition锛夛紝鐒跺悗璧嬪�笺�傜敱浜巌浠�0鍒發ength-1锛岃�宯ewPosition = (i + shift) % length锛岃繖涓�间篃鍦�0鍒發ength-1涔嬮棿銆備絾鏄紝涓嶅悓鐨刬鍙兘浼氬緱鍒扮浉鍚岀殑newPosition锛堝綋鍋忕Щ閲忎笉鍚屾椂锛屼絾鍚屼竴涓亸绉婚噺锛熸敞鎰忔瘡涓瓧绗︾殑鍋忕Щ閲忓彲鑳戒笉鍚岋紝鍥犱负mapping.shift鏄粠瀛楀吀涓彇鍑虹殑锛屾瘡涓瓧绗﹀搴旂殑shift鍙兘涓嶅悓锛夈�傚洜姝わ紝濡傛灉涓や釜涓嶅悓鐨刬璁$畻鍑虹殑newPosition鐩稿悓锛岄偅涔堝悗璧嬪�肩殑浼氳鐩栧墠闈㈢殑銆俓n\n 鍙﹀锛岀敱浜庢垜浠娇鐢ㄧ殑鏄悓涓�涓暟缁勶紝鍒濆鏃舵暟缁勭殑姣忎釜浣嶇疆閮芥槸'\\0'锛堢┖瀛楃锛夛紝濡傛灉鏌愪釜newPosition鍙璧嬪�间竴娆★紝閭d箞娌℃湁闂锛涘鏋滀竴娆¢兘娌℃湁琚祴鍊硷紝閭d箞璇ヤ綅缃氨鏄┖瀛楃锛堜絾鐞嗚涓婃瘡涓猧閮戒細璧嬪�间竴娆★紝鍥犱负姣忎釜i閮戒細璁$畻涓�涓猲ewPosition骞惰祴鍊硷紝鎵�浠ユ瘡涓綅缃嚦灏戜細琚祴鍊间竴娆★紵涓嶅锛屽洜涓簄ewPosition鐨勫彇鍊艰寖鍥存槸0鍒發ength-1锛屽苟涓旀瘡涓猧閮戒細璧嬪�间竴娆★紝鎵�浠ユ瘡涓綅缃兘浼氳璧嬪�硷紵浣嗘槸锛屽鏋滀袱涓猧鎸囧悜鍚屼竴涓猲ewPosition锛岄偅涔堝叾涓竴涓祴鍊间細琚鐩栵紝鑰屽彟涓�涓祴鍊间細淇濈暀锛岃繖鏍锋瘡涓綅缃繕鏄細琚祴鍊硷紙鍙笉杩囧彲鑳借澶氭璧嬪�硷紝鏈�鍚庝竴娆¤鐩栵級銆傛墍浠ワ紝姣忎釜浣嶇疆閮戒細鏈夊�硷紝涓嶄細鍑虹幇绌哄瓧绗︺�俓n\n 閭d箞涓轰粈涔堢敤鎴疯鈥滀笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濓紵鍙兘鏄寚缁撴灉瀛楃涓蹭腑鍑虹幇浜嗗師濮嬪瓧绗︼紵鎴栬�呭嚭鐜颁簡绌哄瓧绗︼紵\n\n 閲嶆柊瀹¤锛氬湪寰幆涓紝鎴戜滑璺宠繃浜�'-'锛屼絾鍓嶉潰宸茬粡灏哹aseRandom涓殑'-'绉婚櫎浜嗭紝鎵�浠ュ惊鐜腑涓嶄細閬囧埌'-'锛屽洜姝や笉浼氳烦杩囥�傛墍浠ユ瘡涓瓧绗﹂兘浼氳澶勭悊銆俓n\n 浣嗘槸锛屽鏋滃師濮嬪瓧绗︿覆涓笉鍖呭惈'-'锛岄偅涔坆aseRandom灏辨槸鍘熷瀛楃涓层�傚惊鐜腑姣忎釜瀛楃閮戒細琚鐞嗭紝姣忎釜浣嶇疆i閮戒細璁$畻涓�涓猲ewPosition锛岀劧鍚庤祴鍊笺�傛墍浠ョ粨鏋滄暟缁勭殑姣忎釜浣嶇疆閮戒細琚祴鍊硷紙鍥犱负newPosition瑕嗙洊浜�0鍒發ength-1锛夛紝鎵�浠ヤ笉浼氭湁绌哄瓧绗︺�俓n\n 閭d箞闂鍙兘鍑哄湪鍋忕Щ閲忓鑷寸殑浣嶇疆鍐茬獊锛熶緥濡傦紝涓や釜涓嶅悓鐨勫瓧绗﹁鏄犲皠鍒颁簡鍚屼竴涓綅缃紝閭d箞鍚庝竴涓瓧绗︿細瑕嗙洊鍓嶄竴涓紝瀵艰嚧鍓嶄竴涓瓧绗︿涪澶便�傝繖鏍凤紝缁撴灉瀛楃涓蹭腑灏变細涓㈠け涓�浜涘瓧绗︼紝鑰屽嚭鐜伴噸澶嶇殑瀛楃锛堝悗涓�涓鐩栧墠涓�涓紝浣嗗悗涓�涓瓧绗﹁姝g‘鏀剧疆锛屽墠涓�涓瑕嗙洊浜嗭級銆傝繖鏍凤紝缁撴灉瀛楃涓茬殑闀垮害铏界劧杩樻槸length锛屼絾鍙兘缂哄皯浜嗗師濮嬪瓧绗︿覆涓殑鏌愪簺瀛楃锛堣瑕嗙洊浜嗭級锛岃�屽鍑轰簡閲嶅鐨勫瓧绗︼紙瑕嗙洊鍒汉鐨勫瓧绗︼級銆俓n\n 鍥犳锛屾垜浠渶瑕侀伩鍏嶈鐩栥�傚浣曢伩鍏嶏紵鎴戜滑鍙互鍏堝垱寤轰竴涓拰鍘熷瀛楃涓茬瓑闀跨殑瀛楃鏁扮粍锛岀劧鍚庡垵濮嬪寲姣忎釜浣嶇疆涓轰竴涓粯璁ゅ�硷紙姣斿绌烘牸鎴栬�呬竴涓壒娈婂瓧绗︼級锛岀劧鍚庤祴鍊兼椂濡傛灉鍙戠幇鐩爣浣嶇疆宸茬粡琚崰鐢紝鍒欓噰鍙栨煇绉嶅啿绐佽В鍐崇瓥鐣ワ紙姣斿绾挎�ф帰娴嬶級锛熶絾鏄紝杩欐牱鍙兘浼氭敼鍙樺瓧绗︾殑椤哄簭锛岃�屼笖鍐茬獊瑙e喅绛栫暐鍙兘浼氬鏉傘�俓n\n 鎴栬�咃紝鎴戜滑鏀瑰彉鎬濊矾锛氭垜浠笉瀵瑰瓧绗﹁繘琛屼綅缃亸绉伙紝鑰屾槸鍏堝姣忎釜瀛楃杩涜鏄犲皠锛堝緱鍒颁竴涓柊鐨勫瓧绗︼級锛岀劧鍚庢牴鎹亸绉婚噺璋冩暣瀛楃鐨勯『搴忋�備篃灏辨槸璇达紝鎴戜滑鍙互鍏堝緱鍒颁竴涓瓧绗﹀簭鍒楋紙鏄犲皠鍚庣殑瀛楃搴忓垪锛夛紝鐒跺悗瀵硅繖涓簭鍒楄繘琛岄噸鎺掞紙鎸夌収鍋忕Щ瑙勫垯锛夈�俓n\n 鍏蜂綋姝ラ锛歕n 1. 鍒涘缓涓�涓垪琛紙鎴栨暟缁勶級鐢ㄤ簬瀛樻斁鏄犲皠鍚庣殑瀛楃锛堝寘鎷壒娈婂彉鎹級銆俓n 2. 閬嶅巻baseRandom鐨勬瘡涓瓧绗︼紝寰楀埌鏄犲皠鍚庣殑瀛楃锛堝彲鑳藉簲鐢ㄧ壒娈婂彉鎹級锛屽苟鏀惧叆涓�涓复鏃舵暟缁勶紙鎸夊師濮嬮『搴忥級銆俓n 3. 鐒跺悗锛屽垱寤轰竴涓柊鐨勭粨鏋滄暟缁勶紝闀垮害鍜屼复鏃舵暟缁勭浉鍚屻�俓n 4. 閬嶅巻涓存椂鏁扮粍锛屽浜庣i涓厓绱狅紝璁$畻瀹冨簲璇ユ斁缃殑浣嶇疆锛歯ewPosition = (i + shift) % length锛岀劧鍚庡皢璇ュ厓绱犳斁鍏ョ粨鏋滄暟缁勭殑newPosition浣嶇疆銆俓n\n 浣嗘槸锛岃繖鏍疯繕鏄細鏈夊啿绐侊紒鍥犱负鍚屼竴涓綅缃彲鑳借澶氫釜鍏冪礌瑕佹眰鏀惧叆銆俓n\n 鍙︿竴绉嶆柟娉曪細鎴戜滑涓嶆槸灏嗘瘡涓瓧绗︾嫭绔嬪湴鏀惧叆鏂颁綅缃紝鑰屾槸瀵规暣涓簭鍒楄繘琛岀Щ浣嶃�備絾鏄紝姣忎釜瀛楃鐨勭Щ浣嶉噺鍙兘涓嶅悓锛屾墍浠ヤ笉鑳界畝鍗曞湴鏁翠綋绉讳綅銆俓n\n 鍥犳锛屾垜浠渶瑕佷竴涓腑闂寸粨鏋勬潵璁板綍姣忎釜瀛楃鐨勫師濮嬩綅缃拰瀹冨簲璇ュ幓鐨勪綅缃紝鐒跺悗鎸夌収浣嶇疆璋冩暣椤哄簭銆備絾鏄紝鐢变簬姣忎釜瀛楃鐨勭Щ浣嶉噺涓嶅悓锛屾墍浠ユ瘡涓瓧绗︾殑鐩爣浣嶇疆鐙珛璁$畻銆俓n\n 涓轰簡閬垮厤鍐茬獊锛屾垜浠彲浠ヤ娇鐢ㄤ竴涓垪琛紙鎴栨暟缁勶級鏉ュ瓨鍌ㄦ瘡涓綅缃簲璇ユ斁缃殑瀛楃锛屼絾鏄厑璁镐竴涓綅缃湁澶氫釜瀛楃锛熶笉琛岋紝鍥犱负涓�涓綅缃彧鑳芥斁涓�涓瓧绗︺�俓n\n 鎵�浠ワ紝鎴戜滑鍙兘闇�瑕佹敼鍙樿璁★細浣嶇疆鍋忕Щ绠楁硶涓嶅簲璇ョ嫭绔嬪湴瀵规瘡涓瓧绗﹁繘琛岋紝鑰屽簲璇ュ熀浜庢暣涓瓧绗︿覆鐨勫彉鎹€�傛垨鑰咃紝鎴戜滑鏀惧純浣嶇疆鍋忕Щ锛岄噰鐢ㄥ叾浠栨柟寮忋�俓n\n 浣嗘槸锛岀敤鎴疯姹備慨澶嶉棶棰橈紝鑰屼笉鏄敼鍙樼畻娉曘�傛墍浠ワ紝鎴戜滑鍙兘闇�瑕佷竴涓啿绐佽В鍐虫満鍒躲�俓n\n 鐒惰�岋紝鍘熻璁℃剰鍥惧彲鑳芥槸锛氭瘡涓瓧绗︽牴鎹叾浣嶇疆鍜岃嚜韬殑shift鍊硷紝绉诲姩鍒版柊鐨勪綅缃�傚鏋滀袱涓瓧绗︾Щ鍔ㄥ埌鍚屼竴涓綅缃紝閭d箞鍚庡鐞嗙殑瀛楃浼氳鐩栧厛澶勭悊鐨勫瓧绗︼紙鍥犱负寰幆椤哄簭鏄粠0鍒發ength-1锛夈�傛墍浠ワ紝鍚庡鐞嗙殑瀛楃浼氳鐩栧厛澶勭悊鐨勫瓧绗︺�傝繖鍙兘鏄璁$己闄枫�俓n\n 濡備綍淇锛熸垜浠彲浠ヨ姣忎釜瀛楃鍦ㄧЩ鍔ㄦ椂锛屽鏋滅洰鏍囦綅缃凡缁忚鍗犵敤锛屽垯瀵绘壘涓嬩竴涓┖浣嶇疆锛堢嚎鎬ф帰娴嬶級銆備絾鏄紝杩欐牱鍙兘浼氭敼鍙樺瓧绗︾殑鐩稿椤哄簭锛岃�屼笖鍙兘浼氬鍔犺绠楅噺銆俓n\n 姝ラ锛歕n 1. 鍒濆鍖栫粨鏋滄暟缁勶紝姣忎釜浣嶇疆涓�'\\0'锛堣〃绀虹┖锛夈�俓n 2. 閬嶅巻姣忎釜瀛楃锛堟寜椤哄簭锛夛細\n 璁$畻newPosition = (i + mapping.shift) % length\n 濡傛灉缁撴灉鏁扮粍鐨刵ewPosition浣嶇疆涓虹┖锛屽垯鏀惧叆銆俓n 濡傛灉涓嶄负绌猴紝鍒欎粠newPosition寮�濮嬪悜鍚庡鎵撅紙寰幆锛夌洿鍒版壘鍒颁竴涓┖浣嶇疆锛堟敞鎰忓彇妯★級锛岀劧鍚庢斁鍏ャ�俓n 3. 杩欐牱锛屾瘡涓瓧绗﹂兘浼氳鏀惧叆锛屼笖涓嶄細瑕嗙洊銆俓n\n 浣嗘槸锛岃繖鏍峰彲鑳戒細瀵艰嚧鏌愪簺瀛楃琚斁鍦ㄨ窛绂荤洰鏍囦綅缃緝杩滅殑鍦版柟锛岃�屼笖椤哄簭鍙兘浼氳鎵撲贡锛堜絾鑷冲皯姣忎釜浣嶇疆閮芥湁瀛楃锛屼笖涓嶄細瑕嗙洊锛夈�俓n\n 浣嗘槸锛岃繖鏍蜂慨鏀瑰悗锛屽瓧绗︾殑浣嶇疆涓嶄粎鍙栧喅浜庡師濮嬩綅缃拰shift锛岃繕鍙栧喅浜庡啿绐佽В鍐崇殑鎯呭喌銆傝�屼笖锛屽鏋滄暟缁勬弧浜嗭紝鎴戜滑涓�瀹氳兘鎵惧埌绌轰綅鍚楋紵鐢变簬鎴戜滑閬嶅巻姣忎釜瀛楃锛屾瘡涓瓧绗﹂兘闇�瑕佹斁缃竴娆★紝鑰屾暟缁勯暱搴︽濂芥槸瀛楃涓暟锛屾墍浠ヤ竴瀹氬彲浠ユ壘鍒扮┖浣嶏紙鍥犱负鎬诲叡鏈塴ength涓綅缃紝鎴戜滑瑕佹斁length涓瓧绗︼紝涓斿啿绐佹椂鎴戜滑绾挎�ф帰娴嬬洿鍒版壘鍒扮┖浣嶏紝鎵�浠ユ渶缁堟瘡涓瓧绗﹂兘浼氳鏀剧疆锛屼笖涓嶄細瑕嗙洊锛夈�俓n\n 浣嗘槸锛岀嚎鎬ф帰娴嬪彲鑳戒細瀵艰嚧鎬ц兘闂锛堝鏋滃啿绐佸锛岄渶瑕侀亶鍘嗗緢澶氫綅缃級锛屼絾length涓嶄細澶ぇ锛堟縺娲荤爜涓�鑸笉浼氬お闀匡級锛屾墍浠ュ彲浠ユ帴鍙椼�俓n\n 淇敼浠g爜锛歕n\n 鎴戜滑淇敼寰幆閮ㄥ垎锛歕n\n 鍘熶唬鐮侊細\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n // 宸茬粡绉婚櫎浜�'-'锛屾墍浠ヤ笉闇�瑕佸垽鏂烦杩嘰n if (!mappingDict.TryGetValue(current, out var mapping))\n throw new InvalidOperationException($\"鏃犳晥瀛楃: {current}\");\n\n int newPosition = (i + mapping.shift) % length;\n char mappedChar = (i % 5 == 4) ? ApplySpecialTransform(mapping.output, i) : mapping.output;\n\n result[newPosition] = mappedChar;\n }\n\n 淇敼涓猴細\n\n // 鍒濆鍖栫粨鏋滄暟缁勶紝鐢�'\\0'琛ㄧず绌轰綅\n char[] result = new char[length];\n // 鎴戜滑涓嶉渶瑕佹樉寮忚祴鍊间负'\\0'锛屽洜涓簄ew char鏁扮粍榛樿灏辨槸'\\0'\n\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n if (!mappingDict.TryGetValue(current, out var mapping))\n throw new InvalidOperationException($\"鏃犳晥瀛楃: {current}\");\n\n char mappedChar = (i % 5 == 4) ? ApplySpecialTransform(mapping.output, i) : mapping.output;\n\n int newPosition = (i + mapping.shift) % length;\n\n // 濡傛灉鐩爣浣嶇疆宸茬粡琚崰鐢紝鍒欏鎵句笅涓�涓┖浣嶇疆锛堢嚎鎬ф帰娴嬶級\n while (result[newPosition] != '\\0')\n {\n newPosition = (newPosition + 1) % length; // 鍚戝悗绉诲姩涓�浣嶏紝濡傛灉鍒版湯灏惧垯鍥炲埌寮�澶碶n }\n result[newPosition] = mappedChar;\n }\n\n 杩欐牱锛屽鏋滆绠楀嚭鐨勪綅缃凡缁忚鍗犵敤锛屾垜浠氨鍚戝悗涓�涓竴涓壘锛岀洿鍒版壘鍒扮┖浣嶇疆銆俓n\n 浣嗘槸锛岃繖鏍蜂慨鏀瑰悗锛屽瓧绗︾殑浣嶇疆鍙兘浼氬洜涓哄啿绐佽�屾敼鍙橈紝浣嗚嚦灏戜繚璇佷簡姣忎釜浣嶇疆閮芥湁瀛楃锛屼笖涓嶄細瑕嗙洊銆俓n\n 浣嗘槸锛岀敤鎴风殑闂鎻忚堪鏄�滄暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濓紝鍙兘鏄寚缁撴灉鏁扮粍涓湁浣嶇疆娌℃湁琚祴鍊硷紙鍗宠繕鏄垵濮嬪��'\\0'锛夈�傛垜浠笂闈㈢殑淇敼淇濊瘉浜嗘瘡涓綅缃兘浼氳璧嬪�硷紙鍥犱负鎴戜滑鏀剧疆浜唋ength涓瓧绗︼紝涓旈�氳繃绾挎�ф帰娴嬮伩鍏嶄簡鍐茬獊锛屾墍浠ユ瘡涓綅缃兘浼氳璧嬪�间竴娆★級銆傛墍浠ワ紝杩欎釜淇敼搴旇鑳借В鍐抽棶棰樸�俓n\n 浣嗘槸锛屾垜浠篃瑕佹敞鎰忥紝绾挎�ф帰娴嬪彲鑳戒細瀵艰嚧瀛楃鐨勯『搴忎笌鍘熷璁捐鎰忓浘鏈夊亸宸紙鍥犱负鍐茬獊鏃跺瓧绗﹁鍚庣Щ浜嗭級銆傚師濮嬭璁℃剰鍥惧彲鑳芥槸姣忎釜瀛楃涓ユ牸鍦版斁鍦�(i+shift)%length鐨勪綅缃紝鍗充娇瑕嗙洊涔熶笉绠★紙浣嗚鐩栦細瀵艰嚧鏁版嵁涓㈠け锛夈�傜幇鍦紝鎴戜滑閫氳繃绾挎�ф帰娴嬮伩鍏嶄簡瑕嗙洊锛屼絾浣嶇疆鍙戠敓浜嗗彉鍖栥�俓n\n 鍙﹀锛屾垜浠繕闇�瑕佽�冭檻锛氬鏋滃師濮嬪瓧绗︿覆涓湁閲嶅瀛楃锛岄偅涔堟槧灏勫悗鐨勫瓧绗︿篃鍙兘閲嶅锛岃繖娌″叧绯伙紝鍥犱负姣忎釜瀛楃閮芥槸鐙珛澶勭悊鐨勩�俓n\n 鍥犳锛屾垜浠寜鐓т笂杩版�濊矾淇敼浠g爜銆俓n\n 娉ㄦ剰锛氱敱浜庢垜浠慨鏀逛簡浣嶇疆鍒嗛厤绠楁硶锛屽彲鑳戒細褰卞搷婵�娲荤爜鐨勭敓鎴愯鍒欍�備絾鐢ㄦ埛瑕佹眰淇瑕嗙洊鍜岀┖浣嶇殑闂锛屾墍浠ヨ繖鏄繀瑕佺殑銆俓n\n 淇敼鍚庣殑浠g爜锛歕n\n 鎴戜滑灏嗗惊鐜唴鐨勮祴鍊兼敼涓轰娇鐢ㄧ嚎鎬ф帰娴嬭В鍐冲啿绐併�俓n\n 浣嗘槸锛屾垜浠繕闇�瑕佹敞鎰忥細鍘熷浠g爜涓紝濡傛灉閬囧埌鐩稿悓鐨勪綅缃紝鍚庡鐞嗙殑瀛楃浼氳鐩栧厛澶勭悊鐨勫瓧绗︺�傜幇鍦紝鎴戜滑璁╁悗澶勭悊鐨勫瓧绗﹀悜鍚庡鎵剧┖浣嶏紝杩欐牱鍏堝鐞嗙殑瀛楃浼氬崰鎹畠璁$畻鐨勪綅缃紝鍚庡鐞嗙殑瀛楃濡傛灉鍐茬獊灏卞悗绉汇�傝繖鏍凤紝缁撴灉瀛楃涓蹭腑瀛楃鐨勯『搴忓彲鑳戒細涓庡師濮嬭璁℃湁杈冨ぇ涓嶅悓锛堢壒鍒槸褰撳啿绐佽緝澶氭椂锛夈�俓n\n 濡傛灉鐢ㄦ埛甯屾湜淇濇寔鍘熷璁捐鎰忓浘锛堝嵆姣忎釜瀛楃鐨勪綅缃敱(i+shift)%length鍞竴纭畾锛屼笉鍏佽鍐茬獊锛夛紝閭d箞鎴戜滑蹇呴』纭繚姣忎釜瀛楃鐨�(i+shift)%length閮芥槸鍞竴鐨勩�備絾杩欏緢闅句繚璇侊紝鍥犱负shift鏄瘡涓瓧绗﹁嚜宸卞喅瀹氱殑锛岃�宨鏄繛缁殑锛屾墍浠ュ綋涓や釜瀛楃鐨�(i1+shift1) % length 绛変簬 (i2+shift2) % length鏃讹紝鍐茬獊灏变細鍙戠敓銆俓n\n 鎵�浠ワ紝鎴戜滑鍙兘閫氳繃鍐茬獊瑙e喅鏈哄埗鏉ラ伩鍏嶈鐩栥�俓n\n 鍥犳锛屾垜浠噰鐢ㄧ嚎鎬ф帰娴嬨�俓n\n 淇敼鍚庣殑浠g爜锛歕n\n 娉ㄦ剰锛氭垜浠笉闇�瑕佹敼鍙樼壒娈婂彉鎹㈢殑閮ㄥ垎锛屽彧闇�瑕佹敼鍙樻斁缃瓧绗︾殑閫昏緫銆俓n\n 鎴戜滑杈撳嚭淇敼鍚庣殑鏁翠釜鏂规硶銆俓n\n 鍙﹀锛岀敤鎴疯姹備娇鐢ㄤ腑鏂囧洖绛旓紝浣嗕唬鐮侀儴鍒嗚繕鏄疌#浠g爜銆俓n\n 鎴戜滑閲嶅啓鏁翠釜鏂规硶锛屽彧淇敼鍐茬獊閮ㄥ垎銆俓n</think>","contentId":1887140099,"children":[],"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"","children":[],"contentId":0,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"鏍规嵁鎮ㄦ弿杩扮殑闂锛屼唬鐮佷腑鐨勪綅缃亸绉荤畻娉曠‘瀹炲瓨鍦ㄧ己闄枫�備富瑕侀棶棰樻槸褰撳涓瓧绗﹁绠楀嚭鐨勬柊浣嶇疆鐩稿悓鏃讹紝鍚庡啓鍏ョ殑瀛楃浼氳鐩栧墠涓�涓瓧绗︼紝瀵艰嚧閮ㄥ垎鏁版嵁涓㈠け銆備互涓嬫槸淇鍚庣殑浠g爜锛�","children":[],"contentId":-1453729221,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"","children":[],"contentId":0,"parent":null,"settled":true,"xmlData":{}},{"type":"code-block","content":"public string GenerateActivationCode(string baseRandom)\n{\n baseRandom = baseRandom.Replace(\"-\", string.Empty);\n Dictionary<char, (char output, int shift)> mappingDict = _charMappingRepository.QueryData()\n .ToDictionary(x => x.InputChar[0], x => (x.OutputChar[0], x.ShiftFactor));\n\n char[] result = new char[baseRandom.Length];\n bool[] positionFilled = new bool[baseRandom.Length]; // 鏂板浣嶇疆鏍囪鏁扮粍\n int length = baseRandom.Length;\n\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n if (!mappingDict.TryGetValue(current, out var mapping))\n throw new InvalidOperationException($\"鏃犳晥瀛楃: {current}\");\n\n // 搴旂敤浣嶇疆鍋忕Щ绠楁硶\n int newPosition = (i + mapping.shift) % length;\n \n // 澶勭悊浣嶇疆鍐茬獊锛氭壘鍒颁笅涓�涓彲鐢ㄤ綅缃甛n while (positionFilled[newPosition]) \n {\n newPosition = (newPosition + 1) % length;\n }\n\n // 鐗规畩鍙樻崲\n char mappedChar = (i % 5 == 4) \n ? ApplySpecialTransform(mapping.output, i) \n : mapping.output;\n\n result[newPosition] = mappedChar;\n positionFilled[newPosition] = true; // 鏍囪浣嶇疆宸蹭娇鐢╘n }\n\n return FormatCode(new string(result));\n}\n","children":[],"contentId":-1250221828,"parent":null,"settled":true,"xmlData":{},"expectEnding":"```","language":"CSharp"},{"type":"line","content":"","children":[],"contentId":0,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"涓昏淇敼鐐癸細","children":[],"contentId":909926770,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"1. 娣诲姞浜哷positionFilled`鏁扮粍璺熻釜姣忎釜浣嶇疆鏄惁宸茶鍗犵敤","children":[],"contentId":-777929306,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"2. 褰撹绠楀嚭鐨勬柊浣嶇疆宸茶鍗犵敤鏃讹紝浣跨敤寰幆鏌ユ壘涓嬩竴涓彲鐢ㄤ綅缃�","children":[],"contentId":-1929862225,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"3. 纭繚姣忎釜瀛楃閮借鍐欏叆涓斾笉浼氳鐩栧凡鏈夋暟鎹�","children":[],"contentId":1241464494,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"4. 绉婚櫎浜嗗浣欑殑`-`瀛楃妫�鏌ワ紙宸插湪鍓嶇疆澶勭悊涓Щ闄わ級","children":[],"contentId":-676263493,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"","children":[],"contentId":0,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"姝や慨鏀归�氳繃浣嶇疆鍐茬獊妫�娴嬫満鍒剁‘淇濈粨鏋滄暟缁勪腑鐨勬瘡涓綅缃兘浼氳姝g‘濉厖锛岃В鍐充簡鏁版嵁涓㈠け闂銆�","children":[],"contentId":-1875507872,"parent":null,"settled":false,"xmlData":{}}],"parserState":{"line":193,"column":42,"offset":7268,"metadata":false,"buffer":"","closing":false,"currentParent":null,"moveCursor":true,"tagBuffer":"<","isCollectingTag":false},"content":"<think>\n鎴戜滑姝e湪鏌ョ湅鐨勪唬鐮佺墖娈垫槸GenerateActivationCode鏂规硶銆傜敤鎴锋寚鍑衡�滃簲鐢ㄤ綅缃亸绉荤畻娉曟湁闂锛屽鑷存暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濄�俓n 闂鍒嗘瀽锛歕n 褰撳墠浠g爜涓紝鎴戜滑鍒涘缓浜嗕竴涓粨鏋滄暟缁刞result`锛岄暱搴︿负`baseRandom.Length`銆傜劧鍚庨亶鍘哷baseRandom`鐨勬瘡涓瓧绗︼紙璺宠繃'-'锛夛紝鏍规嵁鏄犲皠瀛楀吀寰楀埌杈撳嚭瀛楃鍜屽亸绉婚噺銆俓n 鐒跺悗璁$畻鏂颁綅缃細`newPosition = (i + mapping.shift) % length`锛屽苟灏嗘槧灏勫悗鐨勫瓧绗︼紙鍙兘缁忚繃鐗规畩鍙樻崲锛夋斁鍏ョ粨鏋滄暟缁勭殑`newPosition`浣嶇疆銆俓n\n 闂鍦ㄤ簬锛氬鏋滀袱涓笉鍚岀殑瀛楃璁$畻鍑虹殑`newPosition`鐩稿悓锛岄偅涔堝悗鏀惧叆鐨勫瓧绗︿細瑕嗙洊鍓嶄竴涓瓧绗︺�傚悓鏃讹紝濡傛灉鏌愪釜浣嶇疆娌℃湁琚换浣曞瓧绗﹁祴鍊硷紝閭d箞璇ヤ綅缃皢淇濇寔鍒濆鍊硷紙鍗�'\\0'锛岀┖瀛楃锛夈�傝繖浼氬鑷存渶缁堢敓鎴愮殑瀛楃涓蹭腑鏈変簺浣嶇疆鏄┖瀛楃锛堝嵆娌℃湁琚浛鎹級锛屼粠鑰屼骇鐢熼敊璇�俓n\n 瑙e喅鏂规锛歕n 鎴戜滑闇�瑕佺‘淇濇瘡涓綅缃兘琚纭祴鍊硷紝骞朵笖涓嶈兘鏈夎鐩栵紙闄ら潪璁捐濡傛锛屼絾杩欓噷鏄剧劧涓嶆槸锛夈�備絾鏄紝鏍规嵁闂鎻忚堪锛屼技涔庢湁浜涗綅缃病鏈夎璧嬪�硷紝瀵艰嚧缁撴灉瀛楃涓蹭腑鏈夌┖瀛楃銆俓n\n 鍙︿竴绉嶆�濊矾锛氭垜浠笉搴旇鐩存帴鏍规嵁鍋忕Щ閲忓皢瀛楃鏀惧叆鏂颁綅缃紝鍥犱负杩欐牱浼氬鑷村啿绐佸拰鏈祴鍊肩殑浣嶇疆銆傛垜浠彲浠ュ厛瀵规瘡涓瓧绗﹁繘琛屾槧灏勶紙寰楀埌鏂扮殑瀛楃锛夛紝鐒跺悗鏍规嵁鍋忕Щ閲忚皟鏁翠綅缃紝浣嗚繖鏍疯皟鏁翠綅缃彲鑳戒細寰堝鏉傘�俓n\n 瀹為檯涓婏紝鍘熶唬鐮佺殑閫昏緫鏄細瀵逛簬杈撳叆瀛楃涓蹭腑鐨勬瘡涓瓧绗︼紙璺宠繃'-'锛夛紝鎴戜滑灏嗗叾鏄犲皠涓轰竴涓柊鐨勫瓧绗︼紝鐒跺悗鏍规嵁鍋忕Щ閲忓喅瀹氳繖涓柊瀛楃鍦ㄧ粨鏋滃瓧绗︿覆涓殑浣嶇疆銆備絾鏄紝鐢变簬杈撳叆瀛楃涓蹭腑姣忎釜瀛楃鐨勪綅缃甶鏄敮涓�鐨勶紙闄や簡璺宠繃'-'锛屼絾璺宠繃浼氬鑷磋緭鍏ュ瓧绗︿覆涓湁鏁堝瓧绗︽暟灏戜簬闀垮害锛岃�岀粨鏋滄暟缁勯暱搴﹀嵈鏄師濮嬪瓧绗︿覆闀垮害锛屽寘鎷偅浜涜璺宠繃鐨勪綅缃紵娉ㄦ剰锛岃繖閲岃烦杩囩殑瀛楃鏄�'-'锛屼絾寰幆涓亣鍒�'-'鏃朵娇鐢ㄤ簡continue锛屾墍浠ヤ笉浼氬鐞嗚瀛楃锛屼篃涓嶄細鍦ㄧ粨鏋滄暟缁勪腑鏀剧疆浠讳綍涓滆タ銆傝�屼笖锛屽師濮嬪瓧绗︿覆涓彲鑳藉寘鍚涓�'-'锛屼絾宸茬粡琚浛鎹负绌猴紝鎵�浠ュ疄闄呬笂baseRandom宸茬粡鍘婚櫎浜�'-'銆傛墍浠ワ紝鍦ㄥ惊鐜箣鍓嶏紝baseRandom宸茬粡绉婚櫎浜嗘墍鏈夌殑'-'锛屽洜姝ゅ惊鐜腑涓嶄細閬囧埌'-'銆傛墍浠ワ紝寰幆涓笉浼氳烦杩囦换浣曞瓧绗︺�傞偅涔堬紝姣忎釜瀛楃閮戒細琚鐞嗐�俓n\n 浣嗘槸锛岄棶棰樺嚭鍦ㄥ亸绉诲悗鐨勪綅缃彲鑳藉啿绐侊紝鎴栬�呭亸绉诲悗鏌愪簺浣嶇疆娌℃湁琚祴鍊硷紵瀹為檯涓婏紝鐢变簬鎴戜滑閬嶅巻姣忎釜浣嶇疆锛�0鍒發ength-1锛夛紝骞朵笖姣忎釜浣嶇疆閮戒細璁$畻涓�涓柊浣嶇疆锛坣ewPosition锛夛紝鐒跺悗璧嬪�笺�傜敱浜巌浠�0鍒發ength-1锛岃�宯ewPosition = (i + shift) % length锛岃繖涓�间篃鍦�0鍒發ength-1涔嬮棿銆備絾鏄紝涓嶅悓鐨刬鍙兘浼氬緱鍒扮浉鍚岀殑newPosition锛堝綋鍋忕Щ閲忎笉鍚屾椂锛屼絾鍚屼竴涓亸绉婚噺锛熸敞鎰忔瘡涓瓧绗︾殑鍋忕Щ閲忓彲鑳戒笉鍚岋紝鍥犱负mapping.shift鏄粠瀛楀吀涓彇鍑虹殑锛屾瘡涓瓧绗﹀搴旂殑shift鍙兘涓嶅悓锛夈�傚洜姝わ紝濡傛灉涓や釜涓嶅悓鐨刬璁$畻鍑虹殑newPosition鐩稿悓锛岄偅涔堝悗璧嬪�肩殑浼氳鐩栧墠闈㈢殑銆俓n\n 鍙﹀锛岀敱浜庢垜浠娇鐢ㄧ殑鏄悓涓�涓暟缁勶紝鍒濆鏃舵暟缁勭殑姣忎釜浣嶇疆閮芥槸'\\0'锛堢┖瀛楃锛夛紝濡傛灉鏌愪釜newPosition鍙璧嬪�间竴娆★紝閭d箞娌℃湁闂锛涘鏋滀竴娆¢兘娌℃湁琚祴鍊硷紝閭d箞璇ヤ綅缃氨鏄┖瀛楃锛堜絾鐞嗚涓婃瘡涓猧閮戒細璧嬪�间竴娆★紝鍥犱负姣忎釜i閮戒細璁$畻涓�涓猲ewPosition骞惰祴鍊硷紝鎵�浠ユ瘡涓綅缃嚦灏戜細琚祴鍊间竴娆★紵涓嶅锛屽洜涓簄ewPosition鐨勫彇鍊艰寖鍥存槸0鍒發ength-1锛屽苟涓旀瘡涓猧閮戒細璧嬪�间竴娆★紝鎵�浠ユ瘡涓綅缃兘浼氳璧嬪�硷紵浣嗘槸锛屽鏋滀袱涓猧鎸囧悜鍚屼竴涓猲ewPosition锛岄偅涔堝叾涓竴涓祴鍊间細琚鐩栵紝鑰屽彟涓�涓祴鍊间細淇濈暀锛岃繖鏍锋瘡涓綅缃繕鏄細琚祴鍊硷紙鍙笉杩囧彲鑳借澶氭璧嬪�硷紝鏈�鍚庝竴娆¤鐩栵級銆傛墍浠ワ紝姣忎釜浣嶇疆閮戒細鏈夊�硷紝涓嶄細鍑虹幇绌哄瓧绗︺�俓n\n 閭d箞涓轰粈涔堢敤鎴疯鈥滀笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濓紵鍙兘鏄寚缁撴灉瀛楃涓蹭腑鍑虹幇浜嗗師濮嬪瓧绗︼紵鎴栬�呭嚭鐜颁簡绌哄瓧绗︼紵\n\n 閲嶆柊瀹¤锛氬湪寰幆涓紝鎴戜滑璺宠繃浜�'-'锛屼絾鍓嶉潰宸茬粡灏哹aseRandom涓殑'-'绉婚櫎浜嗭紝鎵�浠ュ惊鐜腑涓嶄細閬囧埌'-'锛屽洜姝や笉浼氳烦杩囥�傛墍浠ユ瘡涓瓧绗﹂兘浼氳澶勭悊銆俓n\n 浣嗘槸锛屽鏋滃師濮嬪瓧绗︿覆涓笉鍖呭惈'-'锛岄偅涔坆aseRandom灏辨槸鍘熷瀛楃涓层�傚惊鐜腑姣忎釜瀛楃閮戒細琚鐞嗭紝姣忎釜浣嶇疆i閮戒細璁$畻涓�涓猲ewPosition锛岀劧鍚庤祴鍊笺�傛墍浠ョ粨鏋滄暟缁勭殑姣忎釜浣嶇疆閮戒細琚祴鍊硷紙鍥犱负newPosition瑕嗙洊浜�0鍒發ength-1锛夛紝鎵�浠ヤ笉浼氭湁绌哄瓧绗︺�俓n\n 閭d箞闂鍙兘鍑哄湪鍋忕Щ閲忓鑷寸殑浣嶇疆鍐茬獊锛熶緥濡傦紝涓や釜涓嶅悓鐨勫瓧绗﹁鏄犲皠鍒颁簡鍚屼竴涓綅缃紝閭d箞鍚庝竴涓瓧绗︿細瑕嗙洊鍓嶄竴涓紝瀵艰嚧鍓嶄竴涓瓧绗︿涪澶便�傝繖鏍凤紝缁撴灉瀛楃涓蹭腑灏变細涓㈠け涓�浜涘瓧绗︼紝鑰屽嚭鐜伴噸澶嶇殑瀛楃锛堝悗涓�涓鐩栧墠涓�涓紝浣嗗悗涓�涓瓧绗﹁姝g‘鏀剧疆锛屽墠涓�涓瑕嗙洊浜嗭級銆傝繖鏍凤紝缁撴灉瀛楃涓茬殑闀垮害铏界劧杩樻槸length锛屼絾鍙兘缂哄皯浜嗗師濮嬪瓧绗︿覆涓殑鏌愪簺瀛楃锛堣瑕嗙洊浜嗭級锛岃�屽鍑轰簡閲嶅鐨勫瓧绗︼紙瑕嗙洊鍒汉鐨勫瓧绗︼級銆俓n\n 鍥犳锛屾垜浠渶瑕侀伩鍏嶈鐩栥�傚浣曢伩鍏嶏紵鎴戜滑鍙互鍏堝垱寤轰竴涓拰鍘熷瀛楃涓茬瓑闀跨殑瀛楃鏁扮粍锛岀劧鍚庡垵濮嬪寲姣忎釜浣嶇疆涓轰竴涓粯璁ゅ�硷紙姣斿绌烘牸鎴栬�呬竴涓壒娈婂瓧绗︼級锛岀劧鍚庤祴鍊兼椂濡傛灉鍙戠幇鐩爣浣嶇疆宸茬粡琚崰鐢紝鍒欓噰鍙栨煇绉嶅啿绐佽В鍐崇瓥鐣ワ紙姣斿绾挎�ф帰娴嬶級锛熶絾鏄紝杩欐牱鍙兘浼氭敼鍙樺瓧绗︾殑椤哄簭锛岃�屼笖鍐茬獊瑙e喅绛栫暐鍙兘浼氬鏉傘�俓n\n 鎴栬�咃紝鎴戜滑鏀瑰彉鎬濊矾锛氭垜浠笉瀵瑰瓧绗﹁繘琛屼綅缃亸绉伙紝鑰屾槸鍏堝姣忎釜瀛楃杩涜鏄犲皠锛堝緱鍒颁竴涓柊鐨勫瓧绗︼級锛岀劧鍚庢牴鎹亸绉婚噺璋冩暣瀛楃鐨勯『搴忋�備篃灏辨槸璇达紝鎴戜滑鍙互鍏堝緱鍒颁竴涓瓧绗﹀簭鍒楋紙鏄犲皠鍚庣殑瀛楃搴忓垪锛夛紝鐒跺悗瀵硅繖涓簭鍒楄繘琛岄噸鎺掞紙鎸夌収鍋忕Щ瑙勫垯锛夈�俓n\n 鍏蜂綋姝ラ锛歕n 1. 鍒涘缓涓�涓垪琛紙鎴栨暟缁勶級鐢ㄤ簬瀛樻斁鏄犲皠鍚庣殑瀛楃锛堝寘鎷壒娈婂彉鎹級銆俓n 2. 閬嶅巻baseRandom鐨勬瘡涓瓧绗︼紝寰楀埌鏄犲皠鍚庣殑瀛楃锛堝彲鑳藉簲鐢ㄧ壒娈婂彉鎹級锛屽苟鏀惧叆涓�涓复鏃舵暟缁勶紙鎸夊師濮嬮『搴忥級銆俓n 3. 鐒跺悗锛屽垱寤轰竴涓柊鐨勭粨鏋滄暟缁勶紝闀垮害鍜屼复鏃舵暟缁勭浉鍚屻�俓n 4. 閬嶅巻涓存椂鏁扮粍锛屽浜庣i涓厓绱狅紝璁$畻瀹冨簲璇ユ斁缃殑浣嶇疆锛歯ewPosition = (i + shift) % length锛岀劧鍚庡皢璇ュ厓绱犳斁鍏ョ粨鏋滄暟缁勭殑newPosition浣嶇疆銆俓n\n 浣嗘槸锛岃繖鏍疯繕鏄細鏈夊啿绐侊紒鍥犱负鍚屼竴涓綅缃彲鑳借澶氫釜鍏冪礌瑕佹眰鏀惧叆銆俓n\n 鍙︿竴绉嶆柟娉曪細鎴戜滑涓嶆槸灏嗘瘡涓瓧绗︾嫭绔嬪湴鏀惧叆鏂颁綅缃紝鑰屾槸瀵规暣涓簭鍒楄繘琛岀Щ浣嶃�備絾鏄紝姣忎釜瀛楃鐨勭Щ浣嶉噺鍙兘涓嶅悓锛屾墍浠ヤ笉鑳界畝鍗曞湴鏁翠綋绉讳綅銆俓n\n 鍥犳锛屾垜浠渶瑕佷竴涓腑闂寸粨鏋勬潵璁板綍姣忎釜瀛楃鐨勫師濮嬩綅缃拰瀹冨簲璇ュ幓鐨勪綅缃紝鐒跺悗鎸夌収浣嶇疆璋冩暣椤哄簭銆備絾鏄紝鐢变簬姣忎釜瀛楃鐨勭Щ浣嶉噺涓嶅悓锛屾墍浠ユ瘡涓瓧绗︾殑鐩爣浣嶇疆鐙珛璁$畻銆俓n\n 涓轰簡閬垮厤鍐茬獊锛屾垜浠彲浠ヤ娇鐢ㄤ竴涓垪琛紙鎴栨暟缁勶級鏉ュ瓨鍌ㄦ瘡涓綅缃簲璇ユ斁缃殑瀛楃锛屼絾鏄厑璁镐竴涓綅缃湁澶氫釜瀛楃锛熶笉琛岋紝鍥犱负涓�涓綅缃彧鑳芥斁涓�涓瓧绗︺�俓n\n 鎵�浠ワ紝鎴戜滑鍙兘闇�瑕佹敼鍙樿璁★細浣嶇疆鍋忕Щ绠楁硶涓嶅簲璇ョ嫭绔嬪湴瀵规瘡涓瓧绗﹁繘琛岋紝鑰屽簲璇ュ熀浜庢暣涓瓧绗︿覆鐨勫彉鎹€�傛垨鑰咃紝鎴戜滑鏀惧純浣嶇疆鍋忕Щ锛岄噰鐢ㄥ叾浠栨柟寮忋�俓n\n 浣嗘槸锛岀敤鎴疯姹備慨澶嶉棶棰橈紝鑰屼笉鏄敼鍙樼畻娉曘�傛墍浠ワ紝鎴戜滑鍙兘闇�瑕佷竴涓啿绐佽В鍐虫満鍒躲�俓n\n 鐒惰�岋紝鍘熻璁℃剰鍥惧彲鑳芥槸锛氭瘡涓瓧绗︽牴鎹叾浣嶇疆鍜岃嚜韬殑shift鍊硷紝绉诲姩鍒版柊鐨勪綅缃�傚鏋滀袱涓瓧绗︾Щ鍔ㄥ埌鍚屼竴涓綅缃紝閭d箞鍚庡鐞嗙殑瀛楃浼氳鐩栧厛澶勭悊鐨勫瓧绗︼紙鍥犱负寰幆椤哄簭鏄粠0鍒發ength-1锛夈�傛墍浠ワ紝鍚庡鐞嗙殑瀛楃浼氳鐩栧厛澶勭悊鐨勫瓧绗︺�傝繖鍙兘鏄璁$己闄枫�俓n\n 濡備綍淇锛熸垜浠彲浠ヨ姣忎釜瀛楃鍦ㄧЩ鍔ㄦ椂锛屽鏋滅洰鏍囦綅缃凡缁忚鍗犵敤锛屽垯瀵绘壘涓嬩竴涓┖浣嶇疆锛堢嚎鎬ф帰娴嬶級銆備絾鏄紝杩欐牱鍙兘浼氭敼鍙樺瓧绗︾殑鐩稿椤哄簭锛岃�屼笖鍙兘浼氬鍔犺绠楅噺銆俓n\n 姝ラ锛歕n 1. 鍒濆鍖栫粨鏋滄暟缁勶紝姣忎釜浣嶇疆涓�'\\0'锛堣〃绀虹┖锛夈�俓n 2. 閬嶅巻姣忎釜瀛楃锛堟寜椤哄簭锛夛細\n 璁$畻newPosition = (i + mapping.shift) % length\n 濡傛灉缁撴灉鏁扮粍鐨刵ewPosition浣嶇疆涓虹┖锛屽垯鏀惧叆銆俓n 濡傛灉涓嶄负绌猴紝鍒欎粠newPosition寮�濮嬪悜鍚庡鎵撅紙寰幆锛夌洿鍒版壘鍒颁竴涓┖浣嶇疆锛堟敞鎰忓彇妯★級锛岀劧鍚庢斁鍏ャ�俓n 3. 杩欐牱锛屾瘡涓瓧绗﹂兘浼氳鏀惧叆锛屼笖涓嶄細瑕嗙洊銆俓n\n 浣嗘槸锛岃繖鏍峰彲鑳戒細瀵艰嚧鏌愪簺瀛楃琚斁鍦ㄨ窛绂荤洰鏍囦綅缃緝杩滅殑鍦版柟锛岃�屼笖椤哄簭鍙兘浼氳鎵撲贡锛堜絾鑷冲皯姣忎釜浣嶇疆閮芥湁瀛楃锛屼笖涓嶄細瑕嗙洊锛夈�俓n\n 浣嗘槸锛岃繖鏍蜂慨鏀瑰悗锛屽瓧绗︾殑浣嶇疆涓嶄粎鍙栧喅浜庡師濮嬩綅缃拰shift锛岃繕鍙栧喅浜庡啿绐佽В鍐崇殑鎯呭喌銆傝�屼笖锛屽鏋滄暟缁勬弧浜嗭紝鎴戜滑涓�瀹氳兘鎵惧埌绌轰綅鍚楋紵鐢变簬鎴戜滑閬嶅巻姣忎釜瀛楃锛屾瘡涓瓧绗﹂兘闇�瑕佹斁缃竴娆★紝鑰屾暟缁勯暱搴︽濂芥槸瀛楃涓暟锛屾墍浠ヤ竴瀹氬彲浠ユ壘鍒扮┖浣嶏紙鍥犱负鎬诲叡鏈塴ength涓綅缃紝鎴戜滑瑕佹斁length涓瓧绗︼紝涓斿啿绐佹椂鎴戜滑绾挎�ф帰娴嬬洿鍒版壘鍒扮┖浣嶏紝鎵�浠ユ渶缁堟瘡涓瓧绗﹂兘浼氳鏀剧疆锛屼笖涓嶄細瑕嗙洊锛夈�俓n\n 浣嗘槸锛岀嚎鎬ф帰娴嬪彲鑳戒細瀵艰嚧鎬ц兘闂锛堝鏋滃啿绐佸锛岄渶瑕侀亶鍘嗗緢澶氫綅缃級锛屼絾length涓嶄細澶ぇ锛堟縺娲荤爜涓�鑸笉浼氬お闀匡級锛屾墍浠ュ彲浠ユ帴鍙椼�俓n\n 淇敼浠g爜锛歕n\n 鎴戜滑淇敼寰幆閮ㄥ垎锛歕n\n 鍘熶唬鐮侊細\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n // 宸茬粡绉婚櫎浜�'-'锛屾墍浠ヤ笉闇�瑕佸垽鏂烦杩嘰n if (!mappingDict.TryGetValue(current, out var mapping))\n throw new InvalidOperationException($\"鏃犳晥瀛楃: {current}\");\n\n int newPosition = (i + mapping.shift) % length;\n char mappedChar = (i % 5 == 4) ? ApplySpecialTransform(mapping.output, i) : mapping.output;\n\n result[newPosition] = mappedChar;\n }\n\n 淇敼涓猴細\n\n // 鍒濆鍖栫粨鏋滄暟缁勶紝鐢�'\\0'琛ㄧず绌轰綅\n char[] result = new char[length];\n // 鎴戜滑涓嶉渶瑕佹樉寮忚祴鍊间负'\\0'锛屽洜涓簄ew char鏁扮粍榛樿灏辨槸'\\0'\n\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n if (!mappingDict.TryGetValue(current, out var mapping))\n throw new InvalidOperationException($\"鏃犳晥瀛楃: {current}\");\n\n char mappedChar = (i % 5 == 4) ? ApplySpecialTransform(mapping.output, i) : mapping.output;\n\n int newPosition = (i + mapping.shift) % length;\n\n // 濡傛灉鐩爣浣嶇疆宸茬粡琚崰鐢紝鍒欏鎵句笅涓�涓┖浣嶇疆锛堢嚎鎬ф帰娴嬶級\n while (result[newPosition] != '\\0')\n {\n newPosition = (newPosition + 1) % length; // 鍚戝悗绉诲姩涓�浣嶏紝濡傛灉鍒版湯灏惧垯鍥炲埌寮�澶碶n }\n result[newPosition] = mappedChar;\n }\n\n 杩欐牱锛屽鏋滆绠楀嚭鐨勪綅缃凡缁忚鍗犵敤锛屾垜浠氨鍚戝悗涓�涓竴涓壘锛岀洿鍒版壘鍒扮┖浣嶇疆銆俓n\n 浣嗘槸锛岃繖鏍蜂慨鏀瑰悗锛屽瓧绗︾殑浣嶇疆鍙兘浼氬洜涓哄啿绐佽�屾敼鍙橈紝浣嗚嚦灏戜繚璇佷簡姣忎釜浣嶇疆閮芥湁瀛楃锛屼笖涓嶄細瑕嗙洊銆俓n\n 浣嗘槸锛岀敤鎴风殑闂鎻忚堪鏄�滄暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濓紝鍙兘鏄寚缁撴灉鏁扮粍涓湁浣嶇疆娌℃湁琚祴鍊硷紙鍗宠繕鏄垵濮嬪��'\\0'锛夈�傛垜浠笂闈㈢殑淇敼淇濊瘉浜嗘瘡涓綅缃兘浼氳璧嬪�硷紙鍥犱负鎴戜滑鏀剧疆浜唋ength涓瓧绗︼紝涓旈�氳繃绾挎�ф帰娴嬮伩鍏嶄簡鍐茬獊锛屾墍浠ユ瘡涓綅缃兘浼氳璧嬪�间竴娆★級銆傛墍浠ワ紝杩欎釜淇敼搴旇鑳借В鍐抽棶棰樸�俓n\n 浣嗘槸锛屾垜浠篃瑕佹敞鎰忥紝绾挎�ф帰娴嬪彲鑳戒細瀵艰嚧瀛楃鐨勯『搴忎笌鍘熷璁捐鎰忓浘鏈夊亸宸紙鍥犱负鍐茬獊鏃跺瓧绗﹁鍚庣Щ浜嗭級銆傚師濮嬭璁℃剰鍥惧彲鑳芥槸姣忎釜瀛楃涓ユ牸鍦版斁鍦�(i+shift)%length鐨勪綅缃紝鍗充娇瑕嗙洊涔熶笉绠★紙浣嗚鐩栦細瀵艰嚧鏁版嵁涓㈠け锛夈�傜幇鍦紝鎴戜滑閫氳繃绾挎�ф帰娴嬮伩鍏嶄簡瑕嗙洊锛屼絾浣嶇疆鍙戠敓浜嗗彉鍖栥�俓n\n 鍙﹀锛屾垜浠繕闇�瑕佽�冭檻锛氬鏋滃師濮嬪瓧绗︿覆涓湁閲嶅瀛楃锛岄偅涔堟槧灏勫悗鐨勫瓧绗︿篃鍙兘閲嶅锛岃繖娌″叧绯伙紝鍥犱负姣忎釜瀛楃閮芥槸鐙珛澶勭悊鐨勩�俓n\n 鍥犳锛屾垜浠寜鐓т笂杩版�濊矾淇敼浠g爜銆俓n\n 娉ㄦ剰锛氱敱浜庢垜浠慨鏀逛簡浣嶇疆鍒嗛厤绠楁硶锛屽彲鑳戒細褰卞搷婵�娲荤爜鐨勭敓鎴愯鍒欍�備絾鐢ㄦ埛瑕佹眰淇瑕嗙洊鍜岀┖浣嶇殑闂锛屾墍浠ヨ繖鏄繀瑕佺殑銆俓n\n 淇敼鍚庣殑浠g爜锛歕n\n 鎴戜滑灏嗗惊鐜唴鐨勮祴鍊兼敼涓轰娇鐢ㄧ嚎鎬ф帰娴嬭В鍐冲啿绐併�俓n\n 浣嗘槸锛屾垜浠繕闇�瑕佹敞鎰忥細鍘熷浠g爜涓紝濡傛灉閬囧埌鐩稿悓鐨勪綅缃紝鍚庡鐞嗙殑瀛楃浼氳鐩栧厛澶勭悊鐨勫瓧绗︺�傜幇鍦紝鎴戜滑璁╁悗澶勭悊鐨勫瓧绗﹀悜鍚庡鎵剧┖浣嶏紝杩欐牱鍏堝鐞嗙殑瀛楃浼氬崰鎹畠璁$畻鐨勪綅缃紝鍚庡鐞嗙殑瀛楃濡傛灉鍐茬獊灏卞悗绉汇�傝繖鏍凤紝缁撴灉瀛楃涓蹭腑瀛楃鐨勯『搴忓彲鑳戒細涓庡師濮嬭璁℃湁杈冨ぇ涓嶅悓锛堢壒鍒槸褰撳啿绐佽緝澶氭椂锛夈�俓n\n 濡傛灉鐢ㄦ埛甯屾湜淇濇寔鍘熷璁捐鎰忓浘锛堝嵆姣忎釜瀛楃鐨勪綅缃敱(i+shift)%length鍞竴纭畾锛屼笉鍏佽鍐茬獊锛夛紝閭d箞鎴戜滑蹇呴』纭繚姣忎釜瀛楃鐨�(i+shift)%length閮芥槸鍞竴鐨勩�備絾杩欏緢闅句繚璇侊紝鍥犱负shift鏄瘡涓瓧绗﹁嚜宸卞喅瀹氱殑锛岃�宨鏄繛缁殑锛屾墍浠ュ綋涓や釜瀛楃鐨�(i1+shift1) % length 绛変簬 (i2+shift2) % length鏃讹紝鍐茬獊灏变細鍙戠敓銆俓n\n 鎵�浠ワ紝鎴戜滑鍙兘閫氳繃鍐茬獊瑙e喅鏈哄埗鏉ラ伩鍏嶈鐩栥�俓n\n 鍥犳锛屾垜浠噰鐢ㄧ嚎鎬ф帰娴嬨�俓n\n 淇敼鍚庣殑浠g爜锛歕n\n 娉ㄦ剰锛氭垜浠笉闇�瑕佹敼鍙樼壒娈婂彉鎹㈢殑閮ㄥ垎锛屽彧闇�瑕佹敼鍙樻斁缃瓧绗︾殑閫昏緫銆俓n\n 鎴戜滑杈撳嚭淇敼鍚庣殑鏁翠釜鏂规硶銆俓n\n 鍙﹀锛岀敤鎴疯姹備娇鐢ㄤ腑鏂囧洖绛旓紝浣嗕唬鐮侀儴鍒嗚繕鏄疌#浠g爜銆俓n\n 鎴戜滑閲嶅啓鏁翠釜鏂规硶锛屽彧淇敼鍐茬獊閮ㄥ垎銆俓n</think>\n\n鏍规嵁鎮ㄦ弿杩扮殑闂锛屼唬鐮佷腑鐨勪綅缃亸绉荤畻娉曠‘瀹炲瓨鍦ㄧ己闄枫�備富瑕侀棶棰樻槸褰撳涓瓧绗﹁绠楀嚭鐨勬柊浣嶇疆鐩稿悓鏃讹紝鍚庡啓鍏ョ殑瀛楃浼氳鐩栧墠涓�涓瓧绗︼紝瀵艰嚧閮ㄥ垎鏁版嵁涓㈠け銆備互涓嬫槸淇鍚庣殑浠g爜锛歕n\n```CSharp\npublic string GenerateActivationCode(string baseRandom)\n{\n baseRandom = baseRandom.Replace(\"-\", string.Empty);\n Dictionary<char, (char output, int shift)> mappingDict = _charMappingRepository.QueryData()\n .ToDictionary(x => x.InputChar[0], x => (x.OutputChar[0], x.ShiftFactor));\n\n char[] result = new char[baseRandom.Length];\n bool[] positionFilled = new bool[baseRandom.Length]; // 鏂板浣嶇疆鏍囪鏁扮粍\n int length = baseRandom.Length;\n\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n if (!mappingDict.TryGetValue(current, out var mapping))\n throw new InvalidOperationException($\"鏃犳晥瀛楃: {current}\");\n\n // 搴旂敤浣嶇疆鍋忕Щ绠楁硶\n int newPosition = (i + mapping.shift) % length;\n \n // 澶勭悊浣嶇疆鍐茬獊锛氭壘鍒颁笅涓�涓彲鐢ㄤ綅缃甛n while (positionFilled[newPosition]) \n {\n newPosition = (newPosition + 1) % length;\n }\n\n // 鐗规畩鍙樻崲\n char mappedChar = (i % 5 == 4) \n ? ApplySpecialTransform(mapping.output, i) \n : mapping.output;\n\n result[newPosition] = mappedChar;\n positionFilled[newPosition] = true; // 鏍囪浣嶇疆宸蹭娇鐢╘n }\n\n return FormatCode(new string(result));\n}\n```\n\n涓昏淇敼鐐癸細\n1. 娣诲姞浜哷positionFilled`鏁扮粍璺熻釜姣忎釜浣嶇疆鏄惁宸茶鍗犵敤\n2. 褰撹绠楀嚭鐨勬柊浣嶇疆宸茶鍗犵敤鏃讹紝浣跨敤寰幆鏌ユ壘涓嬩竴涓彲鐢ㄤ綅缃甛n3. 纭繚姣忎釜瀛楃閮借鍐欏叆涓斾笉浼氳鐩栧凡鏈夋暟鎹甛n4. 绉婚櫎浜嗗浣欑殑`-`瀛楃妫�鏌ワ紙宸插湪鍓嶇疆澶勭悊涓Щ闄わ級\n\n姝や慨鏀归�氳繃浣嶇疆鍐茬獊妫�娴嬫満鍒剁‘淇濈粨鏋滄暟缁勪腑鐨勬瘡涓綅缃兘浼氳姝g‘濉厖锛岃В鍐充簡鏁版嵁涓㈠け闂銆�","columns":[6,73,5,95,94,-1,130,-1,5,76,-1,93,-1,341,-1,305,-1,302,-1,48,-1,76,-1,133,-1,186,-1,139,-1,110,-1,5,33,57,27,91,-1,31,-1,64,-1,77,-1,68,-1,67,-1,38,-1,121,-1,76,-1,3,26,15,48,31,54,22,-1,59,-1,177,-1,63,-1,5,-1,9,-1,4,36,5,37,29,63,68,-1,55,99,-1,41,5,-1,4,-1,24,37,42,-1,36,5,37,63,68,-1,99,-1,55,-1,38,43,9,74,9,41,5,-1,36,-1,46,-1,140,-1,132,-1,58,-1,16,-1,55,-1,7,-1,22,-1,133,-1,180,-1,21,-1,12,-1,7,-1,31,-1,13,-1,26,-1,17,7,-1,80,-1,8,54,0,54,94,81,-1,47,67,34,-1,35,4,36,62,67,-1,18,54,7,26,43,8,52,8,-1,14,38,54,28,-1,40,53,4,-1,41,0,0,-1,5,35,29,21,26,-1]},"source":null,"error":null,"id":"01987cf3f3df711cb076b852aeb05f4b","localReferences":[{"uri":{"scheme":"file","authority":"","path":"file:///E:/0.椤圭洰闆�/瀹芥捣/SMTFangCuoPDA/浠g爜绠$悊/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ActivationCodeService.cs","query":"","fragment":""},"range":[{"character":7,"line":21},{"character":8,"line":50}],"isRequestStage":true}],"references":[{"uri":{"scheme":"file","authority":"","path":"file:///E:/0.椤圭洰闆�/瀹芥捣/SMTFangCuoPDA/浠g爜绠$悊/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ActivationCodeService.cs","query":"","fragment":""},"range":[{"character":0,"line":30},{"character":0,"line":70}],"text":null,"isSourceFile":true}],"followup":null,"topic":"","score":null,"command":"","changeToOptimize":null,"button":null,"knowledge":null,"knowledgeReferences":[],"knowledgeStatus":null,"variables":null,"selectedRange":null,"actions":[],"selectedRanges":null,"createdAt":1754443143330},{"role":"user","content":"缁欒繖娈典唬鐮佷腑锛屾坊鍔犳暟缁勪腑鏈鏇挎崲鐨勫�肩殑澶勭悊","isTips":null,"cost":0,"parser":{"nodes":[{"type":"line","content":"缁欒繖娈典唬鐮佷腑锛屾坊鍔犳暟缁勪腑鏈鏇挎崲鐨勫�肩殑澶勭悊","contentId":-1254624024,"children":[],"parent":null,"settled":false,"xmlData":{}}],"parserState":{"line":0,"column":20,"offset":21,"metadata":false,"buffer":"","closing":false,"currentParent":null,"moveCursor":true,"tagBuffer":"","isCollectingTag":false},"content":"缁欒繖娈典唬鐮佷腑锛屾坊鍔犳暟缁勪腑鏈鏇挎崲鐨勫�肩殑澶勭悊","columns":[]},"source":null,"error":null,"id":null,"localReferences":[],"references":null,"followup":null,"topic":"","score":null,"command":"","changeToOptimize":null,"button":null,"knowledge":null,"knowledgeReferences":null,"knowledgeStatus":null,"variables":[],"selectedRange":null,"actions":null,"selectedRanges":[],"createdAt":1754443345736},{"role":"assistant","content":"<think>\n鎴戜滑涔嬪墠宸茬粡娣诲姞浜嗕綅缃爣璁版暟缁刞positionFilled`鏉ヨ窡韪瘡涓綅缃槸鍚﹁濉厖銆備絾鏄紝濡傛灉鍥犱负鏌愪簺鍘熷洜锛堟瘮濡傛墍鏈変綅缃兘琚皾璇曡繃锛夎�屼粛鐒舵湁鏈~鍏呯殑浣嶇疆锛岄偅涔堟垜浠渶瑕佺‘淇濊繖浜涗綅缃濉厖銆俓n 鐒惰�岋紝鍦ㄦ垜浠殑寰幆涓紝鎴戜滑涓烘瘡涓緭鍏ュ瓧绗﹂兘鎵惧埌浜嗕竴涓綅缃紙閫氳繃绾挎�ф帰娴嬫硶锛夛紝鎵�浠ョ悊璁轰笂姣忎釜浣嶇疆閮戒細琚~鍏呬竴娆°�傚洜涓烘垜浠湁n涓瓧绗﹀拰n涓綅缃紝骞朵笖鎴戜滑浣跨敤鍙栨ā杩愮畻寰幆鏌ユ壘锛屾墍浠ユ渶缁堟瘡涓綅缃兘浼氳濉厖銆傚洜姝わ紝瀹為檯涓婁笉浼氬嚭鐜版湭琚浛鎹㈢殑鍊笺�俓n\n 浣嗘槸锛屼负浜嗙‘淇濅唬鐮佺殑鍋ュ.鎬э紝鎴戜滑鍙互娣诲姞涓�涓鏌ワ細鍦ㄥ惊鐜粨鏉熷悗锛屾鏌ユ槸鍚︽墍鏈変綅缃兘琚~鍏呫�傚鏋滄病鏈夛紝鍒欒鏄庣畻娉曟湁璇紝鎴戜滑鍙互鎶涘嚭寮傚父銆俓n\n 涓嶈繃锛屾牴鎹棶棰樻弿杩帮紝鐢ㄦ埛瑕佹眰鈥滄坊鍔犳暟缁勪腑鏈鏇挎崲鐨勫�肩殑澶勭悊鈥濄�傝繖閲屽彲鑳芥槸鎸囷紝濡傛灉鏌愪釜浣嶇疆娌℃湁琚浛鎹紙鍗虫病鏈夎璧嬪�硷級锛岄偅涔堟垜浠渶瑕佺粰瀹冧竴涓粯璁ゅ�硷紵浣嗘牴鎹垜浠殑绠楁硶锛屾瘡涓綅缃兘浼氳璧嬪�间竴娆★紝鎵�浠ヤ笉浼氬嚭鐜版湭鏇挎崲鐨勫�笺�俓n\n 浣嗘槸锛屽鏋滅敤鎴锋媴蹇冨湪鏋佺鎯呭喌涓嬶紙姣斿鏄犲皠瀛楀吀涓己灏戝瓧绗﹀鑷村紓甯革紝浣嗘垜浠凡缁忓鐞嗕簡缂哄け瀛楃鐨勬儏鍐碉級鎴栬�呭惊鐜帰娴嬮�昏緫鏈夌己闄凤紝鎴戜滑鍙互娣诲姞涓�涓悗澶囧鐞嗭細鍦ㄨ繑鍥炵粨鏋滀箣鍓嶏紝妫�鏌positionFilled`鏁扮粍锛屽鏋滄湁鏈~鍏呯殑浣嶇疆锛屽垯鐢ㄦ煇涓粯璁ゅ瓧绗︼紙姣斿鍘熷瓧绗︿覆涓搴斾綅缃殑瀛楃锛熶絾鍘熷瓧绗︿覆宸茬粡琚墦涔憋級濉厖銆備絾杩欐牱閫昏緫灏卞彉寰楀鏉備簡銆俓n\n 瀹為檯涓婏紝鎴戜滑鐨勭畻娉曞凡缁忎繚璇佷簡姣忎釜浣嶇疆閮戒細琚~鍏呫�傚洜姝わ紝鎴戜滑鍙互閫夋嫨鍦ㄦ渶鍚庢坊鍔犱竴涓鏌ワ紝濡傛灉鍙戠幇杩樻湁鏈~鍏呯殑浣嶇疆锛屽垯璁板綍閿欒鎴栦娇鐢ㄥ師瀛楃涓茬殑瀛楃濉厖銆備絾杩欐牱鍙兘浼氬紩鍏ユ柊鐨勯棶棰樸�俓n\n 鑰冭檻鍒板師闂鎻忚堪鏄�滄暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濓紝鑰屾垜浠凡缁忛�氳繃绾挎�ф帰娴嬫硶淇濊瘉浜嗘瘡涓綅缃兘琚~鍏咃紝鎵�浠ヨ繖閲屾垜浠笉闇�瑕侀澶栧鐞嗐�備絾鏄紝涓轰簡婊¤冻鐢ㄦ埛瑕佹眰锛屾垜浠彲浠ユ坊鍔犱竴涓鏌ワ紝濡傛灉杩樻湁鏈~鍏呯殑浣嶇疆锛屽垯鐢ㄥ師瀛楃涓蹭腑瀵瑰簲浣嶇疆鐨勫瓧绗﹀~鍏咃紙浣嗘敞鎰忥紝鍘熷瓧绗︿覆宸茬粡琚鐞嗭紝鎴戜滑骞舵病鏈変繚鐣欏師鏁扮粍鐨勫浠斤紝鎵�浠ヤ笉鍙锛夈�俓n\n 鍙︿竴绉嶈В閲婏細鐢ㄦ埛鍙兘鏄寚鍘熷瓧绗︿覆涓殑姣忎釜瀛楃閮藉繀椤昏澶勭悊锛堝嵆琚槧灏勶級锛熸垜浠殑浠g爜宸茬粡纭繚姣忎釜瀛楃閮借澶勭悊骞舵斁鍏ョ粨鏋滄暟缁勭殑鏌愪釜浣嶇疆銆俓n\n 鍥犳锛屾垜寤鸿涓嶆坊鍔犻澶栫殑澶勭悊锛屽洜涓虹畻娉曞凡缁忎繚璇佷簡姣忎釜浣嶇疆閮戒細琚~鍏呫�備絾鏄紝濡傛灉鐢ㄦ埛鍧氭寔瑕佸鐞嗏�滄湭琚浛鎹㈢殑鍊尖�濓紝鎴戜滑鍙互鐞嗚В涓猴細鍦ㄧ粨鏋滄暟缁勪腑锛屽鏋滄煇涓綅缃病鏈夎璧嬪�硷紙鍗宠繕鏄垵濮嬪�糮\\0`锛夛紝閭d箞鎴戜滑灏辩敤鍘熷瓧绗︿覆涓搴斾綅缃殑瀛楃锛堜絾杩欐牱浼氱牬鍧忕畻娉曪級锛熻繖鏄剧劧涓嶆槸鎴戜滑鎯宠鐨勩�俓n\n 閲嶆柊闃呰鐢ㄦ埛鐨勯棶棰橈細鈥滄坊鍔犳暟缁勪腑鏈鏇挎崲鐨勫�肩殑澶勭悊鈥濄�傝繖閲屽彲鑳芥槸鎸囷紝鍦ㄤ綅缃亸绉荤畻娉曚腑锛屽鏋滄煇涓綅缃病鏈夎鏇挎崲锛堝嵆娌℃湁琚鐩栵級锛岄偅涔堜繚鐣欏畠鍘熸潵鐨勫�硷紵浣嗘槸锛屽湪鍘熷浠g爜涓紝鎴戜滑骞舵病鏈変繚鐣欏師鏁扮粍鐨勫�硷紝鑰屾槸鍒涘缓浜嗕竴涓柊鐨勬暟缁勶紙鍒濆鍖栦负`\\0`锛夈�傛墍浠ワ紝鍦ㄥ師濮嬩唬鐮佷腑锛屽鏋滄煇涓綅缃病鏈夎璧嬪�硷紝閭d箞瀹冨氨鏄痐\\0`锛岃繖鏄剧劧鏄笉瀵圭殑銆俓n\n 鍥犳锛屾垜浠幇鍦ㄧ殑绠楁硶宸茬粡閫氳繃`positionFilled`鏁扮粍鍜岀嚎鎬ф帰娴嬬‘淇濅簡姣忎釜浣嶇疆閮借璧嬪�笺�傛墍浠ワ紝鎴戜滑涓嶉渶瑕侀澶栧鐞嗐�俓n\n 浣嗘槸锛屼负浜嗕唬鐮佺殑鍋ュ.鎬э紝鎴戜滑鍙互鍦ㄥ惊鐜粨鏉熷悗妫�鏌positionFilled`鏁扮粍鏄惁鍏ㄩ儴涓簍rue锛屽鏋滀笉鏄紝鍒欒鏄庢湁浣嶇疆娌℃湁琚~鍏咃紝鎴戜滑鍙互鎶涘嚭涓�涓紓甯革紝杩欐牱鍦ㄦ祴璇曢樁娈靛氨鑳藉彂鐜伴棶棰樸�俓n\n 淇敼锛氬湪杩斿洖缁撴灉涔嬪墠锛屾鏌positionFilled`鏁扮粍锛屽鏋滄湁浠讳綍涓�涓綅缃槸false锛屽垯鎶涘嚭寮傚父銆俓n\n 浠g爜淇敼濡備笅锛歕n\n 鍦╮eturn涔嬪墠娣诲姞锛歕n```csharp\n if (positionFilled.Any(filled => !filled))\n throw new InvalidOperationException(\"绠楁硶閿欒锛氬瓨鍦ㄦ湭濉厖鐨勪綅缃甛");\n```\n\n 浣嗘槸锛岀敱浜庢垜浠箣鍓嶅凡缁忛�氳繃寰幆涓烘瘡涓瓧绗﹂兘鎵惧埌浜嗕綅缃紝鎵�浠ヨ繖涓紓甯哥悊璁轰笂姘歌繙涓嶄細鎶涘嚭銆傛墍浠ワ紝杩欏彧鏄竴涓畨鍏ㄦ帾鏂姐�俓n\n 鍥犳锛屽畬鏁寸殑浠g爜淇敼濡備笅锛歕n</think>\n\n濂界殑锛屾垜宸茬悊瑙f偍鐨勮姹傘�備互涓嬫槸淇敼鍚庣殑浠g爜锛屾坊鍔犱簡瀵规湭鏇挎崲浣嶇疆鐨勫鐞嗭細\n\n```CSharp\npublic string GenerateActivationCode(string baseRandom)\n{\n baseRandom = baseRandom.Replace(\"-\", string.Empty);\n Dictionary<char, (char output, int shift)> mappingDict = _charMappingRepository.QueryData()\n .ToDictionary(x => x.InputChar[0], x => (x.OutputChar[0], x.ShiftFactor));\n\n char[] result = new char[baseRandom.Length];\n bool[] positionFilled = new bool[baseRandom.Length];\n int length = baseRandom.Length;\n\n // 鍒濆鍖栫粨鏋滄暟缁勪负鍘熷瀛楃锛堜綔涓烘湭鏇挎崲鏃剁殑榛樿鍊硷級\n for (int i = 0; i < length; i++)\n {\n result[i] = baseRandom[i];\n }\n\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n if (!mappingDict.TryGetValue(current, out var mapping))\n continue; // 璺宠繃鏃犳晥瀛楃锛屼繚鐣欏師濮嬪�糪n\n int newPosition = (i + mapping.shift) % length;\n int attempts = 0;\n \n // 鏌ユ壘鍙敤浣嶇疆锛堟渶澶氬皾璇曟暣涓暟缁勯暱搴︼級\n while (positionFilled[newPosition] && attempts < length)\n {\n newPosition = (newPosition + 1) % length;\n attempts++;\n }\n\n // 搴旂敤鐗规畩鍙樻崲\n char mappedChar = (i % 5 == 4) \n ? ApplySpecialTransform(mapping.output, i) \n : mapping.output;\n\n // 浠呭綋鎵惧埌鏈夋晥浣嶇疆鏃舵墠鏇挎崲\n if (attempts < length)\n {\n result[newPosition] = mappedChar;\n positionFilled[newPosition] = true;\n }\n }\n\n return FormatCode(new string(result));\n}\n```\n\n涓昏鏀硅繘锛歕n1. **鍒濆鍖栫粨鏋滄暟缁�**锛氫娇鐢ㄥ師濮嬪瓧绗﹀~鍏呯粨鏋滄暟缁勪綔涓洪粯璁ゅ�糪n2. **璺宠繃鏃犳晥瀛楃**锛氬綋閬囧埌鏃犳晥瀛楃鏃朵娇鐢� `continue` 淇濈暀鍘熷鍊糪n3. **娣诲姞灏濊瘯闄愬埗**锛氳缃渶澶у皾璇曟鏁伴伩鍏嶆寰幆\n4. **鏉′欢鏇挎崲**锛氫粎褰撴壘鍒版湁鏁堜綅缃椂鎵嶆浛鎹㈠瓧绗n5. **淇濈暀鍘熷鍊�**锛氭湭鎴愬姛鏇挎崲鐨勪綅缃繚鎸佸師濮嬪瓧绗︿笉鍙榎n\n杩欐牱纭繚锛歕n- 鎵�鏈変綅缃兘鏈夋湁鏁堝瓧绗n- 鏈垚鍔熸浛鎹㈢殑浣嶇疆淇濈暀鍘熷鍊糪n- 閬垮厤鏃犻檺寰幆\n- 鎵�鏈夊瓧绗﹂兘浼氳姝g‘澶勭悊undefined","isTips":null,"cost":49131,"parser":{"nodes":[{"type":"reasoning","content":"<think>\n鎴戜滑涔嬪墠宸茬粡娣诲姞浜嗕綅缃爣璁版暟缁刞positionFilled`鏉ヨ窡韪瘡涓綅缃槸鍚﹁濉厖銆備絾鏄紝濡傛灉鍥犱负鏌愪簺鍘熷洜锛堟瘮濡傛墍鏈変綅缃兘琚皾璇曡繃锛夎�屼粛鐒舵湁鏈~鍏呯殑浣嶇疆锛岄偅涔堟垜浠渶瑕佺‘淇濊繖浜涗綅缃濉厖銆俓n 鐒惰�岋紝鍦ㄦ垜浠殑寰幆涓紝鎴戜滑涓烘瘡涓緭鍏ュ瓧绗﹂兘鎵惧埌浜嗕竴涓綅缃紙閫氳繃绾挎�ф帰娴嬫硶锛夛紝鎵�浠ョ悊璁轰笂姣忎釜浣嶇疆閮戒細琚~鍏呬竴娆°�傚洜涓烘垜浠湁n涓瓧绗﹀拰n涓綅缃紝骞朵笖鎴戜滑浣跨敤鍙栨ā杩愮畻寰幆鏌ユ壘锛屾墍浠ユ渶缁堟瘡涓綅缃兘浼氳濉厖銆傚洜姝わ紝瀹為檯涓婁笉浼氬嚭鐜版湭琚浛鎹㈢殑鍊笺�俓n\n 浣嗘槸锛屼负浜嗙‘淇濅唬鐮佺殑鍋ュ.鎬э紝鎴戜滑鍙互娣诲姞涓�涓鏌ワ細鍦ㄥ惊鐜粨鏉熷悗锛屾鏌ユ槸鍚︽墍鏈変綅缃兘琚~鍏呫�傚鏋滄病鏈夛紝鍒欒鏄庣畻娉曟湁璇紝鎴戜滑鍙互鎶涘嚭寮傚父銆俓n\n 涓嶈繃锛屾牴鎹棶棰樻弿杩帮紝鐢ㄦ埛瑕佹眰鈥滄坊鍔犳暟缁勪腑鏈鏇挎崲鐨勫�肩殑澶勭悊鈥濄�傝繖閲屽彲鑳芥槸鎸囷紝濡傛灉鏌愪釜浣嶇疆娌℃湁琚浛鎹紙鍗虫病鏈夎璧嬪�硷級锛岄偅涔堟垜浠渶瑕佺粰瀹冧竴涓粯璁ゅ�硷紵浣嗘牴鎹垜浠殑绠楁硶锛屾瘡涓綅缃兘浼氳璧嬪�间竴娆★紝鎵�浠ヤ笉浼氬嚭鐜版湭鏇挎崲鐨勫�笺�俓n\n 浣嗘槸锛屽鏋滅敤鎴锋媴蹇冨湪鏋佺鎯呭喌涓嬶紙姣斿鏄犲皠瀛楀吀涓己灏戝瓧绗﹀鑷村紓甯革紝浣嗘垜浠凡缁忓鐞嗕簡缂哄け瀛楃鐨勬儏鍐碉級鎴栬�呭惊鐜帰娴嬮�昏緫鏈夌己闄凤紝鎴戜滑鍙互娣诲姞涓�涓悗澶囧鐞嗭細鍦ㄨ繑鍥炵粨鏋滀箣鍓嶏紝妫�鏌positionFilled`鏁扮粍锛屽鏋滄湁鏈~鍏呯殑浣嶇疆锛屽垯鐢ㄦ煇涓粯璁ゅ瓧绗︼紙姣斿鍘熷瓧绗︿覆涓搴斾綅缃殑瀛楃锛熶絾鍘熷瓧绗︿覆宸茬粡琚墦涔憋級濉厖銆備絾杩欐牱閫昏緫灏卞彉寰楀鏉備簡銆俓n\n 瀹為檯涓婏紝鎴戜滑鐨勭畻娉曞凡缁忎繚璇佷簡姣忎釜浣嶇疆閮戒細琚~鍏呫�傚洜姝わ紝鎴戜滑鍙互閫夋嫨鍦ㄦ渶鍚庢坊鍔犱竴涓鏌ワ紝濡傛灉鍙戠幇杩樻湁鏈~鍏呯殑浣嶇疆锛屽垯璁板綍閿欒鎴栦娇鐢ㄥ師瀛楃涓茬殑瀛楃濉厖銆備絾杩欐牱鍙兘浼氬紩鍏ユ柊鐨勯棶棰樸�俓n\n 鑰冭檻鍒板師闂鎻忚堪鏄�滄暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濓紝鑰屾垜浠凡缁忛�氳繃绾挎�ф帰娴嬫硶淇濊瘉浜嗘瘡涓綅缃兘琚~鍏咃紝鎵�浠ヨ繖閲屾垜浠笉闇�瑕侀澶栧鐞嗐�備絾鏄紝涓轰簡婊¤冻鐢ㄦ埛瑕佹眰锛屾垜浠彲浠ユ坊鍔犱竴涓鏌ワ紝濡傛灉杩樻湁鏈~鍏呯殑浣嶇疆锛屽垯鐢ㄥ師瀛楃涓蹭腑瀵瑰簲浣嶇疆鐨勫瓧绗﹀~鍏咃紙浣嗘敞鎰忥紝鍘熷瓧绗︿覆宸茬粡琚鐞嗭紝鎴戜滑骞舵病鏈変繚鐣欏師鏁扮粍鐨勫浠斤紝鎵�浠ヤ笉鍙锛夈�俓n\n 鍙︿竴绉嶈В閲婏細鐢ㄦ埛鍙兘鏄寚鍘熷瓧绗︿覆涓殑姣忎釜瀛楃閮藉繀椤昏澶勭悊锛堝嵆琚槧灏勶級锛熸垜浠殑浠g爜宸茬粡纭繚姣忎釜瀛楃閮借澶勭悊骞舵斁鍏ョ粨鏋滄暟缁勭殑鏌愪釜浣嶇疆銆俓n\n 鍥犳锛屾垜寤鸿涓嶆坊鍔犻澶栫殑澶勭悊锛屽洜涓虹畻娉曞凡缁忎繚璇佷簡姣忎釜浣嶇疆閮戒細琚~鍏呫�備絾鏄紝濡傛灉鐢ㄦ埛鍧氭寔瑕佸鐞嗏�滄湭琚浛鎹㈢殑鍊尖�濓紝鎴戜滑鍙互鐞嗚В涓猴細鍦ㄧ粨鏋滄暟缁勪腑锛屽鏋滄煇涓綅缃病鏈夎璧嬪�硷紙鍗宠繕鏄垵濮嬪�糮\\0`锛夛紝閭d箞鎴戜滑灏辩敤鍘熷瓧绗︿覆涓搴斾綅缃殑瀛楃锛堜絾杩欐牱浼氱牬鍧忕畻娉曪級锛熻繖鏄剧劧涓嶆槸鎴戜滑鎯宠鐨勩�俓n\n 閲嶆柊闃呰鐢ㄦ埛鐨勯棶棰橈細鈥滄坊鍔犳暟缁勪腑鏈鏇挎崲鐨勫�肩殑澶勭悊鈥濄�傝繖閲屽彲鑳芥槸鎸囷紝鍦ㄤ綅缃亸绉荤畻娉曚腑锛屽鏋滄煇涓綅缃病鏈夎鏇挎崲锛堝嵆娌℃湁琚鐩栵級锛岄偅涔堜繚鐣欏畠鍘熸潵鐨勫�硷紵浣嗘槸锛屽湪鍘熷浠g爜涓紝鎴戜滑骞舵病鏈変繚鐣欏師鏁扮粍鐨勫�硷紝鑰屾槸鍒涘缓浜嗕竴涓柊鐨勬暟缁勶紙鍒濆鍖栦负`\\0`锛夈�傛墍浠ワ紝鍦ㄥ師濮嬩唬鐮佷腑锛屽鏋滄煇涓綅缃病鏈夎璧嬪�硷紝閭d箞瀹冨氨鏄痐\\0`锛岃繖鏄剧劧鏄笉瀵圭殑銆俓n\n 鍥犳锛屾垜浠幇鍦ㄧ殑绠楁硶宸茬粡閫氳繃`positionFilled`鏁扮粍鍜岀嚎鎬ф帰娴嬬‘淇濅簡姣忎釜浣嶇疆閮借璧嬪�笺�傛墍浠ワ紝鎴戜滑涓嶉渶瑕侀澶栧鐞嗐�俓n\n 浣嗘槸锛屼负浜嗕唬鐮佺殑鍋ュ.鎬э紝鎴戜滑鍙互鍦ㄥ惊鐜粨鏉熷悗妫�鏌positionFilled`鏁扮粍鏄惁鍏ㄩ儴涓簍rue锛屽鏋滀笉鏄紝鍒欒鏄庢湁浣嶇疆娌℃湁琚~鍏咃紝鎴戜滑鍙互鎶涘嚭涓�涓紓甯革紝杩欐牱鍦ㄦ祴璇曢樁娈靛氨鑳藉彂鐜伴棶棰樸�俓n\n 淇敼锛氬湪杩斿洖缁撴灉涔嬪墠锛屾鏌positionFilled`鏁扮粍锛屽鏋滄湁浠讳綍涓�涓綅缃槸false锛屽垯鎶涘嚭寮傚父銆俓n\n 浠g爜淇敼濡備笅锛歕n\n 鍦╮eturn涔嬪墠娣诲姞锛歕n```csharp\n if (positionFilled.Any(filled => !filled))\n throw new InvalidOperationException(\"绠楁硶閿欒锛氬瓨鍦ㄦ湭濉厖鐨勪綅缃甛");\n```\n\n 浣嗘槸锛岀敱浜庢垜浠箣鍓嶅凡缁忛�氳繃寰幆涓烘瘡涓瓧绗﹂兘鎵惧埌浜嗕綅缃紝鎵�浠ヨ繖涓紓甯哥悊璁轰笂姘歌繙涓嶄細鎶涘嚭銆傛墍浠ワ紝杩欏彧鏄竴涓畨鍏ㄦ帾鏂姐�俓n\n 鍥犳锛屽畬鏁寸殑浠g爜淇敼濡備笅锛歕n</think>","contentId":-2126276719,"children":[],"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"","children":[],"contentId":0,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"濂界殑锛屾垜宸茬悊瑙f偍鐨勮姹傘�備互涓嬫槸淇敼鍚庣殑浠g爜锛屾坊鍔犱簡瀵规湭鏇挎崲浣嶇疆鐨勫鐞嗭細","children":[],"contentId":523892228,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"","children":[],"contentId":0,"parent":null,"settled":true,"xmlData":{}},{"type":"code-block","content":"public string GenerateActivationCode(string baseRandom)\n{\n baseRandom = baseRandom.Replace(\"-\", string.Empty);\n Dictionary<char, (char output, int shift)> mappingDict = _charMappingRepository.QueryData()\n .ToDictionary(x => x.InputChar[0], x => (x.OutputChar[0], x.ShiftFactor));\n\n char[] result = new char[baseRandom.Length];\n bool[] positionFilled = new bool[baseRandom.Length];\n int length = baseRandom.Length;\n\n // 鍒濆鍖栫粨鏋滄暟缁勪负鍘熷瀛楃锛堜綔涓烘湭鏇挎崲鏃剁殑榛樿鍊硷級\n for (int i = 0; i < length; i++)\n {\n result[i] = baseRandom[i];\n }\n\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n if (!mappingDict.TryGetValue(current, out var mapping))\n continue; // 璺宠繃鏃犳晥瀛楃锛屼繚鐣欏師濮嬪�糪n\n int newPosition = (i + mapping.shift) % length;\n int attempts = 0;\n \n // 鏌ユ壘鍙敤浣嶇疆锛堟渶澶氬皾璇曟暣涓暟缁勯暱搴︼級\n while (positionFilled[newPosition] && attempts < length)\n {\n newPosition = (newPosition + 1) % length;\n attempts++;\n }\n\n // 搴旂敤鐗规畩鍙樻崲\n char mappedChar = (i % 5 == 4) \n ? ApplySpecialTransform(mapping.output, i) \n : mapping.output;\n\n // 浠呭綋鎵惧埌鏈夋晥浣嶇疆鏃舵墠鏇挎崲\n if (attempts < length)\n {\n result[newPosition] = mappedChar;\n positionFilled[newPosition] = true;\n }\n }\n\n return FormatCode(new string(result));\n}\n","children":[],"contentId":729307478,"parent":null,"settled":true,"xmlData":{},"expectEnding":"```","language":"CSharp"},{"type":"line","content":"","children":[],"contentId":0,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"涓昏鏀硅繘锛�","children":[],"contentId":-1904699086,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"1. **鍒濆鍖栫粨鏋滄暟缁�**锛氫娇鐢ㄥ師濮嬪瓧绗﹀~鍏呯粨鏋滄暟缁勪綔涓洪粯璁ゅ��","children":[],"contentId":264851743,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"2. **璺宠繃鏃犳晥瀛楃**锛氬綋閬囧埌鏃犳晥瀛楃鏃朵娇鐢� `continue` 淇濈暀鍘熷鍊�","children":[],"contentId":593697014,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"3. **娣诲姞灏濊瘯闄愬埗**锛氳缃渶澶у皾璇曟鏁伴伩鍏嶆寰幆","children":[],"contentId":700206594,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"4. **鏉′欢鏇挎崲**锛氫粎褰撴壘鍒版湁鏁堜綅缃椂鎵嶆浛鎹㈠瓧绗�","children":[],"contentId":-733880315,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"5. **淇濈暀鍘熷鍊�**锛氭湭鎴愬姛鏇挎崲鐨勪綅缃繚鎸佸師濮嬪瓧绗︿笉鍙�","children":[],"contentId":268845344,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"","children":[],"contentId":0,"parent":null,"settled":true,"xmlData":{}},{"type":"line","content":"杩欐牱纭繚锛�","children":[],"contentId":474043277,"parent":null,"settled":true,"xmlData":{}},{"type":"list-item","content":"鎵�鏈変綅缃兘鏈夋湁鏁堝瓧绗�","children":[],"contentId":-494483772,"parent":null,"settled":true,"xmlData":{},"startSymbol":"-","indentSize":0},{"type":"list-item","content":"鏈垚鍔熸浛鎹㈢殑浣嶇疆淇濈暀鍘熷鍊�","children":[],"contentId":1102266923,"parent":null,"settled":true,"xmlData":{},"startSymbol":"-","indentSize":0},{"type":"list-item","content":" 閬垮厤鏃犻檺寰幆","children":[],"contentId":-644559997,"parent":null,"settled":true,"xmlData":{},"startSymbol":"-","indentSize":0},{"type":"list-item","content":" 鎵�鏈夊瓧绗﹂兘浼氳姝g‘澶勭悊","children":[],"contentId":-1372256925,"parent":null,"settled":false,"xmlData":{},"startSymbol":"-","indentSize":0}],"parserState":{"line":102,"column":12,"offset":3293,"metadata":false,"buffer":"","closing":false,"currentParent":null,"moveCursor":true,"tagBuffer":"<","isCollectingTag":false},"content":"<think>\n鎴戜滑涔嬪墠宸茬粡娣诲姞浜嗕綅缃爣璁版暟缁刞positionFilled`鏉ヨ窡韪瘡涓綅缃槸鍚﹁濉厖銆備絾鏄紝濡傛灉鍥犱负鏌愪簺鍘熷洜锛堟瘮濡傛墍鏈変綅缃兘琚皾璇曡繃锛夎�屼粛鐒舵湁鏈~鍏呯殑浣嶇疆锛岄偅涔堟垜浠渶瑕佺‘淇濊繖浜涗綅缃濉厖銆俓n 鐒惰�岋紝鍦ㄦ垜浠殑寰幆涓紝鎴戜滑涓烘瘡涓緭鍏ュ瓧绗﹂兘鎵惧埌浜嗕竴涓綅缃紙閫氳繃绾挎�ф帰娴嬫硶锛夛紝鎵�浠ョ悊璁轰笂姣忎釜浣嶇疆閮戒細琚~鍏呬竴娆°�傚洜涓烘垜浠湁n涓瓧绗﹀拰n涓綅缃紝骞朵笖鎴戜滑浣跨敤鍙栨ā杩愮畻寰幆鏌ユ壘锛屾墍浠ユ渶缁堟瘡涓綅缃兘浼氳濉厖銆傚洜姝わ紝瀹為檯涓婁笉浼氬嚭鐜版湭琚浛鎹㈢殑鍊笺�俓n\n 浣嗘槸锛屼负浜嗙‘淇濅唬鐮佺殑鍋ュ.鎬э紝鎴戜滑鍙互娣诲姞涓�涓鏌ワ細鍦ㄥ惊鐜粨鏉熷悗锛屾鏌ユ槸鍚︽墍鏈変綅缃兘琚~鍏呫�傚鏋滄病鏈夛紝鍒欒鏄庣畻娉曟湁璇紝鎴戜滑鍙互鎶涘嚭寮傚父銆俓n\n 涓嶈繃锛屾牴鎹棶棰樻弿杩帮紝鐢ㄦ埛瑕佹眰鈥滄坊鍔犳暟缁勪腑鏈鏇挎崲鐨勫�肩殑澶勭悊鈥濄�傝繖閲屽彲鑳芥槸鎸囷紝濡傛灉鏌愪釜浣嶇疆娌℃湁琚浛鎹紙鍗虫病鏈夎璧嬪�硷級锛岄偅涔堟垜浠渶瑕佺粰瀹冧竴涓粯璁ゅ�硷紵浣嗘牴鎹垜浠殑绠楁硶锛屾瘡涓綅缃兘浼氳璧嬪�间竴娆★紝鎵�浠ヤ笉浼氬嚭鐜版湭鏇挎崲鐨勫�笺�俓n\n 浣嗘槸锛屽鏋滅敤鎴锋媴蹇冨湪鏋佺鎯呭喌涓嬶紙姣斿鏄犲皠瀛楀吀涓己灏戝瓧绗﹀鑷村紓甯革紝浣嗘垜浠凡缁忓鐞嗕簡缂哄け瀛楃鐨勬儏鍐碉級鎴栬�呭惊鐜帰娴嬮�昏緫鏈夌己闄凤紝鎴戜滑鍙互娣诲姞涓�涓悗澶囧鐞嗭細鍦ㄨ繑鍥炵粨鏋滀箣鍓嶏紝妫�鏌positionFilled`鏁扮粍锛屽鏋滄湁鏈~鍏呯殑浣嶇疆锛屽垯鐢ㄦ煇涓粯璁ゅ瓧绗︼紙姣斿鍘熷瓧绗︿覆涓搴斾綅缃殑瀛楃锛熶絾鍘熷瓧绗︿覆宸茬粡琚墦涔憋級濉厖銆備絾杩欐牱閫昏緫灏卞彉寰楀鏉備簡銆俓n\n 瀹為檯涓婏紝鎴戜滑鐨勭畻娉曞凡缁忎繚璇佷簡姣忎釜浣嶇疆閮戒細琚~鍏呫�傚洜姝わ紝鎴戜滑鍙互閫夋嫨鍦ㄦ渶鍚庢坊鍔犱竴涓鏌ワ紝濡傛灉鍙戠幇杩樻湁鏈~鍏呯殑浣嶇疆锛屽垯璁板綍閿欒鎴栦娇鐢ㄥ師瀛楃涓茬殑瀛楃濉厖銆備絾杩欐牱鍙兘浼氬紩鍏ユ柊鐨勯棶棰樸�俓n\n 鑰冭檻鍒板師闂鎻忚堪鏄�滄暟缁勪腑鐨勬暟鎹笉鏄瘡涓�涓兘琚浛鎹㈡帀鈥濓紝鑰屾垜浠凡缁忛�氳繃绾挎�ф帰娴嬫硶淇濊瘉浜嗘瘡涓綅缃兘琚~鍏咃紝鎵�浠ヨ繖閲屾垜浠笉闇�瑕侀澶栧鐞嗐�備絾鏄紝涓轰簡婊¤冻鐢ㄦ埛瑕佹眰锛屾垜浠彲浠ユ坊鍔犱竴涓鏌ワ紝濡傛灉杩樻湁鏈~鍏呯殑浣嶇疆锛屽垯鐢ㄥ師瀛楃涓蹭腑瀵瑰簲浣嶇疆鐨勫瓧绗﹀~鍏咃紙浣嗘敞鎰忥紝鍘熷瓧绗︿覆宸茬粡琚鐞嗭紝鎴戜滑骞舵病鏈変繚鐣欏師鏁扮粍鐨勫浠斤紝鎵�浠ヤ笉鍙锛夈�俓n\n 鍙︿竴绉嶈В閲婏細鐢ㄦ埛鍙兘鏄寚鍘熷瓧绗︿覆涓殑姣忎釜瀛楃閮藉繀椤昏澶勭悊锛堝嵆琚槧灏勶級锛熸垜浠殑浠g爜宸茬粡纭繚姣忎釜瀛楃閮借澶勭悊骞舵斁鍏ョ粨鏋滄暟缁勭殑鏌愪釜浣嶇疆銆俓n\n 鍥犳锛屾垜寤鸿涓嶆坊鍔犻澶栫殑澶勭悊锛屽洜涓虹畻娉曞凡缁忎繚璇佷簡姣忎釜浣嶇疆閮戒細琚~鍏呫�備絾鏄紝濡傛灉鐢ㄦ埛鍧氭寔瑕佸鐞嗏�滄湭琚浛鎹㈢殑鍊尖�濓紝鎴戜滑鍙互鐞嗚В涓猴細鍦ㄧ粨鏋滄暟缁勪腑锛屽鏋滄煇涓綅缃病鏈夎璧嬪�硷紙鍗宠繕鏄垵濮嬪�糮\\0`锛夛紝閭d箞鎴戜滑灏辩敤鍘熷瓧绗︿覆涓搴斾綅缃殑瀛楃锛堜絾杩欐牱浼氱牬鍧忕畻娉曪級锛熻繖鏄剧劧涓嶆槸鎴戜滑鎯宠鐨勩�俓n\n 閲嶆柊闃呰鐢ㄦ埛鐨勯棶棰橈細鈥滄坊鍔犳暟缁勪腑鏈鏇挎崲鐨勫�肩殑澶勭悊鈥濄�傝繖閲屽彲鑳芥槸鎸囷紝鍦ㄤ綅缃亸绉荤畻娉曚腑锛屽鏋滄煇涓綅缃病鏈夎鏇挎崲锛堝嵆娌℃湁琚鐩栵級锛岄偅涔堜繚鐣欏畠鍘熸潵鐨勫�硷紵浣嗘槸锛屽湪鍘熷浠g爜涓紝鎴戜滑骞舵病鏈変繚鐣欏師鏁扮粍鐨勫�硷紝鑰屾槸鍒涘缓浜嗕竴涓柊鐨勬暟缁勶紙鍒濆鍖栦负`\\0`锛夈�傛墍浠ワ紝鍦ㄥ師濮嬩唬鐮佷腑锛屽鏋滄煇涓綅缃病鏈夎璧嬪�硷紝閭d箞瀹冨氨鏄痐\\0`锛岃繖鏄剧劧鏄笉瀵圭殑銆俓n\n 鍥犳锛屾垜浠幇鍦ㄧ殑绠楁硶宸茬粡閫氳繃`positionFilled`鏁扮粍鍜岀嚎鎬ф帰娴嬬‘淇濅簡姣忎釜浣嶇疆閮借璧嬪�笺�傛墍浠ワ紝鎴戜滑涓嶉渶瑕侀澶栧鐞嗐�俓n\n 浣嗘槸锛屼负浜嗕唬鐮佺殑鍋ュ.鎬э紝鎴戜滑鍙互鍦ㄥ惊鐜粨鏉熷悗妫�鏌positionFilled`鏁扮粍鏄惁鍏ㄩ儴涓簍rue锛屽鏋滀笉鏄紝鍒欒鏄庢湁浣嶇疆娌℃湁琚~鍏咃紝鎴戜滑鍙互鎶涘嚭涓�涓紓甯革紝杩欐牱鍦ㄦ祴璇曢樁娈靛氨鑳藉彂鐜伴棶棰樸�俓n\n 淇敼锛氬湪杩斿洖缁撴灉涔嬪墠锛屾鏌positionFilled`鏁扮粍锛屽鏋滄湁浠讳綍涓�涓綅缃槸false锛屽垯鎶涘嚭寮傚父銆俓n\n 浠g爜淇敼濡備笅锛歕n\n 鍦╮eturn涔嬪墠娣诲姞锛歕n```csharp\n if (positionFilled.Any(filled => !filled))\n throw new InvalidOperationException(\"绠楁硶閿欒锛氬瓨鍦ㄦ湭濉厖鐨勪綅缃甛");\n```\n\n 浣嗘槸锛岀敱浜庢垜浠箣鍓嶅凡缁忛�氳繃寰幆涓烘瘡涓瓧绗﹂兘鎵惧埌浜嗕綅缃紝鎵�浠ヨ繖涓紓甯哥悊璁轰笂姘歌繙涓嶄細鎶涘嚭銆傛墍浠ワ紝杩欏彧鏄竴涓畨鍏ㄦ帾鏂姐�俓n\n 鍥犳锛屽畬鏁寸殑浠g爜淇敼濡備笅锛歕n</think>\n\n濂界殑锛屾垜宸茬悊瑙f偍鐨勮姹傘�備互涓嬫槸淇敼鍚庣殑浠g爜锛屾坊鍔犱簡瀵规湭鏇挎崲浣嶇疆鐨勫鐞嗭細\n\n```CSharp\npublic string GenerateActivationCode(string baseRandom)\n{\n baseRandom = baseRandom.Replace(\"-\", string.Empty);\n Dictionary<char, (char output, int shift)> mappingDict = _charMappingRepository.QueryData()\n .ToDictionary(x => x.InputChar[0], x => (x.OutputChar[0], x.ShiftFactor));\n\n char[] result = new char[baseRandom.Length];\n bool[] positionFilled = new bool[baseRandom.Length];\n int length = baseRandom.Length;\n\n // 鍒濆鍖栫粨鏋滄暟缁勪负鍘熷瀛楃锛堜綔涓烘湭鏇挎崲鏃剁殑榛樿鍊硷級\n for (int i = 0; i < length; i++)\n {\n result[i] = baseRandom[i];\n }\n\n for (int i = 0; i < length; i++)\n {\n char current = baseRandom[i];\n if (!mappingDict.TryGetValue(current, out var mapping))\n continue; // 璺宠繃鏃犳晥瀛楃锛屼繚鐣欏師濮嬪�糪n\n int newPosition = (i + mapping.shift) % length;\n int attempts = 0;\n \n // 鏌ユ壘鍙敤浣嶇疆锛堟渶澶氬皾璇曟暣涓暟缁勯暱搴︼級\n while (positionFilled[newPosition] && attempts < length)\n {\n newPosition = (newPosition + 1) % length;\n attempts++;\n }\n\n // 搴旂敤鐗规畩鍙樻崲\n char mappedChar = (i % 5 == 4) \n ? ApplySpecialTransform(mapping.output, i) \n : mapping.output;\n\n // 浠呭綋鎵惧埌鏈夋晥浣嶇疆鏃舵墠鏇挎崲\n if (attempts < length)\n {\n result[newPosition] = mappedChar;\n positionFilled[newPosition] = true;\n }\n }\n\n return FormatCode(new string(result));\n}\n```\n\n涓昏鏀硅繘锛歕n1. **鍒濆鍖栫粨鏋滄暟缁�**锛氫娇鐢ㄥ師濮嬪瓧绗﹀~鍏呯粨鏋滄暟缁勪綔涓洪粯璁ゅ�糪n2. **璺宠繃鏃犳晥瀛楃**锛氬綋閬囧埌鏃犳晥瀛楃鏃朵娇鐢� `continue` 淇濈暀鍘熷鍊糪n3. **娣诲姞灏濊瘯闄愬埗**锛氳缃渶澶у皾璇曟鏁伴伩鍏嶆寰幆\n4. **鏉′欢鏇挎崲**锛氫粎褰撴壘鍒版湁鏁堜綅缃椂鎵嶆浛鎹㈠瓧绗n5. **淇濈暀鍘熷鍊�**锛氭湭鎴愬姛鏇挎崲鐨勪綅缃繚鎸佸師濮嬪瓧绗︿笉鍙榎n\n杩欐牱纭繚锛歕n- 鎵�鏈変綅缃兘鏈夋湁鏁堝瓧绗n- 鏈垚鍔熸浛鎹㈢殑浣嶇疆淇濈暀鍘熷鍊糪n- 閬垮厤鏃犻檺寰幆\n- 鎵�鏈夊瓧绗﹂兘浼氳姝g‘澶勭悊","columns":[6,94,116,-1,67,-1,105,-1,162,-1,87,-1,152,-1,65,-1,134,-1,158,-1,62,-1,94,-1,54,-1,7,-1,12,8,45,60,2,-1,56,-1,13,7,-1,34,-1,8,54,0,54,94,81,-1,47,55,34,-1,30,35,4,33,4,-1,35,4,36,62,36,-1,54,24,7,28,63,8,52,22,8,-1,16,38,54,28,-1,22,29,8,44,46,8,4,-1,41,0,0,-1,4,31,40,26,25,28,-1,4,11,14,7]},"source":null,"error":null,"id":"01987cf8ef48711cb076c2b138a5cbb1","localReferences":null,"references":[{"uri":{"scheme":"file","authority":"","path":"file:///E:/0.椤圭洰闆�/瀹芥捣/SMTFangCuoPDA/浠g爜绠$悊/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ActivationCodeService.cs","query":"","fragment":""},"range":[{"character":0,"line":26},{"character":0,"line":66}],"text":null,"isSourceFile":true}],"followup":null,"topic":"","score":null,"command":"","changeToOptimize":null,"button":null,"knowledge":null,"knowledgeReferences":[],"knowledgeStatus":null,"variables":null,"selectedRange":null,"actions":[],"selectedRanges":null,"createdAt":1754443394874}],"source":null}} \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/CopilotIndices/17.14.734.62261/CodeChunks.db" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/CopilotIndices/17.14.734.62261/CodeChunks.db" new file mode 100644 index 0000000..67f22f6 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/CopilotIndices/17.14.734.62261/CodeChunks.db" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/CopilotIndices/17.14.734.62261/SemanticSymbols.db" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/CopilotIndices/17.14.734.62261/SemanticSymbols.db" new file mode 100644 index 0000000..c834c11 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/CopilotIndices/17.14.734.62261/SemanticSymbols.db" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/1070cb09-ea00-48d7-aa5a-981caeb74f04.vsidx" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/1070cb09-ea00-48d7-aa5a-981caeb74f04.vsidx" new file mode 100644 index 0000000..5f2693d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/1070cb09-ea00-48d7-aa5a-981caeb74f04.vsidx" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/7c7e5e60-8670-43b4-ab23-b60ba11637cb.vsidx" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/7c7e5e60-8670-43b4-ab23-b60ba11637cb.vsidx" new file mode 100644 index 0000000..99a4b28 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/7c7e5e60-8670-43b4-ab23-b60ba11637cb.vsidx" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/9c3714cb-a523-4bd7-9919-13c7296da019.vsidx" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/9c3714cb-a523-4bd7-9919-13c7296da019.vsidx" new file mode 100644 index 0000000..19b3bb0 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/9c3714cb-a523-4bd7-9919-13c7296da019.vsidx" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/a1a75bb8-01fc-457b-8a35-9aa191663ad9.vsidx" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/a1a75bb8-01fc-457b-8a35-9aa191663ad9.vsidx" new file mode 100644 index 0000000..af85cbf --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/a1a75bb8-01fc-457b-8a35-9aa191663ad9.vsidx" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/bc990f7e-fcec-42af-9567-e682197ee62b.vsidx" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/bc990f7e-fcec-42af-9567-e682197ee62b.vsidx" new file mode 100644 index 0000000..63a3eac --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/FileContentIndex/bc990f7e-fcec-42af-9567-e682197ee62b.vsidx" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/config/applicationhost.config" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/config/applicationhost.config" new file mode 100644 index 0000000..269dc55 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/.vs/WIDESEA_ProductMgmtServer/config/applicationhost.config" @@ -0,0 +1,1021 @@ +锘�<?xml version="1.0" encoding="UTF-8"?> +<!-- + + IIS configuration sections. + + For schema documentation, see + %IIS_BIN%\config\schema\IIS_schema.xml. + + Please make a backup of this file before making any changes to it. + + NOTE: The following environment variables are available to be used + within this file and are understood by the IIS Express. + + %IIS_USER_HOME% - The IIS Express home directory for the user + %IIS_SITES_HOME% - The default home directory for sites + %IIS_BIN% - The location of the IIS Express binaries + %SYSTEMDRIVE% - The drive letter of %IIS_BIN% + +--> + +<configuration> + + <!-- + + The <configSections> section controls the registration of sections. + Section is the basic unit of deployment, locking, searching and + containment for configuration settings. + + Every section belongs to one section group. + A section group is a container of logically-related sections. + + Sections cannot be nested. + Section groups may be nested. + + <section + name="" [Required, Collection Key] [XML name of the section] + allowDefinition="Everywhere" [MachineOnly|MachineToApplication|AppHostOnly|Everywhere] [Level where it can be set] + overrideModeDefault="Allow" [Allow|Deny] [Default delegation mode] + allowLocation="true" [true|false] [Allowed in location tags] + /> + + The recommended way to unlock sections is by using a location tag: + <location path="Default Web Site" overrideMode="Allow"> + <system.webServer> + <asp /> + </system.webServer> + </location> + + --> + <configSections> + <sectionGroup name="system.applicationHost"> + <section name="applicationPools" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="configHistory" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="customMetadata" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="listenerAdapters" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="log" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="serviceAutoStartProviders" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="sites" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="webLimits" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + </sectionGroup> + + <sectionGroup name="system.webServer"> + <section name="asp" overrideModeDefault="Deny" /> + <section name="caching" overrideModeDefault="Allow" /> + <section name="cgi" overrideModeDefault="Deny" /> + <section name="defaultDocument" overrideModeDefault="Allow" /> + <section name="directoryBrowse" overrideModeDefault="Allow" /> + <section name="fastCgi" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="globalModules" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="handlers" overrideModeDefault="Deny" /> + <section name="httpCompression" overrideModeDefault="Allow" allowDefinition="Everywhere" /> + <section name="httpErrors" overrideModeDefault="Allow" /> + <section name="httpLogging" overrideModeDefault="Deny" /> + <section name="httpProtocol" overrideModeDefault="Allow" /> + <section name="httpRedirect" overrideModeDefault="Allow" /> + <section name="httpTracing" overrideModeDefault="Deny" /> + <section name="isapiFilters" allowDefinition="MachineToApplication" overrideModeDefault="Deny" /> + <section name="modules" allowDefinition="MachineToApplication" overrideModeDefault="Deny" /> + <section name="applicationInitialization" allowDefinition="MachineToApplication" overrideModeDefault="Allow" /> + <section name="odbcLogging" overrideModeDefault="Deny" /> + <sectionGroup name="security"> + <section name="access" overrideModeDefault="Deny" /> + <section name="applicationDependencies" overrideModeDefault="Deny" /> + <sectionGroup name="authentication"> + <section name="anonymousAuthentication" overrideModeDefault="Deny" /> + <section name="basicAuthentication" overrideModeDefault="Deny" /> + <section name="clientCertificateMappingAuthentication" overrideModeDefault="Deny" /> + <section name="digestAuthentication" overrideModeDefault="Deny" /> + <section name="iisClientCertificateMappingAuthentication" overrideModeDefault="Deny" /> + <section name="windowsAuthentication" overrideModeDefault="Deny" /> + </sectionGroup> + <section name="authorization" overrideModeDefault="Allow" /> + <section name="ipSecurity" overrideModeDefault="Deny" /> + <section name="dynamicIpSecurity" overrideModeDefault="Deny" /> + <section name="isapiCgiRestriction" allowDefinition="AppHostOnly" overrideModeDefault="Deny" /> + <section name="requestFiltering" overrideModeDefault="Allow" /> + </sectionGroup> + <section name="serverRuntime" overrideModeDefault="Deny" /> + <section name="serverSideInclude" overrideModeDefault="Deny" /> + <section name="staticContent" overrideModeDefault="Allow" /> + <sectionGroup name="tracing"> + <section name="traceFailedRequests" overrideModeDefault="Allow" /> + <section name="traceProviderDefinitions" overrideModeDefault="Deny" /> + </sectionGroup> + <section name="urlCompression" overrideModeDefault="Allow" /> + <section name="validation" overrideModeDefault="Allow" /> + <sectionGroup name="webdav"> + <section name="globalSettings" overrideModeDefault="Deny" /> + <section name="authoring" overrideModeDefault="Deny" /> + <section name="authoringRules" overrideModeDefault="Deny" /> + </sectionGroup> + <sectionGroup name="rewrite"> + <section name="allowedServerVariables" overrideModeDefault="Deny" /> + <section name="rules" overrideModeDefault="Allow" /> + <section name="outboundRules" overrideModeDefault="Allow" /> + <section name="globalRules" overrideModeDefault="Deny" allowDefinition="AppHostOnly" /> + <section name="providers" overrideModeDefault="Allow" /> + <section name="rewriteMaps" overrideModeDefault="Allow" /> + </sectionGroup> + <section name="webSocket" overrideModeDefault="Deny" /> + </sectionGroup> + </configSections> + + <configProtectedData> + <providers> + <add name="IISWASOnlyRsaProvider" type="" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useMachineContainer="true" useOAEP="false" /> + <add name="AesProvider" type="Microsoft.ApplicationHost.AesProtectedConfigurationProvider" description="Uses an AES session key to encrypt and decrypt" keyContainerName="iisConfigurationKey" cspProviderName="" useOAEP="false" useMachineContainer="true" sessionKey="AQIAAA5mAAAApAAA/HKxkz6alrlAPez0IUgujj/6k3WxCDriHp6jvpv3yEZmo7h6SMzGLxo4mTrIQVHSkB7tmElHKfUFTzE2BWF7nFWHY6Z6qmGBauFzwJMwESjril7Gjz69RBFH259HQ6aRDq9Xfx7U7H4HtdmnKNqGjgl/hwPQBGeIlWiDh+sYv3vKB0QU971tjX6H2B+9armlnC8UOuA6JYMDMI/VLLL16sng0fWAy5JYe0YVABVjiAWDW264RZW9Tr1Oax4qHZKg+SdjULxeOc2YmpX+d0yeITo1HkPF1hN1gHpIPIUDo05ilHUNfR3OkjVCIQK4cFKCq1s8NH+y+13MxUC4Fn1AlQ==" /> + <add name="IISWASOnlyAesProvider" type="Microsoft.ApplicationHost.AesProtectedConfigurationProvider" description="Uses an AES session key to encrypt and decrypt" keyContainerName="iisWasKey" cspProviderName="" useOAEP="false" useMachineContainer="true" sessionKey="AQIAAA5mAAAApAAALmU8lTC+v2qtfQiiiquvvLpUQqKLEXs+jSKoWCM/uPhyB++k4dwug19mGidNK5FYiWK2KYE1yhjVJcbp12E98Q0R2nT7eBiCMY2JairxQ591rqABK7keGaIjwH7PwGzSpILl3RJ4YFvJ/7ZXEJxeDZIjW8ZxWVXx+/VyHs9U3WguLEkgMUX3jrxJi8LouxaIVPJAv/YQ1ZCWs8zImitxX/C/7o7yaIxznfsN5nGQzQfpUDPeby99aw2zPVTtZI2LaWIBON8guABvZ6JtJVDWmfdK6sodbnwdZkr6/Z2rfvamT1dC1SpQrGG7ulR/f9/GXvCaW10ZVKxekBF/CYlNMg==" /> + </providers> + </configProtectedData> + + <system.applicationHost> + + <applicationPools> + <add name="Clr4IntegratedAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" /> + <add name="Clr4ClassicAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" /> + <add name="Clr2IntegratedAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" /> + <add name="Clr2ClassicAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" /> + <add name="UnmanagedClassicAppPool" managedRuntimeVersion="" managedPipelineMode="Classic" autoStart="true" /> + <applicationPoolDefaults managedRuntimeVersion="v4.0"> + <processModel loadUserProfile="true" setProfileEnvironment="false" /> + </applicationPoolDefaults> + </applicationPools> + + <!-- + + The <listenerAdapters> section defines the protocols with which the + Windows Process Activation Service (WAS) binds. + + --> + <listenerAdapters> + <add name="http" /> + </listenerAdapters> + + <sites> + <site name="WebSite1" id="1" serverAutoStart="true"> + <application path="/"> + <virtualDirectory path="/" physicalPath="%IIS_SITES_HOME%\WebSite1" /> + </application> + <bindings> + <binding protocol="http" bindingInformation=":8080:localhost" /> + </bindings> + </site> + <siteDefaults> + <!-- To enable logging, please change the below attribute "enabled" to "true" --> + <logFile logFormat="W3C" directory="%AppData%\Microsoft\IISExpressLogs" enabled="false"/> + <traceFailedRequestsLogging directory="%AppData%\Microsoft" enabled="false" maxLogFileSizeKB="1024" /> + </siteDefaults> + <applicationDefaults applicationPool="Clr4IntegratedAppPool" /> + <virtualDirectoryDefaults allowSubDirConfig="true" /> + </sites> + + <webLimits /> + + </system.applicationHost> + + <system.webServer> + + <serverRuntime /> + + <asp scriptErrorSentToBrowser="true"> + <cache diskTemplateCacheDirectory="%TEMP%\iisexpress\ASP Compiled Templates" /> + <limits /> + </asp> + + <caching enabled="true" enableKernelCache="true"> + </caching> + + <cgi /> + + <defaultDocument enabled="true"> + <files> + <add value="Default.htm" /> + <add value="Default.asp" /> + <add value="index.htm" /> + <add value="index.html" /> + <add value="iisstart.htm" /> + <add value="default.aspx" /> + </files> + </defaultDocument> + + <directoryBrowse enabled="false" /> + + <fastCgi /> + + <!-- + + The <globalModules> section defines all native-code modules. + To enable a module, specify it in the <modules> section. + + --> + <globalModules> + <add name="HttpLoggingModule" image="%IIS_BIN%\loghttp.dll" /> + <add name="UriCacheModule" image="%IIS_BIN%\cachuri.dll" /> + <add name="TokenCacheModule" image="%IIS_BIN%\cachtokn.dll" /> + <add name="DynamicCompressionModule" image="%IIS_BIN%\compdyn.dll" /> + <add name="StaticCompressionModule" image="%IIS_BIN%\compstat.dll" /> + <add name="DefaultDocumentModule" image="%IIS_BIN%\defdoc.dll" /> + <add name="DirectoryListingModule" image="%IIS_BIN%\dirlist.dll" /> + <add name="ProtocolSupportModule" image="%IIS_BIN%\protsup.dll" /> + <add name="HttpRedirectionModule" image="%IIS_BIN%\redirect.dll" /> + <add name="ServerSideIncludeModule" image="%IIS_BIN%\iis_ssi.dll" /> + <add name="StaticFileModule" image="%IIS_BIN%\static.dll" /> + <add name="AnonymousAuthenticationModule" image="%IIS_BIN%\authanon.dll" /> + <add name="CertificateMappingAuthenticationModule" image="%IIS_BIN%\authcert.dll" /> + <add name="UrlAuthorizationModule" image="%IIS_BIN%\urlauthz.dll" /> + <add name="BasicAuthenticationModule" image="%IIS_BIN%\authbas.dll" /> + <add name="WindowsAuthenticationModule" image="%IIS_BIN%\authsspi.dll" /> + <add name="IISCertificateMappingAuthenticationModule" image="%IIS_BIN%\authmap.dll" /> + <add name="IpRestrictionModule" image="%IIS_BIN%\iprestr.dll" /> + <add name="DynamicIpRestrictionModule" image="%IIS_BIN%\diprestr.dll" /> + <add name="RequestFilteringModule" image="%IIS_BIN%\modrqflt.dll" /> + <add name="CustomLoggingModule" image="%IIS_BIN%\logcust.dll" /> + <add name="CustomErrorModule" image="%IIS_BIN%\custerr.dll" /> + <add name="FailedRequestsTracingModule" image="%IIS_BIN%\iisfreb.dll" /> + <add name="RequestMonitorModule" image="%IIS_BIN%\iisreqs.dll" /> + <add name="IsapiModule" image="%IIS_BIN%\isapi.dll" /> + <add name="IsapiFilterModule" image="%IIS_BIN%\filter.dll" /> + <add name="CgiModule" image="%IIS_BIN%\cgi.dll" /> + <add name="FastCgiModule" image="%IIS_BIN%\iisfcgi.dll" /> +<!-- <add name="WebDAVModule" image="%IIS_BIN%\webdav.dll" /> --> + <add name="RewriteModule" image="%IIS_BIN%\rewrite.dll" /> + <add name="ConfigurationValidationModule" image="%IIS_BIN%\validcfg.dll" /> + <add name="WebSocketModule" image="%IIS_BIN%\iiswsock.dll" /> + <add name="WebMatrixSupportModule" image="%IIS_BIN%\webmatrixsup.dll" /> + <add name="ManagedEngine" image="%windir%\Microsoft.NET\Framework\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness32" /> + <add name="ManagedEngine64" image="%windir%\Microsoft.NET\Framework64\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness64" /> + <add name="ManagedEngineV4.0_32bit" image="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness32" /> + <add name="ManagedEngineV4.0_64bit" image="%windir%\Microsoft.NET\Framework64\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness64" /> + <add name="ApplicationInitializationModule" image="%IIS_BIN%\warmup.dll" /> + </globalModules> + + <httpCompression directory="%TEMP%"> + <scheme name="gzip" dll="%IIS_BIN%\gzip.dll" /> + <dynamicTypes> + <add mimeType="text/*" enabled="true" /> + <add mimeType="message/*" enabled="true" /> + <add mimeType="application/x-javascript" enabled="true" /> + <add mimeType="application/javascript" enabled="true" /> + <add mimeType="*/*" enabled="false" /> + </dynamicTypes> + <staticTypes> + <add mimeType="text/*" enabled="true" /> + <add mimeType="message/*" enabled="true" /> + <add mimeType="application/javascript" enabled="true" /> + <add mimeType="application/atom+xml" enabled="true" /> + <add mimeType="application/xaml+xml" enabled="true" /> + <add mimeType="image/svg+xml" enabled="true" /> + <add mimeType="*/*" enabled="false" /> + </staticTypes> + </httpCompression> + + <httpErrors lockAttributes="allowAbsolutePathsWhenDelegated,defaultPath"> + <error statusCode="401" prefixLanguageFilePath="%IIS_BIN%\custerr" path="401.htm" /> + <error statusCode="403" prefixLanguageFilePath="%IIS_BIN%\custerr" path="403.htm" /> + <error statusCode="404" prefixLanguageFilePath="%IIS_BIN%\custerr" path="404.htm" /> + <error statusCode="405" prefixLanguageFilePath="%IIS_BIN%\custerr" path="405.htm" /> + <error statusCode="406" prefixLanguageFilePath="%IIS_BIN%\custerr" path="406.htm" /> + <error statusCode="412" prefixLanguageFilePath="%IIS_BIN%\custerr" path="412.htm" /> + <error statusCode="500" prefixLanguageFilePath="%IIS_BIN%\custerr" path="500.htm" /> + <error statusCode="501" prefixLanguageFilePath="%IIS_BIN%\custerr" path="501.htm" /> + <error statusCode="502" prefixLanguageFilePath="%IIS_BIN%\custerr" path="502.htm" /> + </httpErrors> + + <httpLogging dontLog="false" /> + + <httpProtocol> + <customHeaders> + <clear /> + <add name="X-Powered-By" value="ASP.NET" /> + </customHeaders> + <redirectHeaders> + <clear /> + </redirectHeaders> + </httpProtocol> + + <httpRedirect enabled="false" /> + + <httpTracing /> + + <isapiFilters> + <filter name="ASP.Net_2.0.50727-64" path="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="bitness64,runtimeVersionv2.0" /> + <filter name="ASP.Net_2.0.50727.0" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv2.0" /> + <filter name="ASP.Net_2.0_for_v1.1" path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_filter.dll" enableCache="true" preCondition="runtimeVersionv1.1" /> + <filter name="ASP.Net_4.0_32bit" path="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_filter.dll" enableCache="true" preCondition="bitness32,runtimeVersionv4.0" /> + <filter name="ASP.Net_4.0_64bit" path="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_filter.dll" enableCache="true" preCondition="bitness64,runtimeVersionv4.0" /> + </isapiFilters> + + <odbcLogging /> + + <security> + + <access sslFlags="None" /> + + <applicationDependencies> + <application name="Active Server Pages" groupId="ASP" /> + </applicationDependencies> + + <authentication> + + <anonymousAuthentication enabled="true" userName="" /> + + <basicAuthentication enabled="false" /> + + <clientCertificateMappingAuthentication enabled="false" /> + + <digestAuthentication enabled="false" /> + + <iisClientCertificateMappingAuthentication enabled="false"> + </iisClientCertificateMappingAuthentication> + + <windowsAuthentication enabled="false"> + <providers> + <add value="Negotiate" /> + <add value="NTLM" /> + </providers> + </windowsAuthentication> + + </authentication> + + <authorization> + <add accessType="Allow" users="*" /> + </authorization> + + <ipSecurity allowUnlisted="true" /> + + <isapiCgiRestriction notListedIsapisAllowed="true" notListedCgisAllowed="true"> + <add path="%windir%\Microsoft.NET\Framework64\v4.0.30319\webengine4.dll" allowed="true" groupId="ASP.NET_v4.0" description="ASP.NET_v4.0" /> + <add path="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" allowed="true" groupId="ASP.NET_v4.0" description="ASP.NET_v4.0" /> + <add path="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v2.0.50727" description="ASP.NET v2.0.50727" /> + <add path="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" allowed="true" groupId="ASP.NET v2.0.50727" description="ASP.NET v2.0.50727" /> + </isapiCgiRestriction> + + <requestFiltering> + <fileExtensions allowUnlisted="true" applyToWebDAV="true"> + <add fileExtension=".asa" allowed="false" /> + <add fileExtension=".asax" allowed="false" /> + <add fileExtension=".ascx" allowed="false" /> + <add fileExtension=".master" allowed="false" /> + <add fileExtension=".skin" allowed="false" /> + <add fileExtension=".browser" allowed="false" /> + <add fileExtension=".sitemap" allowed="false" /> + <add fileExtension=".config" allowed="false" /> + <add fileExtension=".cs" allowed="false" /> + <add fileExtension=".csproj" allowed="false" /> + <add fileExtension=".vb" allowed="false" /> + <add fileExtension=".vbproj" allowed="false" /> + <add fileExtension=".webinfo" allowed="false" /> + <add fileExtension=".licx" allowed="false" /> + <add fileExtension=".resx" allowed="false" /> + <add fileExtension=".resources" allowed="false" /> + <add fileExtension=".mdb" allowed="false" /> + <add fileExtension=".vjsproj" allowed="false" /> + <add fileExtension=".java" allowed="false" /> + <add fileExtension=".jsl" allowed="false" /> + <add fileExtension=".ldb" allowed="false" /> + <add fileExtension=".dsdgm" allowed="false" /> + <add fileExtension=".ssdgm" allowed="false" /> + <add fileExtension=".lsad" allowed="false" /> + <add fileExtension=".ssmap" allowed="false" /> + <add fileExtension=".cd" allowed="false" /> + <add fileExtension=".dsprototype" allowed="false" /> + <add fileExtension=".lsaprototype" allowed="false" /> + <add fileExtension=".sdm" allowed="false" /> + <add fileExtension=".sdmDocument" allowed="false" /> + <add fileExtension=".mdf" allowed="false" /> + <add fileExtension=".ldf" allowed="false" /> + <add fileExtension=".ad" allowed="false" /> + <add fileExtension=".dd" allowed="false" /> + <add fileExtension=".ldd" allowed="false" /> + <add fileExtension=".sd" allowed="false" /> + <add fileExtension=".adprototype" allowed="false" /> + <add fileExtension=".lddprototype" allowed="false" /> + <add fileExtension=".exclude" allowed="false" /> + <add fileExtension=".refresh" allowed="false" /> + <add fileExtension=".compiled" allowed="false" /> + <add fileExtension=".msgx" allowed="false" /> + <add fileExtension=".vsdisco" allowed="false" /> + <add fileExtension=".rules" allowed="false" /> + </fileExtensions> + <verbs allowUnlisted="true" applyToWebDAV="true" /> + <hiddenSegments applyToWebDAV="true"> + <add segment="web.config" /> + <add segment="bin" /> + <add segment="App_code" /> + <add segment="App_GlobalResources" /> + <add segment="App_LocalResources" /> + <add segment="App_WebReferences" /> + <add segment="App_Data" /> + <add segment="App_Browsers" /> + </hiddenSegments> + </requestFiltering> + + </security> + + <serverSideInclude ssiExecDisable="false" /> + + <staticContent lockAttributes="isDocFooterFileName"> + <mimeMap fileExtension=".323" mimeType="text/h323" /> + <mimeMap fileExtension=".3g2" mimeType="video/3gpp2" /> + <mimeMap fileExtension=".3gp2" mimeType="video/3gpp2" /> + <mimeMap fileExtension=".3gp" mimeType="video/3gpp" /> + <mimeMap fileExtension=".3gpp" mimeType="video/3gpp" /> + <mimeMap fileExtension=".aac" mimeType="audio/aac" /> + <mimeMap fileExtension=".aaf" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".aca" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".accdb" mimeType="application/msaccess" /> + <mimeMap fileExtension=".accde" mimeType="application/msaccess" /> + <mimeMap fileExtension=".accdt" mimeType="application/msaccess" /> + <mimeMap fileExtension=".acx" mimeType="application/internet-property-stream" /> + <mimeMap fileExtension=".adt" mimeType="audio/vnd.dlna.adts" /> + <mimeMap fileExtension=".adts" mimeType="audio/vnd.dlna.adts" /> + <mimeMap fileExtension=".afm" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".ai" mimeType="application/postscript" /> + <mimeMap fileExtension=".aif" mimeType="audio/x-aiff" /> + <mimeMap fileExtension=".aifc" mimeType="audio/aiff" /> + <mimeMap fileExtension=".aiff" mimeType="audio/aiff" /> + <mimeMap fileExtension=".appcache" mimeType="text/cache-manifest" /> + <mimeMap fileExtension=".application" mimeType="application/x-ms-application" /> + <mimeMap fileExtension=".art" mimeType="image/x-jg" /> + <mimeMap fileExtension=".asd" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".asf" mimeType="video/x-ms-asf" /> + <mimeMap fileExtension=".asi" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".asm" mimeType="text/plain" /> + <mimeMap fileExtension=".asr" mimeType="video/x-ms-asf" /> + <mimeMap fileExtension=".asx" mimeType="video/x-ms-asf" /> + <mimeMap fileExtension=".atom" mimeType="application/atom+xml" /> + <mimeMap fileExtension=".au" mimeType="audio/basic" /> + <mimeMap fileExtension=".avi" mimeType="video/avi" /> + <mimeMap fileExtension=".axs" mimeType="application/olescript" /> + <mimeMap fileExtension=".bas" mimeType="text/plain" /> + <mimeMap fileExtension=".bcpio" mimeType="application/x-bcpio" /> + <mimeMap fileExtension=".bin" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".bmp" mimeType="image/bmp" /> + <mimeMap fileExtension=".c" mimeType="text/plain" /> + <mimeMap fileExtension=".cab" mimeType="application/vnd.ms-cab-compressed" /> + <mimeMap fileExtension=".calx" mimeType="application/vnd.ms-office.calx" /> + <mimeMap fileExtension=".cat" mimeType="application/vnd.ms-pki.seccat" /> + <mimeMap fileExtension=".cdf" mimeType="application/x-cdf" /> + <mimeMap fileExtension=".chm" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".class" mimeType="application/x-java-applet" /> + <mimeMap fileExtension=".clp" mimeType="application/x-msclip" /> + <mimeMap fileExtension=".cmx" mimeType="image/x-cmx" /> + <mimeMap fileExtension=".cnf" mimeType="text/plain" /> + <mimeMap fileExtension=".cod" mimeType="image/cis-cod" /> + <mimeMap fileExtension=".cpio" mimeType="application/x-cpio" /> + <mimeMap fileExtension=".cpp" mimeType="text/plain" /> + <mimeMap fileExtension=".crd" mimeType="application/x-mscardfile" /> + <mimeMap fileExtension=".crl" mimeType="application/pkix-crl" /> + <mimeMap fileExtension=".crt" mimeType="application/x-x509-ca-cert" /> + <mimeMap fileExtension=".csh" mimeType="application/x-csh" /> + <mimeMap fileExtension=".css" mimeType="text/css" /> + <mimeMap fileExtension=".csv" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".cur" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".dcr" mimeType="application/x-director" /> + <mimeMap fileExtension=".deploy" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".der" mimeType="application/x-x509-ca-cert" /> + <mimeMap fileExtension=".dib" mimeType="image/bmp" /> + <mimeMap fileExtension=".dir" mimeType="application/x-director" /> + <mimeMap fileExtension=".disco" mimeType="text/xml" /> + <mimeMap fileExtension=".dll" mimeType="application/x-msdownload" /> + <mimeMap fileExtension=".dll.config" mimeType="text/xml" /> + <mimeMap fileExtension=".dlm" mimeType="text/dlm" /> + <mimeMap fileExtension=".doc" mimeType="application/msword" /> + <mimeMap fileExtension=".docm" mimeType="application/vnd.ms-word.document.macroEnabled.12" /> + <mimeMap fileExtension=".docx" mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" /> + <mimeMap fileExtension=".dot" mimeType="application/msword" /> + <mimeMap fileExtension=".dotm" mimeType="application/vnd.ms-word.template.macroEnabled.12" /> + <mimeMap fileExtension=".dotx" mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.template" /> + <mimeMap fileExtension=".dsp" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".dtd" mimeType="text/xml" /> + <mimeMap fileExtension=".dvi" mimeType="application/x-dvi" /> + <mimeMap fileExtension=".dvr-ms" mimeType="video/x-ms-dvr" /> + <mimeMap fileExtension=".dwf" mimeType="drawing/x-dwf" /> + <mimeMap fileExtension=".dwp" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".dxr" mimeType="application/x-director" /> + <mimeMap fileExtension=".eml" mimeType="message/rfc822" /> + <mimeMap fileExtension=".emz" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" /> + <mimeMap fileExtension=".eps" mimeType="application/postscript" /> + <mimeMap fileExtension=".esd" mimeType="application/vnd.ms-cab-compressed" /> + <mimeMap fileExtension=".etx" mimeType="text/x-setext" /> + <mimeMap fileExtension=".evy" mimeType="application/envoy" /> + <mimeMap fileExtension=".exe" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".exe.config" mimeType="text/xml" /> + <mimeMap fileExtension=".fdf" mimeType="application/vnd.fdf" /> + <mimeMap fileExtension=".fif" mimeType="application/fractals" /> + <mimeMap fileExtension=".fla" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".flr" mimeType="x-world/x-vrml" /> + <mimeMap fileExtension=".flv" mimeType="video/x-flv" /> + <mimeMap fileExtension=".gif" mimeType="image/gif" /> + <mimeMap fileExtension=".glb" mimeType="model/gltf-binary" /> + <mimeMap fileExtension=".gtar" mimeType="application/x-gtar" /> + <mimeMap fileExtension=".gz" mimeType="application/x-gzip" /> + <mimeMap fileExtension=".h" mimeType="text/plain" /> + <mimeMap fileExtension=".hdf" mimeType="application/x-hdf" /> + <mimeMap fileExtension=".hdml" mimeType="text/x-hdml" /> + <mimeMap fileExtension=".hhc" mimeType="application/x-oleobject" /> + <mimeMap fileExtension=".hhk" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".hhp" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".hlp" mimeType="application/winhlp" /> + <mimeMap fileExtension=".hqx" mimeType="application/mac-binhex40" /> + <mimeMap fileExtension=".hta" mimeType="application/hta" /> + <mimeMap fileExtension=".htc" mimeType="text/x-component" /> + <mimeMap fileExtension=".htm" mimeType="text/html" /> + <mimeMap fileExtension=".html" mimeType="text/html" /> + <mimeMap fileExtension=".htt" mimeType="text/webviewhtml" /> + <mimeMap fileExtension=".hxt" mimeType="text/html" /> + <mimeMap fileExtension=".ico" mimeType="image/x-icon" /> + <mimeMap fileExtension=".ics" mimeType="text/calendar" /> + <mimeMap fileExtension=".ief" mimeType="image/ief" /> + <mimeMap fileExtension=".iii" mimeType="application/x-iphone" /> + <mimeMap fileExtension=".inf" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".ins" mimeType="application/x-internet-signup" /> + <mimeMap fileExtension=".isp" mimeType="application/x-internet-signup" /> + <mimeMap fileExtension=".IVF" mimeType="video/x-ivf" /> + <mimeMap fileExtension=".jar" mimeType="application/java-archive" /> + <mimeMap fileExtension=".java" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".jck" mimeType="application/liquidmotion" /> + <mimeMap fileExtension=".jcz" mimeType="application/liquidmotion" /> + <mimeMap fileExtension=".jfif" mimeType="image/pjpeg" /> + <mimeMap fileExtension=".jpb" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".jpe" mimeType="image/jpeg" /> + <mimeMap fileExtension=".jpeg" mimeType="image/jpeg" /> + <mimeMap fileExtension=".jpg" mimeType="image/jpeg" /> + <mimeMap fileExtension=".js" mimeType="application/javascript" /> + <mimeMap fileExtension=".json" mimeType="application/json" /> + <mimeMap fileExtension=".jsonld" mimeType="application/ld+json" /> + <mimeMap fileExtension=".jsx" mimeType="text/jscript" /> + <mimeMap fileExtension=".latex" mimeType="application/x-latex" /> + <mimeMap fileExtension=".less" mimeType="text/css" /> + <mimeMap fileExtension=".lit" mimeType="application/x-ms-reader" /> + <mimeMap fileExtension=".lpk" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".lsf" mimeType="video/x-la-asf" /> + <mimeMap fileExtension=".lsx" mimeType="video/x-la-asf" /> + <mimeMap fileExtension=".lzh" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".m13" mimeType="application/x-msmediaview" /> + <mimeMap fileExtension=".m14" mimeType="application/x-msmediaview" /> + <mimeMap fileExtension=".m1v" mimeType="video/mpeg" /> + <mimeMap fileExtension=".m2ts" mimeType="video/vnd.dlna.mpeg-tts" /> + <mimeMap fileExtension=".m3u" mimeType="audio/x-mpegurl" /> + <mimeMap fileExtension=".m4a" mimeType="audio/mp4" /> + <mimeMap fileExtension=".m4v" mimeType="video/mp4" /> + <mimeMap fileExtension=".man" mimeType="application/x-troff-man" /> + <mimeMap fileExtension=".manifest" mimeType="application/x-ms-manifest" /> + <mimeMap fileExtension=".map" mimeType="text/plain" /> + <mimeMap fileExtension=".mdb" mimeType="application/x-msaccess" /> + <mimeMap fileExtension=".mdp" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".me" mimeType="application/x-troff-me" /> + <mimeMap fileExtension=".mht" mimeType="message/rfc822" /> + <mimeMap fileExtension=".mhtml" mimeType="message/rfc822" /> + <mimeMap fileExtension=".mid" mimeType="audio/mid" /> + <mimeMap fileExtension=".midi" mimeType="audio/mid" /> + <mimeMap fileExtension=".mix" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".mmf" mimeType="application/x-smaf" /> + <mimeMap fileExtension=".mno" mimeType="text/xml" /> + <mimeMap fileExtension=".mny" mimeType="application/x-msmoney" /> + <mimeMap fileExtension=".mov" mimeType="video/quicktime" /> + <mimeMap fileExtension=".movie" mimeType="video/x-sgi-movie" /> + <mimeMap fileExtension=".mp2" mimeType="video/mpeg" /> + <mimeMap fileExtension=".mp3" mimeType="audio/mpeg" /> + <mimeMap fileExtension=".mp4" mimeType="video/mp4" /> + <mimeMap fileExtension=".mp4v" mimeType="video/mp4" /> + <mimeMap fileExtension=".mpa" mimeType="video/mpeg" /> + <mimeMap fileExtension=".mpe" mimeType="video/mpeg" /> + <mimeMap fileExtension=".mpeg" mimeType="video/mpeg" /> + <mimeMap fileExtension=".mpg" mimeType="video/mpeg" /> + <mimeMap fileExtension=".mpp" mimeType="application/vnd.ms-project" /> + <mimeMap fileExtension=".mpv2" mimeType="video/mpeg" /> + <mimeMap fileExtension=".ms" mimeType="application/x-troff-ms" /> + <mimeMap fileExtension=".msi" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".mso" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".mvb" mimeType="application/x-msmediaview" /> + <mimeMap fileExtension=".mvc" mimeType="application/x-miva-compiled" /> + <mimeMap fileExtension=".nc" mimeType="application/x-netcdf" /> + <mimeMap fileExtension=".nsc" mimeType="video/x-ms-asf" /> + <mimeMap fileExtension=".nws" mimeType="message/rfc822" /> + <mimeMap fileExtension=".ocx" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".oda" mimeType="application/oda" /> + <mimeMap fileExtension=".odc" mimeType="text/x-ms-odc" /> + <mimeMap fileExtension=".ods" mimeType="application/oleobject" /> + <mimeMap fileExtension=".oga" mimeType="audio/ogg" /> + <mimeMap fileExtension=".ogg" mimeType="video/ogg" /> + <mimeMap fileExtension=".ogv" mimeType="video/ogg" /> + <mimeMap fileExtension=".one" mimeType="application/onenote" /> + <mimeMap fileExtension=".onea" mimeType="application/onenote" /> + <mimeMap fileExtension=".onetoc" mimeType="application/onenote" /> + <mimeMap fileExtension=".onetoc2" mimeType="application/onenote" /> + <mimeMap fileExtension=".onetmp" mimeType="application/onenote" /> + <mimeMap fileExtension=".onepkg" mimeType="application/onenote" /> + <mimeMap fileExtension=".osdx" mimeType="application/opensearchdescription+xml" /> + <mimeMap fileExtension=".otf" mimeType="font/otf" /> + <mimeMap fileExtension=".p10" mimeType="application/pkcs10" /> + <mimeMap fileExtension=".p12" mimeType="application/x-pkcs12" /> + <mimeMap fileExtension=".p7b" mimeType="application/x-pkcs7-certificates" /> + <mimeMap fileExtension=".p7c" mimeType="application/pkcs7-mime" /> + <mimeMap fileExtension=".p7m" mimeType="application/pkcs7-mime" /> + <mimeMap fileExtension=".p7r" mimeType="application/x-pkcs7-certreqresp" /> + <mimeMap fileExtension=".p7s" mimeType="application/pkcs7-signature" /> + <mimeMap fileExtension=".pbm" mimeType="image/x-portable-bitmap" /> + <mimeMap fileExtension=".pcx" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".pcz" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".pdf" mimeType="application/pdf" /> + <mimeMap fileExtension=".pfb" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".pfm" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".pfx" mimeType="application/x-pkcs12" /> + <mimeMap fileExtension=".pgm" mimeType="image/x-portable-graymap" /> + <mimeMap fileExtension=".pko" mimeType="application/vnd.ms-pki.pko" /> + <mimeMap fileExtension=".pma" mimeType="application/x-perfmon" /> + <mimeMap fileExtension=".pmc" mimeType="application/x-perfmon" /> + <mimeMap fileExtension=".pml" mimeType="application/x-perfmon" /> + <mimeMap fileExtension=".pmr" mimeType="application/x-perfmon" /> + <mimeMap fileExtension=".pmw" mimeType="application/x-perfmon" /> + <mimeMap fileExtension=".png" mimeType="image/png" /> + <mimeMap fileExtension=".pnm" mimeType="image/x-portable-anymap" /> + <mimeMap fileExtension=".pnz" mimeType="image/png" /> + <mimeMap fileExtension=".pot" mimeType="application/vnd.ms-powerpoint" /> + <mimeMap fileExtension=".potm" mimeType="application/vnd.ms-powerpoint.template.macroEnabled.12" /> + <mimeMap fileExtension=".potx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.template" /> + <mimeMap fileExtension=".ppam" mimeType="application/vnd.ms-powerpoint.addin.macroEnabled.12" /> + <mimeMap fileExtension=".ppm" mimeType="image/x-portable-pixmap" /> + <mimeMap fileExtension=".pps" mimeType="application/vnd.ms-powerpoint" /> + <mimeMap fileExtension=".ppsm" mimeType="application/vnd.ms-powerpoint.slideshow.macroEnabled.12" /> + <mimeMap fileExtension=".ppsx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.slideshow" /> + <mimeMap fileExtension=".ppt" mimeType="application/vnd.ms-powerpoint" /> + <mimeMap fileExtension=".pptm" mimeType="application/vnd.ms-powerpoint.presentation.macroEnabled.12" /> + <mimeMap fileExtension=".pptx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" /> + <mimeMap fileExtension=".prf" mimeType="application/pics-rules" /> + <mimeMap fileExtension=".prm" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".prx" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".ps" mimeType="application/postscript" /> + <mimeMap fileExtension=".psd" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".psm" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".psp" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".pub" mimeType="application/x-mspublisher" /> + <mimeMap fileExtension=".qt" mimeType="video/quicktime" /> + <mimeMap fileExtension=".qtl" mimeType="application/x-quicktimeplayer" /> + <mimeMap fileExtension=".qxd" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".ra" mimeType="audio/x-pn-realaudio" /> + <mimeMap fileExtension=".ram" mimeType="audio/x-pn-realaudio" /> + <mimeMap fileExtension=".rar" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".ras" mimeType="image/x-cmu-raster" /> + <mimeMap fileExtension=".rf" mimeType="image/vnd.rn-realflash" /> + <mimeMap fileExtension=".rgb" mimeType="image/x-rgb" /> + <mimeMap fileExtension=".rm" mimeType="application/vnd.rn-realmedia" /> + <mimeMap fileExtension=".rmi" mimeType="audio/mid" /> + <mimeMap fileExtension=".roff" mimeType="application/x-troff" /> + <mimeMap fileExtension=".rpm" mimeType="audio/x-pn-realaudio-plugin" /> + <mimeMap fileExtension=".rtf" mimeType="application/rtf" /> + <mimeMap fileExtension=".rtx" mimeType="text/richtext" /> + <mimeMap fileExtension=".scd" mimeType="application/x-msschedule" /> + <mimeMap fileExtension=".sct" mimeType="text/scriptlet" /> + <mimeMap fileExtension=".sea" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".setpay" mimeType="application/set-payment-initiation" /> + <mimeMap fileExtension=".setreg" mimeType="application/set-registration-initiation" /> + <mimeMap fileExtension=".sgml" mimeType="text/sgml" /> + <mimeMap fileExtension=".sh" mimeType="application/x-sh" /> + <mimeMap fileExtension=".shar" mimeType="application/x-shar" /> + <mimeMap fileExtension=".sit" mimeType="application/x-stuffit" /> + <mimeMap fileExtension=".sldm" mimeType="application/vnd.ms-powerpoint.slide.macroEnabled.12" /> + <mimeMap fileExtension=".sldx" mimeType="application/vnd.openxmlformats-officedocument.presentationml.slide" /> + <mimeMap fileExtension=".smd" mimeType="audio/x-smd" /> + <mimeMap fileExtension=".smi" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".smx" mimeType="audio/x-smd" /> + <mimeMap fileExtension=".smz" mimeType="audio/x-smd" /> + <mimeMap fileExtension=".snd" mimeType="audio/basic" /> + <mimeMap fileExtension=".snp" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".spc" mimeType="application/x-pkcs7-certificates" /> + <mimeMap fileExtension=".spl" mimeType="application/futuresplash" /> + <mimeMap fileExtension=".spx" mimeType="audio/ogg" /> + <mimeMap fileExtension=".src" mimeType="application/x-wais-source" /> + <mimeMap fileExtension=".ssm" mimeType="application/streamingmedia" /> + <mimeMap fileExtension=".sst" mimeType="application/vnd.ms-pki.certstore" /> + <mimeMap fileExtension=".stl" mimeType="application/vnd.ms-pki.stl" /> + <mimeMap fileExtension=".sv4cpio" mimeType="application/x-sv4cpio" /> + <mimeMap fileExtension=".sv4crc" mimeType="application/x-sv4crc" /> + <mimeMap fileExtension=".svg" mimeType="image/svg+xml" /> + <mimeMap fileExtension=".svgz" mimeType="image/svg+xml" /> + <mimeMap fileExtension=".swf" mimeType="application/x-shockwave-flash" /> + <mimeMap fileExtension=".t" mimeType="application/x-troff" /> + <mimeMap fileExtension=".tar" mimeType="application/x-tar" /> + <mimeMap fileExtension=".tcl" mimeType="application/x-tcl" /> + <mimeMap fileExtension=".tex" mimeType="application/x-tex" /> + <mimeMap fileExtension=".texi" mimeType="application/x-texinfo" /> + <mimeMap fileExtension=".texinfo" mimeType="application/x-texinfo" /> + <mimeMap fileExtension=".tgz" mimeType="application/x-compressed" /> + <mimeMap fileExtension=".thmx" mimeType="application/vnd.ms-officetheme" /> + <mimeMap fileExtension=".thn" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".tif" mimeType="image/tiff" /> + <mimeMap fileExtension=".tiff" mimeType="image/tiff" /> + <mimeMap fileExtension=".toc" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".tr" mimeType="application/x-troff" /> + <mimeMap fileExtension=".trm" mimeType="application/x-msterminal" /> + <mimeMap fileExtension=".ts" mimeType="video/vnd.dlna.mpeg-tts" /> + <mimeMap fileExtension=".tsv" mimeType="text/tab-separated-values" /> + <mimeMap fileExtension=".ttf" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".tts" mimeType="video/vnd.dlna.mpeg-tts" /> + <mimeMap fileExtension=".txt" mimeType="text/plain" /> + <mimeMap fileExtension=".u32" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".uls" mimeType="text/iuls" /> + <mimeMap fileExtension=".ustar" mimeType="application/x-ustar" /> + <mimeMap fileExtension=".vbs" mimeType="text/vbscript" /> + <mimeMap fileExtension=".vcf" mimeType="text/x-vcard" /> + <mimeMap fileExtension=".vcs" mimeType="text/plain" /> + <mimeMap fileExtension=".vdx" mimeType="application/vnd.ms-visio.viewer" /> + <mimeMap fileExtension=".vml" mimeType="text/xml" /> + <mimeMap fileExtension=".vsd" mimeType="application/vnd.visio" /> + <mimeMap fileExtension=".vss" mimeType="application/vnd.visio" /> + <mimeMap fileExtension=".vst" mimeType="application/vnd.visio" /> + <mimeMap fileExtension=".vsto" mimeType="application/x-ms-vsto" /> + <mimeMap fileExtension=".vsw" mimeType="application/vnd.visio" /> + <mimeMap fileExtension=".vsx" mimeType="application/vnd.visio" /> + <mimeMap fileExtension=".vtx" mimeType="application/vnd.visio" /> + <mimeMap fileExtension=".wasm" mimeType="application/wasm" /> + <mimeMap fileExtension=".wav" mimeType="audio/wav" /> + <mimeMap fileExtension=".wax" mimeType="audio/x-ms-wax" /> + <mimeMap fileExtension=".wbmp" mimeType="image/vnd.wap.wbmp" /> + <mimeMap fileExtension=".wcm" mimeType="application/vnd.ms-works" /> + <mimeMap fileExtension=".wdb" mimeType="application/vnd.ms-works" /> + <mimeMap fileExtension=".webm" mimeType="video/webm" /> + <mimeMap fileExtension=".wks" mimeType="application/vnd.ms-works" /> + <mimeMap fileExtension=".wm" mimeType="video/x-ms-wm" /> + <mimeMap fileExtension=".wma" mimeType="audio/x-ms-wma" /> + <mimeMap fileExtension=".wmd" mimeType="application/x-ms-wmd" /> + <mimeMap fileExtension=".wmf" mimeType="application/x-msmetafile" /> + <mimeMap fileExtension=".wml" mimeType="text/vnd.wap.wml" /> + <mimeMap fileExtension=".wmlc" mimeType="application/vnd.wap.wmlc" /> + <mimeMap fileExtension=".wmls" mimeType="text/vnd.wap.wmlscript" /> + <mimeMap fileExtension=".wmlsc" mimeType="application/vnd.wap.wmlscriptc" /> + <mimeMap fileExtension=".wmp" mimeType="video/x-ms-wmp" /> + <mimeMap fileExtension=".wmv" mimeType="video/x-ms-wmv" /> + <mimeMap fileExtension=".wmx" mimeType="video/x-ms-wmx" /> + <mimeMap fileExtension=".wmz" mimeType="application/x-ms-wmz" /> + <mimeMap fileExtension=".woff" mimeType="font/x-woff" /> + <mimeMap fileExtension=".woff2" mimeType="application/font-woff2" /> + <mimeMap fileExtension=".wps" mimeType="application/vnd.ms-works" /> + <mimeMap fileExtension=".wri" mimeType="application/x-mswrite" /> + <mimeMap fileExtension=".wrl" mimeType="x-world/x-vrml" /> + <mimeMap fileExtension=".wrz" mimeType="x-world/x-vrml" /> + <mimeMap fileExtension=".wsdl" mimeType="text/xml" /> + <mimeMap fileExtension=".wtv" mimeType="video/x-ms-wtv" /> + <mimeMap fileExtension=".wvx" mimeType="video/x-ms-wvx" /> + <mimeMap fileExtension=".x" mimeType="application/directx" /> + <mimeMap fileExtension=".xaf" mimeType="x-world/x-vrml" /> + <mimeMap fileExtension=".xaml" mimeType="application/xaml+xml" /> + <mimeMap fileExtension=".xap" mimeType="application/x-silverlight-app" /> + <mimeMap fileExtension=".xbap" mimeType="application/x-ms-xbap" /> + <mimeMap fileExtension=".xbm" mimeType="image/x-xbitmap" /> + <mimeMap fileExtension=".xdr" mimeType="text/plain" /> + <mimeMap fileExtension=".xht" mimeType="application/xhtml+xml" /> + <mimeMap fileExtension=".xhtml" mimeType="application/xhtml+xml" /> + <mimeMap fileExtension=".xla" mimeType="application/vnd.ms-excel" /> + <mimeMap fileExtension=".xlam" mimeType="application/vnd.ms-excel.addin.macroEnabled.12" /> + <mimeMap fileExtension=".xlc" mimeType="application/vnd.ms-excel" /> + <mimeMap fileExtension=".xlm" mimeType="application/vnd.ms-excel" /> + <mimeMap fileExtension=".xls" mimeType="application/vnd.ms-excel" /> + <mimeMap fileExtension=".xlsb" mimeType="application/vnd.ms-excel.sheet.binary.macroEnabled.12" /> + <mimeMap fileExtension=".xlsm" mimeType="application/vnd.ms-excel.sheet.macroEnabled.12" /> + <mimeMap fileExtension=".xlsx" mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" /> + <mimeMap fileExtension=".xlt" mimeType="application/vnd.ms-excel" /> + <mimeMap fileExtension=".xltm" mimeType="application/vnd.ms-excel.template.macroEnabled.12" /> + <mimeMap fileExtension=".xltx" mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.template" /> + <mimeMap fileExtension=".xlw" mimeType="application/vnd.ms-excel" /> + <mimeMap fileExtension=".xml" mimeType="text/xml" /> + <mimeMap fileExtension=".xof" mimeType="x-world/x-vrml" /> + <mimeMap fileExtension=".xpm" mimeType="image/x-xpixmap" /> + <mimeMap fileExtension=".xps" mimeType="application/vnd.ms-xpsdocument" /> + <mimeMap fileExtension=".xsd" mimeType="text/xml" /> + <mimeMap fileExtension=".xsf" mimeType="text/xml" /> + <mimeMap fileExtension=".xsl" mimeType="text/xml" /> + <mimeMap fileExtension=".xslt" mimeType="text/xml" /> + <mimeMap fileExtension=".xsn" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".xtp" mimeType="application/octet-stream" /> + <mimeMap fileExtension=".xwd" mimeType="image/x-xwindowdump" /> + <mimeMap fileExtension=".z" mimeType="application/x-compress" /> + <mimeMap fileExtension=".zip" mimeType="application/x-zip-compressed" /> + </staticContent> + + <tracing> + + <traceFailedRequests> + <add path="*"> + <traceAreas> + <add provider="ASP" verbosity="Verbose" /> + <add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" /> + <add provider="ISAPI Extension" verbosity="Verbose" /> + <add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,Rewrite,WebSocket" verbosity="Verbose" /> + </traceAreas> + <failureDefinitions statusCodes="200-999" /> + </add> + </traceFailedRequests> + + <traceProviderDefinitions> + <add name="WWW Server" guid="{3a2a4e84-4c21-4981-ae10-3fda0d9b0f83}"> + <areas> + <clear /> + <add name="Authentication" value="2" /> + <add name="Security" value="4" /> + <add name="Filter" value="8" /> + <add name="StaticFile" value="16" /> + <add name="CGI" value="32" /> + <add name="Compression" value="64" /> + <add name="Cache" value="128" /> + <add name="RequestNotifications" value="256" /> + <add name="Module" value="512" /> + <add name="Rewrite" value="1024" /> + <add name="FastCGI" value="4096" /> + <add name="WebSocket" value="16384" /> + </areas> + </add> + <add name="ASP" guid="{06b94d9a-b15e-456e-a4ef-37c984a2cb4b}"> + <areas> + <clear /> + </areas> + </add> + <add name="ISAPI Extension" guid="{a1c2040e-8840-4c31-ba11-9871031a19ea}"> + <areas> + <clear /> + </areas> + </add> + <add name="ASPNET" guid="{AFF081FE-0247-4275-9C4E-021F3DC1DA35}"> + <areas> + <add name="Infrastructure" value="1" /> + <add name="Module" value="2" /> + <add name="Page" value="4" /> + <add name="AppServices" value="8" /> + </areas> + </add> + </traceProviderDefinitions> + + </tracing> + + <urlCompression /> + + <validation /> + <webdav> + <globalSettings> + <propertyStores> + <add name="webdav_simple_prop" image="%IIS_BIN%\webdav_simple_prop.dll" image32="%IIS_BIN%\webdav_simple_prop.dll" /> + </propertyStores> + <lockStores> + <add name="webdav_simple_lock" image="%IIS_BIN%\webdav_simple_lock.dll" image32="%IIS_BIN%\webdav_simple_lock.dll" /> + </lockStores> + + </globalSettings> + <authoring> + <locks enabled="true" lockStore="webdav_simple_lock" /> + </authoring> + <authoringRules /> + </webdav> + <webSocket /> + <applicationInitialization /> + + </system.webServer> + <location path="" overrideMode="Allow"> + <system.webServer> + <modules> + <add name="IsapiFilterModule" lockItem="true" /> + <add name="BasicAuthenticationModule" lockItem="true" /> + <add name="IsapiModule" lockItem="true" /> + <add name="HttpLoggingModule" lockItem="true" /> + <add name="DynamicCompressionModule" lockItem="true" /> + <add name="StaticCompressionModule" lockItem="true" /> + <add name="DefaultDocumentModule" lockItem="true" /> + <add name="DirectoryListingModule" lockItem="true" /> + <add name="ProtocolSupportModule" lockItem="true" /> + <add name="HttpRedirectionModule" lockItem="true" /> + <add name="ServerSideIncludeModule" lockItem="true" /> + <add name="StaticFileModule" lockItem="true" /> + <add name="AnonymousAuthenticationModule" lockItem="true" /> + <add name="CertificateMappingAuthenticationModule" lockItem="true" /> + <add name="UrlAuthorizationModule" lockItem="true" /> + <add name="WindowsAuthenticationModule" lockItem="true" /> + <add name="IISCertificateMappingAuthenticationModule" lockItem="true" /> + <add name="WebMatrixSupportModule" lockItem="true" /> + <add name="IpRestrictionModule" lockItem="true" /> + <add name="DynamicIpRestrictionModule" lockItem="true" /> + <add name="RequestFilteringModule" lockItem="true" /> + <add name="CustomLoggingModule" lockItem="true" /> + <add name="CustomErrorModule" lockItem="true" /> + <add name="FailedRequestsTracingModule" lockItem="true" /> + <add name="CgiModule" lockItem="true" /> + <add name="FastCgiModule" lockItem="true" /> +<!-- <add name="WebDAVModule" /> --> + <add name="RewriteModule" /> + <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" preCondition="managedHandler" /> + <add name="Session" type="System.Web.SessionState.SessionStateModule" preCondition="managedHandler" /> + <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" preCondition="managedHandler" /> + <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" preCondition="managedHandler" /> + <add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" preCondition="managedHandler" /> + <add name="RoleManager" type="System.Web.Security.RoleManagerModule" preCondition="managedHandler" /> + <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="managedHandler" /> + <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" preCondition="managedHandler" /> + <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" preCondition="managedHandler" /> + <add name="Profile" type="System.Web.Profile.ProfileModule" preCondition="managedHandler" /> + <add name="UrlMappingsModule" type="System.Web.UrlMappingsModule" preCondition="managedHandler" /> + <add name="ApplicationInitializationModule" lockItem="true" /> + <add name="WebSocketModule" lockItem="true" /> + <add name="ServiceModel-4.0" type="System.ServiceModel.Activation.ServiceHttpModule,System.ServiceModel.Activation,Version=4.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler,runtimeVersionv4.0" /> + <add name="ConfigurationValidationModule" lockItem="true" /> + <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler,runtimeVersionv4.0" /> + <add name="ScriptModule-4.0" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler,runtimeVersionv4.0" /> + <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler,runtimeVersionv2.0" /> + </modules> + <handlers accessPolicy="Read, Script"> +<!-- <add name="WebDAV" path="*" verb="PROPFIND,PROPPATCH,MKCOL,PUT,COPY,DELETE,MOVE,LOCK,UNLOCK" modules="WebDAVModule" resourceType="Unspecified" requireAccess="None" /> --> + <add name="AXD-ISAPI-4.0_64bit" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="PageHandlerFactory-ISAPI-4.0_64bit" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="SimpleHandlerFactory-ISAPI-4.0_64bit" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="WebServiceHandlerFactory-ISAPI-4.0_64bit" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="HttpRemotingHandlerFactory-rem-ISAPI-4.0_64bit" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="HttpRemotingHandlerFactory-soap-ISAPI-4.0_64bit" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="svc-ISAPI-4.0_64bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" /> + <add name="rules-ISAPI-4.0_64bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" /> + <add name="xoml-ISAPI-4.0_64bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" /> + <add name="xamlx-ISAPI-4.0_64bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" /> + <add name="aspq-ISAPI-4.0_64bit" path="*.aspq" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="cshtm-ISAPI-4.0_64bit" path="*.cshtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="cshtml-ISAPI-4.0_64bit" path="*.cshtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="vbhtm-ISAPI-4.0_64bit" path="*.vbhtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="vbhtml-ISAPI-4.0_64bit" path="*.vbhtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="svc-Integrated" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="svc-ISAPI-2.0" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" /> + <add name="xoml-Integrated" path="*.xoml" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="xoml-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" /> + <add name="rules-Integrated" path="*.rules" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="rules-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" /> + <add name="AXD-ISAPI-4.0_32bit" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="PageHandlerFactory-ISAPI-4.0_32bit" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="SimpleHandlerFactory-ISAPI-4.0_32bit" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="WebServiceHandlerFactory-ISAPI-4.0_32bit" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="HttpRemotingHandlerFactory-rem-ISAPI-4.0_32bit" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="HttpRemotingHandlerFactory-soap-ISAPI-4.0_32bit" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="svc-ISAPI-4.0_32bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" /> + <add name="rules-ISAPI-4.0_32bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" /> + <add name="xoml-ISAPI-4.0_32bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" /> + <add name="xamlx-ISAPI-4.0_32bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" /> + <add name="aspq-ISAPI-4.0_32bit" path="*.aspq" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="cshtm-ISAPI-4.0_32bit" path="*.cshtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="cshtml-ISAPI-4.0_32bit" path="*.cshtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="vbhtm-ISAPI-4.0_32bit" path="*.vbhtm" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="vbhtml-ISAPI-4.0_32bit" path="*.vbhtml" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="TraceHandler-Integrated-4.0" path="trace.axd" verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TraceHandler" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="WebAdminHandler-Integrated-4.0" path="WebAdmin.axd" verb="GET,DEBUG" type="System.Web.Handlers.WebAdminHandler" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="AssemblyResourceLoader-Integrated-4.0" path="WebResource.axd" verb="GET,DEBUG" type="System.Web.Handlers.AssemblyResourceLoader" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="PageHandlerFactory-Integrated-4.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.SimpleHandlerFactory" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="WebServiceHandlerFactory-Integrated-4.0" path="*.asmx" verb="GET,HEAD,POST,DEBUG" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="HttpRemotingHandlerFactory-rem-Integrated-4.0" path="*.rem" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="HttpRemotingHandlerFactory-soap-Integrated-4.0" path="*.soap" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="svc-Integrated-4.0" path="*.svc" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="rules-Integrated-4.0" path="*.rules" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="xoml-Integrated-4.0" path="*.xoml" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="xamlx-Integrated-4.0" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" type="System.Xaml.Hosting.XamlHttpHandlerFactory, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="aspq-Integrated-4.0" path="*.aspq" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="cshtm-Integrated-4.0" path="*.cshtm" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="cshtml-Integrated-4.0" path="*.cshtml" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="vbhtm-Integrated-4.0" path="*.vbhtm" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="vbhtml-Integrated-4.0" path="*.vbhtml" verb="GET,HEAD,POST,DEBUG" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="ScriptHandlerFactoryAppServices-Integrated-4.0" path="*_AppService.axd" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="ScriptResourceIntegrated-4.0" path="*ScriptResource.axd" verb="GET,HEAD" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" preCondition="integratedMode,runtimeVersionv4.0" /> + <add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%IIS_BIN%\asp.dll" resourceType="File" /> + <add name="SecurityCertificate" path="*.cer" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%IIS_BIN%\asp.dll" resourceType="File" /> + <add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" /> + <add name="TraceHandler-Integrated" path="trace.axd" verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TraceHandler" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="WebAdminHandler-Integrated" path="WebAdmin.axd" verb="GET,DEBUG" type="System.Web.Handlers.WebAdminHandler" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="AssemblyResourceLoader-Integrated" path="WebResource.axd" verb="GET,DEBUG" type="System.Web.Handlers.AssemblyResourceLoader" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="PageHandlerFactory-Integrated" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="SimpleHandlerFactory-Integrated" path="*.ashx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.SimpleHandlerFactory" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="WebServiceHandlerFactory-Integrated" path="*.asmx" verb="GET,HEAD,POST,DEBUG" type="System.Web.Services.Protocols.WebServiceHandlerFactory,System.Web.Services,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="HttpRemotingHandlerFactory-rem-Integrated" path="*.rem" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,System.Runtime.Remoting,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="HttpRemotingHandlerFactory-soap-Integrated" path="*.soap" verb="GET,HEAD,POST,DEBUG" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory,System.Runtime.Remoting,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" /> + <add name="AXD-ISAPI-2.0" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" /> + <add name="PageHandlerFactory-ISAPI-2.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" /> + <add name="SimpleHandlerFactory-ISAPI-2.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" /> + <add name="WebServiceHandlerFactory-ISAPI-2.0" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" /> + <add name="HttpRemotingHandlerFactory-rem-ISAPI-2.0" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" /> + <add name="HttpRemotingHandlerFactory-soap-ISAPI-2.0" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" /> + <add name="svc-ISAPI-2.0-64" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" /> + <add name="AXD-ISAPI-2.0-64" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" /> + <add name="PageHandlerFactory-ISAPI-2.0-64" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" /> + <add name="SimpleHandlerFactory-ISAPI-2.0-64" path="*.ashx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" /> + <add name="WebServiceHandlerFactory-ISAPI-2.0-64" path="*.asmx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" /> + <add name="HttpRemotingHandlerFactory-rem-ISAPI-2.0-64" path="*.rem" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" /> + <add name="HttpRemotingHandlerFactory-soap-ISAPI-2.0-64" path="*.soap" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" /> + <add name="rules-64-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" /> + <add name="xoml-64-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" /> + <add name="CGI-exe" path="*.exe" verb="*" modules="CgiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" /> + <add name="SSINC-stm" path="*.stm" verb="GET,HEAD,POST" modules="ServerSideIncludeModule" resourceType="File" /> + <add name="SSINC-shtm" path="*.shtm" verb="GET,HEAD,POST" modules="ServerSideIncludeModule" resourceType="File" /> + <add name="SSINC-shtml" path="*.shtml" verb="GET,HEAD,POST" modules="ServerSideIncludeModule" resourceType="File" /> + <add name="TRACEVerbHandler" path="*" verb="TRACE" modules="ProtocolSupportModule" requireAccess="None" /> + <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" /> + <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> + <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> + <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" /> + <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" /> + </handlers> + </system.webServer> + </location> +</configuration> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ActivationCodeService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ActivationCodeService.cs" new file mode 100644 index 0000000..bbdb159 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ActivationCodeService.cs" @@ -0,0 +1,164 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Math; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_DTO.BasicInfo; +using WIDESEA_IBasicInfoServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_BasicInfoServices +{ + public class ActivationCodeService : ServiceBase<Dt_ActivationCode, IRepository<Dt_ActivationCode>>, IActivationCodeService + { + private readonly IRepository<Dt_CharMapping> _charMappingRepository; + private readonly IRepository<Dt_RuntimeCode> _runtimeCodeRepository; + private readonly IRepository<Dt_Products> _productRepository; + + public ActivationCodeService(IRepository<Dt_ActivationCode> BaseDal, IRepository<Dt_CharMapping> charMappingRepository, IRepository<Dt_RuntimeCode> runtimeCodeRepository, IRepository<Dt_Products> productRepository) : base(BaseDal) + { + _charMappingRepository = charMappingRepository; + _runtimeCodeRepository = runtimeCodeRepository; + _productRepository = productRepository; + } + + /// <summary> + /// 鐢熸垚婵�娲荤爜 + /// </summary> + /// <param name="activationDTO">鍖呭惈杩愯鐮併�佽澶嘔D鍜屼骇鍝佸悕绉扮殑鏁版嵁浼犺緭瀵硅薄</param> + /// <returns>鐢熸垚鐨勬縺娲荤爜</returns> + public string GenerateActivationCode(ActivationCodeDTO activationDTO) + { + // 鏌ヨ杩愯鐮佸搴旂殑妯″瀷 + Dt_RuntimeCode runtimeCodeModel = _runtimeCodeRepository.QueryFirst(x => x.RuntimeCode == activationDTO.RuntimeCode); + // 1. 妫�鏌ヨ繍琛岀爜鏄惁宸插瓨鍦� + if (runtimeCodeModel == null) + { + throw new InvalidOperationException($"鏃犳晥鐨勮繍琛岀爜: {activationDTO.RuntimeCode}"); + } + + // 鏌ヨ婵�娲荤爜瀵瑰簲鐨勬ā鍨� + Dt_ActivationCode activationCodeModel = BaseDal.QueryFirst(x => x.RuntimeCode == activationDTO.RuntimeCode); + // 2. 妫�鏌ユ縺娲荤爜鏄惁宸插瓨鍦� + if (activationCodeModel != null) + { + return activationCodeModel.ActivationCode; + } + + int productId = -1; + // 鏌ヨ浜у搧瀵瑰簲鐨勬ā鍨� + Dt_Products product = _productRepository.QueryFirst(x => x.ProductName == activationDTO.ProductName); + if (product != null) + { + productId = product.Id; + } + + // 3. 妫�鏌ヨ澶嘔D鍜屼骇鍝両D鏄惁鍖归厤 + if (runtimeCodeModel.DeviceId != activationDTO.DeviceId || runtimeCodeModel.ProductId != productId) + { + throw new InvalidOperationException($"璁惧ID鎴栦骇鍝両D涓嶅尮閰�: {activationDTO.DeviceId}, {productId}"); + } + + // 4. 鐢熸垚婵�娲荤爜 + // 鍘婚櫎杩愯鐮佷腑鐨�"-"瀛楃 + string baseRandom = activationDTO.RuntimeCode.Replace("-", string.Empty); + + // 鏌ヨ瀛楃鏄犲皠瀛楀吀 + Dictionary<char, (char output, int shift)> mappingDict = _charMappingRepository.QueryData().ToDictionary(x => x.InputChar.ToCharArray().FirstOrDefault(), x => (x.OutputChar.ToCharArray().FirstOrDefault(), x.ShiftFactor)); + + char[] result = new char[baseRandom.Length]; + int length = baseRandom.Length; + + // 閬嶅巻杩愯鐮佺殑姣忎釜瀛楃杩涜杞崲 + for (int i = 0; i < length; i++) + { + char current = baseRandom[i]; + if (current == '-') + continue; + if (!mappingDict.TryGetValue(current, out var mapping)) + throw new InvalidOperationException($"鏃犳晥瀛楃: {current}"); + + // 鐗规畩鍙樻崲锛氭瘡5涓瓧绗﹀鍔犲鏉傚害 + char mappedChar = (i % 5 == 4) + ? ApplySpecialTransform(mapping.output, mapping.shift) + : mapping.output; + + result[i] = mappedChar; + } + + // 鏍煎紡鍖栨縺娲荤爜 + string activationCode = FormatCode(new string(result)); + + // 5. 瀛樺偍婵�娲荤爜 + StoredActivationCode(activationDTO.DeviceId, baseRandom, activationCode, activationDTO.RuntimeCode, productId); + + return activationCode; + } + + /// <summary> + /// 瀵硅緭鍏ュ瓧绗﹁繘琛屽熀浜嶢SCII鐮佺殑浜屾鍙樻崲銆� + /// </summary> + /// <param name="c">瑕佸彉鎹㈢殑瀛楃銆�</param> + /// <param name="position">瀛楃鐨勪綅缃紝鐢ㄤ簬璁$畻鍙樻崲鍊笺��</param> + /// <returns>鍙樻崲鍚庣殑瀛楃銆�</returns> + private char ApplySpecialTransform(char c, int position) + { + // 灏嗗瓧绗﹁浆鎹负ASCII鐮� + int ascii = (int)c; + + // 璁$畻鍙樻崲鍚庣殑ASCII鐮佸�硷紝鍩轰簬瀛楃鐨勪綅缃繘琛屽亸绉伙紝骞剁‘淇濈粨鏋滃湪0-35鑼冨洿鍐� + int transformed = (ascii + position) % 36 + 48; + + // 濡傛灉鍙樻崲鍚庣殑ASCII鐮佸�煎湪':'鍒�'@'涔嬮棿锛堝嵆瀛楃'9'鍒板瓧绗�'@'锛夛紝鍒欏啀鍋忕Щ7涓綅缃� + if (transformed >= ':' && transformed <= '@') + { + transformed += 7; + } + + // 灏嗗彉鎹㈠悗鐨凙SCII鐮佸�艰浆鎹㈠洖瀛楃骞惰繑鍥� + return (char)transformed; + } + + /// <summary> + /// 灏嗗師濮嬪瓧绗︿覆鏍煎紡鍖栦负XXXXX-XXXXX-XXXXX-XXXXX-XXXXX鐨勫舰寮� + /// </summary> + /// <param name="raw">闇�瑕佹牸寮忓寲鐨勫師濮嬪瓧绗︿覆锛岄暱搴﹀繀椤讳负25涓瓧绗�</param> + private string FormatCode(string raw) + { + // 鏍煎紡鍖栦负XXXXX-XXXXX-XXXXX-XXXXX-XXXXX + return string.Join("-", + raw.Substring(0, 5), + raw.Substring(5, 5), + raw.Substring(10, 5), + raw.Substring(15, 5), + raw.Substring(20, 5)); + } + + /// <summary> + /// 瀛樺偍婵�娲荤爜淇℃伅鍒版暟鎹簱 + /// </summary> + /// <param name="deviceId">璁惧ID锛岀敤浜庢爣璇嗙壒瀹氳澶�</param> + /// <param name="baseRandom">鍩虹闅忔満鐮侊紝鐢ㄤ簬鐢熸垚婵�娲荤爜鐨勯殢鏈哄瓧绗︿覆</param> + /// <param name="activationCode">婵�娲荤爜锛岀敤浜庝骇鍝佹縺娲荤殑鍞竴浠g爜</param> + /// <param name="runtimeCode">杩愯鏃剁爜锛岀敤浜庨獙璇佹縺娲荤姸鎬佺殑浠g爜</param> + /// <param name="productId">浜у搧ID锛岀敤浜庢爣璇嗕笉鍚岀殑浜у搧</param> + private void StoredActivationCode(string deviceId, string baseRandom, string activationCode, string runtimeCode, int productId) + { + Dt_ActivationCode activationRecord = new Dt_ActivationCode + { + MappedRandom = baseRandom, + ActivationCode = activationCode, + DeviceId = deviceId, + IsUsed = false, + ProductId = productId, + ExpiresTime = null, + RuntimeCode = runtimeCode + }; + + BaseDal.AddData(activationRecord); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ProductsService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ProductsService.cs" new file mode 100644 index 0000000..2498c79 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/ProductsService.cs" @@ -0,0 +1,137 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_DTO.BasicInfo; +using WIDESEA_IBasicInfoServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_BasicInfoServices +{ + public class ProductsService : ServiceBase<Dt_Products, IRepository<Dt_Products>>, IProductsService + { + private readonly IRepository<Dt_RuntimeCode> _runtimeCodeRepository; + private readonly IRepository<Dt_ActivationCode> _activationCodeRepository; + private readonly IActivationCodeService _activationCodeService; + + public ProductsService(IRepository<Dt_Products> BaseDal, IRepository<Dt_RuntimeCode> runtimeCodeRepository, IRepository<Dt_ActivationCode> activationCodeRepository, IActivationCodeService activationCodeService) : base(BaseDal) + { + _runtimeCodeRepository = runtimeCodeRepository; + _activationCodeRepository = activationCodeRepository; + _activationCodeService = activationCodeService; + } + + /// <summary> + /// 楠岃瘉浜у搧婵�娲讳俊鎭� + /// </summary> + /// <param name="activationModel">鍖呭惈浜у搧婵�娲绘墍闇�淇℃伅鐨凞TO瀵硅薄锛屽寘鎷骇鍝佸悕绉般�佽繍琛岀爜銆佹縺娲荤爜鍜岃澶嘔D</param> + /// <returns>杩斿洖涓�涓猈ebResponseContent瀵硅薄锛屽寘鍚獙璇佺粨鏋滀俊鎭細 + /// - 鎴愬姛鏃惰繑鍥濷K鐘舵�� + /// - 澶辫触鏃惰繑鍥炲叿浣撶殑閿欒淇℃伅锛屽"鏃犳晥鐨勮繍琛岀爜"銆�"鏃犳晥鐨勬縺娲荤爜"銆�"婵�娲荤爜宸茶繃鏈�"鎴�"婵�娲荤爜楠岃瘉澶辫触"</returns> + /// <remarks> + /// 楠岃瘉娴佺▼锛� + /// 1. 鏍规嵁浜у搧鍚嶇О鑾峰彇浜у搧ID + /// 2. 楠岃瘉杩愯鐮佹槸鍚﹀瓨鍦ㄤ笖鍖归厤 + /// 3. 楠岃瘉婵�娲荤爜鏄惁瀛樺湪涓斿尮閰� + /// 4. 妫�鏌ユ縺娲荤爜鏄惁杩囨湡 + /// 5. 閲嶆柊鐢熸垚婵�娲荤爜杩涜楠岃瘉 + /// 6. 鏇存柊婵�娲荤姸鎬佷负宸蹭娇鐢� + /// </remarks> + public WebResponseContent ValidateActivation(ActivationDTO activationModel) + { + int productId = -1; + Dt_Products product = BaseDal.QueryFirst(x => x.ProductName == activationModel.ProductName); + if (product != null) + { + productId = product.Id; + } + + // 鑾峰彇杩愯鐮佽褰� + Dt_RuntimeCode runtimeCode = _runtimeCodeRepository.QueryFirst(rc => rc.RuntimeCode == activationModel.RuntimeCode && rc.DeviceId == activationModel.DeviceId && rc.ProductId == productId); + + if (runtimeCode == null) + return WebResponseContent.Instance.Error("鏃犳晥鐨勮繍琛岀爜"); + + // 鑾峰彇瀵瑰簲鐨勬縺娲荤爜 + Dt_ActivationCode activation = _activationCodeRepository.QueryFirst(ac => ac.ActivationCode == activationModel.ActivationCode && ac.RuntimeCode == activationModel.RuntimeCode && ac.DeviceId == activationModel.DeviceId && ac.ProductId == productId); + + if (activation == null) + return WebResponseContent.Instance.Error("鏃犳晥鐨勬縺娲荤爜"); + + if (activation.ExpiresTime != null && activation.ExpiresTime < DateTime.Now) + return WebResponseContent.Instance.Error("婵�娲荤爜宸茶繃鏈�"); + + ActivationCodeDTO activationCodeDTO = new ActivationCodeDTO + { + RuntimeCode = runtimeCode.RuntimeCode, + DeviceId = activation.DeviceId, + ProductName = activationModel.ProductName + }; + + // 閲嶆柊鐢熸垚鏄犲皠杩涜楠岃瘉 + string regenerated = _activationCodeService.GenerateActivationCode(activationCodeDTO); + if (regenerated != activationModel.ActivationCode) + return WebResponseContent.Instance.Error("婵�娲荤爜楠岃瘉澶辫触"); + + // 鏇存柊婵�娲荤姸鎬� + activation.IsUsed = true; + activation.UsedTime = DateTime.Now; + _activationCodeRepository.UpdateData(activation); + + return WebResponseContent.Instance.OK(); + } + + /// <summary> + /// 鑾峰彇璁惧婵�娲讳俊鎭� + /// </summary> + /// <param name="deviceId">璁惧ID</param> + /// <param name="productName">浜у搧鍚嶇О</param> + /// <returns> + /// 杩斿洖WebResponseContent瀵硅薄锛屽寘鍚互涓嬫儏鍐碉細 + /// 1. 浜у搧涓嶅瓨鍦ㄦ椂杩斿洖閿欒 + /// 2. 杩愯鐮佷笉瀛樺湪鏃惰繑鍥為敊璇� + /// 3. 婵�娲荤爜涓嶅瓨鍦ㄦ椂杩斿洖杩愯鐮併�佺┖婵�娲荤爜鍜屾湭婵�娲荤姸鎬� + /// 4. 婵�娲荤爜宸蹭娇鐢ㄦ椂杩斿洖杩愯鐮併�佹縺娲荤爜鍜屽凡婵�娲荤姸鎬� + /// 5. 婵�娲荤爜鏈娇鐢ㄦ椂杩斿洖杩愯鐮併�佹縺娲荤爜鍜屾湭婵�娲荤姸鎬� + /// 6. 鍙戠敓寮傚父鏃惰繑鍥為敊璇俊鎭� + /// </returns> + public WebResponseContent GetActivationInfo(string deviceId, string productName) + { + try + { + Dt_Products product = BaseDal.QueryFirst(x => x.ProductName == productName); + if (product == null) + { + return WebResponseContent.Instance.Error(); + } + + Dt_RuntimeCode runtimeCode = _runtimeCodeRepository.QueryFirst(x => x.DeviceId == deviceId && x.ProductId == product.Id); + if (runtimeCode == null) + { + return WebResponseContent.Instance.Error(); + } + + Dt_ActivationCode activationCode = _activationCodeRepository.QueryFirst(x => x.RuntimeCode == runtimeCode.RuntimeCode && x.ProductId == product.Id && x.DeviceId == deviceId); + if (activationCode == null) + { + return WebResponseContent.Instance.OK(data: new { runtimeCode.RuntimeCode, ActivationCode = "", IsActivated = false }); + } + + if (activationCode.IsUsed && activationCode.UsedTime != null) + { + return WebResponseContent.Instance.OK(data: new { runtimeCode.RuntimeCode, activationCode.ActivationCode, IsActivated = true }); + } + + return WebResponseContent.Instance.OK(data: new { runtimeCode.RuntimeCode, activationCode.ActivationCode, IsActivated = false }); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(message: "鑾峰彇婵�娲荤爜淇℃伅澶辫触"); + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/RuntimeCodeService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/RuntimeCodeService.cs" new file mode 100644 index 0000000..e6c3f60 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/RuntimeCodeService.cs" @@ -0,0 +1,135 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_DTO.BasicInfo; +using WIDESEA_IBasicInfoServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_BasicInfoServices +{ + public class RuntimeCodeService : ServiceBase<Dt_RuntimeCode, IRepository<Dt_RuntimeCode>>, IRuntimeCodeService + { + private const int BaseRandomLength = 25; + private const int RuntimeCodeLength = 25; + + private readonly IRepository<Dt_Products> _productRepository; + + public RuntimeCodeService(IRepository<Dt_RuntimeCode> BaseDal, IRepository<Dt_Products> productRepository) : base(BaseDal) + { + _productRepository = productRepository; + } + + + // 鐢熸垚璁惧杩愯鐮佷富鏂规硶 + public WebResponseContent GenerateRuntimeCode(DeviceInfoDTO deviceInfo) + { + try + { + int productId = -1; + Dt_Products product = _productRepository.QueryFirst(x => x.ProductName == deviceInfo.ProductName); + if (product != null) + { + productId = product.Id; + } + + Dt_RuntimeCode runtimeCodeModel = BaseDal.QueryFirst(x => x.DeviceId == deviceInfo.DeviceId && x.ProductId == productId); + if (runtimeCodeModel != null) + { + return WebResponseContent.Instance.OK(data: runtimeCodeModel.RuntimeCode); + } + + GenerateBaseRandomL: + // 1. 鐢熸垚鍩虹闅忔満鐮� + string baseRandom = GenerateBaseRandom(); + + // 2. 娣诲姞鏍¢獙浣� + char checkDigit = CalculateCheckDigit(baseRandom); + + // 3. 缁勫悎瀹屾暣杩愯鐮� + string runtimeCode = FormatRuntimeCode(baseRandom + checkDigit); + + if (BaseDal.QueryFirst(x => x.RuntimeCode == runtimeCode) != null) + { + goto GenerateBaseRandomL; + } + + // 4. 瀛樺偍鍒版暟鎹簱 + StoreRuntimeCode(deviceInfo.DeviceId, checkDigit.ToString(), baseRandom, runtimeCode, deviceInfo.DeviceInfoJson, productId); + + return WebResponseContent.Instance.OK(data: runtimeCode); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(message: "鐢熸垚杩愯鐮佸け璐�"); + } + + } + + // 鐢熸垚20浣嶉殢鏈哄熀纭�鐮� + private string GenerateBaseRandom() + { + const string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + var random = new Random(); + return new string(Enumerable.Repeat(chars, BaseRandomLength) + .Select(s => s[random.Next(s.Length)]).ToArray()); + } + + // 璁$畻Luhn鏍¢獙浣� + private char CalculateCheckDigit(string baseRandom) + { + int sum = 0; + bool alternate = true; + + // 浠庡彸鍚戝乏澶勭悊 + for (int i = baseRandom.Length - 1; i >= 0; i--) + { + int n = CharToInt(baseRandom[i]); + sum += alternate ? n : (n * 2 > 9 ? n * 2 - 9 : n * 2); + alternate = !alternate; + } + + int checkDigit = (10 - (sum % 10)) % 10; + return checkDigit.ToString().ToCharArray().FirstOrDefault(); + } + + // 瀛楃杞暟瀛� + private int CharToInt(char c) + { + return c >= '0' && c <= '9' + ? c - '0' + : c - 'A' + 10; + } + + // 鏍煎紡鍖栬繍琛岀爜 (XXXXX-XXXXX-XXXXX-XXXXX-XXXXX) + private string FormatRuntimeCode(string rawCode) + { + return string.Join("-", + rawCode.Substring(0, 5), + rawCode.Substring(5, 5), + rawCode.Substring(10, 5), + rawCode.Substring(15, 5), + rawCode.Substring(20, 5)); + } + + // 瀛樺偍鍒版暟鎹簱 + private void StoreRuntimeCode(string deviceId, string checkDigit, string baseRandom, string runtimeCode, string deviceInfo, int productId) + { + Dt_RuntimeCode runtimeRecord = new Dt_RuntimeCode + { + BaseRandom = baseRandom, + RuntimeCode = runtimeCode, + DeviceInfo = deviceInfo, + DeviceId = deviceId, + CheckDigit = checkDigit, + ProductId = productId // 鍋囪浜у搧ID涓�1锛屽疄闄呭簲鐢ㄤ腑搴旀牴鎹叿浣撻�昏緫鑾峰彇 + }; + + BaseDal.AddData(runtimeRecord); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/VersionsService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/VersionsService.cs" new file mode 100644 index 0000000..46e3e19 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/VersionsService.cs" @@ -0,0 +1,20 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_IBasicInfoServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_BasicInfoServices +{ + public class VersionsService : ServiceBase<Dt_Versions, IRepository<Dt_Versions>>, IVersionsService + { + public VersionsService(IRepository<Dt_Versions> BaseDal) : base(BaseDal) + { + } + + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/WIDESEA_BasicInfoServices.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/WIDESEA_BasicInfoServices.csproj" new file mode 100644 index 0000000..013619a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_BasicInfoServices/WIDESEA_BasicInfoServices.csproj" @@ -0,0 +1,13 @@ +锘�<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\WIDESEA_IBasicInfoServices\WIDESEA_IBasicInfoServices.csproj" /> + </ItemGroup> + +</Project> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Common/WIDESEA_Common.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Common/WIDESEA_Common.csproj" new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Common/WIDESEA_Common.csproj" @@ -0,0 +1,9 @@ +锘�<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + +</Project> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/CacheAOP.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/CacheAOP.cs" new file mode 100644 index 0000000..731f40b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/CacheAOP.cs" @@ -0,0 +1,185 @@ +锘縰sing Castle.DynamicProxy; +using Newtonsoft.Json; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Attributes; +using WIDESEA_Core.Caches; +using WIDESEA_Core.Helper; +using ICacheService = WIDESEA_Core.Caches.ICacheService; + +namespace WIDESEA_Core.AOP +{ + public class CacheAOP : IInterceptor + { + private readonly ICacheService _cacheService; + public CacheAOP(ICacheService cacheService) + { + _cacheService = cacheService; + } + + /// <summary> + /// 鎷︽埅鏂规硶璋冪敤骞跺疄鐜扮紦瀛樺姛鑳� + /// </summary> + /// <remarks> + /// 1. 妫�鏌ユ柟娉曟槸鍚﹀甫鏈塁acheAttribute鐗规�� + /// 2. 濡傛灉瀛樺湪缂撳瓨鍒欑洿鎺ヨ繑鍥炵紦瀛樺�� + /// 3. 濡傛灉涓嶅瓨鍦ㄧ紦瀛樺垯鎵ц鏂规硶骞跺皢缁撴灉缂撳瓨 + /// 4. 鏀寔寮傛鏂规硶(Task)鐨勭紦瀛樺鐞� + /// 5. 浣跨敤鑷畾涔夌紦瀛橀敭(CustomCacheKey)鏉ユ爣璇嗙紦瀛橀」 + /// </remarks> + /// <param name="invocation">琚嫤鎴殑鏂规硶璋冪敤淇℃伅</param> + public void Intercept(IInvocation invocation) + { + //鑾峰彇琚嫤鎴殑鏂规硶 + var method = invocation.MethodInvocationTarget ?? invocation.Method; + + //鑾峰彇鏂规硶涓婄殑缂撳瓨鐗规�� + var cacheAttribute = method.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(CacheAttribute)); + if (cacheAttribute is CacheAttribute qCachingAttribute) + { + //鑾峰彇鑷畾涔夌紦瀛橀敭 + var cacheKey = CustomCacheKey(invocation); + if (_cacheService.Exists(cacheKey)) + { + //灏嗗綋鍓嶈幏鍙栧埌鐨勭紦瀛樺�硷紝璧嬪�肩粰褰撳墠鎵ц鏂规硶 + Type returnType; + if (typeof(Task).IsAssignableFrom(method.ReturnType)) + { + returnType = method.ReturnType.GenericTypeArguments.FirstOrDefault(); + } + else + { + returnType = method.ReturnType; + } + + //鏍规嵁key鑾峰彇鐩稿簲鐨勭紦瀛樺�� + dynamic? cacheValue = _cacheService.Get(returnType, cacheKey); + if (cacheValue != null) + invocation.ReturnValue = (typeof(Task).IsAssignableFrom(method.ReturnType)) ? Task.FromResult(cacheValue) : cacheValue; + return; + } + + //鍘绘墽琛屽綋鍓嶇殑鏂规硶 + invocation.Proceed(); + //瀛樺叆缂撳瓨 + if (!string.IsNullOrWhiteSpace(cacheKey)) + { + object response; + + //Type type = invocation.ReturnValue?.GetType(); + var type = invocation.Method.ReturnType; + if (typeof(Task).IsAssignableFrom(type)) + { + dynamic result = invocation.ReturnValue; + response = result.Result; + } + else + { + response = invocation.ReturnValue; + } + + if (response == null) response = string.Empty; + + _cacheService.AddOrUpdate(cacheKey, response.Serialize(), qCachingAttribute.AbsoluteExpiration * 60); + } + } + else + { + invocation.Proceed(); //鐩存帴鎵ц琚嫤鎴柟娉� + } + } + + /// <summary> + /// 鑷畾涔夌紦瀛樼殑key + /// </summary> + /// <param name="invocation"></param> + /// <returns></returns> + protected string CustomCacheKey(IInvocation invocation) + { + var typeName = invocation.TargetType.Name; + //鑾峰彇璋冪敤鐩爣绫诲瀷鍚嶇О + var methodName = invocation.Method.Name; + //鑾峰彇璋冪敤鏂规硶鍚嶇О + var methodArguments = invocation.Arguments.Select(GetArgumentValue).Take(3).ToList();//鑾峰彇鍙傛暟鍒楄〃锛屾渶澶氫笁涓� + + string key = $"{typeName}:{methodName}:"; + //瀹氫箟key锛屾牸寮忎负锛氱被鍨嬪悕绉�:鏂规硶鍚嶇О: + foreach (var param in methodArguments) + { + key = $"{key}{param}:"; + //閬嶅巻鍙傛暟鍒楄〃锛屽皢鍙傛暟鍊兼坊鍔犲埌key涓紝鏍煎紡涓猴細鍙傛暟鍊�: + } + + return key.TrimEnd(':'); + //杩斿洖key锛屽幓鎺夋湯灏剧殑鍐掑彿 + } + + /// <summary> + /// object 杞� string + /// </summary> + /// <param name="arg"></param> + /// <returns></returns> + protected static string GetArgumentValue(object arg) + { + if (arg is DateTime) + // 濡傛灉arg鏄疍ateTime绫诲瀷锛屽垯杩斿洖鍏跺瓧绗︿覆琛ㄧず褰㈠紡 + return ((DateTime)arg).ToString("yyyyMMddHHmmss"); + + if (!arg.IsNotEmptyOrNull()) + // 濡傛灉arg涓嶆槸绌烘垨null锛屽垯杩斿洖鍏跺瓧绗︿覆琛ㄧず褰㈠紡 + return arg.ObjToString(); + + if (arg != null) + { + // 濡傛灉arg涓嶆槸绌烘垨null + if (arg is Expression) + { + // 濡傛灉arg鏄疎xpression绫诲瀷 + var obj = arg as Expression; + // 瑙f瀽arg + var result = Resolve(obj); + // 杩斿洖MD5鍔犲瘑鍚庣殑瀛楃涓� + return MD5Helper.MD5Encrypt16(result); + } + else if (arg.GetType().IsClass) + { + // 濡傛灉arg鏄被绫诲瀷 + // 灏哸rg搴忓垪鍖栦负JSON瀛楃涓� + return MD5Helper.MD5Encrypt16(JsonConvert.SerializeObject(arg)); + } + + // 鍚﹀垯锛岃繑鍥�"value:"鍔犱笂arg鐨勫瓧绗︿覆琛ㄧず褰㈠紡 + return $"value:{arg.ObjToString()}"; + } + // 濡傛灉arg鏄┖鎴杗ull锛屽垯杩斿洖绌哄瓧绗︿覆 + return string.Empty; + } + + private static string Resolve(Expression expression) + { + // 鍒涘缓涓�涓狤xpressionContext瀵硅薄 + ExpressionContext expContext = new ExpressionContext(); + // 瑙f瀽琛ㄨ揪寮忥紝骞舵寚瀹氳В鏋愮被鍨嬩负WhereSingle + expContext.Resolve(expression, ResolveExpressType.WhereSingle); + // 鑾峰彇瑙f瀽缁撴灉 + var value = expContext.Result.GetString(); + // 鑾峰彇鍙傛暟鍒楄〃 + var pars = expContext.Parameters; + + // 閬嶅巻鍙傛暟鍒楄〃 + pars.ForEach(s => + { + // 灏嗗弬鏁板悕鏇挎崲涓哄弬鏁板�� + value = value.Replace(s.ParameterName, s.Value.ObjToString()); + }); + + // 杩斿洖鏇挎崲鍚庣殑鍊� + return value; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/LogAOP.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/LogAOP.cs" new file mode 100644 index 0000000..9000312 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/LogAOP.cs" @@ -0,0 +1,313 @@ +锘縰sing Castle.DynamicProxy; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.SignalR; +using Newtonsoft.Json; +using StackExchange.Profiling; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; +using WIDESEA_Core.LogHelper; + +namespace WIDESEA_Core.AOP +{ + /// <summary> + /// 鎷︽埅鍣↙ogAOP 缁ф壙IInterceptor鎺ュ彛 + /// </summary> + public class LogAOP : IInterceptor + { + private readonly IHttpContextAccessor _accessor; + + public LogAOP(IHttpContextAccessor accessor) + { + _accessor = accessor; + } + + /// <summary> + /// AOP鎷︽埅鍣ㄦ柟娉曪紝鐢ㄤ簬璁板綍鏂规硶璋冪敤鏃ュ織 + /// </summary> + /// <param name="invocation">琚嫤鎴殑鏂规硶璋冪敤淇℃伅</param> + /// <remarks> + /// 1. 璁板綍鏂规硶璋冪敤鏃堕棿銆佹搷浣滅敤鎴枫�佹柟娉曞悕鍜屽弬鏁颁俊鎭� + /// 2. 澶勭悊鍚屾鍜屽紓姝ユ柟娉曠殑鎵ц + /// 3. 璁板綍鏂规硶鎵ц缁撴灉鎴栧紓甯镐俊鎭� + /// 4. 浣跨敤MiniProfiler杩涜鎬ц兘鐩戞帶 + /// </remarks> + public void Intercept(IInvocation invocation) + { + string UserName = _accessor.HttpContext?.User?.Identity?.Name; + string json; + try + { + if (invocation.Arguments.Any()) + { + json = JsonConvert.SerializeObject(invocation.Arguments); + } + else + { + json = "鏃犲弬鏁�"; + } + } + catch (Exception ex) + { + json = "鏃犳硶搴忓垪鍖栵紝鍙兘鏄叞濮嗚揪琛ㄨ揪寮忕瓑鍘熷洜閫犳垚锛屾寜鐓ф鏋朵紭鍖栦唬鐮�" + ex.ToString(); + } + + DateTime startTime = DateTime.Now; + AOPLogInfo apiLogAopInfo = new AOPLogInfo + { + RequestTime = startTime.ToString("yyyy-MM-dd hh:mm:ss fff"), + OpUserName = "銆愬綋鍓嶆搷浣滅敤鎴枫�戯細" + UserName, + RequestMethodName = "銆愬綋鍓嶆墽琛屾柟娉曘�戯細" + invocation.Method.Name, + RequestParamsName = "銆愭惡甯︾殑鍙傛暟鏈夈�戯細" + string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()), + RequestParamsData = json + }; + + var dataIntercept = $""; + + //try + //{ + MiniProfiler.Current.Step($"鎵ц{invocation.InvocationTarget}.{invocation.Method.Name}()鏂规硶 -> "); + //鍦ㄨ鎷︽埅鐨勬柟娉曟墽琛屽畬姣曞悗 缁х画鎵ц褰撳墠鏂规硶锛屾敞鎰忔槸琚嫤鎴殑鏄紓姝ョ殑 + invocation.Proceed(); + + // 寮傛鑾峰彇寮傚父锛屽厛鎵ц + if (IsAsyncMethod(invocation.Method)) + { + if (invocation.Method.ReturnType == typeof(Task)) + { + invocation.ReturnValue = InternalAsyncHelper.AwaitTaskWithPostActionAndFinally( + (Task)invocation.ReturnValue, + async () => await SuccessAction(invocation, apiLogAopInfo, startTime), /*鎴愬姛鏃舵墽琛�*/ + ex => + { + LogEx(ex, apiLogAopInfo); + }); + } + else + { + invocation.ReturnValue = InternalAsyncHelper.CallAwaitTaskWithPostActionAndFinallyAndGetResult( + invocation.Method.ReturnType.GenericTypeArguments[0], + invocation.ReturnValue, + async (o) => await SuccessAction(invocation, apiLogAopInfo, startTime, o), /*鎴愬姛鏃舵墽琛�*/ + ex => + { + LogEx(ex, apiLogAopInfo); + }); + } + } + else + { + // 鍚屾1 + string jsonResult; + try + { + jsonResult = JsonConvert.SerializeObject(invocation.ReturnValue); + } + catch (Exception ex) + { + jsonResult = "鏃犳硶搴忓垪鍖栵紝鍙兘鏄叞濮嗚揪琛ㄨ揪寮忕瓑鍘熷洜閫犳垚锛屾寜鐓ф鏋朵紭鍖栦唬鐮�" + ex.ToString(); + } + + var type = invocation.Method.ReturnType; + var resultProperty = type.GetProperty("Result"); + DateTime endTime = DateTime.Now; + string ResponseTime = (endTime - startTime).Milliseconds.ToString(); + apiLogAopInfo.ResponseTime = endTime.ToString("yyyy-MM-dd hh:mm:ss fff"); + apiLogAopInfo.ResponseIntervalTime = ResponseTime + "ms"; + apiLogAopInfo.ResponseJsonData = jsonResult; + Parallel.For(0, 1, e => + { + LogLock.OutLogAOP("鍏ㄥ眬鏃ュ織AOP", new string[] { apiLogAopInfo.GetType().ToString(), JsonConvert.SerializeObject(apiLogAopInfo) }); + }); + + + } + //} + //catch (Exception ex) // 鍚屾2 + //{ + // LogEx(ex, apiLogAopInfo); + // throw ex; + //} + } + + /// <summary> + /// 璁板綍鎴愬姛鎿嶄綔鐨凙OP鏃ュ織淇℃伅 + /// </summary> + /// <param name="invocation">鏂规硶璋冪敤淇℃伅</param> + /// <param name="apiLogAopInfo">AOP鏃ュ織瀵硅薄</param> + /// <param name="startTime">鎿嶄綔寮�濮嬫椂闂�</param> + /// <param name="o">杩斿洖缁撴灉瀵硅薄(鍙��)</param> + /// <remarks> + /// 璇ユ柟娉曚細璁$畻鎿嶄綔鑰楁椂锛屽簭鍒楀寲杩斿洖缁撴灉锛屽苟閫氳繃骞惰鏂瑰紡璁板綍鏃ュ織 + /// </remarks> + private async Task SuccessAction(IInvocation invocation, AOPLogInfo apiLogAopInfo, DateTime startTime, object o = null) + { + DateTime endTime = DateTime.Now; + string ResponseTime = (endTime - startTime).Milliseconds.ToString(); + apiLogAopInfo.ResponseTime = endTime.ToString("yyyy-MM-dd hh:mm:ss fff"); + apiLogAopInfo.ResponseIntervalTime = ResponseTime + "ms"; + apiLogAopInfo.ResponseJsonData = JsonConvert.SerializeObject(o); + + await Task.Run(() => + { + Parallel.For(0, 1, e => + { + LogLock.OutLogAOP("鍏ㄥ眬鏃ュ織AOP", new string[] { apiLogAopInfo.GetType().ToString(), JsonConvert.SerializeObject(apiLogAopInfo) }); + }); + }); + } + + /// <summary> + /// 璁板綍寮傚父鏃ュ織淇℃伅 + /// </summary> + /// <param name="ex">鍙戠敓鐨勫紓甯稿璞�</param> + /// <param name="dataIntercept">AOP鎷︽埅鐨勬棩蹇椾俊鎭�</param> + /// <remarks> + /// 璇ユ柟娉曚細璁板綍寮傚父娑堟伅銆佸唴閮ㄥ紓甯稿拰鍫嗘爤璺熻釜淇℃伅锛屽苟閫氳繃骞惰鏂瑰紡鍐欏叆鏃ュ織 + /// </remarks> + private void LogEx(Exception ex, AOPLogInfo dataIntercept) + { + if (ex != null) + { + //鎵ц鐨� service 涓紝鏀跺綍寮傚父 + MiniProfiler.Current.CustomTiming("Errors锛�", ex.Message); + //鎵ц鐨� service 涓紝鎹曡幏寮傚父 + AOPLogExInfo apiLogAopExInfo = new AOPLogExInfo + { + ExMessage = ex.Message, + InnerException = "InnerException-鍐呴儴寮傚父:\r\n" + (ex.InnerException == null ? "" : ex.InnerException.InnerException.ToString()) + + "\r\nStackTrace-鍫嗘爤璺熻釜:\r\n" + (ex.StackTrace == null ? "" : ex.StackTrace.ToString()), + ApiLogAopInfo = dataIntercept + }; + // 寮傚父鏃ュ織閲屾湁璇︾粏鐨勫爢鏍堜俊鎭� + Parallel.For(0, 1, e => + { + LogLock.OutLogAOP("鍏ㄥ眬寮傚父閿欒鏃ュ織AOP", new string[] { apiLogAopExInfo.GetType().ToString(), JsonConvert.SerializeObject(apiLogAopExInfo) }); + }); + } + } + + + public static bool IsAsyncMethod(MethodInfo method) + { + return method.ReturnType == typeof(Task) || method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>); + } + } + + + internal static class InternalAsyncHelper + { + public static async Task AwaitTaskWithPostActionAndFinally(Task actualReturnValue, Func<Task> postAction, Action<Exception> finalAction) + { + Exception exception = null; + + try + { + await actualReturnValue; + await postAction(); + } + catch (Exception ex) + { + exception = ex; + } + finally + { + finalAction(exception); + } + } + + public static async Task<T> AwaitTaskWithPostActionAndFinallyAndGetResult<T>(Task<T> actualReturnValue, Func<object, Task> postAction, + Action<Exception> finalAction) + { + Exception exception = null; + try + { + var result = await actualReturnValue; + await postAction(result); + return result; + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + finalAction(exception); + } + } + + public static object CallAwaitTaskWithPostActionAndFinallyAndGetResult(Type taskReturnType, object actualReturnValue, + Func<object, Task> action, Action<Exception> finalAction) + { + return typeof(InternalAsyncHelper) + .GetMethod(nameof(AwaitTaskWithPostActionAndFinallyAndGetResult), BindingFlags.Public | BindingFlags.Static) + .MakeGenericMethod(taskReturnType) + .Invoke(null, new object[] { actualReturnValue, action, finalAction }); + } + } + + public class AOPLogInfo + { + /// <summary> + /// 璇锋眰鏃堕棿 + /// </summary> + [Description("璇锋眰鏃堕棿")] + public string RequestTime { get; set; } = string.Empty; + /// <summary> + /// 鎿嶄綔浜哄憳 + /// </summary> + [Description("鎿嶄綔浜哄憳")] + public string OpUserName { get; set; } = string.Empty; + /// <summary> + /// 璇锋眰鏂规硶鍚� + /// </summary> + [Description("璇锋眰鏂规硶鍚�")] + public string RequestMethodName { get; set; } = string.Empty; + /// <summary> + /// 璇锋眰鍙傛暟鍚� + /// </summary> + [Description("璇锋眰鍙傛暟鍚�")] + public string RequestParamsName { get; set; } = string.Empty; + /// <summary> + /// 璇锋眰鍙傛暟鏁版嵁JSON + /// </summary> + [Description("璇锋眰鍙傛暟鏁版嵁JSON")] + public string RequestParamsData { get; set; } = string.Empty; + /// <summary> + /// 璇锋眰鍝嶅簲闂撮殧鏃堕棿 + /// </summary> + [Description("璇锋眰鍝嶅簲闂撮殧鏃堕棿")] + public string ResponseIntervalTime { get; set; } = string.Empty; + /// <summary> + /// 鍝嶅簲鏃堕棿 + /// </summary> + [Description("鍝嶅簲鏃堕棿")] + public string ResponseTime { get; set; } = string.Empty; + /// <summary> + /// 鍝嶅簲缁撴灉 + /// </summary> + [Description("鍝嶅簲缁撴灉")] + public string ResponseJsonData { get; set; } = string.Empty; + } + + public class AOPLogExInfo + { + public AOPLogInfo ApiLogAopInfo { get; set; } + /// <summary> + /// 寮傚父 + /// </summary> + [Description("寮傚父")] + public string InnerException { get; set; } = string.Empty; + /// <summary> + /// 寮傚父淇℃伅 + /// </summary> + [Description("寮傚父淇℃伅")] + public string ExMessage { get; set; } = string.Empty; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/SqlSugarAop.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/SqlSugarAop.cs" new file mode 100644 index 0000000..adc537c --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/AOP/SqlSugarAop.cs" @@ -0,0 +1,126 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Attributes; +using WIDESEA_Core.Const; +using WIDESEA_Core.DB; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Helper; +using WIDESEA_Core.HttpContextUser; +using WIDESEA_Core.Seed; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Core.AOP +{ + public static class SqlSugarAop + { + /// <summary> + /// 鏁版嵁鎵ц鎷︽埅鍣紝鐢ㄤ簬澶勭悊瀹炰綋鎿嶄綔鏃剁殑鍏叡瀛楁璧嬪�煎拰搴忓垪鐢熸垚 + /// </summary> + /// <param name="oldValue">鏃у��</param> + /// <param name="entityInfo">瀹炰綋杩囨护妯″瀷锛屽寘鍚搷浣滅被鍨嬨�佸睘鎬т俊鎭瓑</param> + /// <remarks> + /// 鍔熻兘鍖呮嫭锛� + /// 1. 鑷姩璁剧疆BaseEntity鐨凜reateDate/ModifyDate鏃堕棿鎴� + /// 2. 澶勭悊甯SequenceAttribute]鏍囪鐨勫瓧娈靛簭鍒楃敓鎴� + /// 3. 璁剧疆鎿嶄綔浜轰俊鎭紙鐢ㄦ埛鎴朣ystem锛� + /// 4. 澶勭悊IBaseHistoryEntity鐨勬椂闂存埑瀛楁 + /// 鏀寔鏂板(InsertByObject)鍜屾洿鏂�(UpdateByObject)鎿嶄綔 + /// </remarks> + public static void DataExecuting(object oldValue, DataFilterModel entityInfo) + { + if (entityInfo.EntityValue is BaseEntity baseEntity) + { + // 鏂板鎿嶄綔 + if (entityInfo.OperationType == DataFilterType.InsertByObject) + { + if (entityInfo.PropertyName == nameof(BaseEntity.CreateDate)) + { + baseEntity.CreateDate = DateTime.Now; + } + + PropertyInfo propertyInfo = entityInfo.EntityColumnInfo.PropertyInfo; + SequenceAttribute? sequenceAttirbute = propertyInfo.GetCustomAttribute<SequenceAttribute>(); + if (sequenceAttirbute != null) + { + if (propertyInfo.GetValue(entityInfo.EntityValue)?.ObjToInt() <= 0) + { + SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig + { + ConfigId = MainDb.CurrentDbConnId, + ConnectionString = DBContext.GetMainConnectionDb().Connection, + IsAutoCloseConnection = true, + DbType = DBContext.DbType, + }); + int count = sugarClient.Ado.GetScalar($"SELECT COUNT(*) FROM sys.sequences WHERE name = '{sequenceAttirbute.SequenceName}'").ObjToInt(); + if (count == 0) + { + string sql = $"CREATE SEQUENCE {sequenceAttirbute.SequenceName} AS [int] START WITH {sequenceAttirbute.StartWith} INCREMENT BY {sequenceAttirbute.Increment} MINVALUE {sequenceAttirbute.SeqMinValue} MAXVALUE {sequenceAttirbute.SeqMaxValue} {(sequenceAttirbute.IsCycle ? "CYCLE" : "")} CACHE"; + sugarClient.Ado.ExecuteCommand(sql); + } + int seq = sugarClient.Ado.GetScalar($"SELECT NEXT VALUE FOR {sequenceAttirbute.SequenceName}").ObjToInt(); + propertyInfo.SetValue(entityInfo.EntityValue, seq, null); + } + } + } + + else if (entityInfo.OperationType == DataFilterType.UpdateByObject) + { + baseEntity.ModifyDate = DateTime.Now; + } + + try + { + if (App.User?.UserId > 0) + { + switch (entityInfo.OperationType) + { + case DataFilterType.UpdateByObject: + baseEntity.Modifier = App.User.UserName; + break; + case DataFilterType.InsertByObject: + baseEntity.Creater = App.User.UserName; + break; + } + } + else + { + switch (entityInfo.OperationType) + { + case DataFilterType.UpdateByObject: + baseEntity.Modifier = "System"; + break; + case DataFilterType.InsertByObject: + baseEntity.Creater = "System"; + break; + } + } + } + catch (NullReferenceException) + { + switch (entityInfo.OperationType) + { + case DataFilterType.UpdateByObject: + baseEntity.Modifier = "System"; + break; + case DataFilterType.InsertByObject: + baseEntity.Creater = "System"; + break; + } + } + } + + if (entityInfo.EntityValue is IBaseHistoryEntity baseHistoryEntity) + { + if (entityInfo.OperationType == DataFilterType.InsertByObject && entityInfo.PropertyName == nameof(IBaseHistoryEntity.InsertTime)) + { + baseHistoryEntity.InsertTime = DateTime.Now; + } + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/ApiDoc/ByteHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/ApiDoc/ByteHelper.cs" new file mode 100644 index 0000000..c670ef0 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/ApiDoc/ByteHelper.cs" @@ -0,0 +1,24 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.ApiDoc +{ + public class ByteHelper + { + public static byte[] StreamToBytes(Stream stream) + { + byte[] bytes = new byte[stream.Length]; + stream.Read(bytes, 0, bytes.Length); + stream.Seek(0, SeekOrigin.Begin); + return bytes; + } + + public static Stream BytesToStream(byte[] bytes) + { + return new MemoryStream(bytes); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/ApiDoc/HtmlHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/ApiDoc/HtmlHelper.cs" new file mode 100644 index 0000000..3a4d05d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/ApiDoc/HtmlHelper.cs" @@ -0,0 +1,69 @@ +锘縰sing Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.ApiDoc +{ + public class HtmlHelper + { + /// <summary> + /// 灏嗘暟鎹亶鍘嗛潤鎬侀〉闈腑 + /// </summary> + /// <param name="templatePath">闈欐�侀〉闈㈠湴鍧�</param> + /// <param name="model">鑾峰彇鍒扮殑鏂囦欢鏁版嵁</param> + /// <returns></returns> + public static string GeneritorSwaggerHtml(string templatePath, OpenApiDocument model) + { + var template = System.IO.File.ReadAllText(templatePath); + + return string.Empty; + } + + + + public static Dictionary<string, object> GetBodyParam(IDictionary<string, OpenApiSchema> schemas, string schemaName) + { + if (schemas.ContainsKey(schemaName)) + { + OpenApiSchema schema = schemas[schemaName]; + Dictionary<string, object> pairs = new Dictionary<string, object>(); + foreach (var pair in schema.Properties) + { + if (pair.Value.Type == "object") + { + + } + else if (pair.Value.Type == "array") + { + if (pair.Value.Items.Reference != null) + { + string childSchemaName = pair.Value.Items.Reference.Id; + Dictionary<string, object> keyValuePairs = GetBodyParam(schemas, childSchemaName); + if (keyValuePairs != null && keyValuePairs.Keys.Count > 0) + { + pairs.Add(pair.Key, keyValuePairs); + } + } + + } + else + { + pairs.Add(pair.Key, new + { + ParamName = pair.Key, + Description = pair.Value.Description, + ParamType = pair.Value.Type, + Required = (schema.Required.FirstOrDefault(x => x == pair.Key) != null).ToString() + }); + } + } + return pairs; + } + return null; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/App.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/App.cs" new file mode 100644 index 0000000..a3d99d9 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/App.cs" @@ -0,0 +1,283 @@ +锘縰sing Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Core; +using WIDESEA_Core.Helper; +using WIDESEA_Core.HttpContextUser; + +namespace WIDESEA_Core +{ + /// <summary> + /// 搴旂敤绋嬪簭鍏ㄥ眬闈欐�佺被锛屾彁渚涘簲鐢ㄨ繍琛岀姸鎬併�佹湇鍔¤幏鍙栥�侀厤缃鐞嗙瓑鏍稿績鍔熻兘 + /// </summary> + /// <remarks> + /// 鍖呭惈鍔熻兘锛� + /// 1. 搴旂敤杩愯鐘舵�佺鐞嗭紙IsRun/IsBuild锛� + /// 2. 绋嬪簭闆嗗拰绫诲瀷鍔犺浇锛圓ssemblies/EffectiveTypes锛� + /// 3. 鏈嶅姟瀹瑰櫒璁块棶锛圧ootServices/GetService锛� + /// 4. 鐜閰嶇疆璁块棶锛圵ebHostEnvironment/Configuration锛� + /// 5. 閫夐」妯″紡鏀寔锛圙etOptions/GetConfig锛� + /// 6. HTTP涓婁笅鏂囪闂紙HttpContext/User锛� + /// </remarks> + public class App + { + static App() + { + EffectiveTypes = Assemblies.SelectMany(GetTypes); + } + + /// <summary> + /// 琛ㄧず搴旂敤绋嬪簭鏄惁姝e湪杩愯鐨勬爣蹇� + /// </summary> + private static bool _isRun; + + /// <summary> + /// 鑾峰彇鎴栬缃竴涓�硷紝鎸囩ず褰撳墠鏄惁涓烘瀯寤虹姸鎬� + /// </summary> + public static bool IsBuild { get; set; } + + /// <summary> + /// 鑾峰彇鎴栬缃簲鐢ㄧ▼搴忔槸鍚︽鍦ㄨ繍琛岀殑鏍囧織 + /// </summary> + /// <remarks> + /// 璁剧疆姝ゅ睘鎬ф椂涔熶細鍚屾椂鏇存柊IsBuild灞炴�� + /// </remarks> + public static bool IsRun + { + get => _isRun; + set => _isRun = IsBuild = value; + } + + /// <summary> + /// 鏈夋晥鏈� + /// </summary> + public static DateTime? ExpDateTime = null; + + /// <summary> + /// 鑾峰彇褰撳墠搴旂敤绋嬪簭鍩熶腑鎵�鏈夌▼搴忛泦鐨勯潤鎬侀泦鍚� + /// </summary> + /// <remarks> + /// 璇ラ泦鍚堝湪搴旂敤绋嬪簭鍚姩鏃跺垵濮嬪寲锛屽寘鍚�氳繃RuntimeExtension.GetAllAssemblies()鏂规硶鍔犺浇鐨勬墍鏈夌▼搴忛泦 + /// </remarks> + public static readonly IEnumerable<Assembly> Assemblies = RuntimeExtension.GetAllAssemblies(); + + /// <summary> + /// 鏈夋晥鐨勭被鍨嬮泦鍚堬紝鍖呭惈鎵�鏈夐渶瑕佸鐞嗙殑绫诲瀷 + /// </summary> + public static readonly IEnumerable<Type> EffectiveTypes; + + /// <summary> + /// 鑾峰彇鏍规湇鍔℃彁渚涚▼搴忋�傚綋搴旂敤绋嬪簭姝e湪杩愯鎴栨瀯寤烘椂杩斿洖鏈嶅姟鎻愪緵绋嬪簭锛屽惁鍒欒繑鍥瀗ull銆� + /// </summary> + public static IServiceProvider? RootServices => IsRun || IsBuild ? InternalApp.RootServices : null; + + /// <summary> + /// 鑾峰彇褰撳墠Web涓绘満鐜淇℃伅 + /// </summary> + public static IWebHostEnvironment WebHostEnvironment => InternalApp.WebHostEnvironment; + + /// <summary> + /// 鑾峰彇褰撳墠搴旂敤绋嬪簭鐨勪富鏈虹幆澧冧俊鎭� + /// </summary> + public static IHostEnvironment HostEnvironment => InternalApp.HostEnvironment; + + /// <summary> + /// 鑾峰彇搴旂敤绋嬪簭鐨勯厤缃俊鎭� + /// </summary> + /// <returns>鍏ㄥ眬閰嶇疆鎺ュ彛</returns> + public static IConfiguration Configuration => InternalApp.Configuration; + + /// <summary> + /// 鑾峰彇璇锋眰涓婁笅鏂� + /// </summary> + public static HttpContext? HttpContext => RootServices?.GetService<IHttpContextAccessor>()?.HttpContext; + + /// <summary> + /// 鑾峰彇褰撳墠鐢ㄦ埛鏈嶅姟瀹炰緥 + /// </summary> + /// <returns>褰撳墠鐢ㄦ埛鎺ュ彛瀹炰緥锛屽彲鑳戒负null</returns> + public static IUser? User => GetService<IUser>(); + + #region Service + + /// <summary> + /// 鑾峰彇鎸囧畾绫诲瀷鐨勬湇鍔℃彁渚涜�� + /// </summary> + /// <param name="serviceType">瑕佽幏鍙栫殑鏈嶅姟绫诲瀷</param> + /// <param name="mustBuild">鏄惁蹇呴』鏋勫缓鏈嶅姟鎻愪緵鑰�</param> + /// <param name="throwException">褰撴湇鍔′笉鍙敤鏃舵槸鍚︽姏鍑哄紓甯�</param> + /// <returns>鏈嶅姟鎻愪緵鑰呭疄渚嬶紝鑻ヤ笉鍙敤鍒欒繑鍥瀗ull</returns> + /// <remarks> + /// 璇ユ柟娉曚細鎸変互涓嬮『搴忓皾璇曡幏鍙栨湇鍔℃彁渚涜�咃細 + /// 1. 濡傛灉鏄崟渚嬫湇鍔′笖宸叉敞鍐岋紝杩斿洖鏍规湇鍔℃彁渚涜�� + /// 2. 灏濊瘯浠庡綋鍓岺ttpContext鑾峰彇璇锋眰浣滅敤鍩熺殑鏈嶅姟鎻愪緵鑰� + /// 3. 鍒涘缓鏂扮殑浣滅敤鍩熷苟杩斿洖鍏舵湇鍔℃彁渚涜�� + /// 4. 濡傛灉mustBuild涓簍rue锛屾瀯寤哄苟杩斿洖鏂扮殑鏈嶅姟鎻愪緵鑰� + /// </remarks> + public static IServiceProvider? GetServiceProvider(Type serviceType, bool mustBuild = false, bool throwException = true) + { + if (HostEnvironment == null || RootServices != null && + InternalApp.InternalServices + .Where((u => + u.ServiceType == + (serviceType.IsGenericType ? serviceType.GetGenericTypeDefinition() : serviceType))) + .Any((u => u.Lifetime == ServiceLifetime.Singleton))) + return RootServices; + + //鑾峰彇璇锋眰鐢熷瓨鍛ㄦ湡鐨勬湇鍔� + if (HttpContext?.RequestServices != null) + return HttpContext.RequestServices; + + if (RootServices != null) + { + IServiceScope scope = RootServices.CreateScope(); + return scope.ServiceProvider; + } + + if (mustBuild) + { + if (throwException) + { + throw new ApplicationException("褰撳墠涓嶅彲鐢紝蹇呴』瑕佺瓑鍒� WebApplication Build鍚�"); + } + + return default; + } + + ServiceProvider serviceProvider = InternalApp.InternalServices.BuildServiceProvider(); + return serviceProvider; + } + + /// <summary> + /// 鑾峰彇鎸囧畾绫诲瀷鐨勬湇鍔″疄渚� + /// </summary> + /// <typeparam name="TService">瑕佽幏鍙栫殑鏈嶅姟绫诲瀷</typeparam> + /// <param name="mustBuild">鏄惁蹇呴』鏋勫缓鏈嶅姟瀹炰緥锛岄粯璁や负true</param> + /// <returns>杩斿洖璇锋眰鐨勬湇鍔″疄渚嬶紝鑻ユ湭鎵惧埌鍒欒繑鍥瀗ull</returns> + public static TService? GetService<TService>(bool mustBuild = true) where TService : class + { + TService? test = GetService(typeof(TService), null, mustBuild) as TService; + return test; + } + + /// <summary> + /// 鑾峰彇鎸囧畾绫诲瀷鐨勬湇鍔″疄渚� + /// </summary> + /// <typeparam name="TService">鏈嶅姟绫诲瀷</typeparam> + /// <param name="serviceProvider">鍙�夌殑鏈嶅姟鎻愪緵鑰咃紝濡傛灉涓簄ull鍒欎娇鐢ㄩ粯璁ゆ彁渚涜��</param> + /// <param name="mustBuild">鏄惁蹇呴』鏋勫缓鏈嶅姟锛岄粯璁や负true</param> + /// <returns>鏈嶅姟瀹炰緥锛屽鏋滆幏鍙栧け璐ュ垯杩斿洖null</returns> + public static TService? GetService<TService>(IServiceProvider? serviceProvider, bool mustBuild = true) + where TService : class => (serviceProvider ?? GetServiceProvider(typeof(TService), mustBuild, false))?.GetService<TService>(); + + /// <summary> + /// 鑾峰彇鎸囧畾绫诲瀷鐨勬湇鍔″疄渚� + /// </summary> + /// <param name="type">瑕佽幏鍙栫殑鏈嶅姟绫诲瀷</param> + /// <param name="serviceProvider">鍙�夌殑鏈嶅姟鎻愪緵鑰咃紝鑻ヤ负绌哄垯浣跨敤榛樿鎻愪緵鑰�</param> + /// <param name="mustBuild">鏄惁蹇呴』鏋勫缓鏈嶅姟锛岄粯璁や负true</param> + /// <returns>鏈嶅姟瀹炰緥锛岃嫢鏈壘鍒板垯杩斿洖null</returns> + public static object? GetService(Type type, IServiceProvider? serviceProvider = null, bool mustBuild = true) + { + object? obj = (serviceProvider ?? GetServiceProvider(type, mustBuild, false))?.GetService(type); + return obj; + } + + + #endregion + + #region private + + /// <summary> + /// 浠庢寚瀹氱▼搴忛泦涓幏鍙栨墍鏈夊叕鍏辩被鍨� + /// </summary> + /// <param name="ass">瑕佹壂鎻忕殑绋嬪簭闆�</param> + /// <returns>绋嬪簭闆嗕腑鎵�鏈夊叕鍏辩被鍨嬬殑鏋氫妇</returns> + /// <remarks> + /// 濡傛灉鑾峰彇绫诲瀷鏃跺彂鐢熼敊璇紝灏嗛潤榛樺鐞嗗苟杩斿洖绌洪泦鍚� + /// </remarks> + private static IEnumerable<Type> GetTypes(Assembly ass) + { + Type[] source = Array.Empty<Type>(); + try + { + source = ass.GetTypes(); + } + catch + { + //$@"Error load `{ass.FullName}` assembly.".WriteErrorLine(); + } + + return source.Where(u => u.IsPublic); + } + + #endregion + + #region Options + + /// <summary> + /// 鑾峰彇鎸囧畾绫诲瀷鐨勯厤缃�夐」瀹炰緥 + /// </summary> + /// <typeparam name="TOptions">閰嶇疆閫夐」绫诲瀷锛屽繀椤诲疄鐜癐ConfigurableOptions鎺ュ彛</typeparam> + /// <returns>閰嶇疆鑺備腑瀵瑰簲鐨勯�夐」瀹炰緥</returns> + public static TOptions GetConfig<TOptions>() + where TOptions : class, IConfigurableOptions + { + TOptions instance = Configuration + .GetSection(ConfigurableOptions.GetConfigurationPath(typeof(TOptions))) + .Get<TOptions>(); + return instance; + } + + /// <summary> + /// 浠庢湇鍔℃彁渚涘櫒涓幏鍙栨寚瀹氱被鍨嬬殑閫夐」閰嶇疆 + /// </summary> + /// <typeparam name="TOptions">閫夐」绫诲瀷锛屽繀椤讳负绫讳笖鏈夋棤鍙傛瀯閫犲嚱鏁�</typeparam> + /// <param name="rootServices">鏍规湇鍔℃彁渚涘櫒</param> + /// <param name="serviceProvider">鍙�夌殑鏈嶅姟鎻愪緵鍣紝鑻ユ湭鎸囧畾鍒欎娇鐢ㄦ牴鏈嶅姟鎻愪緵鍣�</param> + /// <returns>鑾峰彇鍒扮殑閫夐」瀹炰緥锛岃嫢鏈壘鍒板垯杩斿洖null</returns> + public static TOptions? GetOptions<TOptions>(IServiceProvider? rootServices, IServiceProvider serviceProvider = null) where TOptions : class, new() + { + IOptions<TOptions>? service = GetService<IOptions<TOptions>>(serviceProvider ?? rootServices, false); + return service?.Value; + } + + /// <summary> + /// 浠庢湇鍔℃彁渚涘櫒涓幏鍙栨寚瀹氱被鍨婽Options鐨勯�夐」鐩戞帶瀹炰緥鐨勫綋鍓嶅�� + /// </summary> + /// <typeparam name="TOptions">閫夐」绫诲瀷锛屽繀椤讳负鍙疄渚嬪寲鐨勭被</typeparam> + /// <param name="serviceProvider">鍙�夌殑鏈嶅姟鎻愪緵鍣紝鑻ユ湭鎸囧畾鍒欎娇鐢ㄦ牴鏈嶅姟</param> + /// <returns>TOptions绫诲瀷鐨勫綋鍓嶉�夐」鍊硷紝鑻ユ湇鍔℃湭娉ㄥ唽鍒欒繑鍥瀗ull</returns> + public static TOptions? GetOptionsMonitor<TOptions>(IServiceProvider serviceProvider = null) + where TOptions : class, new() + { + IOptionsMonitor<TOptions>? service = + GetService<IOptionsMonitor<TOptions>>(serviceProvider ?? RootServices, false); + return service?.CurrentValue; + } + + /// <summary> + /// 鑾峰彇鎸囧畾閫夐」绫诲瀷鐨勫揩鐓у疄渚� + /// </summary> + /// <typeparam name="TOptions">閫夐」绫诲瀷锛屽繀椤绘湁鏃犲弬鏋勯�犲嚱鏁�</typeparam> + /// <param name="serviceProvider">鍙�夌殑鏈嶅姟鎻愪緵鑰咃紝榛樿涓簄ull</param> + /// <returns>閫夐」瀹炰緥鐨勫揩鐓э紝濡傛灉鏈嶅姟鏈敞鍐屽垯杩斿洖null</returns> + public static TOptions? GetOptionsSnapshot<TOptions>(IServiceProvider serviceProvider = null) + where TOptions : class, new() + { + IOptionsSnapshot<TOptions>? service = GetService<IOptionsSnapshot<TOptions>>(serviceProvider, false); + return service?.Value; + } + + #endregion + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/CacheAttribute.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/CacheAttribute.cs" new file mode 100644 index 0000000..22a52f9 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/CacheAttribute.cs" @@ -0,0 +1,20 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Attributes +{ + /// <summary> + /// 杩欎釜Attribute灏辨槸浣跨敤鏃跺�欑殑楠岃瘉锛屾妸瀹冩坊鍔犲埌瑕佺紦瀛樻暟鎹殑鏂规硶涓紝鍗冲彲瀹屾垚缂撳瓨鐨勬搷浣溿�� + /// </summary> + [AttributeUsage(AttributeTargets.Method, Inherited = true)] + public class CacheAttribute : Attribute + { + /// <summary> + /// 缂撳瓨缁濆杩囨湡鏃堕棿锛堝垎閽燂級 + /// </summary> + public int AbsoluteExpiration { get; set; } = 30; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/ModelValidateAttribute.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/ModelValidateAttribute.cs" new file mode 100644 index 0000000..5e742ef --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/ModelValidateAttribute.cs" @@ -0,0 +1,72 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class PropertyValidateAttribute : Attribute + { + /// <summary> + /// 鏈�澶у�� + /// </summary> + public int MaxValue { get; set; } = int.MaxValue; + + /// <summary> + /// 鏈�灏忓�� + /// </summary> + public int MinValue { get; set; } = int.MinValue; + + /// <summary> + /// 闈炵┖ + /// </summary> + public bool NotNullAndEmpty { get; set; } = true; + + /// <summary> + /// 鏄惁鍖呭惈鏈�澶у�� + /// </summary> + public bool IsContainMaxValue { get; set; } = false; + + /// <summary> + /// 鏄惁鍖呭惈鏈�灏忓�� + /// </summary> + public bool IsContainMinValue { get; set; } = false; + + /// <summary> + /// 鏍规嵁鍏朵粬灞炴�ч潪绌哄垽鏂綋鍓嶆槸鍚︿负闈炵┖ + /// </summary> + public string NotNullAndEmptyWithProperty { get; set; } + + /// <summary> + /// 鏍规嵁鍏朵粬灞炴�у�煎垽鏂綋鍓嶆槸鍚︿负闈炵┖(鏍煎紡銆恘ew string[]{ "灞炴�у悕绉�", "灞炴�у��" }銆�) + /// </summary> + public string[] NotNullAndEmptyWithPropertyAndValue { get; set; } + + public string Description { get; set; } + + public PropertyValidateAttribute(string description) + { + if (!string.IsNullOrEmpty(description)) + Description = description; + } + } + + [AttributeUsage(AttributeTargets.Class)] + public class ModelValidateAttribute : Attribute + { + public ModelValidateType ModelValidateType { get; } = ModelValidateType.SimpleValidate; + + public ModelValidateAttribute() + { + } + } + + public enum ModelValidateType + { + SimpleValidate, + CustomValidate, + SimpleAndCustom + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/SequenceAttribute.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/SequenceAttribute.cs" new file mode 100644 index 0000000..bee2047 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Attributes/SequenceAttribute.cs" @@ -0,0 +1,30 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class SequenceAttribute : Attribute + { + public string SequenceName { get; set; } + + public int SeqMaxValue { get; set; } = int.MaxValue; + + public int SeqMinValue { get; set; } = 1; + + public int StartWith { get; set; } = 1; + + public int Increment { get; set; } = 1; + + public bool IsCycle { get; set; } = true; + + public SequenceAttribute(string sequenceName, int seqMaxValue) + { + SequenceName = sequenceName; + SeqMaxValue = seqMaxValue; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/AuthorizationResponse.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/AuthorizationResponse.cs" new file mode 100644 index 0000000..cafe11a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/AuthorizationResponse.cs" @@ -0,0 +1,57 @@ +锘縰sing Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Net; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; +using WIDESEA_Core.Const; + +namespace WIDESEA_Core.Authorization +{ + public static class AuthorizationResponse + { + /// <summary> + /// 鎵╁睍鏂规硶锛氫负 AuthorizationFilterContext 璁剧疆鎺堟潈澶辫触鐨勫搷搴旂粨鏋� + /// </summary> + /// <param name="context">鎺堟潈杩囨护鍣ㄤ笂涓嬫枃</param> + /// <param name="statusCode">HTTP 鐘舵�佺爜</param> + /// <param name="message">鍙�夌殑鑷畾涔夐敊璇秷鎭�</param> + /// <returns>澶勭悊鍚庣殑鎺堟潈杩囨护鍣ㄤ笂涓嬫枃</returns> + /// <remarks> + /// 璇ユ柟娉曚細璁剧疆涓�涓寘鍚敊璇俊鎭殑 JSON 鍝嶅簲锛� + /// 鏍煎紡涓猴細{ message: string, status: false, code: int } + /// </remarks> + public static AuthorizationFilterContext FilterResult( + this AuthorizationFilterContext context, + HttpStatusCode statusCode, + string? message = null) + { + context.Result = new ContentResult() + { + Content = new { message, status = false, code = (int)statusCode }.Serialize(), + ContentType = "application/json", + StatusCode = (int)statusCode + }; + //Logger.Info(LoggerType.ApiAuthorize, message); + return context; + } + public static AuthorizationFilterContext Unauthorized(this AuthorizationFilterContext context, string? message = null) + { + return context.FilterResult(HttpStatusCode.Unauthorized, message); + } + //涓嶉�氳繃JWT楠岃瘉鐨勶紝鐩存帴灏嗙敤鎴蜂俊鎭紦瀛樿捣鏉� + public static void AddIdentity(this AuthorizationFilterContext context, int? userId = null) + { + int _userId = userId ?? JwtHelper.GetUserId(context.HttpContext.Request.Headers[AppSecret.TokenHeaderName]); + if (_userId <= 0) return; + //灏嗙敤鎴稩d缂撳瓨鍒颁笂涓嬫枃(鎴栬�呰嚜瀹氫竴涓璞★紝閫氳繃DI浠ddScoped鏂瑰紡娉ㄥ叆涓婁笅鏂囨潵绠$悊鐢ㄦ埛淇℃伅) + var claims = new Claim[] { new Claim(JwtRegisteredClaimNames.Jti, _userId.ToString()) }; + context.HttpContext.User.AddIdentity(new ClaimsIdentity(claims)); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/AuthorizationSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/AuthorizationSetup.cs" new file mode 100644 index 0000000..e56a4dd --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/AuthorizationSetup.cs" @@ -0,0 +1,88 @@ +锘縰sing Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Const; +using WIDESEA_Core.Extensions; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Authorization +{ + /// <summary> + /// 绯荤粺 鎺堟潈鏈嶅姟 閰嶇疆 + /// </summary> + public static class AuthorizationSetup + { + /// <summary> + /// 娣诲姞JWT璁よ瘉鎺堟潈閰嶇疆 + /// </summary> + /// <param name="services">鏈嶅姟闆嗗悎</param> + /// <remarks> + /// 閰嶇疆JWT Bearer璁よ瘉鏂规锛屽寘鎷細 + /// 1. 璁剧疆榛樿璁よ瘉鏂规涓篔WT Bearer + /// 2. 閰嶇疆Token楠岃瘉鍙傛暟锛堢鍙戣�呫�佸彈浼椼�佺鍚嶅瘑閽ョ瓑锛� + /// 3. 娣诲姞璁よ瘉浜嬩欢澶勭悊锛堟寫鎴樺搷搴斿拰娑堟伅鎺ユ敹锛� + /// 4. 娉ㄥ唽HttpContext璁块棶鍣ㄥ崟渚� + /// </remarks> + /// <exception cref="ArgumentNullException">褰搒ervices涓簄ull鏃舵姏鍑�</exception> + public static void AddAuthorizationSetup(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(options => + { + options.TokenValidationParameters = new TokenValidationParameters + { + SaveSigninToken = true,//淇濆瓨token,鍚庡彴楠岃瘉token鏄惁鐢熸晥(閲嶈) + ValidateIssuer = true,//鏄惁楠岃瘉Issuer + ValidateAudience = true,//鏄惁楠岃瘉Audience + ValidateLifetime = true,//鏄惁楠岃瘉澶辨晥鏃堕棿 + ValidateIssuerSigningKey = true,//鏄惁楠岃瘉SecurityKey + ValidAudience = AppSecret.Audience,//Audience + ValidIssuer = AppSecret.Issuer,//Issuer锛岃繖涓ら」鍜屽墠闈㈢鍙慾wt鐨勮缃竴鑷� + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppSecret.JWT)) + }; + options.Events = new JwtBearerEvents() + { + OnChallenge = context => + { + context.HandleResponse(); + context.Response.Clear(); + context.Response.ContentType = "application/json"; + context.Response.StatusCode = 401; + context.Response.WriteAsync(new { message = "鎺堟潈鏈�氳繃", status = false, code = 401 }.Serialize()); + return Task.CompletedTask; + }, + OnMessageReceived = context => + { + if (context.HttpContext.IsSuccessSwagger() == true) + { + string token = context.HttpContext.GetSuccessSwaggerJwt(); + if (token.IsNotEmptyOrNull()) + { + context.Token = token; + } + } + return Task.CompletedTask; + }, + }; + }); + + services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/JwtHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/JwtHelper.cs" new file mode 100644 index 0000000..0165e1d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Authorization/JwtHelper.cs" @@ -0,0 +1,127 @@ +锘縰sing Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Const; +using WIDESEA_Core.Helper; +using WIDESEA_Core.HttpContextUser; + +namespace WIDESEA_Core.Authorization +{ + public class JwtHelper + { + /// <summary> + /// 棰佸彂JWT浠ょ墝 + /// </summary> + /// <param name="tokenModel">鍖呭惈鐢ㄦ埛淇℃伅鐨勪护鐗屾ā鍨�</param> + /// <returns>鐢熸垚鐨凧WT浠ょ墝瀛楃涓�</returns> + /// <remarks> + /// 璇ユ柟娉曚細鏍规嵁浼犲叆鐨勭敤鎴蜂俊鎭敓鎴怞WT浠ょ墝锛屽寘鍚敤鎴稩D銆佽鑹层�佺鎴风瓑淇℃伅銆� + /// 浠ょ墝杩囨湡鏃堕棿鐢遍厤缃腑鐨凟xpMinutes鍐冲畾锛岄粯璁や娇鐢℉macSha256绠楁硶杩涜绛惧悕銆� + /// </remarks> + public static string IssueJwt(TokenModelJwt tokenModel) + { + string exp = $"{new DateTimeOffset(DateTime.Now.AddMinutes(/*tokenModel.UserId == 1 ? 43200 : */AppSettings.Get("ExpMinutes").ObjToInt())).ToUnixTimeSeconds()}"; + List<Claim> claims = new List<Claim> + { + new Claim(JwtRegisteredClaimNames.Jti, tokenModel.UserId.ToString()), + new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"), + new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") , + //JWT杩囨湡鏃堕棿 + //榛樿璁剧疆jwt杩囨湡鏃堕棿120鍒嗛挓 + new Claim (JwtRegisteredClaimNames.Exp, exp), + new Claim(JwtRegisteredClaimNames.Iss, AppSecret.Issuer), + new Claim(JwtRegisteredClaimNames.Aud, AppSecret.Audience), + new Claim(ClaimTypes.Role, tokenModel.RoleId.ToString()), + new Claim(ClaimTypes.Name, tokenModel.UserName), + new Claim(nameof(TokenModelJwt.TenantId), tokenModel.TenantId.ToString()) + }; + + // 鍙互灏嗕竴涓敤鎴风殑澶氫釜瑙掕壊鍏ㄩ儴璧嬩簣锛� + // 浣滆�咃細DX 鎻愪緵鎶�鏈敮鎸侊紱 + //绉橀挜16浣� + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppSecret.JWT)); + var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + JwtSecurityToken securityToken = new JwtSecurityToken(issuer: AppSecret.Issuer, claims: claims, signingCredentials: creds); + string jwt = new JwtSecurityTokenHandler().WriteToken(securityToken); + return jwt; + } + + /// <summary> + /// 鍙嶅簭鍒楀寲JWT浠ょ墝骞舵彁鍙栫敤鎴蜂俊鎭� + /// </summary> + /// <param name="jwtStr">JWT浠ょ墝瀛楃涓�</param> + /// <returns>鍖呭惈鐢ㄦ埛ID銆佽鑹睮D銆佺敤鎴峰悕鍜岀鎴稩D鐨勭敤鎴蜂俊鎭璞�</returns> + public static UserInfo SerializeJwt(string jwtStr) + { + var jwtHandler = new JwtSecurityTokenHandler(); + JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr); + UserInfo userInfo = new UserInfo + { + UserId = Convert.ToInt32(jwtToken.Id), + RoleId = (jwtToken.Payload[ClaimTypes.Role] ?? 0).ObjToInt(), + UserName = (jwtToken.Payload[ClaimTypes.Name] ?? "")?.ToString() ?? "", + TenantId = (jwtToken.Payload[nameof(TokenModelJwt.TenantId)] ?? 0).ObjToInt(), + }; + return userInfo; + } + + /// <summary> + /// 浠嶫WT瀛楃涓蹭腑鑾峰彇杩囨湡鏃堕棿 + /// </summary> + /// <param name="jwtStr">JWT浠ょ墝瀛楃涓�</param> + /// <returns>JWT鐨勮繃鏈熸椂闂�</returns> + public static DateTime GetExp(string jwtStr) + { + var jwtHandler = new JwtSecurityTokenHandler(); + JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr); + + DateTime expDate = (jwtToken.Payload[JwtRegisteredClaimNames.Exp] ?? 0).ObjToInt().GetTimeSpmpToDate(); + return expDate; + } + public static bool IsExp(string jwtStr) + { + return GetExp(jwtStr) < DateTime.Now; + } + + public static int GetUserId(string jwtStr) + { + try + { + if (jwtStr.IsNullOrEmpty()) return 0; + jwtStr = jwtStr.Replace("Bearer ", ""); + return new JwtSecurityTokenHandler().ReadJwtToken(jwtStr).Id.ObjToInt(); + } + catch + { + return 0; + } + } + } + + /// <summary> + /// 浠ょ墝 + /// </summary> + public class TokenModelJwt + { + /// <summary> + /// UserId + /// </summary> + public long UserId { get; set; } + /// <summary> + /// 瑙掕壊 + /// </summary> + public int RoleId { get; set; } + /// <summary> + /// 鑱岃兘 + /// </summary> + public string UserName { get; set; } + + public long TenantId { get; set; } + + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseController/ApiBaseController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseController/ApiBaseController.cs" new file mode 100644 index 0000000..417d838 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseController/ApiBaseController.cs" @@ -0,0 +1,193 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using WIDESEA_Core.BaseServices; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.BaseController +{ + [Authorize, ApiController] + public class ApiBaseController<IService, TEntity> : Controller + { + protected IService Service; + + public ApiBaseController(IService service) + { + Service = service; + } + + /// <summary> + /// 鑾峰彇鍒嗛〉鏁版嵁 + /// </summary> + /// <param name="options">鍒嗛〉鏌ヨ鍙傛暟</param> + /// <returns>鍒嗛〉鏌ヨ缁撴灉</returns> + [HttpPost, Route("GetPageData")] + public virtual ActionResult GetPageData([FromBody] PageDataOptions options) + { + return Json(InvokeService("GetPageData", new object[] { options })); + } + + /// <summary> + /// 鑾峰彇璇︽儏椤垫暟鎹� + /// </summary> + /// <param name="pageData">鍒嗛〉鏌ヨ鍙傛暟</param> + /// <returns>杩斿洖璇︽儏椤垫暟鎹粨鏋�</returns> + [HttpPost, Route("GetDetailPage")] + public virtual ActionResult GetDetailPage([FromBody] PageDataOptions pageData) + { + return Json(InvokeService("GetDetailPage", new object[] { pageData })); + } + + /// <summary> + /// 娣诲姞鏁版嵁 + /// </summary> + /// <param name="options">瑕佹坊鍔犵殑瀹炰綋鏁版嵁</param> + /// <returns>鎿嶄綔缁撴灉</returns> + [HttpPost, Route("AddData")] + public virtual ActionResult AddData([FromBody] TEntity options) + { + return Json(InvokeService("AddData", new object[] { options })); + } + + /// <summary> + /// 娣诲姞鏁版嵁 + /// </summary> + /// <param name="options">淇濆瓨妯″瀷鍙傛暟</param> + /// <returns>鎿嶄綔缁撴灉</returns> + [HttpPost, Route("Add")] + public virtual ActionResult Add([FromBody] SaveModel options) + { + return Json(InvokeService("AddData", new object[] { options })); + } + + /// <summary> + /// 鏇存柊鏁版嵁 + /// </summary> + /// <param name="options">鍖呭惈鏇存柊鏁版嵁鐨勬ā鍨�</param> + /// <returns>鎿嶄綔缁撴灉</returns> + [HttpPost, Route("Update")] + public virtual ActionResult Update([FromBody] SaveModel options) + { + return Json(InvokeService("UpdateData", new object[] { options })); + } + + /// <summary> + /// 鏇存柊鏁版嵁 + /// </summary> + /// <param name="options">瑕佹洿鏂扮殑瀹炰綋鏁版嵁</param> + /// <returns>鎿嶄綔缁撴灉</returns> + [HttpPost, Route("UpdateData")] + public virtual ActionResult UpdateData([FromBody] TEntity options) + { + return Json(InvokeService("UpdateData", new object[] { options })); + } + + /// <summary> + /// 澶勭悊鍒犻櫎鏁版嵁鐨凥TTP POST璇锋眰 + /// </summary> + /// <param name="key">瑕佸垹闄ょ殑鏁版嵁涓婚敭鏁扮粍</param> + /// <returns>杩斿洖鍒犻櫎鎿嶄綔鐨凧SON鏍煎紡缁撴灉</returns> + /// <remarks> + /// 璇ユ柟娉曟槸铏氭嫙鏂规硶锛屽彲閫氳繃璺敱"Del"璁块棶锛岃皟鐢ㄦ湇鍔″眰鐨凞eleteData鏂规硶鎵ц瀹為檯鍒犻櫎鎿嶄綔 + /// </remarks> + [HttpPost, Route("Del")] + public virtual ActionResult Del([FromBody] object[] key) + { + return Json(InvokeService("DeleteData", new object[] { key })); + } + + /// <summary> + /// 瀵煎嚭鏁版嵁鎺ュ彛 + /// </summary> + /// <param name="loadData">鍒嗛〉鏁版嵁閫夐」</param> + /// <returns> + /// 鎴愬姛鏃惰繑鍥炴枃浠朵笅杞斤紝澶辫触鏃惰繑鍥濲SON鏍煎紡鐨勫搷搴斿唴瀹� + /// </returns> + /// <remarks> + /// 璋冪敤鏈嶅姟灞�"Export"鏂规硶澶勭悊瀵煎嚭璇锋眰锛屾牴鎹繑鍥炵粨鏋滅敓鎴愭枃浠朵笅杞芥垨閿欒鍝嶅簲 + /// </remarks> + [HttpPost, Route("Export")] + public virtual ActionResult Export([FromBody] PageDataOptions loadData) + { + WebResponseContent result = InvokeService("Export", new object[] { loadData }) as WebResponseContent; + if (result.Status) + return File( + System.IO.File.ReadAllBytes(result.Data.ToString()), + System.Net.Mime.MediaTypeNames.Application.Octet, + Path.GetFileName(result.Data.ToString()) + ); + return Json(result); + } + + /// <summary> + /// 涓嬭浇妯℃澘鏂囦欢 + /// </summary> + /// <returns>杩斿洖鏂囦欢娴佹垨JSON缁撴灉</returns> + /// <remarks> + /// 鏀寔POST鍜孏ET璇锋眰銆傚綋鎿嶄綔鎴愬姛鏃惰繑鍥炴枃浠舵祦涓嬭浇锛屽け璐ユ椂杩斿洖鍖呭惈閿欒淇℃伅鐨凧SON鍝嶅簲銆� + /// </remarks> + [HttpPost, HttpGet, Route("DownLoadTemplate")] + public virtual ActionResult DownLoadTemplate() + { + WebResponseContent result = InvokeService("DownLoadTemplate", new object[] { }) as WebResponseContent; + if (result.Status) + return File( + System.IO.File.ReadAllBytes(result.Data.ToString()), + System.Net.Mime.MediaTypeNames.Application.Octet, + Path.GetFileName(result.Data.ToString()) + ); + return Json(result); + } + + /// <summary> + /// 瀵煎叆鏂囦欢鏁版嵁 + /// </summary> + /// <param name="fileInput">涓婁紶鐨勬枃浠跺垪琛�</param> + /// <returns>瀵煎叆鎿嶄綔缁撴灉</returns> + [HttpPost, Route("Import")] + public virtual ActionResult Import(List<IFormFile> fileInput) + { + return Json(InvokeService("Import", new object[] { fileInput })); + } + + /// <summary> + /// 瀵煎嚭绉嶅瓙鏁版嵁API鎺ュ彛 + /// </summary> + /// <returns>杩斿洖绉嶅瓙鏁版嵁瀵煎嚭缁撴灉</returns> + /// <remarks>璇ユ帴鍙e厑璁稿尶鍚嶈闂�</remarks> + [HttpPost, Route("ExportSeedData"), AllowAnonymous] + public ActionResult ExportSeedData() + { + return Json(InvokeService("ExportSeedData", new object[] { })); + } + + /// <summary> + /// 璋冪敤鏈嶅姟鏂规硶 + /// </summary> + /// <param name="methodName">瑕佽皟鐢ㄧ殑鏂规硶鍚嶇О</param> + /// <param name="parameters">鏂规硶鍙傛暟鏁扮粍</param> + /// <returns>璋冪敤鏂规硶鐨勮繑鍥炵粨鏋�</returns> + /// <remarks> + /// 閫氳繃鍙嶅皠鍔ㄦ�佽皟鐢⊿ervice瀵硅薄涓殑鎸囧畾鏂规硶 + /// </remarks> + private object InvokeService(string methodName, object[] parameters) + { + Type t = Service.GetType(); + List<Type> types = new List<Type>(); + foreach (var param in parameters) + { + types.Add(param.GetType()); + } + MethodInfo method = t.GetMethod(methodName, types.ToArray()); + return method.Invoke(Service, parameters); + } + } +} \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/PageDataOptions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/PageDataOptions.cs" new file mode 100644 index 0000000..0f7cc0e --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/PageDataOptions.cs" @@ -0,0 +1,65 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core +{ + /// <summary> + /// 鍒嗛〉鏁版嵁閫夐」 + /// </summary> + public class PageDataOptions + { + /// <summary> + /// 褰撳墠椤电爜 + /// </summary> + public int Page { get; set; } + /// <summary> + /// 姣忛〉鏄剧ず鐨勮鏁� + /// </summary> + public int Rows { get; set; } + /// <summary> + /// 鎬昏褰曟暟 + /// </summary> + public int Total { get; set; } + /// <summary> + /// 琛ㄥ悕 + /// </summary> + public string TableName { get; set; } + /// <summary> + /// 鎺掑簭鍒楀悕 + /// </summary> + public string Sort { get; set; } + /// <summary> + /// 鎺掑簭鏂瑰紡 + /// </summary> + public string Order { get; set; } + /// <summary> + /// 鏌ヨ鏉′欢 + /// </summary> + public string Wheres { get; set; } + /// <summary> + /// 鏄惁瀵煎嚭 + /// </summary> + public bool Export { get; set; } + /// <summary> + /// 鍏朵粬鍙傛暟 + /// </summary> + public object Value { get; set; } + /// <summary> + /// 鏌ヨ鏉′欢 + /// </summary> + public List<SearchParameters> Filter { get; set; } + } + //瀹氫箟涓�涓悳绱㈠弬鏁扮被 + public class SearchParameters + { + //鎼滅储鍙傛暟鍚嶇О + public string Name { get; set; } + //鎼滅储鍙傛暟鍊� + public string Value { get; set; } + //鏌ヨ绫诲瀷锛歀inqExpressionType + public string DisplayType { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/PageGridData.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/PageGridData.cs" new file mode 100644 index 0000000..4570bc0 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/PageGridData.cs" @@ -0,0 +1,32 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core +{ + // 瀹氫箟涓�涓硾鍨嬬被PageGridData锛岀敤浜庡瓨鍌ㄥ垎椤垫暟鎹� + public class PageGridData<T> + { + // 鎬昏褰曟暟 + public int Total { get; set; } + // 鏁版嵁鍒楄〃 + public List<T> Rows { get; set; } + // 姹囨�绘暟鎹� + public object Summary { get; set; } + + // 鏃犲弬鏋勯�犲嚱鏁� + public PageGridData() + { + + } + + // 甯﹀弬鏋勯�犲嚱鏁帮紝鍒濆鍖栨�昏褰曟暟鍜屾暟鎹垪琛� + public PageGridData(int total, List<T> rows) + { + Total = total; + Rows = rows; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/Permissions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/Permissions.cs" new file mode 100644 index 0000000..eb0d979 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/Permissions.cs" @@ -0,0 +1,42 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core +{ + public class Permissions + { + /// <summary> + /// 鑿滃崟ID + /// </summary> + public int MenuId { get; set; } + /// <summary> + /// 鐖剁骇鑿滃崟ID + /// </summary> + public int ParentId { get; set; } + /// <summary> + /// 琛ㄥ悕 + /// </summary> + public string TableName { get; set; } + /// <summary> + /// 鑿滃崟鏉冮檺 + /// </summary> + public string MenuAuth { get; set; } + /// <summary> + /// 鐢ㄦ埛鏉冮檺 + /// </summary> + public string UserAuth { get; set; } + /// <summary> + /// 褰撳墠鐢ㄦ埛鏉冮檺,瀛樺偍鐨勬槸鏉冮檺鐨勫�硷紝濡�:Add,Search绛� + /// </summary> + public string[] UserAuthArr { get; set; } + + /// <summary> + /// 2022.03.26 + /// 鑿滃崟绫诲瀷1:绉诲姩绔紝0:PC绔� + /// </summary> + public int MenuType { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/SaveModel.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/SaveModel.cs" new file mode 100644 index 0000000..ad65314 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/SaveModel.cs" @@ -0,0 +1,30 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core +{ + public class SaveModel + { + /// <summary> + /// 涓绘暟鎹� + /// </summary> + public Dictionary<string, object> MainData { get; set; } + /// <summary> + /// 璇︾粏鏁版嵁 + /// </summary> + public List<Dictionary<string, object>> DetailData { get; set; } + /// <summary> + /// 瑕佸垹闄ょ殑閿� + /// </summary> + public List<object> DelKeys { get; set; } + + /// <summary> + /// 浠庡墠鍙颁紶鍏ョ殑鍏朵粬鍙傛暟(鑷畾涔夋墿灞曞彲浠ヤ娇鐢�) + /// </summary> + public object Extra { get; set; } + + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/WebResponseContent.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/WebResponseContent.cs" new file mode 100644 index 0000000..222012e --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseModels/WebResponseContent.cs" @@ -0,0 +1,64 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core +{ + public class WebResponseContent + { + // 鏋勯�犲嚱鏁帮紝鏃犲弬鏁� + public WebResponseContent() + { + } + // 鏋勯�犲嚱鏁帮紝甯︿竴涓弬鏁帮紝鐢ㄤ簬璁剧疆鐘舵�� + public WebResponseContent(bool status) + { + Status = status; + } + // 鐘舵�佸睘鎬� + public bool Status { get; set; } + + // 浠g爜灞炴�� + public int Code { get; set; } + + // 娑堟伅灞炴�� + public string Message { get; set; } + + // 鏁版嵁灞炴�� + public object Data { get; set; } + + // 寮�鍙戣�呮秷鎭睘鎬� + public string DevMessage { get; set; } + + // OK鏂规硶锛岃缃姸鎬佷负true锛屽苟杩斿洖褰撳墠瀵硅薄 + public WebResponseContent OK() + { + Status = true; + return this; + } + + // 闈欐�佸睘鎬э紝杩斿洖涓�涓柊鐨刉ebResponseContent瀵硅薄 + public static WebResponseContent Instance + { + get { return new WebResponseContent(); } + } + // OK鏂规硶锛岃缃姸鎬佷负true锛屽苟璁剧疆娑堟伅鍜屾暟鎹紝杩斿洖褰撳墠瀵硅薄 + public WebResponseContent OK(string message = null, object data = null) + { + Status = true; + Message = message; + Data = data; + return this; + } + + // Error鏂规硶锛岃缃姸鎬佷负false锛屽苟璁剧疆娑堟伅锛岃繑鍥炲綋鍓嶅璞� + public WebResponseContent Error(string message = null) + { + Status = false; + Message = message; + return this; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/IRepository.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/IRepository.cs" new file mode 100644 index 0000000..05a57ee --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/IRepository.cs" @@ -0,0 +1,416 @@ +锘縰sing Microsoft.Data.SqlClient; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Enums; + +namespace WIDESEA_Core.BaseRepository +{ + public interface IRepository<TEntity> : IDependency where TEntity : class, new() + { + /// <summary> + /// SqlsugarClient瀹炰綋 + /// </summary> + ISqlSugarClient Db { get; } + /// <summary> + /// 閫氳繃涓婚敭鏌ヨ鏁版嵁 + /// </summary> + /// <param name="id">涓婚敭</param> + /// <returns>鏌ヨ缁撴灉</returns> + TEntity QureyDataById(object id); + + Task<TEntity> QureyDataByIdAsync(object id); + + /// <summary> + /// 閫氳繃涓婚敭鏁扮粍鏌ヨ鏁版嵁 + /// </summary> + /// <param name="lstIds">涓婚敭鏁扮粍</param> + /// <returns>鏌ヨ缁撴灉闆嗗悎</returns> + List<TEntity> QureyDataByIds(object[] lstIds); + + Task<List<TEntity>> QureyDataByIdsAsync(object[] lstIds); + + /// <summary> + /// 閫氳繃涓婚敭闆嗗悎鏌ヨ鏁版嵁 + /// </summary> + /// <param name="lstIds">涓婚敭闆嗗悎</param> + /// <returns>鏌ヨ缁撴灉闆嗗悎</returns> + List<TEntity> QureyDataByIds(List<object> lstIds); + + Task<List<TEntity>> QureyDataByIdsAsync(List<object> lstIds); + + /// <summary> + /// 娣诲姞鍗曟潯鏁版嵁 + /// </summary> + /// <param name="entity"></param> + /// <returns>褰卞搷琛屾暟</returns> + int AddData(TEntity entity); + + Task<int> AddDataAsync(TEntity entity); + + /// <summary> + /// 娣诲姞澶氭潯鏁版嵁 + /// </summary> + /// <param name="listEntity"></param> + /// <returns>褰卞搷琛屾暟</returns> + int AddData(List<TEntity> listEntity); + + Task<int> AddDataAsync(List<TEntity> listEntity); + + /// <summary> + /// 閫氳繃涓婚敭鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="id">涓婚敭</param> + /// <returns>鍒犻櫎缁撴灉</returns> + bool DeleteDataById(object id); + + Task<bool> DeleteDataByIdAsync(object id); + + /// <summary> + /// 閫氳繃涓婚敭鏁版嵁鍒犻櫎澶氭潯鏁版嵁 + /// </summary> + /// <param name="ids">涓婚敭鏁扮粍</param> + /// <returns>鍒犻櫎缁撴灉</returns> + bool DeleteDataByIds(object[] ids); + + Task<bool> DeleteDataByIdsAsync(object[] ids); + + /// <summary> + /// 閫氳繃瀹炰綋鏁版嵁鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="ids">涓婚敭鏁扮粍</param> + /// <returns>鍒犻櫎缁撴灉</returns> + bool DeleteData(TEntity entity); + + Task<bool> DeleteDataAsync(TEntity entity); + + /// <summary> + /// 閫氳繃瀹炰綋闆嗗悎鏁版嵁鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="ids">涓婚敭鏁扮粍</param> + /// <returns>鍒犻櫎缁撴灉</returns> + bool DeleteData(List<TEntity> listEntity); + + Task<bool> DeleteDataAsync(List<TEntity> listEntity); + + /// <summary> + /// 鏇存柊鍗曟潯鏁版嵁 + /// </summary> + /// <param name="entity"></param> + /// <returns></returns> + bool UpdateData(TEntity entity); + + Task<bool> UpdateDataAsync(TEntity entity); + + /// <summary> + /// 鏇存柊澶氭潯鏁版嵁 + /// </summary> + /// <param name="listEntity"></param> + /// <returns></returns> + bool UpdateData(List<TEntity> listEntity); + + Task<bool> UpdateDataAsync(List<TEntity> listEntity); + + /// <summary> + /// 鎸囧畾鍒楁洿鏂版暟鎹� + /// </summary> + /// <param name="entity"></param> + /// <param name="lstColumns"></param> + /// <param name="lstIgnoreColumns"></param> + /// <returns></returns> + bool UpdateData(TEntity entity, List<string> lstColumns, List<string>? lstIgnoreColumns = null); + + Task<bool> UpdateDataAsync(TEntity entity, List<string> lstColumns, List<string>? lstIgnoreColumns = null); + + /// <summary> + /// 鏌ヨ鎵�鏈夋暟鎹� + /// </summary> + /// <returns></returns> + List<TEntity> QueryData(); + + Task<List<TEntity>> QueryDataAsync(); + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁 + /// </summary> + /// <param name="where"></param> + /// <returns></returns> + List<TEntity> QueryData(string where); + + Task<List<TEntity>> QueryDataAsync(string where); + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁 + /// </summary> + /// <param name="whereExpression"></param> + /// <returns></returns> + List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression); + + Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression); + + TEntity QueryFirst(Expression<Func<TEntity, bool>> whereExpression); + + Task<TEntity> QueryFirstAsync(Expression<Func<TEntity, bool>> whereExpression); + + TResult QueryFirst<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> expression); + + Task<TResult> QueryFirstAsync<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> expression); + + TResult QueryFirst<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> expression, Dictionary<string, OrderByType> orderBy); + + Task<TResult> QueryFirstAsync<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> expression, Dictionary<string, OrderByType> orderBy); + + TEntity QueryFirst(Expression<Func<TEntity, bool>> whereExpression, Dictionary<string, OrderByType> orderBy); + + Task<TEntity> QueryFirstAsync(Expression<Func<TEntity, bool>> whereExpression, Dictionary<string, OrderByType> orderBy); + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁骞舵帓搴� + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression, Dictionary<string, OrderByType> orderBy); + + Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression, string orderByFields); + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁骞舵帓搴� + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="where"></param> + /// <returns></returns> + List<TEntity> QueryData(string where, Dictionary<string, OrderByType> orderBy); + + Task<List<TEntity>> QueryDataAsync(string where, Dictionary<string, OrderByType> orderBy); + + /// <summary> + /// 鏌ヨ鎸囧畾鏁版嵁瀵硅薄 + /// </summary> + /// <typeparam name="TResult"></typeparam> + /// <param name="expression"></param> + /// <returns></returns> + List<TResult> QueryData<TResult>(Expression<Func<TEntity, TResult>> expression); + + Task<List<TResult>> QueryDataAsync<TResult>(Expression<Func<TEntity, TResult>> expression); + + /// <summary> + /// 鏉′欢鏌ヨ鎸囧畾鏁版嵁瀵硅薄 + /// </summary> + /// <typeparam name="TResult"></typeparam> + /// <param name="expression"></param> + /// <param name="whereExpression"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + List<TResult> QueryData<TResult>(Expression<Func<TEntity, TResult>> expression, Expression<Func<TEntity, bool>> whereExpression, string orderByFields = ""); + + Task<List<TResult>> QueryDataAsync<TResult>(Expression<Func<TEntity, TResult>> expression, Expression<Func<TEntity, bool>> whereExpression, string orderByFields); + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁骞舵帓搴� + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="orderByExpression"></param> + /// <param name="isAsc"></param> + /// <returns></returns> + List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true); + + Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true); + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁骞舵帓搴� + /// </summary> + /// <param name="where"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + List<TEntity> QueryData(string where, string orderByFields); + + Task<List<TEntity>> QueryDataAsync(string where, string orderByFields); + + /// <summary> + /// 鍘熺敓Sql璇彞鏌ヨ鏁版嵁 + /// </summary> + /// <param name="sql"></param> + /// <param name="parameters"></param> + /// <returns></returns> + List<TEntity> QueryDataBySql(string sql, SugarParameter[]? parameters = null); + + Task<List<TEntity>> QueryDataBySqlAsync(string sql, SugarParameter[]? parameters = null); + + /// <summary> + /// 鍘熺敓Sql璇彞鏌ヨ鏁版嵁 + /// </summary> + /// <param name="sql"></param> + /// <param name="parameters"></param> + /// <returns></returns> + List<dynamic> QueryDynamicDataBySql(string sql, SugarParameter[]? parameters = null); + + Task<List<dynamic>> QueryDynamicDataBySqlAsync(string sql, SugarParameter[]? parameters = null); + + List<object> QueryObjectDataBySql(string sql, SugarParameter[]? parameters = null); + + Task<List<object>> QueryObjectDataBySqlAsync(string sql, SugarParameter[]? parameters = null); + + /// <summary> + /// 鍘熺敓Sql璇彞鎵ц鎿嶄綔 + /// </summary> + /// <param name="sql"></param> + /// <param name="sqlParameters"></param> + /// <returns></returns> + int ExecuteSqlCommand(string sql, params SqlParameter[] sqlParameters); + + Task<int> ExecuteSqlCommandAsync(string sql, params SqlParameter[] sqlParameters); + + /// <summary> + /// 鍘熺敓Sql璇彞鏌ヨ鏁版嵁 + /// </summary> + /// <param name="sql"></param> + /// <param name="parameters"></param> + /// <returns></returns> + DataTable QueryTable(string sql, SugarParameter[]? parameters = null); + + Task<DataTable> QueryTableAsync(string sql, SugarParameter[]? parameters = null); + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁鎸囧畾鏁伴噺鐨勮 + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="top"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression, int top, string orderByFields); + + Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression, int top, string orderByFields); + + /// <summary> + /// 鏉′欢鏌ヨ鎸囧畾鏁伴噺鐨勮 + /// </summary> + /// <param name="where"></param> + /// <param name="top"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + List<TEntity> QueryData(string where, int top, string orderByFields); + + Task<List<TEntity>> QueryDataAsync(string where, int top, string orderByFields); + + /// <summary> + /// 鍒嗛〉鏌ヨ + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression, int pageIndex, int pageSize, string orderByFields); + + Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression, int pageIndex, int pageSize, string orderByFields); + + /// <summary> + /// 鍒嗛〉鏌ヨ + /// </summary> + /// <param name="where"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + List<TEntity> QueryData(string where, int pageIndex, int pageSize, string orderByFields); + + Task<List<TEntity>> QueryDataAsync(string where, int pageIndex, int pageSize, string orderByFields); + + /// <summary> + /// 鍒嗛〉鏌ヨ + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + PageGridData<TEntity> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int pageIndex, int pageSize, string? orderByFields = null); + + /// <summary> + /// 鍒嗛〉鏌ヨ + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pagesize"></param> + /// <param name="orderBy"></param> + /// <returns></returns> + PageGridData<TEntity> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int pageIndex, int pagesize, Dictionary<string, OrderByType> orderBy); + + PageGridData<TEntity> QueryPage(string where, int pageIndex, int pageSize, Dictionary<string, OrderByType> orderBy); + + /// <summary> + /// 涓よ〃鑱旀煡 + /// </summary> + /// <typeparam name="T"></typeparam> + /// <typeparam name="T2"></typeparam> + /// <typeparam name="TResult"></typeparam> + /// <param name="joinExpression"></param> + /// <param name="selectExpression"></param> + /// <param name="whereExpression"></param> + /// <returns></returns> + List<TResult> QueryTabs<T, T2, TResult>( + Expression<Func<T, T2, object[]>> joinExpression, + Expression<Func<T, T2, TResult>> selectExpression, + Expression<Func<T,T2, bool>> whereExpressionT1, + Expression<Func<TResult, bool>> whereExpression); + + Task<List<TResult>> QueryTabsAsync<T, T2, TResult>( + Expression<Func<T, T2, object[]>> joinExpression, + Expression<Func<T, T2, TResult>> selectExpression, + Expression<Func<TResult, bool>> whereExpression); + + /// <summary> + /// 涓よ〃鑱旀煡-鍒嗛〉 + /// </summary> + /// <typeparam name="T"></typeparam> + /// <typeparam name="T2"></typeparam> + /// <typeparam name="TResult"></typeparam> + /// <param name="joinExpression"></param> + /// <param name="selectExpression"></param> + /// <param name="whereExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + PageGridData<TResult> QueryTabsPage<T, T2, TResult>( + Expression<Func<T, T2, object[]>> joinExpression, + Expression<Func<T, T2, TResult>> selectExpression, + Expression<Func<TResult, bool>> whereExpression, + int pageIndex = 1, + int pageSize = 20, + string? orderByFields = null); + + /// <summary> + /// 涓よ〃鑱斿悎鏌ヨ-鍒嗛〉-鍒嗙粍 + /// </summary> + /// <typeparam name="T"></typeparam> + /// <typeparam name="T2"></typeparam> + /// <typeparam name="TResult"></typeparam> + /// <param name="joinExpression"></param> + /// <param name="selectExpression"></param> + /// <param name="whereExpression"></param> + /// <param name="groupExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + PageGridData<TResult> QueryTabsPage<T, T2, TResult>( + Expression<Func<T, T2, object[]>> joinExpression, + Expression<Func<T, T2, TResult>> selectExpression, + Expression<Func<TResult, bool>> whereExpression, + Expression<Func<T, object>> groupExpression, + int pageIndex = 1, + int pageSize = 20, + string? orderByFields = null); + + bool DeleteAndMoveIntoHty(TEntity entity, OperateTypeEnum operateType); + + bool DeleteAndMoveIntoHty(List<TEntity> entities, OperateTypeEnum operateType); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/RepositoryBase.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/RepositoryBase.cs" new file mode 100644 index 0000000..b7a7f9c --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/RepositoryBase.cs" @@ -0,0 +1,952 @@ +锘縰sing SqlSugar; +using System.Data; +using System.Linq.Expressions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Reflection; +using WIDESEA_Core.Helper; +using Microsoft.Data.SqlClient; +using System.Drawing.Printing; +using WIDESEA_Core.Tenants; +using WIDESEA_Core.Seed; +using WIDESEA_Core.DB; +using WIDESEA_Core.Const; +using WIDESEA_Core.AOP; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Utilities; +using WIDESEA_Core.Enums; + +namespace WIDESEA_Core.BaseRepository +{ + public class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class, new() + { + //瀹氫箟绉佹湁鍙橀噺 + private readonly IUnitOfWorkManage _unitOfWorkManage; + private readonly SqlSugarClient _dbBase; + + //瀹氫箟鏁版嵁搴撹繛鎺ュ璞� + private ISqlSugarClient _db + { + get + { + ISqlSugarClient db = _dbBase; + + //澶氱鎴� + var mta = typeof(TEntity).GetCustomAttribute<MultiTenantAttribute>(); + if (mta is { TenantType: TenantTypeEnum.Db }) + { + //鑾峰彇绉熸埛淇℃伅 绉熸埛淇℃伅鍙互鎻愬墠缂撳瓨涓嬫潵 + if (App.User is { TenantId: > 0 }) + { + dynamic tenant = db.Queryable(MainDb.TenantTableName, "x").Where(MainDb.TenantId, "=", App.User.TenantId).First(); + if (tenant != null) + { + var iTenant = db.AsTenant(); + if (!iTenant.IsAnyConnection(tenant.TenantId)) + { + string conStr = tenant.ConnectionString; + ConnectionConfig connectionConfig = new ConnectionConfig() + { + ConfigId = tenant.TenantId, + ConnectionString = conStr.DecryptDES(AppSecret.DB), + DbType = (SqlSugar.DbType)tenant.DbType, + IsAutoCloseConnection = true, + AopEvents = new AopEvents() + { + DataExecuting = SqlSugarAop.DataExecuting + } + }; + iTenant.AddConnection(connectionConfig); + } + + return iTenant.GetConnection(tenant.TenantId); + } + } + } + + return db; + } + } + /// <summary> + /// 鍒涘缓鏁版嵁搴撹繛鎺ュ璞� + /// </summary> + public ISqlSugarClient Db => _db; + + //鏋勯�犲嚱鏁� + public RepositoryBase(IUnitOfWorkManage unitOfWorkManage) + { + _unitOfWorkManage = unitOfWorkManage; + _dbBase = unitOfWorkManage.GetDbClient(); + } + + /// <summary> + /// 閫氳繃涓婚敭鏌ヨ鏁版嵁 + /// </summary> + /// <param name="id">涓婚敭</param> + /// <returns>鏌ヨ缁撴灉</returns> + public virtual TEntity QureyDataById(object id) + { + return _db.Queryable<TEntity>().In(id).Single(); + } + + /// <summary> + /// 閫氳繃涓婚敭鏁扮粍鏌ヨ鏁版嵁 + /// </summary> + /// <param name="lstIds">涓婚敭鏁扮粍</param> + /// <returns>鏌ヨ缁撴灉闆嗗悎</returns> + public virtual List<TEntity> QureyDataByIds(object[] lstIds) + { + return _db.Queryable<TEntity>().In(lstIds).ToList(); + } + + /// <summary> + /// 閫氳繃涓婚敭闆嗗悎鏌ヨ鏁版嵁 + /// </summary> + /// <param name="lstIds">涓婚敭闆嗗悎</param> + /// <returns>鏌ヨ缁撴灉闆嗗悎</returns> + public virtual List<TEntity> QureyDataByIds(List<object> lstIds) + { + return _db.Queryable<TEntity>().In(lstIds).ToList(); + } + + /// <summary> + /// 鍚戞暟鎹簱涓坊鍔犲疄浣撴暟鎹苟杩斿洖鑷ID + /// </summary> + /// <param name="entity">瑕佹坊鍔犵殑瀹炰綋瀵硅薄</param> + /// <returns>杩斿洖鎻掑叆璁板綍鐨勮嚜澧濱D</returns> + public virtual int AddData(TEntity entity) + { + IInsertable<TEntity> insert = _db.Insertable(entity); + return insert.ExecuteReturnIdentity(); + } + + /// <summary> + /// 鎵归噺娣诲姞瀹炰綋鏁版嵁鍒版暟鎹簱 + /// </summary> + /// <param name="listEntity">瑕佹坊鍔犵殑瀹炰綋闆嗗悎</param> + /// <returns>鍙楀奖鍝嶇殑琛屾暟</returns> + public virtual int AddData(List<TEntity> listEntity) + { + IInsertable<TEntity> insert = _db.Insertable(listEntity); + return insert.ExecuteCommand(); + } + + /// <summary> + /// 閫氳繃涓婚敭鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="id">涓婚敭</param> + /// <returns>鍒犻櫎缁撴灉</returns> + public virtual bool DeleteDataById(object id) + { + return _db.Deleteable<TEntity>().In(id).ExecuteCommandHasChange(); + } + + /// <summary> + /// 閫氳繃涓婚敭鏁版嵁鍒犻櫎澶氭潯鏁版嵁 + /// </summary> + /// <param name="ids">涓婚敭鏁扮粍</param> + /// <returns>鍒犻櫎缁撴灉</returns> + public virtual bool DeleteDataByIds(object[] ids) + { + return _db.Deleteable<TEntity>().In(ids).ExecuteCommandHasChange(); + } + + /// <summary> + /// 閫氳繃瀹炰綋鏁版嵁鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="ids">涓婚敭鏁扮粍</param> + /// <returns>鍒犻櫎缁撴灉</returns> + public virtual bool DeleteData(TEntity entity) + { + return _db.Deleteable(entity).ExecuteCommandHasChange(); + } + + /// <summary> + /// 閫氳繃瀹炰綋闆嗗悎鏁版嵁鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="ids">涓婚敭鏁扮粍</param> + /// <returns>鍒犻櫎缁撴灉</returns> + public virtual bool DeleteData(List<TEntity> listEntity) + { + return _db.Deleteable(listEntity).ExecuteCommandHasChange(); + } + + /// <summary> + /// 鏇存柊鍗曟潯鏁版嵁 + /// </summary> + /// <param name="entity"></param> + /// <returns></returns> + public virtual bool UpdateData(TEntity entity) + { + return _db.Updateable(entity).ExecuteCommandHasChange(); + } + + /// <summary> + /// 鏇存柊澶氭潯鏁版嵁 + /// </summary> + /// <param name="listEntity"></param> + /// <returns></returns> + public virtual bool UpdateData(List<TEntity> listEntity) + { + return _db.Updateable(listEntity).ExecuteCommandHasChange(); + } + + /// <summary> + /// 鎸囧畾鍒楁洿鏂版暟鎹� + /// </summary> + /// <param name="entity"></param> + /// <param name="lstColumns"></param> + /// <param name="lstIgnoreColumns"></param> + /// <returns></returns> + public virtual bool UpdateData(TEntity entity, List<string> lstColumns, List<string>? lstIgnoreColumns = null) + { + IUpdateable<TEntity> update = _db.Updateable(entity); + + if (lstIgnoreColumns != null && lstIgnoreColumns.Count > 0) + { + update = update.IgnoreColumns(lstIgnoreColumns.ToArray()); + } + + if (lstColumns != null && lstColumns.Count > 0) + { + update = update.UpdateColumns(lstColumns.ToArray()); + } + + return update.ExecuteCommandHasChange(); + } + + /// <summary> + /// 鏌ヨ鎵�鏈夋暟鎹� + /// </summary> + /// <returns></returns> + public virtual List<TEntity> QueryData() + { + return _db.Queryable<TEntity>().ToList(); + } + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁 + /// </summary> + /// <param name="where"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(string where) + { + return _db.Queryable<TEntity>().WhereIF(!string.IsNullOrEmpty(where), where).ToList(); + } + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁 + /// </summary> + /// <param name="whereExpression"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression) + { + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).ToList(); + } + + public virtual TEntity QueryFirst(Expression<Func<TEntity, bool>> whereExpression) + { + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).First(); + } + + public virtual TResult QueryFirst<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> expression) + { + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).Select(expression).First(); + } + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁骞舵帓搴� + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression, Dictionary<string, OrderByType> orderBy) + { + List<OrderByModel> orderByModels = new List<OrderByModel>(); + foreach (var item in orderBy) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).OrderBy(orderByModels).ToList(); + } + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁骞舵帓搴� + /// </summary> + /// <param name="where"></param> + /// <param name="orderBy"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(string where, Dictionary<string, OrderByType> orderBy) + { + List<OrderByModel> orderByModels = new List<OrderByModel>(); + foreach (var item in orderBy) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + return _db.Queryable<TEntity>().WhereIF(!string.IsNullOrEmpty(where), where).OrderBy(orderByModels).ToList(); + } + + /// <summary> + /// 鏌ヨ鎸囧畾鏁版嵁瀵硅薄 + /// </summary> + /// <typeparam name="TResult"></typeparam> + /// <param name="expression"></param> + /// <returns></returns> + public virtual List<TResult> QueryData<TResult>(Expression<Func<TEntity, TResult>> expression) + { + return _db.Queryable<TEntity>().Select(expression).ToList(); + } + + /// <summary> + /// 鏉′欢鏌ヨ鎸囧畾鏁版嵁瀵硅薄 + /// </summary> + /// <typeparam name="TResult"></typeparam> + /// <param name="expression"></param> + /// <param name="whereExpression"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual List<TResult> QueryData<TResult>(Expression<Func<TEntity, TResult>> expression, Expression<Func<TEntity, bool>> whereExpression, string orderByFields = "") + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(whereExpression != null, whereExpression).Select(expression).ToList(); + } + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁骞舵帓搴� + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="orderByExpression"></param> + /// <param name="isAsc"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true) + { + return _db.Queryable<TEntity>().OrderByIF(orderByExpression != null, orderByExpression, isAsc ? OrderByType.Asc : OrderByType.Desc).WhereIF(whereExpression != null, whereExpression).ToList(); + } + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁骞舵帓搴� + /// </summary> + /// <param name="where"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(string where, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(!string.IsNullOrEmpty(where), where).ToList(); + } + + /// <summary> + /// 鍘熺敓Sql璇彞鏌ヨ鏁版嵁 + /// </summary> + /// <param name="sql"></param> + /// <param name="parameters"></param> + /// <returns></returns> + public virtual List<TEntity> QueryDataBySql(string sql, SugarParameter[]? parameters = null) + { + return _db.Ado.SqlQuery<TEntity>(sql, parameters); + } + + /// <summary> + /// 鍘熺敓Sql璇彞鏌ヨ鏁版嵁 + /// </summary> + /// <param name="sql"></param> + /// <param name="parameters"></param> + /// <returns></returns> + public virtual List<dynamic> QueryDynamicDataBySql(string sql, SugarParameter[]? parameters = null) + { + return _db.Ado.SqlQuery<dynamic>(sql, parameters); + } + + /// <summary> + /// 鍘熺敓Sql璇彞鏌ヨ鏁版嵁 + /// </summary> + /// <param name="sql"></param> + /// <param name="parameters"></param> + /// <returns></returns> + public virtual List<object> QueryObjectDataBySql(string sql, SugarParameter[]? parameters = null) + { + return _db.Ado.SqlQuery<object>(sql, parameters); + } + + /// <summary> + /// 鍘熺敓Sql璇彞鎵ц鎿嶄綔 + /// </summary> + /// <param name="sql"></param> + /// <param name="sqlParameters"></param> + /// <returns></returns> + public virtual int ExecuteSqlCommand(string sql, params SqlParameter[] sqlParameters) + { + return _db.Ado.ExecuteCommand(sql, sqlParameters); + } + + /// <summary> + /// 鍘熺敓Sql璇彞鏌ヨ鏁版嵁 + /// </summary> + /// <param name="sql"></param> + /// <param name="parameters"></param> + /// <returns></returns> + public virtual DataTable QueryTable(string sql, SugarParameter[]? parameters = null) + { + return _db.Ado.GetDataTable(sql, parameters); + } + + /// <summary> + /// 鏉′欢鏌ヨ鏁版嵁鎸囧畾鏁伴噺鐨勮 + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="top"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression, int top, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(whereExpression != null, whereExpression).Take(top).ToList(); + } + + /// <summary> + /// 鏉′欢鏌ヨ鎸囧畾鏁伴噺鐨勮 + /// </summary> + /// <param name="where"></param> + /// <param name="top"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(string where, int top, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(!string.IsNullOrEmpty(where), where).Take(top).ToList(); + } + + /// <summary> + /// 鍒嗛〉鏌ヨ + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(Expression<Func<TEntity, bool>> whereExpression, int pageIndex, int pageSize, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields) + .WhereIF(whereExpression != null, whereExpression).ToPageList(pageIndex, pageSize); + } + + /// <summary> + /// 鍒嗛〉鏌ヨ + /// </summary> + /// <param name="where"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual List<TEntity> QueryData(string where, int pageIndex, int pageSize, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields) + .WhereIF(!string.IsNullOrEmpty(where), where).ToPageList(pageIndex, pageSize); + } + + /// <summary> + /// 鍒嗛〉鏌ヨ + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual PageGridData<TEntity> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int pageIndex, int pageSize, string? orderByFields = null) + { + int totalCount = 0; + var list = _db.Queryable<TEntity>() + .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields) + .WhereIF(whereExpression != null, whereExpression) + .ToPageList(pageIndex, pageSize, ref totalCount); + + return new PageGridData<TEntity> { Rows = list, Total = totalCount }; + } + + /// <summary> + /// 鍒嗛〉鏌ヨ + /// </summary> + /// <param name="whereExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderBy"></param> + /// <returns></returns> + public virtual PageGridData<TEntity> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int pageIndex, int pageSize, Dictionary<string, OrderByType> orderBy) + { + List<OrderByModel> orderByModels = new List<OrderByModel>(); + foreach (var item in orderBy) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + int totalCount = 0; + List<TEntity> list = _db.Queryable<TEntity>() + .OrderBy(orderByModels) + .WhereIF(whereExpression != null, whereExpression) + .ToPageList(pageIndex, pageSize, ref totalCount); + + return new PageGridData<TEntity>(totalCount, list); + } + + /// <summary> + /// 鍒嗛〉鏌ヨ + /// </summary> + /// <param name="where"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual PageGridData<TEntity> QueryPage(string where, int pageIndex, int pageSize, Dictionary<string, OrderByType> orderBy) + { + List<OrderByModel> orderByModels = new List<OrderByModel>(); + foreach (var item in orderBy) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + int totalCount = 0; + List<TEntity> list = _db.Queryable<TEntity>().OrderBy(orderByModels) + .WhereIF(!string.IsNullOrEmpty(where), where).ToPageList(pageIndex, pageSize, ref totalCount); + + return new PageGridData<TEntity>(totalCount, list); + } + + /// <summary> + /// 涓よ〃鑱旀煡 + /// </summary> + /// <typeparam name="T"></typeparam> + /// <typeparam name="T2"></typeparam> + /// <typeparam name="TResult"></typeparam> + /// <param name="joinExpression"></param> + /// <param name="selectExpression"></param> + /// <param name="whereExpression"></param> + /// <returns></returns> + public virtual List<TResult> QueryTabs<T, T2, TResult>( + Expression<Func<T, T2, object[]>> joinExpression, + Expression<Func<T, T2, TResult>> selectExpression, + Expression<Func<T,T2, bool>> whereExpressionT1, + Expression<Func<TResult, bool>> whereExpression) + { + List<TResult> list = _db.Queryable(joinExpression).WhereIF(whereExpressionT1 != null, whereExpressionT1) + .Select(selectExpression) + .WhereIF(whereExpression != null, whereExpression).ToList(); + return list; + } + + /// <summary> + /// 涓よ〃鑱旀煡-鍒嗛〉 + /// </summary> + /// <typeparam name="T1"></typeparam> + /// <typeparam name="T2"></typeparam> + /// <typeparam name="TResult"></typeparam> + /// <param name="joinExpression"></param> + /// <param name="selectExpression"></param> + /// <param name="whereExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + public virtual PageGridData<TResult> QueryTabsPage<T1, T2, TResult>(Expression<Func<T1, T2, object[]>> joinExpression, Expression<Func<T1, T2, TResult>> selectExpression, Expression<Func<TResult, bool>> whereExpression, int pageIndex, int pageSize, string? orderByFields = null) + { + int totalCount = 0; + List<TResult> list = _db.Queryable(joinExpression) + .Select(selectExpression) + .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields) + .WhereIF(whereExpression != null, whereExpression) + .ToPageList(pageIndex, pageSize, ref totalCount); + return new PageGridData<TResult>(totalCount, list); + } + + /// <summary> + /// 涓よ〃鑱斿悎鏌ヨ-鍒嗛〉-鍒嗙粍 + /// </summary> + /// <typeparam name="T"></typeparam> + /// <typeparam name="T2"></typeparam> + /// <typeparam name="TResult"></typeparam> + /// <param name="joinExpression"></param> + /// <param name="selectExpression"></param> + /// <param name="whereExpression"></param> + /// <param name="groupExpression"></param> + /// <param name="pageIndex"></param> + /// <param name="pageSize"></param> + /// <param name="orderByFields"></param> + /// <returns></returns> + public virtual PageGridData<TResult> QueryTabsPage<T1, T2, TResult>(Expression<Func<T1, T2, object[]>> joinExpression, Expression<Func<T1, T2, TResult>> selectExpression, Expression<Func<TResult, bool>> whereExpression, Expression<Func<T1, object>> groupExpression, int pageIndex, int pageSize, string? orderByFields = null) + { + int totalCount = 0; + List<TResult> list = _db.Queryable(joinExpression).GroupBy(groupExpression) + .Select(selectExpression) + .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields) + .WhereIF(whereExpression != null, whereExpression) + .ToPageList(pageIndex, pageSize, ref totalCount); + return new PageGridData<TResult>(totalCount, list); + } + + public Task<TEntity> QureyDataByIdAsync(object id) + { + return _db.Queryable<TEntity>().In(id).SingleAsync(); + } + + public Task<List<TEntity>> QureyDataByIdsAsync(object[] lstIds) + { + return _db.Queryable<TEntity>().In(lstIds).ToListAsync(); + } + + public Task<List<TEntity>> QureyDataByIdsAsync(List<object> lstIds) + { + return _db.Queryable<TEntity>().In(lstIds).ToListAsync(); + } + + public Task<int> AddDataAsync(TEntity entity) + { + IInsertable<TEntity> insert = _db.Insertable(entity); + return insert.ExecuteReturnIdentityAsync(); + } + + public Task<int> AddDataAsync(List<TEntity> listEntity) + { + IInsertable<TEntity> insert = _db.Insertable(listEntity); + return insert.ExecuteReturnIdentityAsync(); + } + + public Task<bool> DeleteDataByIdAsync(object id) + { + return _db.Deleteable<TEntity>().In(id).ExecuteCommandHasChangeAsync(); + } + + public Task<bool> DeleteDataByIdsAsync(object[] ids) + { + return _db.Deleteable<TEntity>().In(ids).ExecuteCommandHasChangeAsync(); + } + + public Task<bool> DeleteDataAsync(TEntity entity) + { + return _db.Deleteable(entity).ExecuteCommandHasChangeAsync(); + } + + public Task<bool> DeleteDataAsync(List<TEntity> listEntity) + { + return _db.Deleteable(listEntity).ExecuteCommandHasChangeAsync(); + } + + public Task<bool> UpdateDataAsync(TEntity entity) + { + return _db.Updateable(entity).ExecuteCommandHasChangeAsync(); + } + + public Task<bool> UpdateDataAsync(List<TEntity> listEntity) + { + return _db.Updateable(listEntity).ExecuteCommandHasChangeAsync(); + } + + public Task<bool> UpdateDataAsync(TEntity entity, List<string> lstColumns, List<string>? lstIgnoreColumns = null) + { + IUpdateable<TEntity> update = _db.Updateable(entity); + + if (lstIgnoreColumns != null && lstIgnoreColumns.Count > 0) + { + update = update.IgnoreColumns(lstIgnoreColumns.ToArray()); + } + + if (lstColumns != null && lstColumns.Count > 0) + { + update = update.UpdateColumns(lstColumns.ToArray()); + } + + return update.ExecuteCommandHasChangeAsync(); + } + + public Task<List<TEntity>> QueryDataAsync() + { + return _db.Queryable<TEntity>().ToListAsync(); + } + + public Task<List<TEntity>> QueryDataAsync(string where) + { + return _db.Queryable<TEntity>().WhereIF(!string.IsNullOrEmpty(where), where).ToListAsync(); + } + + public Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression) + { + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).ToListAsync(); + } + + public Task<TEntity> QueryFirstAsync(Expression<Func<TEntity, bool>> whereExpression) + { + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).FirstAsync(); + } + + public Task<TResult> QueryFirstAsync<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> expression) + { + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).Select(expression).FirstAsync(); + } + + public TResult QueryFirst<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> expression, Dictionary<string, OrderByType> orderBy) + { + List<OrderByModel> orderByModels = new List<OrderByModel>(); + foreach (var item in orderBy) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).OrderBy(orderByModels).Select(expression).First(); + } + + public Task<TResult> QueryFirstAsync<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> expression, Dictionary<string, OrderByType> orderBy) + { + List<OrderByModel> orderByModels = new List<OrderByModel>(); + foreach (var item in orderBy) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).OrderBy(orderByModels).Select(expression).FirstAsync(); + } + + public TEntity QueryFirst(Expression<Func<TEntity, bool>> whereExpression, Dictionary<string, OrderByType> orderBy) + { + List<OrderByModel> orderByModels = new List<OrderByModel>(); + foreach (var item in orderBy) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).OrderBy(orderByModels).First(); + } + + public Task<TEntity> QueryFirstAsync(Expression<Func<TEntity, bool>> whereExpression, Dictionary<string, OrderByType> orderBy) + { + List<OrderByModel> orderByModels = new List<OrderByModel>(); + foreach (var item in orderBy) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).OrderBy(orderByModels).FirstAsync(); + } + + public Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression, string orderByFields) + { + return _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).ToListAsync(); + } + + public Task<List<TEntity>> QueryDataAsync(string where, Dictionary<string, OrderByType> orderBy) + { + List<OrderByModel> orderByModels = new List<OrderByModel>(); + foreach (var item in orderBy) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + return _db.Queryable<TEntity>().WhereIF(!string.IsNullOrEmpty(where), where).OrderBy(orderByModels).ToListAsync(); + } + + public Task<List<TResult>> QueryDataAsync<TResult>(Expression<Func<TEntity, TResult>> expression) + { + return _db.Queryable<TEntity>().Select(expression).ToListAsync(); + } + + public Task<List<TResult>> QueryDataAsync<TResult>(Expression<Func<TEntity, TResult>> expression, Expression<Func<TEntity, bool>> whereExpression, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(whereExpression != null, whereExpression).Select(expression).ToListAsync(); + } + + public Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true) + { + return _db.Queryable<TEntity>().OrderByIF(orderByExpression != null, orderByExpression, isAsc ? OrderByType.Asc : OrderByType.Desc).WhereIF(whereExpression != null, whereExpression).ToListAsync(); + } + + public Task<List<TEntity>> QueryDataAsync(string where, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(!string.IsNullOrEmpty(where), where).ToListAsync(); + } + + public Task<List<TEntity>> QueryDataBySqlAsync(string sql, SugarParameter[]? parameters = null) + { + return _db.Ado.SqlQueryAsync<TEntity>(sql, parameters); + } + + public Task<List<dynamic>> QueryDynamicDataBySqlAsync(string sql, SugarParameter[]? parameters = null) + { + return _db.Ado.SqlQueryAsync<dynamic>(sql, parameters); + } + + public Task<List<object>> QueryObjectDataBySqlAsync(string sql, SugarParameter[]? parameters = null) + { + return _db.Ado.SqlQueryAsync<object>(sql, parameters); + } + + public Task<int> ExecuteSqlCommandAsync(string sql, params SqlParameter[] sqlParameters) + { + return _db.Ado.ExecuteCommandAsync(sql, sqlParameters); + } + + public Task<DataTable> QueryTableAsync(string sql, SugarParameter[]? parameters = null) + { + return _db.Ado.GetDataTableAsync(sql, parameters); + } + + public Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression, int top, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(whereExpression != null, whereExpression).Take(top).ToListAsync(); + } + + public Task<List<TEntity>> QueryDataAsync(string where, int top, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(!string.IsNullOrEmpty(where), where).Take(top).ToListAsync(); + } + + public Task<List<TEntity>> QueryDataAsync(Expression<Func<TEntity, bool>> whereExpression, int pageIndex, int pageSize, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields) + .WhereIF(whereExpression != null, whereExpression).ToPageListAsync(pageIndex, pageSize); + } + + public Task<List<TEntity>> QueryDataAsync(string where, int pageIndex, int pageSize, string orderByFields) + { + return _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields) + .WhereIF(!string.IsNullOrEmpty(where), where).ToPageListAsync(pageIndex, pageSize); + } + + public Task<List<TResult>> QueryTabsAsync<T, T2, TResult>(Expression<Func<T, T2, object[]>> joinExpression, Expression<Func<T, T2, TResult>> selectExpression, Expression<Func<TResult, bool>> whereExpression) + { + return _db.Queryable(joinExpression) + .Select(selectExpression) + .WhereIF(whereExpression != null, whereExpression).ToListAsync(); + } + + public bool DeleteAndMoveIntoHty(TEntity entity, OperateTypeEnum operateType) + { + Type type = entity.GetType(); + Assembly assembly = type.Assembly; + Type? htyType = assembly.GetType(type.FullName + "_Hty"); + if (htyType != null) + { + object? obj = Activator.CreateInstance(htyType); + PropertyInfo keyPro = typeof(TEntity).GetKeyProperty(); + PropertyInfo? operateTypePro = htyType.GetProperty(nameof(IBaseHistoryEntity.OperateType)); + PropertyInfo? sourceIdPro = htyType.GetProperty(nameof(IBaseHistoryEntity.SourceId)); + if (obj != null && keyPro != null && operateTypePro != null && sourceIdPro != null) + { + operateTypePro.SetValue(obj, operateType.ToString()); + sourceIdPro.SetValue(obj, keyPro.GetValue(entity)); + + List<PropertyInfo> propertyInfos = htyType.GetProperties().Where(x => x.Name != operateTypePro.Name && x.Name != sourceIdPro.Name && x.Name != keyPro.Name).ToList(); + + for (int i = 0; i < propertyInfos.Count; i++) + { + PropertyInfo propertyInfo = propertyInfos[i]; + PropertyInfo? property = type.GetProperty(propertyInfo.Name); + + if (property != null) + { + if (propertyInfo.Name == nameof(BaseEntity.Modifier)) + { + propertyInfo.SetValue(obj, App.User.UserId > 0 ? App.User.UserName : "System"); + } + else if (propertyInfo.Name == nameof(BaseEntity.ModifyDate)) + { + propertyInfo.SetValue(obj, DateTime.Now); + } + else + { + propertyInfo.SetValue(obj, property.GetValue(entity)); + } + } + } + _db.InsertableByObject(obj).AS(type.Name + "_Hty").ExecuteCommand(); + } + } + return DeleteData(entity); + } + + public bool DeleteAndMoveIntoHty(List<TEntity> entities, OperateTypeEnum operateType) + { + Type type = typeof(TEntity); + Assembly assembly = type.Assembly; + Type? htyType = assembly.GetType(type.FullName + "_Hty"); + if (htyType != null) + { + object? obj2 = Activator.CreateInstance(htyType); + PropertyInfo keyPro = typeof(TEntity).GetKeyProperty(); + PropertyInfo? operateTypePro = htyType.GetProperty(nameof(IBaseHistoryEntity.OperateType)); + PropertyInfo? sourceIdPro = htyType.GetProperty(nameof(IBaseHistoryEntity.SourceId)); + if (obj2 != null && keyPro != null && operateTypePro != null && sourceIdPro != null) + { + List<PropertyInfo> propertyInfos = htyType.GetProperties().Where(x => x.Name != operateTypePro.Name && x.Name != sourceIdPro.Name && x.Name != keyPro.Name).ToList(); + List<object> list = new List<object>(); + foreach (var item in entities) + { + object? obj = Activator.CreateInstance(htyType); + if (obj != null) + { + operateTypePro.SetValue(obj, operateType.ToString()); + sourceIdPro.SetValue(obj, keyPro.GetValue(item)); + for (int i = 0; i < propertyInfos.Count; i++) + { + PropertyInfo propertyInfo = propertyInfos[i]; + PropertyInfo? property = type.GetProperty(propertyInfo.Name); + + if (property != null) + { + if (propertyInfo.Name == nameof(BaseEntity.Modifier)) + { + propertyInfo.SetValue(obj, App.User.UserId > 0 ? App.User.UserName : "System"); + } + else if (propertyInfo.Name == nameof(BaseEntity.ModifyDate)) + { + propertyInfo.SetValue(obj, DateTime.Now); + } + else + { + propertyInfo.SetValue(obj, property.GetValue(item)); + } + } + } + list.Add(obj); + } + } + _db.InsertableByObject(list).AS(type.Name + "_Hty").ExecuteCommand(); + + } + } + return DeleteData(entities); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/IUnitOfWorkManage.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/IUnitOfWorkManage.cs" new file mode 100644 index 0000000..7dccadd --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/IUnitOfWorkManage.cs" @@ -0,0 +1,54 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.BaseRepository +{ + public interface IUnitOfWorkManage + { + /// <summary> + /// 鑾峰彇SqlSugar鏁版嵁搴撳鎴风瀹炰緥 + /// </summary> + /// <returns>SqlSugarClient鏁版嵁搴撳鎴风瀵硅薄</returns> + SqlSugarClient GetDbClient(); + int TranCount { get; } + + /// <summary> + /// 鍒涘缓涓�涓柊鐨勫伐浣滃崟鍏冨疄渚� + /// </summary> + /// <returns>杩斿洖鏂板垱寤虹殑宸ヤ綔鍗曞厓瀵硅薄</returns> + UnitOfWork CreateUnitOfWork(); + + /// <summary> + /// 寮�濮嬩竴涓簨鍔� + /// </summary> + void BeginTran(); + /// <summary> + /// 寮�濮嬩竴涓簨鍔� + /// </summary> + /// <param name="method">瑙﹀彂浜嬪姟鐨勬柟娉曚俊鎭�</param> + void BeginTran(MethodInfo method); + /// <summary> + /// 鎻愪氦褰撳墠浜嬪姟 + /// </summary> + void CommitTran(); + /// <summary> + /// 鎻愪氦浜嬪姟 + /// </summary> + /// <param name="method">瑙﹀彂鎻愪氦浜嬪姟鐨勬柟娉曚俊鎭�</param> + void CommitTran(MethodInfo method); + /// <summary> + /// 鍥炴粴褰撳墠浜嬪姟 + /// </summary> + void RollbackTran(); + /// <summary> + /// 鍥炴粴褰撳墠浜嬪姟 + /// </summary> + /// <param name="method">瑙﹀彂鍥炴粴鐨勬柟娉曚俊鎭�</param> + void RollbackTran(MethodInfo method); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/UnitOfWork.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/UnitOfWork.cs" new file mode 100644 index 0000000..7ad3b70 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/UnitOfWork.cs" @@ -0,0 +1,69 @@ +锘縰sing Microsoft.Extensions.Logging; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.BaseRepository +{ + public class UnitOfWork : IDisposable + { + // 瀹氫箟涓�涓狪Logger绫诲瀷鐨凩ogger灞炴�� + public ILogger Logger { get; set; } + // 瀹氫箟涓�涓狪SqlSugarClient绫诲瀷鐨凞b灞炴�� + public ISqlSugarClient Db { get; internal set; } + + // 瀹氫箟涓�涓狪Tenant绫诲瀷鐨凾enant灞炴�� + public ITenant Tenant { get; internal set; } + + // 瀹氫箟涓�涓猙ool绫诲瀷鐨処sTran灞炴�э紝琛ㄧず鏄惁寮�鍚簨鍔� + public bool IsTran { get; internal set; } + + // 瀹氫箟涓�涓猙ool绫诲瀷鐨処sCommit灞炴�э紝琛ㄧず鏄惁鎻愪氦浜嬪姟 + public bool IsCommit { get; internal set; } + + // 瀹氫箟涓�涓猙ool绫诲瀷鐨処sClose灞炴�э紝琛ㄧず鏄惁鍏抽棴杩炴帴 + public bool IsClose { get; internal set; } + + // 瀹炵幇IDisposable鎺ュ彛鐨凞ispose鏂规硶 + public void Dispose() + { + // 濡傛灉寮�鍚簨鍔′笖鏈彁浜や簨鍔★紝鍒欏洖婊氫簨鍔� + if (IsTran && !IsCommit) + { + Logger.LogDebug("UnitOfWork RollbackTran"); + this.Tenant.RollbackTran(); + } + + // 濡傛灉浜嬪姟涓嶄负绌烘垨鑰呭凡缁忓叧闂繛鎺ワ紝鍒欑洿鎺ヨ繑鍥� + if (this.Db.Ado.Transaction != null || this.IsClose) + return; + // 鍏抽棴杩炴帴 + this.Db.Close(); + } + + // 鎻愪氦浜嬪姟 + public bool Commit() + { + // 濡傛灉寮�鍚簨鍔′笖鏈彁浜や簨鍔★紝鍒欐彁浜や簨鍔� + if (this.IsTran && !this.IsCommit) + { + Logger.LogDebug("UnitOfWork CommitTran"); + this.Tenant.CommitTran(); + this.IsCommit = true; + } + + // 濡傛灉浜嬪姟涓虹┖涓旀湭鍏抽棴杩炴帴锛屽垯鍏抽棴杩炴帴 + if (this.Db.Ado.Transaction == null && !this.IsClose) + { + this.Db.Close(); + this.IsClose = true; + } + + // 杩斿洖鏄惁鎻愪氦浜嬪姟 + return this.IsCommit; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/UnitOfWorkManage.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/UnitOfWorkManage.cs" new file mode 100644 index 0000000..adfed01 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseRepository/UnitOfWorks/UnitOfWorkManage.cs" @@ -0,0 +1,208 @@ +锘縰sing Microsoft.Extensions.Logging; +using SqlSugar; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.BaseRepository +{ + public class UnitOfWorkManage : IUnitOfWorkManage + { + // 瀹氫箟鏃ュ織璁板綍鍣� + private readonly ILogger<UnitOfWorkManage> _logger; + // 瀹氫箟SqlSugarClient + private readonly ISqlSugarClient _sqlSugarClient; + + // 瀹氫箟浜嬪姟璁℃暟鍣� + private int _tranCount { get; set; } + // 瀹氫箟浜嬪姟璁℃暟鍣ㄧ殑鍙灞炴�� + public int TranCount => _tranCount; + // 瀹氫箟浜嬪姟鏍� + public readonly ConcurrentStack<string> TranStack = new(); + + // 鏋勯�犲嚱鏁帮紝鍒濆鍖栨棩蹇楄褰曞櫒鍜孲qlSugarClient + public UnitOfWorkManage(ISqlSugarClient sqlSugarClient, ILogger<UnitOfWorkManage> logger) + { + _sqlSugarClient = sqlSugarClient; + _logger = logger; + _tranCount = 0; + } + + /// <summary> + /// 鑾峰彇DB锛屼繚璇佸敮涓�鎬� + /// </summary> + /// <returns></returns> + public SqlSugarClient GetDbClient() + { + // 蹇呴』瑕乤s锛屽悗杈逛細鐢ㄥ埌鍒囨崲鏁版嵁搴撴搷浣� + return _sqlSugarClient as SqlSugarClient; + } + + + // 鍒涘缓UnitOfWork + public UnitOfWork CreateUnitOfWork() + { + UnitOfWork uow = new UnitOfWork(); + uow.Logger = _logger; + uow.Db = _sqlSugarClient; + uow.Tenant = (ITenant)_sqlSugarClient; + uow.IsTran = true; + + uow.Db.Open(); + uow.Tenant.BeginTran(); + + _logger.LogDebug("UnitOfWork Begin"); + return uow; + } + + // 寮�濮嬩簨鍔� + public void BeginTran() + { + lock (this) + { + _tranCount++; + GetDbClient().BeginTran(); + } + } + + // 寮�濮嬩簨鍔★紝骞惰褰曟柟娉曞悕 + public void BeginTran(MethodInfo method) + { + lock (this) + { + GetDbClient().BeginTran(); + TranStack.Push(method.GetFullName()); + _tranCount = TranStack.Count; + } + } + + // 寮�濮嬩簨鍔★紝骞舵墽琛屽嚱鏁帮紝鏍规嵁鍑芥暟杩斿洖鍊煎喅瀹氭槸鍚︽彁浜や簨鍔� + public WebResponseContent BeginTran(Func<WebResponseContent> func) + { + lock (this) + { + BeginTran(); + try + { + WebResponseContent content = func(); + if (content.Status) + { + CommitTran(); + } + else + { + RollbackTran(); + } + return content; + } + catch(Exception ex) + { + RollbackTran(); + return WebResponseContent.Instance.Error(ex.Message); + } + } + } + + // 鎻愪氦浜嬪姟 + public void CommitTran() + { + lock (this) + { + _tranCount--; + if (_tranCount == 0) + { + try + { + GetDbClient().CommitTran(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + GetDbClient().RollbackTran(); + } + } + } + } + + // 鎻愪氦浜嬪姟锛屽苟璁板綍鏂规硶鍚� + public void CommitTran(MethodInfo method) + { + lock (this) + { + string result = ""; + while (!TranStack.IsEmpty && !TranStack.TryPeek(out result)) + { + Thread.Sleep(1); + } + + + if (result == method.GetFullName()) + { + try + { + GetDbClient().CommitTran(); + + _logger.LogDebug($"Commit Transaction"); + Console.WriteLine($"Commit Transaction"); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + GetDbClient().RollbackTran(); + _logger.LogDebug($"Commit Error , Rollback Transaction"); + } + finally + { + while (!TranStack.TryPop(out _)) + { + Thread.Sleep(1); + } + + _tranCount = TranStack.Count; + } + } + } + } + + // 鍥炴粴浜嬪姟 + public void RollbackTran() + { + lock (this) + { + _tranCount--; + GetDbClient().RollbackTran(); + } + } + + // 鍥炴粴浜嬪姟锛屽苟璁板綍鏂规硶鍚� + public void RollbackTran(MethodInfo method) + { + lock (this) + { + string result = ""; + while (!TranStack.IsEmpty && !TranStack.TryPeek(out result)) + { + Thread.Sleep(1); + } + + if (result == method.GetFullName()) + { + GetDbClient().RollbackTran(); + _logger.LogDebug($"Rollback Transaction"); + Console.WriteLine($"Rollback Transaction"); + while (!TranStack.TryPop(out _)) + { + Thread.Sleep(1); + } + + _tranCount = TranStack.Count; + } + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/IService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/IService.cs" new file mode 100644 index 0000000..9559096 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/IService.cs" @@ -0,0 +1,123 @@ +锘縰sing Microsoft.AspNetCore.Http; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.BaseServices +{ + public interface IService<TEntity>: IDependency where TEntity : class + { + ISqlSugarClient Db { get; } + + /// <summary> + /// 鍒嗛〉鏌ヨ鏁版嵁 + /// </summary> + /// <param name="options"></param> + /// <returns></returns> + PageGridData<TEntity> GetPageData(PageDataOptions options); + + object GetDetailPage(PageDataOptions pageData); + + /// <summary> + /// 娣诲姞鏁版嵁 + /// </summary> + /// <param name="entity">鍗曚釜瀹炰綋</param> + /// <returns></returns> + WebResponseContent AddData(TEntity entity); + + /// <summary> + /// 娣诲姞鏁版嵁 + /// </summary> + /// <param name="entities">瀹炰綋闆嗗悎</param> + /// <returns></returns> + WebResponseContent AddData(List<TEntity> entities); + + /// <summary> + /// 娣诲姞鏁版嵁 + /// </summary> + /// <param name="saveModel"></param> + /// <returns></returns> + WebResponseContent AddData(SaveModel saveModel); + + /// <summary> + /// 淇敼鏁版嵁 + /// </summary> + /// <param name="entity">鍗曚釜瀹炰綋</param> + /// <returns></returns> + WebResponseContent UpdateData(TEntity entity); + + /// <summary> + /// 淇敼鏁版嵁 + /// </summary> + /// <param name="entities">瀹炰綋闆嗗悎</param> + /// <returns></returns> + WebResponseContent UpdateData(List<TEntity> entities); + + /// <summary> + /// 淇敼鏁版嵁 + /// </summary> + /// <param name="saveModel"></param> + /// <returns></returns> + WebResponseContent UpdateData(SaveModel saveModel); + + /// <summary> + /// 鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="key">涓婚敭</param> + /// <returns></returns> + WebResponseContent DeleteData(object key); + + /// <summary> + /// 鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="keys">涓婚敭鏁扮粍</param> + /// <returns></returns> + WebResponseContent DeleteData(object[] keys); + + /// <summary> + /// 鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="entity">鍗曚釜瀹炰綋</param> + /// <returns></returns> + WebResponseContent DeleteData(TEntity entity); + + /// <summary> + /// 鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="entities">瀹炰綋闆嗗悎</param> + /// <returns></returns> + WebResponseContent DeleteData(List<TEntity> entities); + + /// <summary> + /// 瀵煎嚭鏁版嵁 + /// </summary> + /// <param name="pageData"></param> + /// <returns></returns> + WebResponseContent Export(PageDataOptions pageData); + + /// <summary> + /// 瀵煎叆鏁版嵁 + /// </summary> + /// <param name="files"></param> + /// <returns></returns> + WebResponseContent Import(List<IFormFile> files); + + /// <summary> + /// 涓婁紶鏂囦欢 + /// </summary> + /// <param name="files"></param> + /// <returns></returns> + WebResponseContent Upload(List<IFormFile> files); + + /// <summary> + /// 妯℃澘涓嬭浇 + /// </summary> + /// <returns></returns> + WebResponseContent DownLoadTemplate(); + + WebResponseContent ExportSeedData(); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/ServiceBase.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/ServiceBase.cs" new file mode 100644 index 0000000..ebcc923 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/ServiceBase.cs" @@ -0,0 +1,852 @@ +锘縰sing Magicodes.ExporterAndImporter.Core; +using Magicodes.ExporterAndImporter.Core.Models; +using Magicodes.ExporterAndImporter.Excel; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using SqlSugar; +using System.Drawing.Drawing2D; +using System.Dynamic; +using System.Linq.Expressions; +using System.Reflection; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.Const; +using WIDESEA_Core.Enums; +using WIDESEA_Core.Helper; +using WIDESEA_Core.Utilities; + +namespace WIDESEA_Core.BaseServices +{ + public class ServiceBase<TEntity, TRepository> : ServiceFunFilter<TEntity>, IService<TEntity> + where TEntity : class, new() + where TRepository : IRepository<TEntity> + + { + public ServiceBase(TRepository BaseDal) + { + this.BaseDal = BaseDal; + } + + public TRepository BaseDal { get; set; } //閫氳繃鍦ㄥ瓙绫荤殑鏋勯�犲嚱鏁颁腑娉ㄥ叆锛岃繖閲屾槸鍩虹被锛屼笉鐢ㄦ瀯閫犲嚱鏁� + + public ISqlSugarClient Db => BaseDal.Db; + + private PropertyInfo[] _propertyInfo { get; set; } = null; + private PropertyInfo[] TProperties + { + get + { + if (_propertyInfo != null) + { + return _propertyInfo; + } + _propertyInfo = typeof(TEntity).GetProperties(); + return _propertyInfo; + } + } + + public virtual PageGridData<TEntity> GetPageData(PageDataOptions options) + { + ISugarQueryable<TEntity> sugarQueryable = Db.Queryable<TEntity>(); + + ValidatePageOptions(options, ref sugarQueryable); + + List<OrderByModel> orderByModels = new List<OrderByModel>(); + + if (OrderByParameters != null) + { + foreach (var item in OrderByParameters) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + } + if (EnableWebOrderBy) + { + //鑾峰彇鎺掑簭瀛楁 + Dictionary<string, OrderByType> orderbyDic = GetPageDataSort(options, TProperties); + + foreach (var item in orderbyDic) + { + OrderByModel orderByModel = new OrderByModel() + { + FieldName = item.Key, + OrderByType = item.Value + }; + orderByModels.Add(orderByModel); + } + } + + int total = 0; + PageGridData<TEntity> pageGridData = new PageGridData<TEntity>(); + sugarQueryable = sugarQueryable.OrderBy(orderByModels); + pageGridData.Rows = sugarQueryable.ToPageList(options.Page, options.Rows, ref total); + pageGridData.Total = total; + + return pageGridData; + } + + protected void ValidatePageOptions(PageDataOptions options, ref ISugarQueryable<TEntity> sugarQueryable) + { + options = options ?? new PageDataOptions(); + List<SearchParameters> searchParametersList = new List<SearchParameters>(); + if (options.Filter != null && options.Filter.Count > 0) + { + searchParametersList.AddRange(options.Filter); + } + else if (!string.IsNullOrEmpty(options.Wheres)) + { + try + { + searchParametersList = options.Wheres.DeserializeObject<List<SearchParameters>>(); + options.Filter = searchParametersList; + } + catch { } + } + QueryRelativeList?.Invoke(searchParametersList); + + for (int i = 0; i < searchParametersList.Count; i++) + { + if (string.IsNullOrEmpty(searchParametersList[i].Value)) + { + continue; + } + + PropertyInfo? property = TProperties.Where(c => c.Name.ToUpper() == searchParametersList[i].Name.ToUpper()).FirstOrDefault(); + + if (property == null) continue; + + List<(bool, string, object)> results = property.ValidationValueForDbType(searchParametersList[i].Value.Split(',')).ToList(); + if (results == null || results.Count() == 0) + { + continue; + } + for (int j = 0; j < results.Count(); j++) + { + LinqExpressionType expressionType = searchParametersList[i].DisplayType.ToLower().GetLinqCondition(); + if (expressionType == LinqExpressionType.In) + { + Expression<Func<TEntity, bool>> expression = GetWhereExpression(property.Name, results.Select(x => x.Item3).ToArray(), null, expressionType); + sugarQueryable = sugarQueryable.Where(expression); + break; + } + else + { + Expression<Func<TEntity, bool>> expression = GetWhereExpression(property.Name, results[j].Item3, null, expressionType); + sugarQueryable = sugarQueryable.Where(expression); + } + } + } + } + + protected Expression<Func<TEntity, bool>> GetWhereExpression(string propertyName, object propertyValue, ParameterExpression parameter, LinqExpressionType expressionType) + { + Type? proType = typeof(TEntity).GetProperty(propertyName)?.PropertyType; + if (proType == null) return p => true; + if (propertyValue == null) return p => true; + string? value = propertyValue?.ToString(); + if (value == null) return p => true; + + + parameter = parameter ?? Expression.Parameter(typeof(TEntity), "x"); + //鍒涘缓鑺傜偣鐨勫睘鎬=>p.name 灞炴�ame + MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyName); + + if (expressionType == LinqExpressionType.In) + { + if (!(propertyValue is System.Collections.IList list) || list.Count == 0) + { + if (!string.IsNullOrEmpty(propertyValue?.ToString())) + { + list = propertyValue.ToString().Split(",").ToList(); + } + else + { + throw new Exception("灞炴�у�肩被鍨嬩笉姝g‘"); + } + } + // + + bool isStringValue = true; + List<object> objList = new List<object>(); + + if (proType.ToString() != "System.String") + { + isStringValue = false; + foreach (var values in list) + { + objList.Add(values?.ToString().ChangeType(proType)); + } + list = objList; + } + + //if (isStringValue) + //{ + // //string 绫诲瀷鐨勫瓧娈碉紝濡傛灉鍊煎甫鏈�'鍗曞紩鍙�,EF浼氶粯璁ゅ彉鎴�''涓や釜鍗曞紩鍙� + // MethodInfo method = typeof(System.Collections.IList).GetMethod("Contains"); + // //鍒涘缓闆嗗悎甯搁噺骞惰缃负甯搁噺鐨勫�� + // ConstantExpression constantCollection = Expression.Constant(list); + // //鍒涘缓涓�涓〃绀鸿皟鐢ㄥ甫鍙傛暟鐨勬柟娉曠殑锛歯ew string[]{"1","a"}.Contains("a"); + // MethodCallExpression methodCall = Expression.Call(constantCollection, method, memberProperty); + // return Expression.Lambda<Func<TEntity, bool>>(methodCall, parameter); + //} + //闈瀞tring瀛楁锛屾寜涓婇潰鏂瑰紡澶勭悊鎶ュ紓甯窷ull TypeMapping in Sql Tree + BinaryExpression body = null; + foreach (var values in list) + { + ConstantExpression constantExpression = Expression.Constant(values); + UnaryExpression unaryExpression = Expression.Convert(memberProperty, constantExpression.Type); + + body = body == null + ? Expression.Equal(unaryExpression, constantExpression) + : Expression.OrElse(body, Expression.Equal(unaryExpression, constantExpression)); + } + return Expression.Lambda<Func<TEntity, bool>>(body, parameter); + } + + ConstantExpression constant = proType.ToString() == "System.String" + ? Expression.Constant(propertyValue) : Expression.Constant(value.ChangeType(proType)); + + // DateTime鍙�夋嫨浜嗘棩鏈熺殑鏃跺�欒嚜鍔ㄥ湪缁撴潫鏃ユ湡鍔犱竴澶╋紝淇DateTime绫诲瀷浣跨敤鏃ユ湡鍖洪棿鏌ヨ鏃犳硶鏌ヨ鍒扮粨鏉熸棩鏈熺殑闂 + if ((proType == typeof(DateTime) || proType == typeof(DateTime?)) && expressionType == LinqExpressionType.LessThanOrEqual && value.Length == 10) + { + constant = Expression.Constant(Convert.ToDateTime(value).AddDays(1)); + } + + UnaryExpression member = Expression.Convert(memberProperty, constant.Type); + Expression<Func<TEntity, bool>> expression = p => false; + switch (expressionType) + { + case LinqExpressionType.Equal: + expression = Expression.Lambda<Func<TEntity, bool>>(Expression.Equal(member, constant), parameter); + break; + case LinqExpressionType.NotEqual: + expression = Expression.Lambda<Func<TEntity, bool>>(Expression.NotEqual(member, constant), parameter); + break; + case LinqExpressionType.GreaterThan: + expression = Expression.Lambda<Func<TEntity, bool>>(Expression.GreaterThan(member, constant), parameter); + break; + case LinqExpressionType.LessThan: + expression = Expression.Lambda<Func<TEntity, bool>>(Expression.LessThan(member, constant), parameter); + break; + case LinqExpressionType.ThanOrEqual: + expression = Expression.Lambda<Func<TEntity, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter); + break; + case LinqExpressionType.LessThanOrEqual: + expression = Expression.Lambda<Func<TEntity, bool>>(Expression.LessThanOrEqual(member, constant), parameter); + break; + case LinqExpressionType.Contains: + case LinqExpressionType.NotContains: + MethodInfo? method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); + if (method != null) + { + constant = Expression.Constant(propertyValue, typeof(string)); + if (expressionType == LinqExpressionType.Contains) + { + expression = Expression.Lambda<Func<TEntity, bool>>(Expression.Call(member, method, constant), parameter); + } + else + { + expression = Expression.Lambda<Func<TEntity, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter); + } + } + else + { + expression = p => true; + } + break; + default: + expression = p => false; + break; + } + return expression; + } + + /// <summary> + /// 鑾峰彇鎺掑簭瀛楁 + /// </summary> + /// <param name="pageData"></param> + /// <param name="propertyInfo"></param> + /// <returns></returns> + protected Dictionary<string, OrderByType> GetPageDataSort(PageDataOptions pageData, PropertyInfo[] propertyInfo) + { + if (!string.IsNullOrEmpty(pageData.Sort)) + { + if (pageData.Sort.Contains(",")) + { + List<string> sortArr = pageData.Sort.Split(",").Where(x => propertyInfo.Any(p => p.Name == x)).ToList(); + Dictionary<string, OrderByType> sortDic = new Dictionary<string, OrderByType>(); + foreach (var item in sortArr) + { + sortDic[item] = pageData.Order?.ToLower() == OrderByType.Asc.ToString() ? OrderByType.Asc : OrderByType.Desc; + } + return sortDic; + } + else if (propertyInfo.Any(x => x.Name == pageData.Sort.FirstLetterToLower() || x.Name == pageData.Sort.FirstLetterToUpper())) + { + return new Dictionary<string, OrderByType> { + { + pageData.Sort,pageData.Order?.ToLower() == OrderByType.Asc.ToString().ToLower() ? OrderByType.Asc : OrderByType.Desc + } }; + } + } + return new Dictionary<string, OrderByType> { { "CreateDate", pageData.Order?.ToLower() == OrderByType.Asc.ToString() ? OrderByType.Asc : OrderByType.Desc } }; + } + + public virtual object GetDetailPage(PageDataOptions pageData) + { + Type t = typeof(TEntity); + + if (pageData.Value == null) return new PageGridData<object>(total: 0, null); + string keyName = t.GetKeyName(); + ////鐢熸垚鏌ヨ鏉′欢 + //Expression<Func<TEntity, bool>> whereExpression = keyName.CreateExpression<TEntity>(pageData.Value, LinqExpressionType.Equal); + int totalCount = 0; + PropertyInfo propertyInfo = t.GetProperties().FirstOrDefault(x => x.GetCustomAttribute<Navigate>() != null); + if (propertyInfo != null) + { + Type detailType = propertyInfo.PropertyType.GetGenericArguments()[0]; + Navigate navigate = propertyInfo.GetCustomAttribute<Navigate>(); + List<ExpandoObject> list = BaseDal.Db.Queryable(detailType.Name, "detail").Where(navigate.GetName(), "=", pageData.Value).ToPageList(pageData.Page, pageData.Rows, ref totalCount); + return new PageGridData<ExpandoObject>(totalCount, list); + } + return new PageGridData<object>(total: 0, null); + } + + /// <summary> + /// 娣诲姞鏁版嵁 + /// </summary> + /// <param name="entity">鍗曚釜瀹炰綋</param> + /// <returns></returns> + public virtual WebResponseContent AddData(TEntity entity) + { + try + { + return BaseDal.AddData(entity) > 0 ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + /// <summary> + /// 娣诲姞鏁版嵁 + /// </summary> + /// <param name="entities">瀹炰綋闆嗗悎</param> + /// <returns></returns> + public virtual WebResponseContent AddData(List<TEntity> entities) + { + try + { + return BaseDal.AddData(entities) > 0 ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + /// <summary> + /// 娣诲姞鏁版嵁 + /// </summary> + /// <param name="saveModel"></param> + /// <returns></returns> + public virtual WebResponseContent AddData(SaveModel saveModel) + { + try + { + if (saveModel == null || saveModel.MainData == null || saveModel.MainData.Count == 0)//鍒ゆ柇鍙傛暟鏄惁浼犲叆 + { + return WebResponseContent.Instance.Error("浼犲弬閿欒,鍙傛暟涓嶈兘涓虹┖"); + } + string validResult = typeof(TEntity).ValidateDicInEntity(saveModel.MainData, true, TProperties); + + if (!string.IsNullOrEmpty(validResult)) + { + return WebResponseContent.Instance.Error(validResult); + } + + PropertyInfo keyPro = typeof(TEntity).GetKeyProperty(); + if (keyPro == null) + { + return WebResponseContent.Instance.Error("璇峰厛璁剧疆涓婚敭"); + } + if (keyPro.PropertyType == typeof(Guid)) + { + saveModel.MainData.Add(keyPro.Name, Guid.NewGuid()); + } + else if (keyPro.PropertyType == typeof(int) || keyPro.PropertyType == typeof(long)) + { + SugarColumn sugarColumn = keyPro.GetCustomAttribute<SugarColumn>(); + if (sugarColumn.IsIdentity) + { + saveModel.MainData.Remove(keyPro.Name.FirstLetterToUpper()); + saveModel.MainData.Remove(keyPro.Name.FirstLetterToLower()); + } + } + TEntity entity = saveModel.MainData.DicToModel<TEntity>(); + if (saveModel.DetailData == null || saveModel.DetailData.Count == 0) + { + BaseDal.AddData(entity); + return WebResponseContent.Instance.OK(); + } + + if (typeof(TEntity).GetNavigatePro() == null) + { + return WebResponseContent.Instance.Error("鏈厤缃鑸睘鎬�"); + } + + Type detailType = typeof(TEntity).GetDetailType(); + MethodInfo? methodInfo = GetType().GetMethod(nameof(AddDataIncludesDetail)); + methodInfo = methodInfo?.MakeGenericMethod(new Type[] { detailType }); + object? obj = methodInfo?.Invoke(this, new object[] { entity, detailType, saveModel.DetailData }); + return obj as WebResponseContent; + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + public WebResponseContent AddDataIncludesDetail<TDetail>(TEntity entity, Type detailType, List<Dictionary<string, object>> detailDics) where TDetail : class, new() + { + WebResponseContent content = new WebResponseContent(); + try + { + string name = typeof(TEntity).GetMainIdByDetail(); + string reslut = detailType.ValidateDicInEntity(detailDics, true, new string[] { name }); + if (reslut != string.Empty) + return WebResponseContent.Instance.Error(reslut); + + List<TDetail> list = detailDics.DicToIEnumerable<TDetail>(); + + ((SqlSugarClient)BaseDal.Db).BeginTran(); + + int id = BaseDal.Db.Insertable(entity).ExecuteReturnIdentity(); + + for (int i = 0; i < list.Count; i++) + { + TDetail detail = list[i]; + typeof(TDetail).SetDetailId(detail, id, name); + } + + BaseDal.Db.Insertable(list).ExecuteCommand(); + + ((SqlSugarClient)BaseDal.Db).CommitTran(); + + content = WebResponseContent.Instance.OK(); + } + catch (Exception ex) + { + ((SqlSugarClient)BaseDal.Db).RollbackTran(); + content = WebResponseContent.Instance.Error(ex.Message); + } + return content; + } + + /// <summary> + /// 淇敼鏁版嵁 + /// </summary> + /// <param name="entity">鍗曚釜瀹炰綋</param> + /// <returns></returns> + public virtual WebResponseContent UpdateData(TEntity entity) + { + try + { + return BaseDal.UpdateData(entity) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + /// <summary> + /// 淇敼鏁版嵁 + /// </summary> + /// <param name="entities">瀹炰綋闆嗗悎</param> + /// <returns></returns> + public virtual WebResponseContent UpdateData(List<TEntity> entities) + { + try + { + return BaseDal.UpdateData(entities) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + /// <summary> + /// 淇敼鏁版嵁 + /// </summary> + /// <param name="saveModel"></param> + /// <returns></returns> + public virtual WebResponseContent UpdateData(SaveModel saveModel) + { + try + { + List<string>? list = UpdateIgnoreColOnExecute?.Invoke(saveModel); + if (saveModel == null || saveModel.MainData == null || saveModel.MainData.Count == 0)//鍒ゆ柇鍙傛暟鏄惁浼犲叆 + { + return WebResponseContent.Instance.Error("浼犲弬閿欒,鍙傛暟涓嶈兘涓虹┖"); + } + string validResult = typeof(TEntity).ValidateDicInEntity(saveModel.MainData, false, TProperties, list?.ToArray()); + + if (!string.IsNullOrEmpty(validResult)) + { + return WebResponseContent.Instance.Error(validResult); + } + + PropertyInfo keyPro = typeof(TEntity).GetKeyProperty(); + if (keyPro == null) + { + return WebResponseContent.Instance.Error("璇峰厛璁剧疆涓婚敭"); + } + + TEntity entity = saveModel.MainData.DicToModel<TEntity>(); + + if (saveModel.DetailData == null || saveModel.DetailData.Count == 0) + { + //if (list != null) + // listCol = listCol.Where(x => !list.Contains(x)).ToList(); + bool result = BaseDal.UpdateData(entity); + return WebResponseContent.Instance.OK(); + } + + if (typeof(TEntity).GetNavigatePro() == null) + { + return WebResponseContent.Instance.Error("鏈厤缃鑸睘鎬�"); + } + + Type detailType = typeof(TEntity).GetDetailType(); + MethodInfo? methodInfo = GetType().GetMethod(nameof(UpdateDataInculdesDetail)); + methodInfo = methodInfo?.MakeGenericMethod(new Type[] { detailType }); + object? obj = methodInfo?.Invoke(this, new object[] { entity, detailType, saveModel.DetailData, saveModel.DelKeys }); + return obj as WebResponseContent; + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + public WebResponseContent UpdateDataInculdesDetail<TDetail>(TEntity entity, Type detailType, List<Dictionary<string, object>> detailDics, List<object> delKeys) where TDetail : class, new() + { + WebResponseContent content = new WebResponseContent(); + try + { + string name = typeof(TEntity).GetMainIdByDetail(); + string reslut = detailType.ValidateDicInEntity(detailDics, true, new string[] { name }); + if (reslut != string.Empty) + return WebResponseContent.Instance.Error(reslut); + + List<TDetail> list = detailDics.DicToIEnumerable<TDetail>(); + + List<object> dynamicDelKeys = new List<object>(); + if (delKeys != null) + { + for (int i = 0; i < delKeys.Count; i++) + { + dynamicDelKeys.Add(delKeys[i]); + } + } + + List<TDetail> updateRows = new List<TDetail>(); + List<TDetail> addRows = new List<TDetail>(); + + for (int i = 0; i < list.Count; i++) + { + object detailId = typeof(TDetail).GetPropertyValue(list[i], typeof(TDetail).GetKeyName()); + if (detailId != null) + { + if (detailId.ToString() != "0") + { + updateRows.Add(list[i]); + } + else + { + addRows.Add(list[i]); + } + } + } + + object mainId = typeof(TEntity).GetPropertyValue(entity, typeof(TEntity).GetKeyName()); + if (mainId != null) + { + ((SqlSugarClient)BaseDal.Db).BeginTran(); + + if (dynamicDelKeys.Count > 0) + BaseDal.Db.Deleteable<object>().AS(detailType.Name).Where($"{detailType.GetKeyName()} in (@id)", new { id = dynamicDelKeys.ToArray() }).ExecuteCommandHasChange(); + + BaseDal.Db.Updateable(entity).ExecuteCommandHasChange(); + + BaseDal.Db.Updateable(updateRows).ExecuteCommand(); + + for (int i = 0; i < addRows.Count; i++) + { + TDetail detail = addRows[i]; + typeof(TDetail).SetDetailId(detail, mainId, name); + } + + BaseDal.Db.Insertable(addRows).ExecuteCommand(); + + ((SqlSugarClient)BaseDal.Db).CommitTran(); + + content = WebResponseContent.Instance.OK(); + } + else + { + content = WebResponseContent.Instance.Error("鏈壘鍒颁富琛ㄤ富閿��"); + } + + } + catch (Exception ex) + { + ((SqlSugarClient)BaseDal.Db).RollbackTran(); + content = WebResponseContent.Instance.Error(ex.Message); + } + return content; + } + + /// <summary> + /// 鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="key">涓婚敭</param> + /// <returns></returns> + public virtual WebResponseContent DeleteData(object key) + { + try + { + return BaseDal.DeleteDataById(key) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + /// <summary> + /// 鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="keys">涓婚敭鏁扮粍</param> + /// <returns></returns> + public virtual WebResponseContent DeleteData(object[] keys) + { + try + { + if (typeof(TEntity).GetNavigatePro() == null) + return BaseDal.DeleteDataByIds(keys) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error(); + else + { + if (keys != null) + { + Type detailType = typeof(TEntity).GetDetailType(); + string name = typeof(TEntity).GetMainIdByDetail(); + List<object> dynamicDelKeys = new List<object>(); + + for (int i = 0; i < keys.Length; i++) + { + dynamicDelKeys.Add(keys[i]); + } + ((SqlSugarClient)BaseDal.Db).BeginTran(); + + if (dynamicDelKeys.Count > 0) + BaseDal.Db.Deleteable<object>().AS(detailType.Name).Where($"{name} in (@id)", new { id = dynamicDelKeys.ToArray() }).ExecuteCommandHasChange(); + + BaseDal.DeleteDataByIds(keys); + + ((SqlSugarClient)BaseDal.Db).CommitTran(); + + return WebResponseContent.Instance.OK(); + } + else + { + return WebResponseContent.Instance.Error("鍙傛暟閿欒"); + } + } + } + catch (Exception ex) + { + ((SqlSugarClient)BaseDal.Db).RollbackTran(); + return WebResponseContent.Instance.Error(ex.Message); + } + } + + /// <summary> + /// 鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="entity">鍗曚釜瀹炰綋</param> + /// <returns></returns> + public virtual WebResponseContent DeleteData(TEntity entity) + { + try + { + return BaseDal.DeleteData(entity) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + /// <summary> + /// 鍒犻櫎鏁版嵁 + /// </summary> + /// <param name="entities">瀹炰綋闆嗗悎</param> + /// <returns></returns> + public virtual WebResponseContent DeleteData(List<TEntity> entities) + { + try + { + return BaseDal.DeleteData(entities) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + /// <summary> + /// 瀵煎嚭鏁版嵁 + /// </summary> + /// <param name="pageData"></param> + /// <returns></returns> + public virtual WebResponseContent Export(PageDataOptions options) + { + WebResponseContent content = new WebResponseContent(); + try + { + Type t = typeof(TEntity); + ISugarQueryable<TEntity> sugarQueryable = Db.Queryable<TEntity>(); + string savePath = AppDomain.CurrentDomain.BaseDirectory + $"ExcelExport"; + IExporter exporter = new ExcelExporter(); + ValidatePageOptions(options, ref sugarQueryable); + //鑾峰彇鎺掑簭瀛楁 + Dictionary<string, OrderByType> orderbyDic = GetPageDataSort(options, TProperties); + + List<TEntity> entities = sugarQueryable.ToList(); + + byte[] data = exporter.ExportAsByteArray(entities).Result; + + string fileName = ""; + SugarTable sugarTable = t.GetCustomAttribute<SugarTable>(); + if (sugarTable != null) + { + fileName = sugarTable.TableDescription + ".xlsx"; + } + else + { + fileName = nameof(TEntity) + ".xlsx"; + } + + FileHelper.WriteFile(savePath, fileName, data); + + content = WebResponseContent.Instance.OK(data: savePath + "\\" + fileName); + } + catch (Exception ex) + { + content = WebResponseContent.Instance.Error(ex.Message); + } + return content; + } + + /// <summary> + /// 瀵煎叆鏁版嵁 + /// </summary> + /// <param name="files"></param> + /// <returns></returns> + public virtual WebResponseContent Import(List<IFormFile> files) + { + try + { + if (files == null || files.Count == 0) + return new WebResponseContent { Status = true, Message = "璇烽�夋嫨涓婁紶鐨勬枃浠�" }; + Microsoft.AspNetCore.Http.IFormFile formFile = files[0]; + string dicPath = AppDomain.CurrentDomain.BaseDirectory + $"ExcelImprot/{DateTime.Now.ToString("yyyMMdd")}/{typeof(TEntity).Name}/"; + if (!Directory.Exists(dicPath)) Directory.CreateDirectory(dicPath); + string fileName = $"{Guid.NewGuid()}_{formFile.FileName}"; + dicPath = $"{dicPath}{fileName}"; + using (FileStream stream = new FileStream(dicPath, FileMode.Create)) + { + formFile.CopyTo(stream); + } + ExcelImporter importer = new ExcelImporter(); + ImportResult<TEntity> importResult = importer.Import<TEntity>(dicPath, "").Result; + if (importResult.HasError) + { + return WebResponseContent.Instance.Error(importResult.TemplateErrors.Serialize()); + } + BaseDal.AddData(importResult.Data.ToList()); + return WebResponseContent.Instance.OK(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + /// <summary> + /// 涓婁紶鏂囦欢 + /// </summary> + /// <param name="files"></param> + /// <returns></returns> + public virtual WebResponseContent Upload(List<IFormFile> files) + { + throw new NotImplementedException(); + } + + /// <summary> + /// 妯℃澘涓嬭浇 + /// </summary> + /// <returns></returns> + public virtual WebResponseContent DownLoadTemplate() + { + WebResponseContent content = new WebResponseContent(); + Type t = typeof(TEntity); + IExporter exporter = new ExcelExporter(); + byte[] data = exporter.ExportHeaderAsByteArray(new TEntity()).Result; + string fileName = ""; + SugarTable sugarTable = t.GetCustomAttribute<SugarTable>(); + if (sugarTable != null) + { + fileName = sugarTable.TableDescription + "瀵煎叆妯℃澘.xlsx"; + } + else + { + fileName = nameof(TEntity) + "瀵煎叆妯℃澘.xlsx"; + } + string savePath = AppDomain.CurrentDomain.BaseDirectory + $"ExcelImprotTemplate"; + FileHelper.WriteFile(savePath, fileName, data); + + content = WebResponseContent.Instance.OK(data: savePath + "\\" + fileName); + return content; + } + + public WebResponseContent ExportSeedData() + { + WebResponseContent content = new WebResponseContent(); + try + { + string seedDataFolder = $"WIDESEA_DB.DBSeed.Json/{typeof(TEntity).Name}.tsv"; + List<TEntity> deviceInfos = BaseDal.QueryData(); + string str = JsonConvert.SerializeObject(deviceInfos, Formatting.Indented); + List<Dictionary<string, object>> keyValuePairs = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(str); + FileHelper.WriteFileAndDelOldFile($"{AppDomain.CurrentDomain.BaseDirectory}wwwroot/{seedDataFolder}", str); + content = WebResponseContent.Instance.OK(); + } + catch (Exception ex) + { + content = WebResponseContent.Instance.Error(ex.Message); + } + return content; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/ServiceFunFilter.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/ServiceFunFilter.cs" new file mode 100644 index 0000000..645355c --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/BaseServices/ServiceFunFilter.cs" @@ -0,0 +1,238 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.BaseServices +{ + public abstract class ServiceFunFilter<T> where T : class + { + /// <summary> + /// 2020.08.15鏄惁寮�鍚绉熸埛鍔熻兘 + /// 浣跨敤鏂规硶瑙佹枃妗f垨SellOrderService.cs + /// </summary> + protected bool IsMultiTenancy { get; set; } + + /// <summary> + /// 鏌ヨ鐣岄潰table 缁熻銆佹眰鍜屻�佸钩鍧囧�肩瓑 + /// 瀹炵幇鏂瑰紡 + ///SummaryExpress = (IQueryable<App_TransactionAvgPrice> queryable) => + // { + // return queryable.GroupBy(x => 1).Select(x => new + // { + // AvgPrice = x.Average(o => o.AvgPrice), + // Enable = x.Sum(o => o.Enable) + // }).FirstOrDefault(); + //}; + /// </summary> + // protected Func<IGrouping<T, T>, object> SummaryExpress = null; + protected Func<IQueryable<T>, object> SummaryExpress = null; + + /// <summary> + /// 鏄庣粏table 缁熻銆佹眰鍜屻�佸钩鍧囧�肩瓑 + /// </summary> + /// <typeparam name="Detail"></typeparam> + /// <param name="queryeable"></param> + /// <returns></returns> + //protected abstract object GetDetailSummary<Detail>(IQueryable<Detail> queryeable); + + /// <summary> + /// 鏄惁寮�鍚敤鎴锋暟鎹潈闄�,true=鐢ㄦ埛鍙兘鎿嶄綔鑷繁(鍙婁笅绾ц鑹�)鍒涘缓鐨勬暟鎹�,濡�:鏌ヨ銆佸垹闄ゃ�佷慨鏀圭瓑鎿嶄綔 + /// 娉ㄦ剰锛氶渶瑕佸湪浠g爜鐢熸垚鍣ㄧ晫闈㈤�夋嫨銆愭槸銆戝強鐢熸垚Model鎵嶄細鐢熸晥) + /// </summary> + protected bool LimitCurrentUserPermission { get; set; } = false; + + ///榛樿瀵煎嚭鏈�澶ц〃鏁伴噺锛�0涓嶉檺鍒� + protected int Limit { get; set; } = 0; + + /// <summary> + /// 榛樿涓婁紶鏂囦欢澶у皬闄愬埗3M + /// </summary> + protected int LimitUpFileSizee { get; set; } = 3; + + + /// <summary> + /// 2020.08.15娣诲姞鑷畾涔夊師鐢熸煡璇ql,杩欎釜瀵逛簬涓嶆兂鍐欒〃杈惧紡鍏宠仈鎴栬�呭鏉傛煡璇㈤潪甯告湁鐢� + /// 渚嬶細QuerySql=$"select * from tb1 as a where a.name='xxxx' x.id in (select b.id from tb2 b)"; + /// select * 杩欓噷鍙互鑷畾涔夛紝浣唖elect 蹇呴』杩斿洖琛ㄦ墍鏈夌殑鍒楋紝涓嶈兘灏� + /// </summary> + protected string QuerySql = null; + + /// <summary> + /// 鏌ヨ鍓�,瀵圭幇鍦ㄦ湁鐨勬煡璇㈠瓧绗︿覆鏉′欢澧炲姞鎴栧垹闄� + /// </summary> + protected Action<List<SearchParameters>> QueryRelativeList { get; set; } + + //鏌ヨ鍓�,鍦ㄧ幇鏈夌殑鏌ヨ鏉′欢涓婇�氳繃琛ㄨ揪寮忎慨鏀规煡璇㈡潯浠� + protected Func<IQueryable<T>, IQueryable<T>> QueryRelativeExpression { get; set; } + + + /// <summary> + /// 鎸囧畾鏌ヨ鐨勫垪锛屾牸寮�:Expression<Func<T, object>> exp = x => new { x.瀛楁1, x.瀛楁2 }(鏆傛椂鏈惎鐢�) + /// </summary> + protected Expression<Func<T, object>> Columns { get; set; } + + /// <summary> + /// 璁剧疆鏌ヨ鎺掑簭鍙傛暟鍙婃柟寮�,鍙傛暟鏍煎紡涓猴細 + /// Expression<Func<T, Dictionary<object, bool>>> orderBy = x => new Dictionary<object, QueryOrderBy>() + /// {{ x.ID, QueryOrderBy.Asc },{ x.DestWarehouseName, QueryOrderBy.Desc } }; + /// 杩斿洖鐨勬槸new Dictionary<object, bool>(){{}}key涓烘帓搴忓瓧娈碉紝QueryOrderBy涓烘帓搴忔柟寮� + /// </summary> + protected Expression<Func<T, Dictionary<object, OrderByType>>> OrderByExpression; + + protected Dictionary<string, OrderByType> OrderByParameters { get; set; } + + protected bool EnableWebOrderBy { get; set; } = true; + + /// <summary> + /// 璁剧疆鏌ヨ鐨勮〃鍚�(宸插純鐢�) + /// </summary> + protected string TableName { get; set; } + + /// <summary> + /// 椤甸潰鏌ヨ鎴栧鍑猴紝浠庢暟鎹簱鏌ヨ鍑烘潵鐨勭粨鏋� + /// </summary> + protected Action<PageGridData<T>> GetPageDataOnExecuted; + + /// <summary> + /// 璋冪敤鏂板缓澶勭悊鍓�(SaveModel涓轰紶鍏ョ殑鍘熺敓鏁版嵁) + /// </summary> + protected Func<SaveModel, WebResponseContent> AddOnExecute; + + /// <summary> + /// 璋冪敤鏂板缓淇濆瓨鏁版嵁搴撳墠澶勭悊(宸插皢鎻愪氦鐨勫師鐢熸暟鎹浆鎹㈡垚浜嗗璞�) + /// Func<T, object,ResponseData> T涓轰富琛ㄦ暟鎹紝object涓烘槑缁嗘暟鎹�(濡傛灉闇�瑕佷娇鐢ㄦ槑缁嗗璞�,璇风敤 object as List<T>杞崲) + /// </summary> + protected Func<T, object, WebResponseContent> AddOnExecuting; + + /// <summary> + /// 璋冪敤鏂板缓淇濆瓨鏁版嵁搴撳悗澶勭悊銆� + /// **瀹炵幇褰撳墠鏂规硶鏃讹紝鍐呴儴榛樿宸茬粡寮�鍚簨鍔★紝濡傛灉瀹炵幇鐨勬柟娉曟搷浣滅殑鏄悓涓�鏁版嵁搴�,鍒欎笉闇�瑕佸湪AddOnExecuted涓簨鍔� + /// Func<T, object,ResponseData> T涓轰富琛ㄦ暟鎹紝object涓烘槑缁嗘暟鎹�(濡傛灉闇�瑕佷娇鐢ㄦ槑缁嗗璞�,璇风敤 object as List<T>杞崲) + /// 姝ゅ宸插紑鍚簡DbContext浜嬪姟(閲嶇偣),濡傛灉杩樻湁鍏朵粬涓氬姟澶勪簨锛岀洿鎺ュ湪杩欓噷鍐橢F浠g爜,涓嶉渶瑕佸啀寮�鍚簨鍔� + /// 濡傛灉鎵ц鐨勬槸鎵嬪啓sql璇风敤repository.DbContext.Database.ExecuteSqlCommand()鎴� repository.DbContext.Set<T>().FromSql鎵ц鍏蜂綋sql璇彞 + /// </summary> + protected Func<T, object, WebResponseContent> AddOnExecuted; + + /// <summary> + /// 杩涘叆瀹℃壒娴佺▼鏂规硶涔嬪墠 + /// </summary> + protected Func<T, bool> AddWorkFlowExecuting; + + /// <summary> + /// 鍐欏叆瀹℃壒娴佺▼鏁版嵁涔嬪悗 + /// list:瀹℃壒鐨勪汉id + /// </summary> + protected Action<T, List<int>> AddWorkFlowExecuted; + + /// <summary> + /// 璋冪敤鏇存柊鏂规硶鍓嶅鐞�(SaveModel涓轰紶鍏ョ殑鍘熺敓鏁版嵁) + /// </summary> + protected Func<SaveModel, WebResponseContent> UpdateOnExecute; + + /// <summary> + /// 璋冪敤鏇存柊鏂规硶鍓嶅鐞�(SaveModel涓轰紶鍏ョ殑鍘熺敓鏁版嵁) + /// </summary> + protected Func<SaveModel, List<string>> UpdateIgnoreColOnExecute; + + /// <summary> + /// 璋冪敤鏇存柊鏂规硶淇濆瓨鏁版嵁搴撳墠澶勭悊 + /// (宸插皢鎻愪氦鐨勫師鐢熸暟鎹浆鎹㈡垚浜嗗璞�,灏嗘槑缁嗘柊澧炪�佷慨鏀广�佸垹闄ょ殑鏁版嵁鍒嗗埆鐢╫bject1/2/3鏍囪瘑鍑烘潵 ) + /// T=鏇存柊鐨勪富琛ㄥ璞� + /// object1=涓烘柊澧炴槑缁嗙殑瀵硅薄锛屼娇鐢ㄦ椂灏唎bject as List<T>杞崲涓�涓� + /// object2=涓烘洿鏂版槑缁嗙殑瀵硅薄 + /// List<object>=涓哄垹闄ょ殑缁嗙殑瀵硅薄Key + /// </summary> + protected Func<T, object, object, List<object>, WebResponseContent> UpdateOnExecuting; + + /// <summary> + /// 璋冪敤鏇存柊鏂规硶淇濆瓨鏁版嵁搴撳悗澶勭悊 + /// **瀹炵幇褰撳墠鏂规硶鏃讹紝鍐呴儴榛樿宸茬粡寮�鍚簨鍔★紝濡傛灉瀹炵幇鐨勬柟娉曟搷浣滅殑鏄悓涓�鏁版嵁搴�,鍒欎笉闇�瑕佸湪UpdateOnExecuted涓簨鍔� + /// (宸插皢鎻愪氦鐨勫師鐢熸暟鎹浆鎹㈡垚浜嗗璞�,灏嗘槑缁嗘柊澧炪�佷慨鏀广�佸垹闄ょ殑鏁版嵁鍒嗗埆鐢╫bject1/2/3鏍囪瘑鍑烘潵 ) + /// T=鏇存柊鐨勪富琛ㄥ璞� + /// object1=涓烘柊澧炴槑缁嗙殑瀵硅薄锛屼娇鐢ㄦ椂灏唎bject as List<T>杞崲涓�涓� + /// object2=涓烘洿鏂版槑缁嗙殑瀵硅薄 + /// List<object>=涓哄垹闄ょ殑缁嗙殑瀵硅薄Key + /// 姝ゅ宸插紑鍚簡DbContext浜嬪姟(閲嶇偣),濡傛灉杩樻湁鍏朵粬涓氬姟澶勪簨锛岀洿鎺ュ湪杩欓噷鍐橢F浠g爜,涓嶉渶瑕佸啀寮�鍚簨鍔� + /// 濡傛灉鎵ц鐨勬槸鎵嬪啓sql璇风敤repository.DbContext.Database.ExecuteSqlCommand()鎴� repository.DbContext.Set<T>().FromSql鎵ц鍏蜂綋sql璇彞 + /// </summary> + protected Func<T, object, object, List<object>, WebResponseContent> UpdateOnExecuted; + + /// <summary> + /// 鍒犻櫎鍓嶅鐞�,object[]鍑嗗鍒犻櫎鐨勪富閿� + /// </summary> + protected Func<object[], WebResponseContent> DelOnExecuting; + + /// <summary> + /// 鍒犻櫎鍚庡鐞�,object[]宸插垹闄ょ殑涓婚敭,姝ゅ宸插紑鍚簡DbContext浜嬪姟(閲嶇偣),濡傛灉杩樻湁鍏朵粬涓氬姟澶勪簨锛岀洿鎺ュ湪杩欓噷鍐橢F浠g爜,涓嶉渶瑕佸啀寮�鍚簨鍔� + /// 濡傛灉鎵ц鐨勬槸鎵嬪啓sql璇风敤repository.DbContext.Database.ExecuteSqlCommand()鎴� repository.DbContext.Set<T>().FromSql鎵ц鍏蜂綋sql璇彞 + /// </summary> + protected Func<object[], WebResponseContent> DelOnExecuted; + + /// <summary> + /// 瀹℃牳鍓嶅鐞� + /// </summary> + protected Func<List<T>, WebResponseContent> AuditOnExecuting; + /// <summary> + /// 瀹℃牳鍚庡鐞� + /// </summary> + protected Func<List<T>, WebResponseContent> AuditOnExecuted; + + + /// <summary> + ///瀵煎嚭鍓嶅鐞�,DataTable瀵煎嚭鐨勮〃鏁版嵁 + ///List<T>瀵煎嚭鐨勬暟鎹�, List<string>蹇界暐涓嶉渶瑕佸鍑虹殑瀛楁 + ///姝ゆ柟娉曚笉寤鸿浣跨敤,鐢变笅闈xportColumns濮旀墭鏇夸唬2020.05.07 + /// </summary> + protected Func<List<T>, List<string>, WebResponseContent> ExportOnExecuting; + + /// <summary> + /// 2020.05.07 + /// 瀵煎嚭琛ㄦ暟鎹�(鐣岄潰涓婂鍑烘搷浣�),鎸囧畾瑕佸鍑虹殑鍒楋紝鏍煎紡:Expression<Func<T, object>> exp = x => new { x.瀛楁1, x.瀛楁2 } + /// </summary> + protected Expression<Func<T, object>> ExportColumns { get; set; } + + + /// <summary> + /// 2020.05.07 + /// 瀵煎嚭涓嬭浇妯℃澘锛屾寚瀹氳瀵煎嚭鐨勬ā鏉垮垪锛屾牸寮�:Expression<Func<T, object>> exp = x => new { x.瀛楁1, x.瀛楁2 } + /// </summary> + protected Expression<Func<T, object>> DownLoadTemplateColumns { get; set; } + + + /// <summary> + /// 瀵煎叆淇濆瓨鍚� + /// </summary> + protected Func<List<T>, WebResponseContent> ImportOnExecuted; + + /// <summary> + /// 瀵煎叆淇濆瓨鍓� + /// </summary> + protected Func<List<T>, WebResponseContent> ImportOnExecuting; + + /// <summary> + /// 瀵煎叆鏃朵笉楠岃瘉涓嬫媺妗嗘暟鎹簮鐨勫瓧娈靛��2023.05.03 + /// </summary> + protected Expression<Func<T, object>> ImportIgnoreSelectValidationColumns; + + /// <summary> + /// 2022.06.20澧炲姞鍘熺敓excel璇诲彇鏂规硶(瀵煎叆鏃跺彲浠ヨ嚜瀹氫箟璇诲彇excel鍐呭) + /// string=褰撳墠璇诲彇鐨別xcel鍗曞厓鏍肩殑鍊� + /// ExcelWorksheet=excel瀵硅薄 + /// ExcelRange褰撳墠excel鍗曞厓鏍煎璞� + /// int=褰撳墠璇诲彇鐨勭鍑犳暟 + /// int=褰撳墠璇诲彇鐨勭鍑犲垪 + /// string=杩斿洖鐨勫�� + /// </summary> + //protected Func<string, ExcelWorksheet, ExcelRange, int, int, string> ImportOnReadCellValue; + + + /// <summary> + /// 鑷畾涔変笂浼犳枃浠跺す(2022.10.07) + /// </summary> + protected string UploadFolder = null; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Caches/ICacheService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Caches/ICacheService.cs" new file mode 100644 index 0000000..58813de --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Caches/ICacheService.cs" @@ -0,0 +1,64 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Caches +{ + public interface ICacheService : IDisposable + { + /// <summary> + /// 楠岃瘉缂撳瓨椤规槸鍚﹀瓨鍦� + /// </summary> + /// <param name="key">缂撳瓨Key</param> + /// <returns></returns> + bool Exists(string key); + + /// <summary> + /// 娣诲姞缂撳瓨 + /// </summary> + /// <param name="key">缂撳瓨Key</param> + /// <param name="value">缂撳瓨Value</param> + /// <param name="expiresIn">缂撳瓨鏃堕暱</param> + /// <param name="isSliding">鏄惁婊戝姩杩囨湡锛堝鏋滃湪杩囨湡鏃堕棿鍐呮湁鎿嶄綔锛屽垯浠ュ綋鍓嶆椂闂寸偣寤堕暱杩囨湡鏃堕棿锛� //new TimeSpan(0, 60, 0);</param> + /// <returns></returns> + bool AddObject(string key, object value, int expireSeconds = -1, bool isSliding = false); + + bool Add(string key, string value, int expireSeconds = -1, bool isSliding = false); + + void AddOrUpdate(string key, string value, int expireSeconds = -1, bool isSliding = false); + + void AddOrUpdate(string key, object value, int expireSeconds = -1, bool isSliding = false); + + /// <summary> + /// 鍒犻櫎缂撳瓨 + /// </summary> + /// <param name="key">缂撳瓨Key</param> + /// <returns></returns> + bool Remove(string key); + + /// <summary> + /// 鎵归噺鍒犻櫎缂撳瓨 + /// </summary> + /// <param name="key">缂撳瓨Key闆嗗悎</param> + /// <returns></returns> + void Remove(IEnumerable<string> keys); + + /// <summary> + /// 鑾峰彇缂撳瓨 + /// </summary> + /// <param name="key">缂撳瓨Key</param> + /// <returns></returns> + T? Get<T>(string key) where T : class; + + object? Get(Type type, string key); + + /// <summary> + /// 鑾峰彇缂撳瓨 + /// </summary> + /// <param name="key">缂撳瓨Key</param> + /// <returns></returns> + string? Get(string key); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Caches/MemoryCacheService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Caches/MemoryCacheService.cs" new file mode 100644 index 0000000..d2cd75d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Caches/MemoryCacheService.cs" @@ -0,0 +1,148 @@ +锘縰sing Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Caches +{ + public class MemoryCacheService : ICacheService + { + protected IMemoryCache _cache; + public MemoryCacheService(IMemoryCache cache) + { + _cache = cache; + + } + + public bool Add(string key, string value, int expireSeconds = -1, bool isSliding = false) + { + return AddObject(key, value, expireSeconds, isSliding); + } + + public bool AddObject(string key, object value, int expireSeconds = -1, bool isSliding = false) + { + if (expireSeconds > 0) + { + _cache.Set(key, + value, + new MemoryCacheEntryOptions() + .SetSlidingExpiration(new TimeSpan(0, 0, expireSeconds)) + ); + } + else + { + _cache.Set(key, value); + } + + return true; + } + + public void AddOrUpdate(string key, string value, int expireSeconds = -1, bool isSliding = false) + { + if (!string.IsNullOrEmpty(Get(key))) + { + Remove(key); + Add(key, value, expireSeconds, isSliding); + } + else + { + Add(key, value, expireSeconds, isSliding); + } + } + + public void AddOrUpdate(string key, object value, int expireSeconds = -1, bool isSliding = false) + { + if (!string.IsNullOrEmpty(Get(key))) + { + Remove(key); + Add(key, value.Serialize(), expireSeconds, isSliding); + } + else + { + Add(key, value.Serialize(), expireSeconds, isSliding); + } + } + + public void Dispose() + { + if (_cache != null) + _cache.Dispose(); + GC.SuppressFinalize(this); + } + + public bool Exists(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + return _cache.Get(key) != null; + } + + public T? Get<T>(string key) where T : class + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + object? value = _cache.Get(key); + if (value == null) + { + throw new ArgumentNullException(nameof(key)); + } + return value as T; + } + + public string? Get(string key) + { + try + { + return _cache.Get(key)?.ToString(); + } + catch + { + return string.Empty; + } + } + + public object? Get(Type type, string key) + { + try + { + object res = _cache.Get(key); + return res == null ? default : JsonConvert.DeserializeObject(res?.ToString() ?? "{}", type); + } + catch + { + return string.Empty; + } + } + + public bool Remove(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + _cache.Remove(key); + + return !Exists(key); + } + + public void Remove(IEnumerable<string> keys) + { + if (keys == null) + { + throw new ArgumentNullException(nameof(keys)); + } + + keys.ToList().ForEach(item => _cache.Remove(item)); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/CodeGenerator/CodeGenertors.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/CodeGenerator/CodeGenertors.cs" new file mode 100644 index 0000000..7c2881b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/CodeGenerator/CodeGenertors.cs" @@ -0,0 +1,411 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; +using WIDESEA_Core.DB; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.CodeGenerator +{ + public class CodeGenertors + { + public static WebResponseContent CreateIRepository(string tableName, string module) + { + try + { + string startName = "WIDESEA"; + + string thisNameSpace = typeof(CodeGenertors).Namespace ?? "WIDESEA_"; + int nameSpaceIndex = thisNameSpace.IndexOf("_"); + + if (nameSpaceIndex > -1) + { + startName = thisNameSpace.Substring(0, nameSpaceIndex); + } + + List<Assembly> assemblies = App.Assemblies.ToList(); + Assembly? assembly = assemblies.FirstOrDefault(x => x.GetName()?.Name?.Contains($"I{module}Repository") ?? false); + if (assembly == null) + { + return WebResponseContent.Instance.Error($"鏈壘鍒扮▼搴忛泦{startName}_I{module}Repository"); + } + + string? nameSpaceFullName = assembly.GetName()?.Name; + if (string.IsNullOrEmpty(nameSpaceFullName)) + { + return WebResponseContent.Instance.Error($"{nameSpaceFullName} not found."); + } + + int index = tableName.IndexOf("_"); + + string tableShortName = tableName; + + if (index > -1) + { + tableShortName = tableName.Substring(index + 1); + } + + string rootPath = App.WebHostEnvironment.WebRootPath; + string templatePath = Path.Combine(rootPath, $"CodeTemplate\\BaseIRepository.txt"); + + if (!File.Exists(templatePath)) + { + return WebResponseContent.Instance.Error($"鏈壘鍒版ā鏉挎枃浠�"); + } + + string template = FileHelper.ReadFile(templatePath); + + string classStr = template.Replace("[TableName]", tableName).Replace("[TableShortName]", tableShortName).Replace("[NameSpace]", nameSpaceFullName).Replace("[StartName]", startName).Replace("[Module]", module); + + int rootPathIndex = App.HostEnvironment.ContentRootPath.LastIndexOf("\\"); + + string rootPaht = App.HostEnvironment.ContentRootPath.Substring(0, rootPathIndex - 1); + + int rootPathIndex2 = rootPaht.LastIndexOf("\\"); + + string projectPath = Path.Combine(rootPaht.Substring(0, rootPathIndex2), nameSpaceFullName); + + string filePath = Path.Combine(projectPath, $"I{tableShortName}Repository.cs"); + + FileHelper.WriteFileAndDelOldFile(filePath, classStr); + + return WebResponseContent.Instance.OK(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + public static WebResponseContent CreateRepository(string tableName, string module) + { + try + { + string startName = "WIDESEA"; + + string thisNameSpace = typeof(CodeGenertors).Namespace ?? "WIDESEA_"; + int nameSpaceIndex = thisNameSpace.IndexOf("_"); + + if (nameSpaceIndex > -1) + { + startName = thisNameSpace.Substring(0, nameSpaceIndex); + } + + List<Assembly> assemblies = App.Assemblies.ToList(); + Assembly? assembly = assemblies.FirstOrDefault(x => (x.GetName()?.Name?.Contains($"{module}Repository") ?? false) && (!x.GetName()?.Name?.Contains($"I{module}Repository") ?? false)); + if (assembly == null) + { + return WebResponseContent.Instance.Error($"鏈壘鍒扮▼搴忛泦{startName}_{module}Repository"); + } + + string? nameSpaceFullName = assembly.GetName()?.Name; + if (string.IsNullOrEmpty(nameSpaceFullName)) + { + return WebResponseContent.Instance.Error($"{nameSpaceFullName} not found."); + } + + int index = tableName.IndexOf("_"); + + string tableShortName = tableName; + + if (index > -1) + { + tableShortName = tableName.Substring(index + 1); + } + + string rootPath = App.WebHostEnvironment.WebRootPath; + string templatePath = Path.Combine(rootPath, $"CodeTemplate\\BaseRepository.txt"); + + if (!File.Exists(templatePath)) + { + return WebResponseContent.Instance.Error($"鏈壘鍒版ā鏉挎枃浠�"); + } + + string template = FileHelper.ReadFile(templatePath); + + string classStr = template.Replace("[TableName]", tableName).Replace("[TableShortName]", tableShortName).Replace("[NameSpace]", nameSpaceFullName).Replace("[StartName]", startName).Replace("[Module]", module); + + int rootPathIndex = App.HostEnvironment.ContentRootPath.LastIndexOf("\\"); + + string rootPaht = App.HostEnvironment.ContentRootPath.Substring(0, rootPathIndex - 1); + + int rootPathIndex2 = rootPaht.LastIndexOf("\\"); + + string projectPath = Path.Combine(rootPaht.Substring(0, rootPathIndex2), nameSpaceFullName); + + string filePath = Path.Combine(projectPath, $"{tableShortName}Repository.cs"); + + FileHelper.WriteFileAndDelOldFile(filePath, classStr); + + return WebResponseContent.Instance.OK(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + public static WebResponseContent CreateIService(string tableName, string module) + { + try + { + string startName = "WIDESEA"; + + string thisNameSpace = typeof(CodeGenertors).Namespace ?? "WIDESEA_"; + int nameSpaceIndex = thisNameSpace.IndexOf("_"); + + if (nameSpaceIndex > -1) + { + startName = thisNameSpace.Substring(0, nameSpaceIndex); + } + + List<Assembly> assemblies = App.Assemblies.ToList(); + Assembly? assembly = assemblies.FirstOrDefault(x => x.GetName()?.Name?.Contains($"I{module}Service") ?? false); + if (assembly == null) + { + return WebResponseContent.Instance.Error($"鏈壘鍒扮▼搴忛泦{startName}_I{module}Service"); + } + + string? nameSpaceFullName = assembly.GetName()?.Name; + if (string.IsNullOrEmpty(nameSpaceFullName)) + { + return WebResponseContent.Instance.Error($"{nameSpaceFullName} not found."); + } + + int index = tableName.IndexOf("_"); + + string tableShortName = tableName; + + if (index > -1) + { + tableShortName = tableName.Substring(index + 1); + } + + string rootPath = App.WebHostEnvironment.WebRootPath; + string templatePath = Path.Combine(rootPath, $"CodeTemplate\\BaseIService.txt"); + + if (!File.Exists(templatePath)) + { + return WebResponseContent.Instance.Error($"鏈壘鍒版ā鏉挎枃浠�"); + } + + string template = FileHelper.ReadFile(templatePath); + + string classStr = template.Replace("[TableName]", tableName).Replace("[TableShortName]", tableShortName).Replace("[NameSpace]", nameSpaceFullName).Replace("[StartName]", startName).Replace("[Module]", module); + + int rootPathIndex = App.HostEnvironment.ContentRootPath.LastIndexOf("\\"); + + string rootPaht = App.HostEnvironment.ContentRootPath.Substring(0, rootPathIndex - 1); + + int rootPathIndex2 = rootPaht.LastIndexOf("\\"); + + string projectPath = Path.Combine(rootPaht.Substring(0, rootPathIndex2), nameSpaceFullName); + + string filePath = Path.Combine(projectPath, $"I{tableShortName}Service.cs"); + + FileHelper.WriteFileAndDelOldFile(filePath, classStr); + + return WebResponseContent.Instance.OK(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + public static WebResponseContent CreateService(string tableName, string module) + { + try + { + string startName = "WIDESEA"; + + string thisNameSpace = typeof(CodeGenertors).Namespace ?? "WIDESEA_"; + int nameSpaceIndex = thisNameSpace.IndexOf("_"); + + if (nameSpaceIndex > -1) + { + startName = thisNameSpace.Substring(0, nameSpaceIndex); + } + + List<Assembly> assemblies = App.Assemblies.ToList(); + Assembly? assembly = assemblies.FirstOrDefault(x => (x.GetName()?.Name?.Contains($"{module}Service") ?? false) && (!x.GetName()?.Name?.Contains($"I{module}Service") ?? false)); + if (assembly == null) + { + return WebResponseContent.Instance.Error($"鏈壘鍒扮▼搴忛泦{startName}_{module}Service"); + } + + string? nameSpaceFullName = assembly.GetName()?.Name; + if (string.IsNullOrEmpty(nameSpaceFullName)) + { + return WebResponseContent.Instance.Error($"{nameSpaceFullName} not found."); + } + + int index = tableName.IndexOf("_"); + + string tableShortName = tableName; + + if (index > -1) + { + tableShortName = tableName.Substring(index + 1); + } + + string rootPath = App.WebHostEnvironment.WebRootPath; + string templatePath = Path.Combine(rootPath, $"CodeTemplate\\BaseService.txt"); + + if (!File.Exists(templatePath)) + { + return WebResponseContent.Instance.Error($"鏈壘鍒版ā鏉挎枃浠�"); + } + + string template = FileHelper.ReadFile(templatePath); + + string classStr = template.Replace("[TableName]", tableName).Replace("[TableShortName]", tableShortName).Replace("[NameSpace]", nameSpaceFullName).Replace("[StartName]", startName).Replace("[Module]", module); + + int rootPathIndex = App.HostEnvironment.ContentRootPath.LastIndexOf("\\"); + + string rootPaht = App.HostEnvironment.ContentRootPath.Substring(0, rootPathIndex - 1); + + int rootPathIndex2 = rootPaht.LastIndexOf("\\"); + + string projectPath = Path.Combine(rootPaht.Substring(0, rootPathIndex2), nameSpaceFullName); + + string filePath = Path.Combine(projectPath, $"{tableShortName}Service.cs"); + + FileHelper.WriteFileAndDelOldFile(filePath, classStr); + + return WebResponseContent.Instance.OK(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + public static WebResponseContent CreateController(string tableName, string module) + { + try + { + string startName = "WIDESEA"; + + string thisNameSpace = typeof(CodeGenertors).Namespace ?? "WIDESEA_"; + int nameSpaceIndex = thisNameSpace.IndexOf("_"); + + if (nameSpaceIndex > -1) + { + startName = thisNameSpace.Substring(0, nameSpaceIndex); + } + + List<Assembly> assemblies = App.Assemblies.ToList(); + Assembly? assembly = assemblies.FirstOrDefault(x => (x.GetName()?.Name?.Contains($"{module}Service") ?? false) && (!x.GetName()?.Name?.Contains($"I{module}Service") ?? false)); + if (assembly == null) + { + return WebResponseContent.Instance.Error($"鏈壘鍒扮▼搴忛泦{startName}_{module}Service"); + } + + string? nameSpaceFullName = assembly.GetName()?.Name; + if (string.IsNullOrEmpty(nameSpaceFullName)) + { + return WebResponseContent.Instance.Error($"{nameSpaceFullName} not found."); + } + + int index = tableName.IndexOf("_"); + + string tableShortName = tableName; + + if (index > -1) + { + tableShortName = tableName.Substring(index + 1); + } + + string rootPath = App.WebHostEnvironment.WebRootPath; + string templatePath = Path.Combine(rootPath, $"CodeTemplate\\BaseController.txt"); + + if (!File.Exists(templatePath)) + { + return WebResponseContent.Instance.Error($"鏈壘鍒版ā鏉挎枃浠�"); + } + + string template = FileHelper.ReadFile(templatePath); + + string classStr = template.Replace("[TableName]", tableName).Replace("[TableShortName]", tableShortName).Replace("[NameSpace]", nameSpaceFullName).Replace("[StartName]", startName).Replace("[Module]", module); + + string projectPath = Path.Combine(App.HostEnvironment.ContentRootPath , $"Controllers\\{module}"); + + string filePath = Path.Combine(projectPath, $"{tableShortName}Controller.cs"); + + FileHelper.WriteFileAndDelOldFile(filePath, classStr); + + return WebResponseContent.Instance.OK(); + } + catch (Exception ex) + { + return WebResponseContent.Instance.Error(ex.Message); + } + } + + //public WebResponseContent CreateVuePage(string tableName, string module) + //{ + // try + // { + // string startName = "WIDESEA"; + + // string thisNameSpace = typeof(CodeGenertors).Namespace ?? "WIDESEA_"; + // int nameSpaceIndex = thisNameSpace.IndexOf("_"); + + // if (nameSpaceIndex > -1) + // { + // startName = thisNameSpace.Substring(0, nameSpaceIndex); + // } + + // List<Assembly> assemblies = App.Assemblies.ToList(); + // Assembly? assembly = assemblies.FirstOrDefault(x => (x.GetName()?.Name?.Contains($"{module}Service") ?? false) && (!x.GetName()?.Name?.Contains($"I{module}Service") ?? false)); + // if (assembly == null) + // { + // return WebResponseContent.Instance.Error($"鏈壘鍒扮▼搴忛泦{startName}_{module}Service"); + // } + + // string? nameSpaceFullName = assembly.GetName()?.Name; + // if (string.IsNullOrEmpty(nameSpaceFullName)) + // { + // return WebResponseContent.Instance.Error($"{nameSpaceFullName} not found."); + // } + + // int index = tableName.IndexOf("_"); + + // string tableShortName = tableName; + + // if (index > -1) + // { + // tableShortName = tableName.Substring(index + 1); + // } + + // string rootPath = App.WebHostEnvironment.WebRootPath; + // string templatePath = Path.Combine(rootPath, $"CodeTemplate\\BaseController.txt"); + + // if (!File.Exists(templatePath)) + // { + // return WebResponseContent.Instance.Error($"鏈壘鍒版ā鏉挎枃浠�"); + // } + + // string template = FileHelper.ReadFile(templatePath); + + // string classStr = template.Replace("[TableName]", tableName).Replace("[TableShortName]", tableShortName).Replace("[NameSpace]", nameSpaceFullName).Replace("[StartName]", startName).Replace("[Module]", module); + + // string projectPath = Path.Combine(App.HostEnvironment.ContentRootPath, $"Controllers\\{module}"); + + // string filePath = Path.Combine(projectPath, $"{tableShortName}Controller.cs"); + + // FileHelper.WriteFileAndDelOldFile(filePath, classStr); + + // return WebResponseContent.Instance.OK(); + // } + // catch (Exception ex) + // { + // return WebResponseContent.Instance.Error(ex.Message); + // } + //} + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/AppSecret.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/AppSecret.cs" new file mode 100644 index 0000000..8760498 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/AppSecret.cs" @@ -0,0 +1,29 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Const +{ + /// <summary> + /// 绉橀挜閰嶇疆 + /// </summary> + public struct AppSecret + { + public const string JWT = "BB3647441FFA4B5DB4E64A29B53CE525"; + + public const string Audience = "WIDESEA_WMS"; + + public const string Issuer = "WIDESEA_WMS_Owner"; + + public const string TokenHeaderName = "Authorization"; + + public const string User = "C5ABA9E202D94C43A3CA66002BF77FAF"; + + public const string DB = "3F8B7B38AD3D484A89ACA513CBD79F36"; + + //杩炴帴瀛楃涓� + //Data Source=.;Initial Catalog=WIDESEA_DB_2;User ID=sa;Password=P@ssw0rd;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/CacheConst.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/CacheConst.cs" new file mode 100644 index 0000000..841d5d2 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/CacheConst.cs" @@ -0,0 +1,94 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Const +{ + /// <summary> + /// 缂撳瓨鐩稿叧甯搁噺 + /// </summary> + public class CacheConst + { + /// <summary> + /// 鐢ㄦ埛缂撳瓨 + /// </summary> + public const string KeyUser = "user:"; + + /// <summary> + /// 鐢ㄦ埛閮ㄩ棬缂撳瓨 + /// </summary> + public const string KeyUserDepart = "userDepart:"; + + /// <summary> + /// 鑿滃崟缂撳瓨 + /// </summary> + public const string KeyMenu = "menu:"; + + /// <summary> + /// 鑿滃崟 + /// </summary> + public const string KeyPermissions = "permissions"; + + /// <summary> + /// 鏉冮檺缂撳瓨 + /// </summary> + public const string KeyPermission = "permission:"; + + /// <summary> + /// 鎺ュ彛璺敱 + /// </summary> + public const string KeyModules = "modules"; + + /// <summary> + /// 绯荤粺閰嶇疆 + /// </summary> + public const string KeySystemConfig = "sysConfig"; + + /// <summary> + /// 鏌ヨ杩囨护鍣ㄧ紦瀛� + /// </summary> + public const string KeyQueryFilter = "queryFilter:"; + + /// <summary> + /// 鏈烘瀯Id闆嗗悎缂撳瓨 + /// </summary> + public const string KeyOrgIdList = "org:"; + + /// <summary> + /// 鏈�澶ц鑹叉暟鎹寖鍥寸紦瀛� + /// </summary> + public const string KeyMaxDataScopeType = "maxDataScopeType:"; + + /// <summary> + /// 楠岃瘉鐮佺紦瀛� + /// </summary> + public const string KeyVerCode = "verCode:"; + + /// <summary> + /// 鎵�鏈夌紦瀛樺叧閿瓧闆嗗悎 + /// </summary> + public const string KeyAll = "keys"; + + /// <summary> + /// 瀹氭椂浠诲姟缂撳瓨 + /// </summary> + public const string KeyTimer = "timer:"; + + /// <summary> + /// 鍦ㄧ嚎鐢ㄦ埛缂撳瓨 + /// </summary> + public const string KeyOnlineUser = "onlineuser:"; + + /// <summary> + /// 甯搁噺涓嬫媺妗� + /// </summary> + public const string KeyConstSelector = "selector:"; + + /// <summary> + /// swagger鐧诲綍缂撳瓨 + /// </summary> + public const string SwaggerLogin = "swaggerLogin:"; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/ErrorMsgConst.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/ErrorMsgConst.cs" new file mode 100644 index 0000000..3456c44 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/ErrorMsgConst.cs" @@ -0,0 +1,15 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Const +{ + public class ErrorMsgConst + { + public const string ParamIsNull = "鍙傛暟鏃犳晥"; + public const string EntityValueIsNull = "涓哄繀椤绘彁浜ら」"; + public const string SugarColumnIsNull = "璇烽厤缃甋ugarColumn灞炴��"; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/HtmlElementType.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/HtmlElementType.cs" new file mode 100644 index 0000000..7b30b9e --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/HtmlElementType.cs" @@ -0,0 +1,32 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Const +{ + public struct HtmlElementType + { + public const string drop = "drop"; + public const string droplist = "droplist"; + public const string select = "select"; + public const string selectlist = "selectlist"; + public const string checkbox = "checkbox"; + public const string textarea = "textarea"; + public const string thanorequal = "thanorequal"; + public const string lessorequal = "lessorequal"; + + + public const string gt = "gt"; + public const string lt = "lt"; + public const string GT = ">"; + public const string LT = "<"; + public const string like = "like"; + + public const string ThanOrEqual = ">="; + public const string LessOrEqual = "<="; + public const string Contains = "in"; + public const string Equal = "="; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/SqlDbTypeName.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/SqlDbTypeName.cs" new file mode 100644 index 0000000..b12f10d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/SqlDbTypeName.cs" @@ -0,0 +1,29 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Const +{ + public struct SqlDbTypeName + { + public const string NVarChar = "nvarchar"; + public const string VarChar = "varchar"; + public const string NChar = "nchar"; + public const string Char = "char"; + public const string Text = "text"; + public const string Int = "int"; + public const string BigInt = "bigint"; + public const string DateTime = "datetime"; + public const string Date = "date"; + public const string SmallDateTime = "smalldatetime"; + public const string SmallDate = "smalldate"; + public const string Float = "float"; + public const string Decimal = "decimal"; + public const string Double = "double"; + public const string Bit = "bit"; + public const string Bool = "bool"; + public const string UniqueIdentifier = "uniqueidentifier"; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/TenantConst.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/TenantConst.cs" new file mode 100644 index 0000000..ac05532 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/TenantConst.cs" @@ -0,0 +1,13 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Const +{ + public class TenantConst + { + public const string DBConStr = "Data Source={0};Initial Catalog={1};User ID={2};Password={3};Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/TenantStatus.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/TenantStatus.cs" new file mode 100644 index 0000000..581b035 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Const/TenantStatus.cs" @@ -0,0 +1,14 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Const +{ + public struct TenantStatus + { + public const int Enable = 1; + public const int Disable = 2; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/ConfigurableOptions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/ConfigurableOptions.cs" new file mode 100644 index 0000000..a313a78 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/ConfigurableOptions.cs" @@ -0,0 +1,66 @@ +锘縰sing Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Core +{ + public static class ConfigurableOptions + { + /// <summary>娣诲姞閫夐」閰嶇疆</summary> + /// <typeparam name="TOptions">閫夐」绫诲瀷</typeparam> + /// <param name="services">鏈嶅姟闆嗗悎</param> + /// <returns>鏈嶅姟闆嗗悎</returns> + public static IServiceCollection AddConfigurableOptions<TOptions>(this IServiceCollection services) + where TOptions : class, IConfigurableOptions + { + Type optionsType = typeof(TOptions); + string path = GetConfigurationPath(optionsType); + services.Configure<TOptions>(App.Configuration.GetSection(path)); + + return services; + } + + public static IServiceCollection AddConfigurableOptions(this IServiceCollection services, Type type) + { + string path = GetConfigurationPath(type); + var config = App.Configuration.GetSection(path); + + Type iOptionsChangeTokenSource = typeof(IOptionsChangeTokenSource<>); + Type iConfigureOptions = typeof(IConfigureOptions<>); + Type configurationChangeTokenSource = typeof(ConfigurationChangeTokenSource<>); + Type namedConfigureFromConfigurationOptions = typeof(NamedConfigureFromConfigurationOptions<>); + iOptionsChangeTokenSource = iOptionsChangeTokenSource.MakeGenericType(type); + iConfigureOptions = iConfigureOptions.MakeGenericType(type); + configurationChangeTokenSource = configurationChangeTokenSource.MakeGenericType(type); + namedConfigureFromConfigurationOptions = namedConfigureFromConfigurationOptions.MakeGenericType(type); + + services.AddOptions(); + services.AddSingleton(iOptionsChangeTokenSource, + Activator.CreateInstance(configurationChangeTokenSource, Options.DefaultName, config) ?? throw new InvalidOperationException()); + return services.AddSingleton(iConfigureOptions, + Activator.CreateInstance(namedConfigureFromConfigurationOptions, Options.DefaultName, config) ?? throw new InvalidOperationException()); + } + + /// <summary>鑾峰彇閰嶇疆璺緞</summary> + /// <param name="optionsType">閫夐」绫诲瀷</param> + /// <returns></returns> + public static string GetConfigurationPath(Type optionsType) + { + var endPath = new[] { "Option", "Options" }; + var configurationPath = optionsType.Name; + foreach (var s in endPath) + { + if (configurationPath.EndsWith(s)) + { + return configurationPath[..^s.Length]; + } + } + + return configurationPath; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/IConfigurableOptions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/IConfigurableOptions.cs" new file mode 100644 index 0000000..a891834 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/IConfigurableOptions.cs" @@ -0,0 +1,12 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Core +{ + public interface IConfigurableOptions + { + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/InternalApp.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/InternalApp.cs" new file mode 100644 index 0000000..5dfff8e --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Core/InternalApp.cs" @@ -0,0 +1,47 @@ +锘縰sing Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Core +{ + public static class InternalApp + { + internal static IServiceCollection InternalServices; + + /// <summary>鏍规湇鍔�</summary> + internal static IServiceProvider RootServices; + + /// <summary>鑾峰彇Web涓绘満鐜</summary> + internal static IWebHostEnvironment WebHostEnvironment; + + /// <summary>鑾峰彇娉涘瀷涓绘満鐜</summary> + internal static IHostEnvironment HostEnvironment; + + /// <summary>閰嶇疆瀵硅薄</summary> + internal static IConfiguration Configuration; + + public static void ConfigureApplication(this WebApplicationBuilder wab) + { + HostEnvironment = wab.Environment; + WebHostEnvironment = wab.Environment; + InternalServices = wab.Services; + } + + public static void ConfigureApplication(this IConfiguration configuration) + { + Configuration = configuration; + } + + public static void ConfigureApplication(this IHost app) + { + RootServices = app.Services; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/BaseDBConfig.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/BaseDBConfig.cs" new file mode 100644 index 0000000..e049d7a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/BaseDBConfig.cs" @@ -0,0 +1,122 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Const; +using WIDESEA_Core.Helper; +using WIDESEA_Core.Seed; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Core.DB +{ + public class BaseDBConfig + { + /* 涔嬪墠鐨勫崟搴撴搷浣滃凡缁忓垹闄わ紝濡傛灉鎯宠涔嬪墠鐨勪唬鐮侊紝鍙互鏌ョ湅鎴戠殑GitHub鐨勫巻鍙茶褰� + * 鐩墠鏄搴撴搷浣滐紝榛樿鍔犺浇鐨勬槸appsettings.json璁剧疆涓簍rue鐨勭涓�涓猟b杩炴帴銆� + */ + public static List<MutiDBOperate> MutiConnectionString => MutiInitConn(); + + private static string DifDBConnOfSecurity(params string[] conn) + { + foreach (var item in conn) + { + try + { + if (File.Exists(item)) + { + return File.ReadAllText(item).Trim(); + } + } + catch (System.Exception) + { + } + } + + return conn[conn.Length - 1]; + } + + public static List<MutiDBOperate> MutiInitConn() + { + SqlSugarClient sqlSugarClient = new SqlSugarClient(new ConnectionConfig + { + ConfigId = MainDb.CurrentDbConnId, + ConnectionString = AppSettings.Get(MainDb.ConnectionString).DecryptDES(AppSecret.DB), + IsAutoCloseConnection = true, + DbType = DBContext.DbType, + AopEvents = new AopEvents + { + OnError = x => + { + Console.WriteLine(x.Sql); + } + } + }); + + List<ExpandoObject> list = sqlSugarClient.Queryable(MainDb.TenantTableName, "x").Where(MainDb.TenantStatus, "=", TenantStatus.Enable).Select(TenantUtil.GetTenantSelectModels()).ToList(); + List<MutiDBOperate> listdatabaseSlaveDB = new List<MutiDBOperate>(); + MutiDBOperate mainDb = new MutiDBOperate() + { + Connection = AppSettings.Get(MainDb.ConnectionString).DecryptDES(AppSecret.DB), + ConnId = MainDb.CurrentDbConnId, + DbType = DBContext.DbType + }; + listdatabaseSlaveDB.Add(mainDb); + for (int i = 0; i < list.Count; i++) + { + dynamic data = list[i]; + MutiDBOperate mutiDBOperate = new MutiDBOperate() + { + Connection = data.ConnectionString, + ConnId = data.TenantId + "", + DbType = data.DbType, + }; + mutiDBOperate.Connection = mutiDBOperate.Connection.DecryptDES(AppSecret.DB); + listdatabaseSlaveDB.Add(mutiDBOperate); + } + + return listdatabaseSlaveDB; + } + } + + public enum DataBaseType + { + MySql = 0, + SqlServer = 1, + Sqlite = 2, + Oracle = 3, + PostgreSQL = 4, + Dm = 5, + Kdbndp = 6, + } + + public class MutiDBOperate + { + /// <summary> + /// 杩炴帴鍚敤寮�鍏� + /// </summary> + public bool Enabled { get; set; } + + /// <summary> + /// 杩炴帴ID + /// </summary> + public string ConnId { get; set; } + + /// <summary> + /// 浠庡簱鎵ц绾у埆锛岃秺澶ц秺鍏堟墽琛� + /// </summary> + public int HitRate { get; set; } + + /// <summary> + /// 杩炴帴瀛楃涓� + /// </summary> + public string Connection { get; set; } + + /// <summary> + /// 鏁版嵁搴撶被鍨� + /// </summary> + public DbType DbType { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/MainDb.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/MainDb.cs" new file mode 100644 index 0000000..567cb25 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/MainDb.cs" @@ -0,0 +1,27 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.DB +{ + public static class MainDb + { + public const string CurrentDbConnId = "WIDESEA"; + public const string ConnectionStringsEncryption = "ConnectionStringsEncryption"; + public const string ConnectionString = "ConnectionString"; + public const string TenantTableName = "Sys_Tenant"; + public const string TenantStatus = "Status"; + public const string TenantId = "TenantId"; + public const string TenantName = "TenantName"; + public const string EntityNameSpace = "WIDESEA_Model.Models"; + public const string TenantDbType = "DbType"; + public const string AssemblyName = "WIDESEA_Model.dll"; + public const string UserTableName = "Sys_User"; + public const string RoleId = "Role_Id"; + public const string UserName = "UserName"; + public const string UserId = "User_Id"; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/Models/BaseEntity.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/Models/BaseEntity.cs" new file mode 100644 index 0000000..73ba606 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/Models/BaseEntity.cs" @@ -0,0 +1,82 @@ +锘縰sing Magicodes.ExporterAndImporter.Core; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.DB.Models +{ + public class BaseEntity + { + #region 鏁版嵁鐘舵�佺鐞� + + /// <summary> + /// 鐘舵�� <br/> + /// 涓珛瀛楁锛屾煇浜涜〃鍙娇鐢ㄦ煇浜涜〃涓嶄娇鐢� + /// </summary> + //public bool Enabled { get; set; } = true; + + /// <summary> + /// 涓珛瀛楁锛屾煇浜涜〃鍙娇鐢ㄦ煇浜涜〃涓嶄娇鐢� <br/> + /// 閫昏緫涓婄殑鍒犻櫎锛岄潪鐗╃悊鍒犻櫎 <br/> + /// 渚嬪锛氬崟鎹垹闄ゅ苟闈炵洿鎺ュ垹闄� + /// </summary> + //public bool IsDeleted { get; set; } + + /// <summary> + /// 涓珛瀛楁 <br/> + /// 鏄惁鍐呯疆鏁版嵁 + /// </summary> + //public bool IsInternal { get; set; } + + #endregion + + #region 鍒涘缓 + + /// <summary> + /// 鍒涘缓鑰� + /// </summary> + [ImporterHeader(IsIgnore = true)] + [ExporterHeader(DisplayName = "鍒涘缓鑰�")] + [SugarColumn(IsNullable = false, Length = 50, IsOnlyIgnoreUpdate = true, ColumnDescription = "鍒涘缓鑰�")] + public string Creater { get; set; } + + /// <summary> + /// 鍒涘缓鏃堕棿 + /// </summary> + [ImporterHeader(IsIgnore = true)] + [ExporterHeader(DisplayName = "鍒涘缓鏃堕棿")] + [SugarColumn(IsNullable = false, IsOnlyIgnoreUpdate = true, ColumnDescription = "鍒涘缓鏃堕棿")] + public DateTime CreateDate { get; set; } = DateTime.Now; + + #endregion + + #region 淇敼 + + /// <summary> + /// 鏇存柊鑰� + /// </summary> + [ImporterHeader(IsIgnore = true)] + [ExporterHeader(DisplayName = "淇敼浜�")] + [SugarColumn(IsNullable = true, Length = 50, IsOnlyIgnoreInsert = true, ColumnDescription = "淇敼浜�")] + public string Modifier { get; set; } + + /// <summary> + /// 淇敼鏃ユ湡 + /// </summary> + [ImporterHeader(IsIgnore = true)] + [ExporterHeader(DisplayName = "淇敼鏃ユ湡")] + [SugarColumn(IsNullable = true, IsOnlyIgnoreInsert = true, ColumnDescription = "淇敼鏃ユ湡")] + public DateTime? ModifyDate { get; set; } + + /// <summary> + /// 鏁版嵁鐗堟湰 + /// </summary> + //[SugarColumn(DefaultValue = "0", IsEnableUpdateVersionValidation = true)] //鏍囪瘑鐗堟湰瀛楁 + //public long Version { get; set; } + + #endregion + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/Models/IBaseHistoryEntity.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/Models/IBaseHistoryEntity.cs" new file mode 100644 index 0000000..a5b560f --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/Models/IBaseHistoryEntity.cs" @@ -0,0 +1,37 @@ +锘縰sing Magicodes.ExporterAndImporter.Core; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.DB.Models +{ + public interface IBaseHistoryEntity + { + /// <summary> + /// 鍘熻〃涓婚敭 + /// </summary> + [ImporterHeader(Name = "鍘熻〃涓婚敭")] + [ExporterHeader(DisplayName = "鍘熻〃涓婚敭")] + [SugarColumn(IsNullable = false, DefaultValue = "0", ColumnDescription = "鍘熻〃涓婚敭")] + public int SourceId { get; set; } + + /// <summary> + /// 鎿嶄綔绫诲瀷 + /// </summary> + [ImporterHeader(Name = "鎿嶄綔绫诲瀷")] + [ExporterHeader(DisplayName = "鎿嶄綔绫诲瀷")] + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "鎿嶄綔绫诲瀷")] + public string OperateType { get; set; } + + /// <summary> + /// 绉诲叆鍘嗗彶鏃堕棿 + /// </summary> + [ImporterHeader(Name = "绉诲叆鍘嗗彶鏃堕棿")] + [ExporterHeader(DisplayName = "绉诲叆鍘嗗彶鏃堕棿")] + [SugarColumn(IsNullable = false, ColumnDescription = "绉诲叆鍘嗗彶鏃堕棿")] + public DateTime InsertTime { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/RepositorySetting.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/RepositorySetting.cs" new file mode 100644 index 0000000..67c4968 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/DB/RepositorySetting.cs" @@ -0,0 +1,53 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Core.DB +{ + public class RepositorySetting + { + private static readonly Lazy<IEnumerable<Type>> AllEntitys = new(() => + { + var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory; + var referencedAssemblies = System.IO.Directory.GetFiles(path, MainDb.AssemblyName).Select(Assembly.LoadFrom).FirstOrDefault(); + return referencedAssemblies + .GetTypes() + .Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(BaseEntity))) + .Where(it => it.FullName != null && it.FullName.StartsWith(MainDb.EntityNameSpace)); + }); + + public static IEnumerable<Type> Entitys => AllEntitys.Value; + + /// <summary> + /// 閰嶇疆瀹炰綋杞垹闄よ繃婊ゅ櫒<br/> + /// 缁熶竴杩囨护 杞垹闄� 鏃犻渶鑷繁鍐欐潯浠� + /// </summary> + public static void SetDeletedEntityFilter(SqlSugarScopeProvider db) + { + //db.QueryFilter.AddTableFilter<IDeleteFilter>(it => it.IsDeleted == false); + } + + /// <summary> + /// 閰嶇疆绉熸埛 + /// </summary> + public static void SetTenantEntityFilter(SqlSugarScopeProvider db) + { + if (App.User is not { UserId: > 0, TenantId: > 0 }) + { + return; + } + + //澶氱鎴� 鍗曡〃 + //db.QueryFilter.AddTableFilter<ITenantEntity>(it => it.TenantId == App.User.TenantId || it.TenantId == 0); + + //澶氱鎴� 澶氳〃 + //db.SetTenantTable(App.User.TenantId.ToString()); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/EnumHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/EnumHelper.cs" new file mode 100644 index 0000000..8c7094a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/EnumHelper.cs" @@ -0,0 +1,118 @@ +锘縰sing System.ComponentModel; +using System.Reflection; + +namespace WIDESEA_Core.Enums +{ + public static class EnumHelper + { + /// <summary> + /// 鏋氫妇杞瓧鍏搁泦鍚� + /// </summary> + /// <typeparam name="T">鏋氫妇绫诲悕绉�</typeparam> + /// <param name="keyDefault">榛樿key鍊�</param> + /// <param name="valueDefault">榛樿value鍊�</param> + /// <returns>杩斿洖鐢熸垚鐨勫瓧鍏搁泦鍚�</returns> + public static Dictionary<string, object> EnumListDic<T>(string keyDefault, string valueDefault = "") + { + Dictionary<string, object> dicEnum = new Dictionary<string, object>(); + Type enumType = typeof(T); + if (!enumType.IsEnum) + { + return dicEnum; + } + if (!string.IsNullOrEmpty(keyDefault)) //鍒ゆ柇鏄惁娣诲姞榛樿閫夐」 + { + dicEnum.Add(keyDefault, valueDefault); + } + string[] fieldstrs = Enum.GetNames(enumType); //鑾峰彇鏋氫妇瀛楁鏁扮粍 + foreach (var item in fieldstrs) + { + string description = string.Empty; + var field = enumType.GetField(item); + object[] arr = field.GetCustomAttributes(typeof(DescriptionAttribute), true); //鑾峰彇灞炴�у瓧娈垫暟缁� + if (arr != null && arr.Length > 0) + { + description = ((DescriptionAttribute)arr[0]).Description; //灞炴�ф弿杩� + } + else + { + description = item; //鎻忚堪涓嶅瓨鍦ㄥ彇瀛楁鍚嶇О + } + dicEnum.Add(description, (int)Enum.Parse(enumType, item)); //涓嶇敤鏋氫妇鐨剉alue鍊间綔涓哄瓧鍏竗ey鍊肩殑鍘熷洜浠庢灇涓句緥瀛愯兘鐪嬪嚭鏉ワ紝鍏跺疄杩欒竟搴旇鍒ゆ柇浠栫殑鍊间笉瀛樺湪锛岄粯璁ゅ彇瀛楁鍚嶇О + } + return dicEnum; + } + /// <summary> + /// 鑾峰彇鏋氫妇椤规弿杩颁俊鎭� 渚嬪GetEnumDesc(Days.Sunday) + /// </summary> + /// <param name="en">鏋氫妇椤� 濡侱ays.Sunday</param> + /// <returns></returns> + public static string GetIntegralRuleTypeEnumDesc(this Enum en) + { + Type type = en.GetType(); + MemberInfo[] memInfo = type.GetMember(en.ToString()); + if (memInfo != null && memInfo.Length > 0) + { + object[] attrs = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false); + if (attrs != null && attrs.Length > 0) + return ((DescriptionAttribute)attrs[0]).Description; + } + return en.ToString(); + } + /// <summary> + /// 鑾峰彇鏋氫妇闆嗗悎 + /// </summary> + /// <typeparam name="T">鏋氫妇绫诲悕绉�</typeparam> + /// <returns></returns> + public static IEnumerable<EnumModel> GetEnumList<T>() + { + var model = default(T); + FieldInfo[] fieldinfo = typeof(T).GetFields(); + List<EnumModel> result = new List<EnumModel>(); + foreach (FieldInfo field in fieldinfo) + { + EnumModel enumModel = new EnumModel(); + if (!(Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute)) + { + enumModel.Desc = field.GetValue(model).ToString(); + } + else + { + enumModel.Desc = attribute.Description; + } + enumModel.Value = field.GetValue(model).GetHashCode(); + enumModel.Key = field.GetValue(model) as ValueType; + if (field.GetValue(model).ToString() != "0") + { + result.Add(enumModel); + } + + } + return result; + } + + public static int GetEnumMaxValue(this Enum @enum) + { + Type type = @enum.GetType(); + MemberInfo[] memInfo = type.GetMember(@enum.ToString()); + return 0; + } + } + + public class EnumModel + { + /// <summary> + /// Enum鐨勫�� + /// </summary> + public int Value { get; set; } + /// <summary> + /// Enum鐨刱ey + /// </summary> + public ValueType Key { get; set; } + /// <summary> + /// Enum鎻忚堪 + /// </summary> + public string Desc { get; set; } + } + +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/LinqExpressionType.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/LinqExpressionType.cs" new file mode 100644 index 0000000..cd90b5a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/LinqExpressionType.cs" @@ -0,0 +1,21 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Enums +{ + public enum LinqExpressionType + { + Equal = 0,//= + NotEqual = 1,//!= + GreaterThan,//> + LessThan,//< + ThanOrEqual,//>= + LessThanOrEqual,//<= + In, + Contains,//Contains + NotContains//NotContains + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/OperateTypeEnum.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/OperateTypeEnum.cs" new file mode 100644 index 0000000..23647b6 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/OperateTypeEnum.cs" @@ -0,0 +1,20 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Enums +{ + public enum OperateTypeEnum + { + 浜哄伐鍒犻櫎 = 1, + 鑷姩鍒犻櫎 = 2, + 浜哄伐鎭㈠ = 3, + 鑷姩鎭㈠ = 4, + 浜哄伐瀹屾垚 = 5, + 鑷姩瀹屾垚 = 6, + 鍏抽棴 = 7, + 鍏朵粬 = 99 + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/RouterInOutType.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/RouterInOutType.cs" new file mode 100644 index 0000000..e866bd0 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Enums/RouterInOutType.cs" @@ -0,0 +1,24 @@ +锘縰sing System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Enums +{ + public enum RouterInOutType + { + /// <summary> + /// 鍏ュ簱璺敱 + /// </summary> + [Description("鍏ュ簱璺敱")] + In = 1, + + /// <summary> + /// 鍑哄簱璺敱 + /// </summary> + [Description("鍑哄簱璺敱")] + Out = 2, + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/AllOptionRegister.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/AllOptionRegister.cs" new file mode 100644 index 0000000..faf8fd1 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/AllOptionRegister.cs" @@ -0,0 +1,29 @@ +锘縰sing Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Core; + +namespace WIDESEA_Core.Extensions +{ + public static class AllOptionRegister + { + /// <summary> + /// 娉ㄥ唽鎵�鏈夊疄鐜颁簡 IConfigurableOptions 鎺ュ彛鐨勫彲閰嶇疆閫夐」 + /// </summary> + /// <param name="services">鏈嶅姟闆嗗悎</param> + /// <exception cref="ArgumentNullException">褰� services 涓� null 鏃舵姏鍑�</exception> + public static void AddAllOptionRegister(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + foreach (var optionType in App.EffectiveTypes.Where(s => + !s.IsInterface && typeof(IConfigurableOptions).IsAssignableFrom(s))) + { + services.AddConfigurableOptions(optionType); + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/ApplicationSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/ApplicationSetup.cs" new file mode 100644 index 0000000..c44a549 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/ApplicationSetup.cs" @@ -0,0 +1,35 @@ +锘縰sing Microsoft.AspNetCore.Builder; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Extensions +{ + public static class ApplicationSetup + { + /// <summary> + /// 閰嶇疆搴旂敤绋嬪簭鐢熷懡鍛ㄦ湡浜嬩欢 + /// </summary> + /// <param name="app">Web搴旂敤绋嬪簭瀹炰緥</param> + /// <remarks> + /// 鍦ㄥ簲鐢ㄧ▼搴忓惎鍔ㄦ椂璁剧疆App.IsRun涓簍rue锛屽湪鍋滄鏃惰缃负false + /// </remarks> + public static void UseApplicationSetup(this WebApplication app) + { + app.Lifetime.ApplicationStarted.Register(() => + { + App.IsRun = true; + }); + + app.Lifetime.ApplicationStopped.Register(() => + { + App.IsRun = false; + + //娓呴櫎鏃ュ織 + //Log.CloseAndFlush(); + }); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/AutofacModuleRegister.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/AutofacModuleRegister.cs" new file mode 100644 index 0000000..fd56efb --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/AutofacModuleRegister.cs" @@ -0,0 +1,86 @@ +锘縰sing Autofac; +using Autofac.Extras.DynamicProxy; +using Microsoft.Extensions.DependencyModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.AOP; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_Core.Helper; +using WIDESEA_Core.LogHelper; + +namespace WIDESEA_Core.Extensions +{ + public class AutofacModuleRegister : Autofac.Module + { + /// <summary> + /// Autofac妯″潡娉ㄥ唽绫伙紝鐢ㄤ簬渚濊禆娉ㄥ叆閰嶇疆 + /// </summary> + /// <remarks> + /// 1. 鏍规嵁閰嶇疆鍔ㄦ�佹敞鍐屾棩蹇桝OP鎷︽埅鍣� + /// 2. 娉ㄥ唽娉涘瀷浠撳偍鍜屾湇鍔″熀绫� + /// 3. 鎵弿椤圭洰绋嬪簭闆嗚嚜鍔ㄦ敞鍐屽疄鐜颁簡IDependency鎺ュ彛鐨勭被鍨� + /// 4. 娉ㄥ唽宸ヤ綔鍗曞厓绠$悊鍣ㄥ拰璇锋眰鏃ュ織妯″瀷 + /// </remarks> + protected override void Load(ContainerBuilder builder) + { + var basePath = AppContext.BaseDirectory; + var cacheType = new List<Type>(); + + if (AppSettings.Get("LogAopEnable").ObjToBool()) + { + builder.RegisterType<LogAOP>(); + cacheType.Add(typeof(LogAOP)); + } + + builder.RegisterGeneric(typeof(RepositoryBase<>)).As(typeof(IRepository<>)).InstancePerDependency();//娉ㄥ唽浠撳偍 + builder.RegisterGeneric(typeof(ServiceBase<,>)).As(typeof(IService<>)).InstancePerDependency();//娉ㄥ唽鏈嶅姟 + + Type baseType = typeof(IDependency); + + List<RuntimeLibrary> compilationLibrary = DependencyContext.Default + .RuntimeLibraries + .Where(x => !x.Serviceable + && x.Type == "project") + .ToList(); + List<Assembly> assemblyList = new List<Assembly>(); + foreach (var library in compilationLibrary) + { + try + { + string path = Path.Combine(basePath, $"{library.Name}.dll"); + if (!File.Exists(path)) + { + var msg = $"{library.Name}.dll涓㈠け锛屽洜涓洪」鐩В鑰︿簡锛屾墍浠ラ渶瑕佸厛F6缂栬瘧锛屽啀F5杩愯锛岃妫�鏌� bin 鏂囦欢澶癸紝骞舵嫹璐濄��"; + //log.Error(msg); + throw new Exception(msg); + } + assemblyList.Add(Assembly.LoadFrom(path)); + } + catch (Exception ex) + { + Console.WriteLine(library.Name + ex.Message); + } + } + + builder.RegisterAssemblyTypes(assemblyList.ToArray()).Where(x => !x.IsInterface && !x.IsAbstract && baseType.IsAssignableFrom(x)) + .AsImplementedInterfaces() + .PropertiesAutowired() + .InstancePerDependency(). + EnableInterfaceInterceptors() + .InterceptedBy(cacheType.ToArray()); + + builder.RegisterType<UnitOfWorkManage>().As<IUnitOfWorkManage>() + .AsImplementedInterfaces() + .InstancePerLifetimeScope() + .PropertiesAutowired(); + + builder.RegisterType<RequestLogModel>().InstancePerLifetimeScope(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/CorsSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/CorsSetup.cs" new file mode 100644 index 0000000..417610d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/CorsSetup.cs" @@ -0,0 +1,56 @@ +锘縰sing Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Extensions +{ + /// <summary> + /// Cors 璺ㄥ煙 + /// </summary> + public static class CorsSetup + { + /// <summary> + /// 璺ㄥ煙 + /// </summary> + /// <param name="services"></param> + /// <exception cref="ArgumentNullException"></exception> + public static void AddCorsSetup(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + services.AddCors(c => + { + if (!AppSettings.Get(new string[] { "Cors", "EnableAllIPs" }).ObjToBool()) + { + c.AddPolicy(AppSettings.Get(new string[] {"Cors", "PolicyName" }), + + policy => + { + policy + .WithOrigins(AppSettings.Get(new string[] { "Cors", "IPs" }).Split(',')) + .AllowAnyHeader()//Ensures that the policy allows any header. + .AllowAnyMethod(); + }); + } + else + { + //鍏佽浠绘剰璺ㄥ煙璇锋眰 + c.AddPolicy(AppSettings.Get(new string[] { "Cors", "PolicyName" }), + policy => + { + policy + .SetIsOriginAllowed((host) => true) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); + }); + } + + }); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/DbSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/DbSetup.cs" new file mode 100644 index 0000000..30f2698 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/DbSetup.cs" @@ -0,0 +1,32 @@ +锘縰sing Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Seed; + +namespace WIDESEA_Core +{ + /// <summary> + /// Db 鍚姩鏈嶅姟 + /// </summary> + public static class DbSetup + { + /// <summary> + /// 娣诲姞鏁版嵁搴撹缃湇鍔″埌渚濊禆娉ㄥ叆瀹瑰櫒 + /// </summary> + /// <param name="services">鏈嶅姟闆嗗悎</param> + /// <exception cref="ArgumentNullException">褰搒ervices涓簄ull鏃舵姏鍑�</exception> + /// <remarks> + /// 娉ㄥ唽DBSeed鍜孌BContext涓篠coped鐢熷懡鍛ㄦ湡鏈嶅姟 + /// </remarks> + public static void AddDbSetup(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + services.AddScoped<DBSeed>(); + services.AddScoped<DBContext>(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/HttpContextExtension.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/HttpContextExtension.cs" new file mode 100644 index 0000000..390b2ef --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/HttpContextExtension.cs" @@ -0,0 +1,30 @@ +锘縰sing Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Extensions +{ + public static class HttpContextExtension + { + /// <summary> + /// 鑾峰彇褰撳墠HTTP涓婁笅鏂囩殑Session瀵硅薄 + /// </summary> + /// <param name="context">HTTP涓婁笅鏂�</param> + /// <returns>濡傛灉鎴愬姛鍒欒繑鍥濻ession瀵硅薄锛屽け璐ュ垯杩斿洖null</returns> + /// <remarks>姝ゆ柟娉曚細鎹曡幏骞跺鐞嗚幏鍙朣ession鏃跺彲鑳藉彂鐢熺殑寮傚父</remarks> + public static ISession GetSession(this HttpContext context) + { + try + { + return context.Session; + } + catch (Exception) + { + return default; + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/HttpContextSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/HttpContextSetup.cs" new file mode 100644 index 0000000..2615700 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/HttpContextSetup.cs" @@ -0,0 +1,30 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.HttpContextUser; + +namespace WIDESEA_Core.Extensions +{ + /// <summary> + /// HttpContext 鐩稿叧鏈嶅姟 + /// </summary> + public static class HttpContextSetup + { + /// <summary> + /// HttpContext 鐩稿叧鏈嶅姟 + /// </summary> + /// <param name="services"></param> + /// <exception cref="ArgumentNullException"></exception> + public static void AddHttpContextSetup(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); + services.AddScoped<IUser, AspNetUser>(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/InitializationHostServiceSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/InitializationHostServiceSetup.cs" new file mode 100644 index 0000000..7243165 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/InitializationHostServiceSetup.cs" @@ -0,0 +1,28 @@ +锘縰sing Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Extensions +{ + public static class InitializationHostServiceSetup + { + /// <summary> + /// 搴旂敤鍒濆鍖栨湇鍔℃敞鍏� + /// </summary> + /// <param name="services"></param> + public static void AddInitializationHostServiceSetup(this IServiceCollection services) + { + if (services is null) + { + ArgumentNullException.ThrowIfNull(nameof(services)); + } + services.AddHostedService<SeedDataHostedService>(); + //services.AddHostedService<QuartzJobHostedService>(); + //services.AddHostedService<ConsulHostedService>(); + //services.AddHostedService<EventBusHostedService>(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/IpPolicyRateLimitSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/IpPolicyRateLimitSetup.cs" new file mode 100644 index 0000000..9684dfa --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/IpPolicyRateLimitSetup.cs" @@ -0,0 +1,43 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Extensions +{ + /// <summary> + /// IPLimit闄愭祦 鍚姩鏈嶅姟 + /// </summary> + public static class IpPolicyRateLimitSetup + { + public static void AddIpPolicyRateLimitSetup(this IServiceCollection services, IConfiguration Configuration) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + // needed to store rate limit counters and ip rules + //services.AddMemoryCache(); + + //load general configuration from appsettings.json + //services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting")); + + // inject counter and rules stores + //services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>(); + //services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>(); + //services.AddSingleton<IProcessingStrategy, AsyncKeyLockProcessingStrategy>(); + + // inject counter and rules distributed cache stores + //services.AddSingleton<IIpPolicyStore, DistributedCacheIpPolicyStore>(); + //services.AddSingleton<IRateLimitCounterStore, DistributedCacheRateLimitCounterStore>(); + + // the clientId/clientIp resolvers use it. + //services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); + + // configuration (resolvers, counter key builders) + //services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/MemoryCacheSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/MemoryCacheSetup.cs" new file mode 100644 index 0000000..2da3a39 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/MemoryCacheSetup.cs" @@ -0,0 +1,28 @@ +锘縰sing Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System; +using WIDESEA_Core.Caches; + +namespace WIDESEA_Core.Extensions +{ + /// <summary> + /// Memory缂撳瓨 鍚姩鏈嶅姟 + /// </summary> + public static class MemoryCacheSetup + { + /// <summary> + /// 娣诲姞鍐呭瓨缂撳瓨閰嶇疆鍒版湇鍔¢泦鍚� + /// </summary> + /// <param name="services">鏈嶅姟闆嗗悎</param> + /// <exception cref="ArgumentNullException">褰搒ervices涓簄ull鏃舵姏鍑�</exception> + public static void AddMemoryCacheSetup(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + + services.AddSingleton<ICacheService, MemoryCacheService>(); + services.AddMemoryCache(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/MiniProfilerSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/MiniProfilerSetup.cs" new file mode 100644 index 0000000..4bec8af --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/MiniProfilerSetup.cs" @@ -0,0 +1,33 @@ +锘縰sing Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Extensions +{ + /// <summary> + /// MiniProfiler 鎬ц兘鍒嗘瀽 + /// </summary> + public static class MiniProfilerSetup + { + /// <summary> + /// 娣诲姞 MiniProfiler 閰嶇疆鍒版湇鍔¢泦鍚� + /// </summary> + /// <param name="services">鏈嶅姟闆嗗悎</param> + /// <exception cref="ArgumentNullException">褰� services 涓� null 鏃舵姏鍑�</exception> + /// <remarks>閰嶇疆 MiniProfiler 鐨勫熀纭�璺敱璺緞涓� "/profiler"</remarks> + public static void AddMiniProfilerSetup(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + //if (AppSettings.app(new string[] { "Startup", "MiniProfiler", "Enabled" }).ObjToBool()) + //{ + services.AddMiniProfiler(options => + { + options.RouteBasePath = "/profiler"; + }); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SqlsugarSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SqlsugarSetup.cs" new file mode 100644 index 0000000..4d9cc53 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SqlsugarSetup.cs" @@ -0,0 +1,160 @@ +锘縰sing Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; +using SqlSugar; +using StackExchange.Profiling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.AOP; +using WIDESEA_Core.DB; +using WIDESEA_Core.Helper; +using WIDESEA_Core.LogHelper; +using WIDESEA_Core.Seed; + +namespace WIDESEA_Core +{ + /// <summary> + /// SqlSugar 鍚姩鏈嶅姟 + /// </summary> + public static class SqlsugarSetup + { + private static readonly MemoryCache Cache = new MemoryCache(new MemoryCacheOptions()); + + /// <summary> + /// 娣诲姞SqlSugar鏁版嵁搴撻厤缃埌鏈嶅姟瀹瑰櫒 + /// </summary> + /// <param name="services">鏈嶅姟闆嗗悎</param> + /// <remarks> + /// 1. 閰嶇疆涓绘暟鎹簱杩炴帴瀛楃涓� + /// 2. 浣跨敤SqlSugarScope瀹炵幇绾跨▼瀹夊叏 + /// 3. 鏀寔SQL鎵ц鏃ュ織璁板綍(閫氳繃MiniProfiler鍜孋onsole杈撳嚭) + /// 4. 鍖呭惈AOP浜嬩欢澶勭悊(鏁版嵁鎵ц鍓嶄簨浠�) + /// </remarks> + /// <exception cref="ArgumentNullException">褰搒ervices鍙傛暟涓簄ull鏃舵姏鍑�</exception> + public static void AddSqlsugarSetup(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + // 榛樿娣诲姞涓绘暟鎹簱杩炴帴 + //MainDb.CurrentDbConnId = AppSettings.app(new string[] { "MainDB" }); + + // SqlSugarScope鏄嚎绋嬪畨鍏紝鍙娇鐢ㄥ崟渚嬫敞鍏� + // 鍙傝�冿細https://www.donet5.com/Home/Doc?typeId=1181 + services.AddScoped<ISqlSugarClient>(o => + { + var memoryCache = o.GetRequiredService<IMemoryCache>(); + + // 杩炴帴瀛楃涓� + var listConfig = new List<ConnectionConfig> + { + new ConnectionConfig + { + ConfigId = MainDb.CurrentDbConnId, + ConnectionString = DBContext.GetMainConnectionDb().Connection, + IsAutoCloseConnection = true, + DbType = DBContext.DbType, + AopEvents = new AopEvents + { + OnLogExecuting = (sql, p) => + { + Parallel.For(0, 1, e => + { + MiniProfiler.Current.CustomTiming("SQL锛�", GetParas(p) + "銆怱QL璇彞銆戯細" + sql); + }); + if(AppSettings.GetValue("PrintSql").ObjToBool()) + { + Console.Out.WriteLine(GetParas(p)); + Console.Out.WriteLine(sql); + Console.Out.WriteLine(); + } + } + }, + } + }; + #region 浠庡簱 + //var listConfig_Slave = new List<SlaveConnectionConfig>(); + //BaseDBConfig.MutiConnectionString.ForEach(s => + //{ + // if(s.ConnId != MainDb.CurrentDbConnId) + // { + // listConfig_Slave.Add(new SlaveConnectionConfig() + // { + // HitRate = s.HitRate, + // ConnectionString = s.Connection + // }); + // } + + //}); + + //BaseDBConfig.MutiConnectionString.ForEach(m => + //{ + // listConfig.Add(new ConnectionConfig() + // { + // ConfigId = m.ConnId.ObjToString().ToLower(), + // ConnectionString = m.Connection, + // DbType = (DbType)m.DbType, + // IsAutoCloseConnection = true, + // MoreSettings = new ConnMoreSettings() + // { + // //IsWithNoLockQuery = true, + // IsAutoRemoveDataCache = true + // }, + // // 浠庡簱 + // //SlaveConnectionConfigs = listConfig_Slave, + // // 鑷畾涔夌壒鎬� + // ConfigureExternalServices = new ConfigureExternalServices() + // { + // DataInfoCacheService = new SqlSugarMemoryCacheService(memoryCache), + // EntityService = (property, column) => + // { + // if (column.IsPrimarykey && property.PropertyType == typeof(int)) + // { + // column.IsIdentity = true; + // } + // } + // }, + // InitKeyType = InitKeyType.Attribute, + // AopEvents = new AopEvents() + // { + // OnError = x => + // { + // Console.WriteLine(x.Sql); + // } + // } + // } + // ); + //}); + #endregion + + SqlSugarClient sqlSugarClient = new SqlSugarClient(listConfig, db => + { + db.Aop.DataExecuting = SqlSugarAop.DataExecuting; + }); + return sqlSugarClient; + }); + } + + private static string GetWholeSql(SugarParameter[] paramArr, string sql) + { + foreach (var param in paramArr) + { + sql.Replace(param.ParameterName, param.Value.ObjToString()); + } + + return sql; + } + + private static string GetParas(SugarParameter[] pars) + { + string key = "銆怱QL鍙傛暟銆戯細"; + foreach (var param in pars) + { + key += $"{param.ParameterName}:{param.Value}\n"; + } + + return key; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SwaggerContextExtension.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SwaggerContextExtension.cs" new file mode 100644 index 0000000..8014c45 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SwaggerContextExtension.cs" @@ -0,0 +1,116 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Extensions +{ + public static class SwaggerContextExtension + { + public const string SwaggerCodeKey = "swagger-code"; + public const string SwaggerJwt = "swagger-jwt"; + + /// <summary> + /// 妫�鏌ュ綋鍓峉wagger璇锋眰鏄惁楠岃瘉鎴愬姛 + /// </summary> + /// <returns>濡傛灉Session涓璖wagger楠岃瘉鐮佷负"success"鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse</returns> + public static bool IsSuccessSwagger() + { + return App.HttpContext?.GetSession()?.GetString(SwaggerCodeKey) == "success"; + } + + /// <summary> + /// 鍒ゆ柇褰撳墠Swagger璇锋眰鏄惁宸查�氳繃楠岃瘉 + /// </summary> + /// <param name="context">Http涓婁笅鏂囧璞�</param> + /// <returns>濡傛灉Swagger楠岃瘉鎴愬姛杩斿洖true锛屽惁鍒欒繑鍥瀎alse</returns> + public static bool IsSuccessSwagger(this HttpContext context) + { + return context.GetSession()?.GetString(SwaggerCodeKey) == "success"; + } + + /// <summary> + /// 璁剧疆Swagger楠岃瘉鎴愬姛鐘舵�� + /// </summary> + /// <remarks> + /// 灏哠wagger楠岃瘉鐘舵�佺爜"success"瀛樺偍鍒板綋鍓嶄細璇濅腑 + /// </remarks> + public static void SuccessSwagger() + { + App.HttpContext?.GetSession()?.SetString(SwaggerCodeKey, "success"); + } + + /// <summary> + /// 璁剧疆Swagger鎿嶄綔鎴愬姛鐨勭姸鎬佺爜 + /// </summary> + /// <param name="context">Http涓婁笅鏂囧璞�</param> + public static void SuccessSwagger(this HttpContext context) + { + context.GetSession()?.SetString(SwaggerCodeKey, "success"); + } + + /// <summary> + /// 涓篠wagger JWT璁よ瘉璁剧疆鎴愬姛涓婁笅鏂� + /// </summary> + /// <param name="context">Http涓婁笅鏂囧璞�</param> + /// <param name="token">JWT浠ょ墝</param> + /// <remarks> + /// 灏咼WT浠ょ墝瑙f瀽涓篊laimsIdentity骞舵坊鍔犲埌鐢ㄦ埛韬唤涓紝鍚屾椂灏嗕护鐗屽瓨鍌ㄥ湪浼氳瘽涓� + /// </remarks> + public static void SuccessSwaggerJwt(this HttpContext context, string token) + { + var claims = new ClaimsIdentity(GetClaimsIdentity(token)); + context.User.AddIdentity(claims); + context.GetSession().SetString(SwaggerJwt, token); + } + + /// <summary> + /// 浠嶫WT浠ょ墝涓幏鍙栧0鏄�(Claims)闆嗗悎 + /// </summary> + /// <param name="token">JWT浠ょ墝瀛楃涓�</param> + /// <returns>鍖呭惈澹版槑淇℃伅鐨勯泦鍚堬紝鑻ヤ护鐗屾棤鏁堝垯杩斿洖绌洪泦鍚�</returns> + private static IEnumerable<Claim> GetClaimsIdentity(string token) + { + var jwtHandler = new JwtSecurityTokenHandler(); + // token鏍¢獙 + if (token.IsNotEmptyOrNull() && jwtHandler.CanReadToken(token)) + { + var jwtToken = jwtHandler.ReadJwtToken(token); + + return jwtToken.Claims; + } + + return new List<Claim>(); + } + + /// <summary> + /// 浠庡綋鍓岺TTP涓婁笅鏂囦腑鑾峰彇鎴愬姛鐨凷wagger JWT浠ょ墝 + /// </summary> + /// <param name="context">HTTP涓婁笅鏂�</param> + /// <returns>Swagger JWT浠ょ墝瀛楃涓�</returns> + public static string GetSuccessSwaggerJwt(this HttpContext context) + { + return context.GetSession().GetString(SwaggerJwt); + } + + + /// <summary> + /// 閲嶅畾鍚戝埌Swagger鐧诲綍椤甸潰 + /// </summary> + /// <param name="context">Http涓婁笅鏂囧璞�</param> + /// <remarks> + /// 灏嗗綋鍓嶈姹傞噸瀹氬悜鍒�/swg-login.html椤甸潰锛屽苟闄勫甫褰撳墠URL浣滀负杩斿洖鍦板潃鍙傛暟 + /// </remarks> + public static void RedirectSwaggerLogin(this HttpContext context) + { + var returnUrl = context.Request.GetDisplayUrl(); //鑾峰彇褰撳墠url鍦板潃 + context.Response.Redirect("/swg-login.html?returnUrl=" + returnUrl); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SwaggerSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SwaggerSetup.cs" new file mode 100644 index 0000000..3cdbc21 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Extensions/SwaggerSetup.cs" @@ -0,0 +1,132 @@ +锘� +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; +using static WIDESEA_Core.Extensions.CustomApiVersion; +using Swashbuckle.AspNetCore.Filters; +using Microsoft.Extensions.Logging; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Math; + +namespace WIDESEA_Core.Extensions +{ + /// <summary> + /// Swagger + /// </summary> + public static class SwaggerSetup + { + /// <summary> + /// 閰嶇疆Swagger鏂囨。鏈嶅姟 + /// </summary> + /// <param name="services">鏈嶅姟闆嗗悎</param> + /// <remarks> + /// 1. 璁剧疆API鏂囨。鍩烘湰淇℃伅 + /// 2. 鍔犺浇XML娉ㄩ噴鏂囨。(鍖呮嫭Controller鍜孧odel灞�) + /// 3. 閰嶇疆JWT璁よ瘉鏂瑰紡 + /// 4. 閰嶇疆API琛屼负閫夐」 + /// </remarks> + /// <exception cref="ArgumentNullException">褰搒ervices涓簄ull鏃舵姏鍑�</exception> + public static void AddSwaggerSetup(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + var basePath = AppContext.BaseDirectory; + var ApiName = AppSettings.Get(new string[] { "ApiName" }); + + services.AddSwaggerGen(c => + { + //閬嶅巻鍑哄叏閮ㄧ殑鐗堟湰锛屽仛鏂囨。淇℃伅灞曠ず + //typeof(ApiVersions).GetEnumNames().ToList().ForEach(version => + //{ + c.SwaggerDoc("v1", new OpenApiInfo + { + Version = "v1", + Title = $"{ApiName} 鎺ュ彛鏂囨。鈥斺�攞RuntimeInformation.FrameworkDescription}", + Description = $"{ApiName} HTTP API " + "v1" + }); + c.OrderActionsBy(o => o.RelativePath); + //}); + + c.UseInlineDefinitionsForEnums(); + try + { + //杩欎釜灏辨槸鍒氬垰閰嶇疆鐨剎ml鏂囦欢鍚� + var xmlPath = Path.Combine(basePath, "WIDESEA_Server.xml"); + //榛樿鐨勭浜屼釜鍙傛暟鏄痜alse锛岃繖涓槸controller鐨勬敞閲婏紝璁板緱淇敼 + c.IncludeXmlComments(xmlPath, true); + + //杩欎釜灏辨槸Model灞傜殑xml鏂囦欢鍚� + var xmlModelPath = Path.Combine(basePath, "WIDESEA_Server.Model.xml"); + c.IncludeXmlComments(xmlModelPath); + } + catch (Exception ex) + { + //log.Error("Blog.Core.xml鍜孊log.Core.Model.xml 涓㈠け锛岃妫�鏌ュ苟鎷疯礉銆俓n" + ex.Message); + } + + // 寮�鍚姞鏉冨皬閿� + c.OperationFilter<AddResponseHeadersFilter>(); + c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>(); + + // 鍦╤eader涓坊鍔爐oken锛屼紶閫掑埌鍚庡彴 + c.OperationFilter<SecurityRequirementsOperationFilter>(); + + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = "JWT鎺堟潈token鍓嶉潰闇�瑕佸姞涓婂瓧娈礏earer涓庝竴涓┖鏍�,濡侭earer token", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.ApiKey, + BearerFormat = "JWT", + Scheme = "Bearer" + }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + new string[] { } + } + }); + }).AddControllers() + .ConfigureApiBehaviorOptions(options => + { + options.SuppressConsumesConstraintForFormFileParameters = true; + options.SuppressInferBindingSourcesForParameters = true; + options.SuppressModelStateInvalidFilter = true; + options.SuppressMapClientErrors = true; + options.ClientErrorMapping[404].Link = + "https://*/404"; + }); + //services.AddSwaggerGenNewtonsoftSupport(); + } + } + + /// <summary> + /// 鑷畾涔夌増鏈� + /// </summary> + public class CustomApiVersion + { + /// <summary> + /// Api鎺ュ彛鐗堟湰 鑷畾涔� + /// </summary> + public enum ApiVersions + { + /// <summary> + /// V1 鐗堟湰 + /// </summary> + V1 = 1 + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ActionExecuteFilter.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ActionExecuteFilter.cs" new file mode 100644 index 0000000..3364abc --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ActionExecuteFilter.cs" @@ -0,0 +1,37 @@ +锘縰sing Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Filter +{ + public class ActionExecuteFilter : IActionFilter + { + public void OnActionExecuted(ActionExecutedContext context) + { + //throw new NotImplementedException(); + } + + public void OnActionExecuting(ActionExecutingContext context) + { + //throw new NotImplementedException(); + //foreach (KeyValuePair<string, object?> item in context.ActionArguments) + //{ + // if (item.Value != null) + // { + // string name = item.Value.GetType().Name; + // Console.Out.WriteLine(name); + // } + // else + // { + // context.Result = new JsonResult(new { Status = false, Message = "鍙傛暟涓嶈兘涓虹┖" }); + // return; + // } + //} + + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ApiAuthorizeFilter.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ApiAuthorizeFilter.cs" new file mode 100644 index 0000000..364fa0a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ApiAuthorizeFilter.cs" @@ -0,0 +1,117 @@ +锘縰sing Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Hosting; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Runtime; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Authorization; +using WIDESEA_Core.Const; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Filter +{ + /// <summary> + /// 鍒ゆ柇token鏄惁姝g‘ + /// </summary> + public class ApiAuthorizeFilter : IAuthorizationFilter + { + private static readonly string replaceTokenPath = "/api/User/replaceToken"; + private static readonly string loginPath = "/api/User/login"; + private static readonly string vierificationCodePath = "/api/User/getVierificationCode"; + + public ApiAuthorizeFilter() + { + + } + + /// <summary> + /// 鍙垽鏂璽oken鏄惁姝g‘锛屼笉鍒ゆ柇鏉冮檺 + /// 濡傛灉闇�瑕佸垽鏂潈闄愮殑鍦ˋction涓婂姞涓夾piActionPermission灞炴�ф爣璇嗘潈闄愮被鍒紝ActionPermissionFilter浣滄潈闄愬鐞� + ///(string,string,string)1銆佽姹傚弬鏁�,2銆佽繑鍥炴秷鎭紝3,寮傚父娑堟伅,4鐘舵�� + /// </summary> + /// <param name="context"></param> + public void OnAuthorization(AuthorizationFilterContext context) + { + //if (!App.HostEnvironment.IsProduction() || context.HttpContext.Request.Path.Value == loginPath || context.HttpContext.Request.Path.Value == vierificationCodePath) + { + if (context.ActionDescriptor.EndpointMetadata.Any(item => item is IAllowAnonymous)) + { + //濡傛灉浣跨敤浜嗗浐瀹歍oken涓嶈繃鏈燂紝鐩存帴瀵箃oken鐨勫悎娉曟�у強token鏄惁瀛樺湪杩涜楠岃瘉 + //if (context.Filters + // .Where(item => item is IFixedTokenFilter) + // .FirstOrDefault() is IFixedTokenFilter tokenFilter) + //{ + // tokenFilter.OnAuthorization(context); + // return; + //} + //鍖垮悕骞朵紶鍏ヤ簡token锛岄渶瑕佸皢鐢ㄦ埛鐨処D缂撳瓨璧锋潵锛屼繚璇乁serHelper閲岃兘姝g‘鑾峰彇鍒扮敤鎴蜂俊鎭� + if (!context.HttpContext.User.Identity?.IsAuthenticated ?? false + && !string.IsNullOrEmpty(context.HttpContext.Request.Headers[AppSecret.TokenHeaderName])) + { + context.AddIdentity(); + } + return; + } + } + //else + //{ + // if (!context.HttpContext.User.Identity.IsAuthenticated + // || !context.HttpContext.Request.Headers.ContainsKey(AppSecret.TokenHeaderName)) + // { + // context.Unauthorized("鏈巿鏉�"); + // return; + // } + //} + + #region 鍗曠偣鐧诲綍 + if (string.IsNullOrEmpty(App.User.Token)) + { + if (!string.IsNullOrEmpty(context.HttpContext.Request.Headers[AppSecret.TokenHeaderName].ObjToString().Replace("Bearer ", ""))) + { + DateTime? expDate = context.HttpContext.User.Claims.Where(x => x.Type == JwtRegisteredClaimNames.Exp).Select(x => x.Value).FirstOrDefault()?.GetTimeSpmpToDate(); + //鍔ㄦ�佹爣璇嗗埛鏂皌oken(2021.05.01) + int ExpMinutes = AppSettings.Get("ExpMinutes").ObjToInt(); + if ((expDate.GetValueOrDefault() - DateTime.Now).TotalMinutes > ExpMinutes) + { + context.Unauthorized("鐧诲綍宸茶繃鏈�"); + return; + } + else + { + App.User.UpdateToke(context.HttpContext.Request.Headers[AppSecret.TokenHeaderName].ObjToString().Replace("Bearer ", "")); + } + } + else + { + context.Unauthorized("鐧诲綍宸茶繃鏈�"); + return; + } + } + else + { + if (App.User.Token != ((ClaimsIdentity?)context.HttpContext.User.Identity)?.BootstrapContext?.ToString()) + { + context.Unauthorized("鐧诲綍宸茶繃鏈�"); + return; + } + } + #endregion + + { + DateTime? expDate = context.HttpContext.User.Claims.Where(x => x.Type == JwtRegisteredClaimNames.Exp) + .Select(x => x.Value).FirstOrDefault()?.GetTimeSpmpToDate(); + //鍔ㄦ�佹爣璇嗗埛鏂皌oken(2021.05.01) + int ExpMinutes = AppSettings.Get("ExpMinutes").ObjToInt(); + if ((expDate.GetValueOrDefault() - DateTime.Now).TotalMinutes < ExpMinutes / 3 && context.HttpContext.Request.Path != replaceTokenPath) + { + context.HttpContext.Response.Headers.Add("WIDESEA_exp", "1"); + } + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ExporterHeaderFilter.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ExporterHeaderFilter.cs" new file mode 100644 index 0000000..81dc421 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/ExporterHeaderFilter.cs" @@ -0,0 +1,23 @@ +锘縰sing Magicodes.ExporterAndImporter.Core.Filters; +using Magicodes.ExporterAndImporter.Core.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Filter +{ + public class ExporterHeaderFilter : IExporterHeaderFilter + { + /// <summary> + /// 琛ㄥご绛涢�夊櫒锛堜慨鏀瑰悕绉帮級 + /// </summary> + /// <param name="exporterHeaderInfo"></param> + /// <returns></returns> + public ExporterHeaderInfo Filter(ExporterHeaderInfo exporterHeaderInfo) + { + return exporterHeaderInfo; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/GlobalExceptionsFilter.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/GlobalExceptionsFilter.cs" new file mode 100644 index 0000000..5b85e43 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/GlobalExceptionsFilter.cs" @@ -0,0 +1,101 @@ +锘縰sing Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; +using StackExchange.Profiling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; +using System.Reflection.Metadata; +using WIDESEA_Core.LogHelper; + +namespace WIDESEA_Core.Filter +{ + /// <summary> + /// 鍏ㄥ眬寮傚父閿欒鏃ュ織 + /// </summary> + public class GlobalExceptionsFilter : IExceptionFilter + { + private readonly IWebHostEnvironment _env; + private readonly ILogger<GlobalExceptionsFilter> _loggerHelper; + + public GlobalExceptionsFilter(IWebHostEnvironment env, ILogger<GlobalExceptionsFilter> loggerHelper) + { + _env = env; + _loggerHelper = loggerHelper; + } + + /// <summary> + /// 鍏ㄥ眬寮傚父澶勭悊鏂规硶 + /// </summary> + /// <param name="context">寮傚父涓婁笅鏂囷紝鍖呭惈寮傚父淇℃伅鍜岃姹備笂涓嬫枃</param> + /// <remarks> + /// 1. 灏嗗紓甯镐俊鎭皝瑁呬负WebResponseContent鏍煎紡杩斿洖 + /// 2. 寮�鍙戠幆澧冧笅闄勫姞鍫嗘爤璺熻釜淇℃伅 + /// 3. 瀵圭壒瀹氶敊璇俊鎭紙鏈嶅姟瑙f瀽澶辫触锛夋坊鍔犳彁绀鸿鏄� + /// 4. 璁板綍閿欒鏃ュ織鍜孧iniProfiler鎬ц兘璺熻釜 + /// </remarks> + public void OnException(ExceptionContext context) + { + var json = new WebResponseContent(); + + json.Message = context.Exception.Message;//閿欒淇℃伅 + json.Code = 500;//500寮傚父 + var errorAudit = "Unable to resolve service for"; + if (!string.IsNullOrEmpty(json.Message) && json.Message.Contains(errorAudit)) + { + json.Message = json.Message.Replace(errorAudit, $"锛堣嫢鏂版坊鍔犳湇鍔★紝闇�瑕侀噸鏂扮紪璇戦」鐩級{errorAudit}"); + } + + if (_env.EnvironmentName.ObjToString().Equals("Development")) + { + json.DevMessage = context.Exception.StackTrace ?? "";//鍫嗘爤淇℃伅 + } + var res = new ContentResult(); + res.Content = json.Serialize(); + + context.Result = res; + MiniProfiler.Current.CustomTiming("Errors锛�", json.Message); + + LogLock.OutLogAOP("鍏ㄥ眬寮傚父閿欒鏃ュ織", new string[] { json.Message + WriteLog(json.Message, context.Exception) }); + } + + /// <summary> + /// 鑷畾涔夎繑鍥炴牸寮� + /// </summary> + /// <param name="throwMsg"></param> + /// <param name="ex"></param> + /// <returns></returns> + public string WriteLog(string throwMsg, Exception ex) + { + return string.Format("\r\n銆愯嚜瀹氫箟閿欒銆戯細{0} \r\n銆愬紓甯哥被鍨嬨�戯細{1} \r\n銆愬紓甯镐俊鎭�戯細{2} \r\n銆愬爢鏍堣皟鐢ㄣ�戯細{3}", new object[] { throwMsg, + ex.GetType().Name, ex.Message, ex.StackTrace }); + } + + } + public class InternalServerErrorObjectResult : ObjectResult + { + public InternalServerErrorObjectResult(object value) : base(value) + { + StatusCode = StatusCodes.Status500InternalServerError; + } + } + //杩斿洖閿欒淇℃伅 + public class JsonErrorResponse + { + /// <summary> + /// 鐢熶骇鐜鐨勬秷鎭� + /// </summary> + public string Message { get; set; } + /// <summary> + /// 寮�鍙戠幆澧冪殑娑堟伅 + /// </summary> + public string DevelopmentMessage { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/UseServiceDIAttribute.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/UseServiceDIAttribute.cs" new file mode 100644 index 0000000..be1d4a8 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Filter/UseServiceDIAttribute.cs" @@ -0,0 +1,38 @@ +锘縰sing Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Filter +{ + public class UseServiceDIAttribute : ActionFilterAttribute + { + + protected readonly ILogger<UseServiceDIAttribute> _logger; + //private readonly IBlogArticleServices _blogArticleServices; + private readonly string _name; + + public UseServiceDIAttribute(ILogger<UseServiceDIAttribute> logger/*, IBlogArticleServices blogArticleServices*/, string Name = "") + { + _logger = logger; + /*_blogArticleServices = blogArticleServices;*/ + _name = Name; + } + + + public override void OnActionExecuted(ActionExecutedContext context) + { + //var dd =await _blogArticleServices.Query(); + base.OnActionExecuted(context); + DeleteSubscriptionFiles(); + } + + private void DeleteSubscriptionFiles() + { + + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/AppSettings.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/AppSettings.cs" new file mode 100644 index 0000000..ba06bb9 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/AppSettings.cs" @@ -0,0 +1,92 @@ +锘縰sing Microsoft.Extensions.Configuration.Json; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Helper +{ + /// <summary> + /// appsettings.json鎿嶄綔绫� + /// </summary> + public class AppSettings + { + // 瀹氫箟涓�涓潤鎬佺殑 IConfiguration 瀵硅薄 + public static IConfiguration Configuration { get; set; } + // 瀹氫箟涓�涓潤鎬佺殑 string 瀵硅薄 + static string contentPath { get; set; } + + // 鏋勯�犲嚱鏁帮紝浼犲叆 contentPath 鍙傛暟 + public AppSettings(string contentPath) + { + string Path = "appsettings.json"; + + //濡傛灉浣犳妸閰嶇疆鏂囦欢 鏄� 鏍规嵁鐜鍙橀噺鏉ュ垎寮�浜嗭紝鍙互杩欐牱鍐� + //Path = $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json"; + + Configuration = new ConfigurationBuilder() + .SetBasePath(contentPath) + .Add(new JsonConfigurationSource { Path = Path, Optional = false, ReloadOnChange = true })//杩欐牱鐨勮瘽锛屽彲浠ョ洿鎺ヨ鐩綍閲岀殑json鏂囦欢锛岃�屼笉鏄� bin 鏂囦欢澶逛笅鐨勶紝鎵�浠ヤ笉鐢ㄤ慨鏀瑰鍒跺睘鎬� + .Build(); + } + + // 鏋勯�犲嚱鏁帮紝浼犲叆 IConfiguration 鍙傛暟 + public AppSettings(IConfiguration configuration) + { + Configuration = configuration; + } + + /// <summary> + /// 灏佽瑕佹搷浣滅殑瀛楃 + /// </summary> + /// <param name="sections">鑺傜偣閰嶇疆</param> + /// <returns></returns> + public static string Get(params string[] sections) + { + try + { + if (sections.Any()) + { + return Configuration[string.Join(":", sections)]; + } + } + catch (Exception) { } + + return ""; + } + + /// <summary> + /// 浠庨厤缃腑鑾峰彇鎸囧畾鑺傜偣涓嬬殑鍒楄〃鏁版嵁 + /// </summary> + /// <typeparam name="T">鍒楄〃鍏冪礌绫诲瀷</typeparam> + /// <param name="sections">閰嶇疆鑺傜偣璺緞鍙傛暟</param> + /// <returns>缁戝畾鍚庣殑鍒楄〃瀵硅薄</returns> + /// <remarks>闇�瑕佸紩鐢� Microsoft.Extensions.Configuration.Binder 鍖�</remarks> + public static List<T> Get<T>(params string[] sections) + { + List<T> list = new List<T>(); + // 寮曠敤 Microsoft.Extensions.Configuration.Binder 鍖� + Configuration.Bind(string.Join(":", sections), list); + return list; + } + + /// <summary> + /// 浠庨厤缃腑鑾峰彇鎸囧畾璺緞鐨勫�� + /// </summary> + /// <param name="sectionsPath">閰嶇疆椤圭殑璺緞</param> + /// <returns>杩斿洖閰嶇疆鍊硷紝鑻ヨ幏鍙栧け璐ュ垯杩斿洖绌哄瓧绗︿覆</returns> + public static string GetValue(string sectionsPath) + { + try + { + return Configuration[sectionsPath]; + } + catch (Exception) { } + + return ""; + + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ConsoleHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ConsoleHelper.cs" new file mode 100644 index 0000000..2cc4614 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ConsoleHelper.cs" @@ -0,0 +1,57 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Helper +{ + public static class ConsoleHelper + { + private static readonly object _objLock = new(); + + /// <summary> + /// 鍦ㄦ帶鍒跺彴杈撳嚭 + /// </summary> + /// <param name="str">鏂囨湰</param> + /// <param name="color">鍓嶉鑹�</param> + public static void WriteColorLine(string str, ConsoleColor color) + { + lock (_objLock) + { + ConsoleColor currentForeColor = Console.ForegroundColor; + Console.ForegroundColor = color; + Console.WriteLine(str); + Console.ForegroundColor = currentForeColor; + } + } + + /// <summary> + /// 鎵撳嵃閿欒淇℃伅 + /// </summary> + /// <param name="str">寰呮墦鍗扮殑瀛楃涓�</param> + /// <param name="color">鎯宠鎵撳嵃鐨勯鑹�</param> + public static void WriteErrorLine(this string str, ConsoleColor color = ConsoleColor.Red) => WriteColorLine(str, color); + + /// <summary> + /// 鎵撳嵃璀﹀憡淇℃伅 + /// </summary> + /// <param name="str">寰呮墦鍗扮殑瀛楃涓�</param> + /// <param name="color">鎯宠鎵撳嵃鐨勯鑹�</param> + public static void WriteWarningLine(this string str, ConsoleColor color = ConsoleColor.Yellow) => WriteColorLine(str, color); + + /// <summary> + /// 鎵撳嵃姝e父淇℃伅 + /// </summary> + /// <param name="str">寰呮墦鍗扮殑瀛楃涓�</param> + /// <param name="color">鎯宠鎵撳嵃鐨勯鑹�</param> + public static void WriteInfoLine(this string str, ConsoleColor color = ConsoleColor.White) => WriteColorLine(str, color); + + /// <summary> + /// 鎵撳嵃鎴愬姛鐨勪俊鎭� + /// </summary> + /// <param name="str">寰呮墦鍗扮殑瀛楃涓�</param> + /// <param name="color">鎯宠鎵撳嵃鐨勯鑹�</param> + public static void WriteSuccessLine(this string str, ConsoleColor color = ConsoleColor.Green) => WriteColorLine(str, color); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ExportHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ExportHelper.cs" new file mode 100644 index 0000000..028906c --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ExportHelper.cs" @@ -0,0 +1,137 @@ +锘縰sing Magicodes.ExporterAndImporter.Core; +using Magicodes.ExporterAndImporter.Excel; +using Magicodes.IE.Core; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Helper +{ + public static class ExportHelper + { + /// <summary> + /// 鍒涘缓涓�涓姩鎬佺被锛岃绫诲寘鍚寚瀹氱殑灞炴�ч泦鍚� + /// </summary> + /// <param name="propertyInfos">瑕佹坊鍔犲埌鍔ㄦ�佺被涓殑灞炴�ч泦鍚�</param> + /// <returns>鐢熸垚鐨勫姩鎬佺被鍨�</returns> + /// <remarks> + /// 璇ユ柟娉曚細涓烘瘡涓睘鎬х敓鎴愬搴旂殑瀛楁鍜岃闂櫒锛屽苟涓哄甫鏈塖ugarColumn鐗规�х殑灞炴�ф坊鍔燛xporterHeaderAttribute鐗规�� + /// 鍔ㄦ�佺被浼氳鏍囪涓篍xcelExporterAttribute鐗规�� + /// </remarks> + public static Type CreateDynamicClass(this PropertyInfo[] propertyInfos) + { + string className = "DynamicClass"; + AssemblyName assemblyName = new AssemblyName("WIDESEA_Model.Models"); + AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);//瀹氫箟鍏锋湁鎸囧畾鍚嶇О鍜岃闂潈闄愮殑鍔ㄦ�佺▼搴忛泦 + ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");//鍦ㄦ绋嬪簭闆嗕腑瀹氫箟鍛藉悕鐨勬殏鏃跺姩鎬佹ā鍧� + TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);//TypeBuilder:鍦ㄨ繍琛屾椂瀹氫箟骞跺垱寤虹被鐨勬柊瀹炰緥 + + Type attributeType1 = typeof(ExcelExporterAttribute); + MethodInfo [] methodInfos = attributeType1.GetMethods(BindingFlags.Public); + ConstructorInfo[] constructorInfos2 = attributeType1.GetConstructors(); + ConstructorInfo constructorInfo2 = constructorInfos2[0]; + CustomAttributeBuilder customAttributeBuilder2 = new CustomAttributeBuilder(constructorInfo2, new object[] { }); + + typeBuilder.SetCustomAttribute(customAttributeBuilder2); + + foreach (var property in propertyInfos) + { + string propertyName = property.Name; + Type propertyType = property.PropertyType; + + FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private); + PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null); + + SugarColumn sugarColumn = property.GetCustomAttribute<SugarColumn>(); + if (sugarColumn != null) + { + Type attributeType = typeof(ExporterHeaderAttribute); + ConstructorInfo[] constructorInfos = attributeType.GetConstructors(); + ConstructorInfo constructorInfo = constructorInfos[0]; + CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(constructorInfo, new object[] { sugarColumn.ColumnDescription, 11f, null, false, true, true, 0, KnownColor.Empty }); + propertyBuilder.SetCustomAttribute(customAttributeBuilder); + } + + MethodAttributes getSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; + + MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + propertyName, getSetAttributes, propertyType, Type.EmptyTypes); + ILGenerator getIL = getMethodBuilder.GetILGenerator(); + getIL.Emit(OpCodes.Ldarg_0); + getIL.Emit(OpCodes.Ldfld, fieldBuilder); + getIL.Emit(OpCodes.Ret); + + MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + propertyName, getSetAttributes, null, new Type[] { propertyType }); + ILGenerator setIL = setMethodBuilder.GetILGenerator(); + setIL.Emit(OpCodes.Ldarg_0); + setIL.Emit(OpCodes.Ldarg_1); + setIL.Emit(OpCodes.Stfld, fieldBuilder); + setIL.Emit(OpCodes.Ret); + + propertyBuilder.SetGetMethod(getMethodBuilder); + propertyBuilder.SetSetMethod(setMethodBuilder); + + + } + + Type generatedType = typeBuilder.CreateType(); + return generatedType; + } + + /// <summary> + /// 璁剧疆瀵硅薄鐨勫睘鎬у�� + /// </summary> + /// <param name="instance">鐩爣瀵硅薄瀹炰緥</param> + /// <param name="propertyName">瑕佽缃殑灞炴�у悕绉�</param> + /// <param name="value">瑕佽缃殑灞炴�у��</param> + public static void SetProperty(object instance, string propertyName, object value) + { + Type type = instance.GetType(); + PropertyInfo propertyInfo = type.GetProperty(propertyName); + propertyInfo.SetValue(instance, value); + } + + /// <summary> + /// 鑾峰彇瀵硅薄瀹炰緥鐨勬寚瀹氬睘鎬у�� + /// </summary> + /// <param name="instance">瑕佽幏鍙栧睘鎬х殑瀵硅薄瀹炰緥</param> + /// <param name="propertyName">瑕佽幏鍙栫殑灞炴�у悕绉�</param> + /// <returns>杩斿洖鎸囧畾灞炴�х殑鍊�</returns> + public static object GetProperty(object instance, string propertyName) + { + Type type = instance.GetType(); + PropertyInfo propertyInfo = type.GetProperty(propertyName); + return propertyInfo.GetValue(instance); + } + + /// <summary> + /// 璁剧疆瀵硅薄瀹炰緥鐨勫睘鎬у�硷紝閫氳繃鍙嶅皠灏嗘簮瀵硅薄T鐨勫睘鎬у�煎鍒跺埌鐩爣瀹炰緥涓� + /// </summary> + /// <typeparam name="T">婧愬璞$被鍨�</typeparam> + /// <param name="instance">鐩爣瀵硅薄瀹炰緥</param> + /// <param name="value">鍖呭惈灞炴�у�肩殑婧愬璞�</param> + /// <remarks> + /// 璇ユ柟娉曚細閬嶅巻婧愬璞鐨勬墍鏈夊睘鎬э紝閫氳繃鍙嶅皠鑾峰彇骞惰缃埌鐩爣瀹炰緥瀵瑰簲鐨勫睘鎬т笂锛� + /// 鍚屾椂浼氭鏌ュ睘鎬ф槸鍚︽爣璁颁簡ExporterHeaderAttribute鐗规�� + /// </remarks> + public static void SetValue<T>(object instance, T value) + { + Type type = instance.GetType(); + + PropertyInfo[] propertyInfos = typeof(T).GetProperties(); + for (int j = 0; j < propertyInfos.Length; j++) + { + PropertyInfo propertyInfo = type.GetProperty(propertyInfos[j].Name); + object obj = propertyInfos[j].GetValue(value); + propertyInfo.SetValue(instance, obj); + ExporterHeaderAttribute exporterHeaderAttribute = propertyInfo.GetCustomAttribute<ExporterHeaderAttribute>(); + } + + } + + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/FileHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/FileHelper.cs" new file mode 100644 index 0000000..df88f8a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/FileHelper.cs" @@ -0,0 +1,451 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Helper +{ + public class FileHelper : IDisposable + { + + private bool _alreadyDispose = false; + + #region 鏋勯�犲嚱鏁� + public FileHelper() + { + + } + ~FileHelper() + { + Dispose(); ; + } + + protected virtual void Dispose(bool isDisposing) + { + if (_alreadyDispose) return; + _alreadyDispose = true; + } + #endregion + + #region IDisposable 鎴愬憳 + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + + #region 鍙栧緱鏂囦欢鍚庣紑鍚� + /**************************************** + * 鍑芥暟鍚嶇О锛欸etPostfixStr + * 鍔熻兘璇存槑锛氬彇寰楁枃浠跺悗缂�鍚� + * 鍙� 鏁帮細filename:鏂囦欢鍚嶇О + * 璋冪敤绀哄垪锛� + * string filename = "aaa.aspx"; + * string s = EC.FileObj.GetPostfixStr(filename); + *****************************************/ + /// <summary> + /// 鍙栧悗缂�鍚� + /// </summary> + /// <param name="filename">鏂囦欢鍚�</param> + /// <returns>.gif|.html鏍煎紡</returns> + public static string GetPostfixStr(string filename) + { + int start = filename.LastIndexOf("."); + int length = filename.Length; + string postfix = filename.Substring(start, length - start); + return postfix; + } + #endregion + + #region 鏍规嵁鏂囦欢澶у皬鑾峰彇鎸囧畾鍓嶇紑鐨勫彲鐢ㄦ枃浠跺悕 + /// <summary> + /// 鏍规嵁鏂囦欢澶у皬鑾峰彇鎸囧畾鍓嶇紑鐨勫彲鐢ㄦ枃浠跺悕 + /// </summary> + /// <param name="folderPath">鏂囦欢澶�</param> + /// <param name="prefix">鏂囦欢鍓嶇紑</param> + /// <param name="size">鏂囦欢澶у皬(1m)</param> + /// <param name="ext">鏂囦欢鍚庣紑(.log)</param> + /// <returns>鍙敤鏂囦欢鍚�</returns> + public static string GetAvailableFileWithPrefixOrderSize(string folderPath, string prefix, int size = 1 * 1024 * 1024, string ext = ".log") + { + var allFiles = new DirectoryInfo(folderPath); + var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(prefix.ToLower()) && fi.Extension.ToLower() == ext.ToLower() && fi.Length < size).OrderByDescending(d => d.Name).ToList(); + + if (selectFiles.Count > 0) + { + return selectFiles.FirstOrDefault().FullName; + } + + return Path.Combine(folderPath, $@"{prefix}_{DateTime.Now.DateToTimeStamp()}.log"); + } + public static string GetAvailableFileNameWithPrefixOrderSize(string _contentRoot, string prefix, int size = 1 * 1024 * 1024, string ext = ".log") + { + var folderPath = Path.Combine(_contentRoot, "Log"); + if (!Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + + var allFiles = new DirectoryInfo(folderPath); + var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(prefix.ToLower()) && fi.Extension.ToLower() == ext.ToLower() && fi.Length < size).OrderByDescending(d => d.Name).ToList(); + + if (selectFiles.Count > 0) + { + return selectFiles.FirstOrDefault().Name.Replace(".log", ""); + } + + return $@"{prefix}_{DateTime.Now.DateToTimeStamp()}"; + } + #endregion + + #region 鍐欐枃浠� + /**************************************** + * 鍑芥暟鍚嶇О锛歐riteFile + * 鍔熻兘璇存槑锛氬啓鏂囦欢,浼氳鐩栨帀浠ュ墠鐨勫唴瀹� + * 鍙� 鏁帮細Path:鏂囦欢璺緞,Strings:鏂囨湰鍐呭 + * 璋冪敤绀哄垪锛� + * string Path = Server.MapPath("Default2.aspx"); + * string Strings = "杩欐槸鎴戝啓鐨勫唴瀹瑰晩"; + * EC.FileObj.WriteFile(Path,Strings); + *****************************************/ + /// <summary> + /// 鍐欐枃浠� + /// </summary> + /// <param name="Path">鏂囦欢璺緞</param> + /// <param name="Strings">鏂囦欢鍐呭</param> + public static void WriteFile(string Path, string Strings) + { + if (!File.Exists(Path)) + { + FileStream f = File.Create(Path); + f.Close(); + } + StreamWriter f2 = new StreamWriter(Path, false, System.Text.Encoding.UTF8); + f2.Write(Strings); + f2.Close(); + f2.Dispose(); + } + + /// <summary> + /// 鍐欐枃浠� + /// </summary> + /// <param name="Path">鏂囦欢璺緞</param> + /// <param name="Strings">鏂囦欢鍐呭</param> + public static void WriteFileAndDelOldFile(string Path, string Strings) + { + if (!File.Exists(Path)) + { + FileStream f = File.Create(Path); + f.Close(); + } + else + { + File.Delete(Path); + } + StreamWriter f2 = new StreamWriter(Path, false, System.Text.Encoding.UTF8); + f2.Write(Strings); + f2.Close(); + f2.Dispose(); + } + + /// <summary> + /// 鍐欐枃浠� + /// </summary> + /// <param name="Path">鏂囦欢璺緞</param> + /// <param name="Strings">鏂囦欢鍐呭</param> + public static void WriteFile(string Path, byte[] buf) + { + if (!File.Exists(Path)) + { + FileStream f = File.Create(Path); + f.Close(); + } + FileStream f2 = new FileStream(Path, FileMode.Create, FileAccess.Write); + f2.Write(buf, 0, buf.Length); + f2.Close(); + f2.Dispose(); + } + + public static void WriteFile(string Path, string fileName, byte[] buf) + { + if (!Directory.Exists(Path)) + { + Directory.CreateDirectory(Path); + } + if (!File.Exists(Path + "\\" + fileName)) + { + FileStream f = File.Create(Path + "\\" + fileName); + f.Close(); + } + FileStream f2 = new FileStream(Path + "\\" + fileName, FileMode.Create, FileAccess.Write); + f2.Write(buf, 0, buf.Length); + f2.Close(); + f2.Dispose(); + } + + /// <summary> + /// 鍐欐枃浠� + /// </summary> + /// <param name="Path">鏂囦欢璺緞</param> + /// <param name="Strings">鏂囦欢鍐呭</param> + /// <param name="encode">缂栫爜鏍煎紡</param> + public static void WriteFile(string Path, string Strings, Encoding encode) + { + if (!File.Exists(Path)) + { + FileStream f = File.Create(Path); + f.Close(); + } + StreamWriter f2 = new StreamWriter(Path, false, encode); + f2.Write(Strings); + f2.Close(); + f2.Dispose(); + } + #endregion + + #region 璇绘枃浠� + /**************************************** + * 鍑芥暟鍚嶇О锛歊eadFile + * 鍔熻兘璇存槑锛氳鍙栨枃鏈唴瀹� + * 鍙� 鏁帮細Path:鏂囦欢璺緞 + * 璋冪敤绀哄垪锛� + * string Path = Server.MapPath("Default2.aspx"); + * string s = EC.FileObj.ReadFile(Path); + *****************************************/ + /// <summary> + /// 璇绘枃浠� + /// </summary> + /// <param name="Path">鏂囦欢璺緞</param> + /// <returns></returns> + public static string ReadFile(string Path) + { + string s = ""; + if (!File.Exists(Path)) + s = "涓嶅瓨鍦ㄧ浉搴旂殑鐩綍"; + else + { + StreamReader f2 = new StreamReader(Path, System.Text.Encoding.GetEncoding("gb2312")); + s = f2.ReadToEnd(); + f2.Close(); + f2.Dispose(); + } + + return s; + } + + /// <summary> + /// 璇绘枃浠� + /// </summary> + /// <param name="Path">鏂囦欢璺緞</param> + /// <param name="encode">缂栫爜鏍煎紡</param> + /// <returns></returns> + public static string ReadFile(string Path, Encoding encode) + { + string s = ""; + if (!File.Exists(Path)) + s = "涓嶅瓨鍦ㄧ浉搴旂殑鐩綍"; + else + { + StreamReader f2 = new StreamReader(Path, encode); + s = f2.ReadToEnd(); + f2.Close(); + f2.Dispose(); + } + + return s; + } + #endregion + + #region 杩藉姞鏂囦欢 + /**************************************** + * 鍑芥暟鍚嶇О锛欶ileAdd + * 鍔熻兘璇存槑锛氳拷鍔犳枃浠跺唴瀹� + * 鍙� 鏁帮細Path:鏂囦欢璺緞,strings:鍐呭 + * 璋冪敤绀哄垪锛� + * string Path = Server.MapPath("Default2.aspx"); + * string Strings = "鏂拌拷鍔犲唴瀹�"; + * EC.FileObj.FileAdd(Path, Strings); + *****************************************/ + /// <summary> + /// 杩藉姞鏂囦欢 + /// </summary> + /// <param name="Path">鏂囦欢璺緞</param> + /// <param name="strings">鍐呭</param> + public static void FileAdd(string Path, string strings) + { + StreamWriter sw = File.AppendText(Path); + sw.Write(strings); + sw.Flush(); + sw.Close(); + } + #endregion + + #region 鎷疯礉鏂囦欢 + /**************************************** + * 鍑芥暟鍚嶇О锛欶ileCoppy + * 鍔熻兘璇存槑锛氭嫹璐濇枃浠� + * 鍙� 鏁帮細OrignFile:鍘熷鏂囦欢,NewFile:鏂版枃浠惰矾寰� + * 璋冪敤绀哄垪锛� + * string orignFile = Server.MapPath("Default2.aspx"); + * string NewFile = Server.MapPath("Default3.aspx"); + * EC.FileObj.FileCoppy(OrignFile, NewFile); + *****************************************/ + /// <summary> + /// 鎷疯礉鏂囦欢 + /// </summary> + /// <param name="OrignFile">鍘熷鏂囦欢</param> + /// <param name="NewFile">鏂版枃浠惰矾寰�</param> + public static void FileCoppy(string orignFile, string NewFile) + { + File.Copy(orignFile, NewFile, true); + } + + #endregion + + #region 鍒犻櫎鏂囦欢 + /**************************************** + * 鍑芥暟鍚嶇О锛欶ileDel + * 鍔熻兘璇存槑锛氬垹闄ゆ枃浠� + * 鍙� 鏁帮細Path:鏂囦欢璺緞 + * 璋冪敤绀哄垪锛� + * string Path = Server.MapPath("Default3.aspx"); + * EC.FileObj.FileDel(Path); + *****************************************/ + /// <summary> + /// 鍒犻櫎鏂囦欢 + /// </summary> + /// <param name="Path">璺緞</param> + public static void FileDel(string Path) + { + File.Delete(Path); + } + #endregion + + #region 绉诲姩鏂囦欢 + /**************************************** + * 鍑芥暟鍚嶇О锛欶ileMove + * 鍔熻兘璇存槑锛氱Щ鍔ㄦ枃浠� + * 鍙� 鏁帮細OrignFile:鍘熷璺緞,NewFile:鏂版枃浠惰矾寰� + * 璋冪敤绀哄垪锛� + * string orignFile = Server.MapPath("../璇存槑.txt"); + * string NewFile = Server.MapPath("http://www.cnblogs.com/璇存槑.txt"); + * EC.FileObj.FileMove(OrignFile, NewFile); + *****************************************/ + /// <summary> + /// 绉诲姩鏂囦欢 + /// </summary> + /// <param name="OrignFile">鍘熷璺緞</param> + /// <param name="NewFile">鏂拌矾寰�</param> + public static void FileMove(string orignFile, string NewFile) + { + File.Move(orignFile, NewFile); + } + #endregion + + #region 鍦ㄥ綋鍓嶇洰褰曚笅鍒涘缓鐩綍 + /**************************************** + * 鍑芥暟鍚嶇О锛欶olderCreate + * 鍔熻兘璇存槑锛氬湪褰撳墠鐩綍涓嬪垱寤虹洰褰� + * 鍙� 鏁帮細OrignFolder:褰撳墠鐩綍,NewFloder:鏂扮洰褰� + * 璋冪敤绀哄垪锛� + * string orignFolder = Server.MapPath("test/"); + * string NewFloder = "new"; + * EC.FileObj.FolderCreate(OrignFolder, NewFloder); + *****************************************/ + /// <summary> + /// 鍦ㄥ綋鍓嶇洰褰曚笅鍒涘缓鐩綍 + /// </summary> + /// <param name="OrignFolder">褰撳墠鐩綍</param> + /// <param name="NewFloder">鏂扮洰褰�</param> + public static void FolderCreate(string orignFolder, string NewFloder) + { + Directory.SetCurrentDirectory(orignFolder); + Directory.CreateDirectory(NewFloder); + } + #endregion + + #region 閫掑綊鍒犻櫎鏂囦欢澶圭洰褰曞強鏂囦欢 + /**************************************** + * 鍑芥暟鍚嶇О锛欴eleteFolder + * 鍔熻兘璇存槑锛氶�掑綊鍒犻櫎鏂囦欢澶圭洰褰曞強鏂囦欢 + * 鍙� 鏁帮細dir:鏂囦欢澶硅矾寰� + * 璋冪敤绀哄垪锛� + * string dir = Server.MapPath("test/"); + * EC.FileObj.DeleteFolder(dir); + *****************************************/ + /// <summary> + /// 閫掑綊鍒犻櫎鏂囦欢澶圭洰褰曞強鏂囦欢 + /// </summary> + /// <param name="dir"></param> + /// <returns></returns> + public static void DeleteFolder(string dir) + { + if (Directory.Exists(dir)) //濡傛灉瀛樺湪杩欎釜鏂囦欢澶瑰垹闄や箣 + { + foreach (string d in Directory.GetFileSystemEntries(dir)) + { + if (File.Exists(d)) + File.Delete(d); //鐩存帴鍒犻櫎鍏朵腑鐨勬枃浠� + else + DeleteFolder(d); //閫掑綊鍒犻櫎瀛愭枃浠跺す + } + Directory.Delete(dir); //鍒犻櫎宸茬┖鏂囦欢澶� + } + + } + #endregion + + #region 灏嗘寚瀹氭枃浠跺す涓嬮潰鐨勬墍鏈夊唴瀹筩opy鍒扮洰鏍囨枃浠跺す涓嬮潰 鏋滅洰鏍囨枃浠跺す涓哄彧璇诲睘鎬у氨浼氭姤閿欍�� + /**************************************** + * 鍑芥暟鍚嶇О锛欳opyDir + * 鍔熻兘璇存槑锛氬皢鎸囧畾鏂囦欢澶逛笅闈㈢殑鎵�鏈夊唴瀹筩opy鍒扮洰鏍囨枃浠跺す涓嬮潰 鏋滅洰鏍囨枃浠跺す涓哄彧璇诲睘鎬у氨浼氭姤閿欍�� + * 鍙� 鏁帮細srcPath:鍘熷璺緞,aimPath:鐩爣鏂囦欢澶� + * 璋冪敤绀哄垪锛� + * string srcPath = Server.MapPath("test/"); + * string aimPath = Server.MapPath("test1/"); + * EC.FileObj.CopyDir(srcPath,aimPath); + *****************************************/ + /// <summary> + /// 鎸囧畾鏂囦欢澶逛笅闈㈢殑鎵�鏈夊唴瀹筩opy鍒扮洰鏍囨枃浠跺す涓嬮潰 + /// </summary> + /// <param name="srcPath">鍘熷璺緞</param> + /// <param name="aimPath">鐩爣鏂囦欢澶�</param> + public static void CopyDir(string srcPath, string aimPath) + { + try + { + // 妫�鏌ョ洰鏍囩洰褰曟槸鍚︿互鐩綍鍒嗗壊瀛楃缁撴潫濡傛灉涓嶆槸鍒欐坊鍔犱箣 + if (aimPath[aimPath.Length - 1] != Path.DirectorySeparatorChar) + aimPath += Path.DirectorySeparatorChar; + // 鍒ゆ柇鐩爣鐩綍鏄惁瀛樺湪濡傛灉涓嶅瓨鍦ㄥ垯鏂板缓涔� + if (!Directory.Exists(aimPath)) + Directory.CreateDirectory(aimPath); + // 寰楀埌婧愮洰褰曠殑鏂囦欢鍒楄〃锛岃閲岄潰鏄寘鍚枃浠朵互鍙婄洰褰曡矾寰勭殑涓�涓暟缁� + //濡傛灉浣犳寚鍚慶opy鐩爣鏂囦欢涓嬮潰鐨勬枃浠惰�屼笉鍖呭惈鐩綍璇蜂娇鐢ㄤ笅闈㈢殑鏂规硶 + //string[] fileList = Directory.GetFiles(srcPath); + string[] fileList = Directory.GetFileSystemEntries(srcPath); + //閬嶅巻鎵�鏈夌殑鏂囦欢鍜岀洰褰� + foreach (string file in fileList) + { + //鍏堝綋浣滅洰褰曞鐞嗗鏋滃瓨鍦ㄨ繖涓洰褰曞氨閫掑綊Copy璇ョ洰褰曚笅闈㈢殑鏂囦欢 + + if (Directory.Exists(file)) + CopyDir(file, aimPath + Path.GetFileName(file)); + //鍚﹀垯鐩存帴Copy鏂囦欢 + else + File.Copy(file, aimPath + Path.GetFileName(file), true); + } + + } + catch (Exception ee) + { + throw new Exception(ee.ToString()); + } + } + #endregion + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/HttpContextHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/HttpContextHelper.cs" new file mode 100644 index 0000000..0ad466f --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/HttpContextHelper.cs" @@ -0,0 +1,45 @@ +锘縰sing Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Helper +{ + public static class HttpContextHelper + { + /// <summary> + /// 鑾峰彇瀹㈡埛绔湡瀹濱P鍦板潃 + /// </summary> + /// <param name="context">Http涓婁笅鏂囧璞�</param> + /// <returns>瀹㈡埛绔疘P鍦板潃瀛楃涓�</returns> + /// <remarks> + /// 浼樺厛浠嶺-Real-IP鍜孹-Forwarded-For璇锋眰澶翠腑鑾峰彇IP鍦板潃锛� + /// 濡傛灉涓嶅瓨鍦ㄥ垯杩斿洖杩炴帴杩滅▼IP鍦板潃 + /// </remarks> + public static string GetUserIp(this HttpContext context) + { + string realIP = null; + string forwarded = null; + string remoteIpAddress = context.Connection.RemoteIpAddress.ToString(); + if (context.Request.Headers.ContainsKey("X-Real-IP")) + { + realIP = context.Request.Headers["X-Real-IP"].ToString(); + if (realIP != remoteIpAddress) + { + remoteIpAddress = realIP; + } + } + if (context.Request.Headers.ContainsKey("X-Forwarded-For")) + { + forwarded = context.Request.Headers["X-Forwarded-For"].ToString(); + if (forwarded != remoteIpAddress) + { + remoteIpAddress = forwarded; + } + } + return remoteIpAddress; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/HttpHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/HttpHelper.cs" new file mode 100644 index 0000000..c1d9952 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/HttpHelper.cs" @@ -0,0 +1,179 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.LogHelper; + +namespace WIDESEA_Core.Helper +{ + public class HttpHelper + { + /// <summary> + /// 寮傛鍙戦�丠TTP GET璇锋眰骞惰繑鍥炲搷搴斿唴瀹� + /// </summary> + /// <param name="serviceAddress">璇锋眰鐨勬湇鍔″湴鍧�</param> + /// <param name="contentType">鍝嶅簲鍐呭绫诲瀷锛岄粯璁や负application/json</param> + /// <param name="headers">璇锋眰澶村瓧鍏革紝鍙�夊弬鏁�</param> + /// <returns>杩斿洖璇锋眰缁撴灉鐨勫瓧绗︿覆鍐呭</returns> + /// <exception cref="Exception">褰撹姹傝繃绋嬩腑鍙戠敓閿欒鏃舵姏鍑哄紓甯�</exception> + /// <remarks> + /// 鏂规硶浼氳嚜鍔ㄨ褰曡姹傛棩蹇楋紝鍖呭惈璇锋眰鍦板潃銆佸搷搴斿唴瀹瑰拰鑰楁椂绛変俊鎭� + /// 榛樿璇锋眰瓒呮椂鏃堕棿涓�60绉� + /// </remarks> + public static async Task<string> GetAsync(string serviceAddress, string contentType = "application/json", Dictionary<string, string>? headers = null) + { + string result = string.Empty; + DateTime beginDate = DateTime.Now; + try + { + using HttpClient httpClient = new HttpClient(); + httpClient.Timeout = new TimeSpan(0, 0, 60); + + if (headers != null) + { + foreach (var header in headers) + httpClient.DefaultRequestHeaders.Add(header.Key, header.Value); + } + + result = await httpClient.GetAsync(serviceAddress).Result.Content.ReadAsStringAsync(); + return result; + } + catch (Exception e) + { + throw new Exception(e.Message); + } + finally + { + Logger.Add(serviceAddress, "", result, beginDate); + } + } + + /// <summary> + /// 寮傛鍙戦�丠TTP POST璇锋眰 + /// </summary> + /// <param name="serviceAddress">鏈嶅姟鍦板潃</param> + /// <param name="requestJson">璇锋眰JSON鏁版嵁</param> + /// <param name="contentType">鍐呭绫诲瀷锛岄粯璁や负application/json</param> + /// <param name="headers">璇锋眰澶村瓧鍏�</param> + /// <returns>杩斿洖鍝嶅簲鍐呭瀛楃涓诧紝澶辫触鏃舵姏鍑哄紓甯�</returns> + /// <remarks> + /// 鑷姩璁板綍璇锋眰鏃ュ織锛屽寘鍚姹傚湴鍧�銆佽姹傛暟鎹�佸搷搴旀暟鎹拰鑰楁椂 + /// </remarks> + public static async Task<string?> PostAsync(string serviceAddress, string requestJson = null, string contentType = "application/json", Dictionary<string, string>? headers = null) + { + string result = string.Empty; + DateTime beginDate = DateTime.Now; + try + { + using (HttpContent httpContent = new StringContent(requestJson)) + { + httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + using HttpClient httpClient = new HttpClient(); + httpClient.Timeout = new TimeSpan(0, 0, 60); + + if (headers != null) + { + foreach (var header in headers) + httpClient.DefaultRequestHeaders.Add(header.Key, header.Value); + } + + result = await httpClient.PostAsync(serviceAddress, httpContent).Result.Content.ReadAsStringAsync(); + } + return result; + } + catch (Exception e) + { + throw new Exception(e.Message); + } + finally + { + Logger.Add(serviceAddress, requestJson == null ? "": requestJson, result, beginDate); + } + } + + /// <summary> + /// 鍙戦�丠TTP GET璇锋眰鍒版寚瀹氭湇鍔″湴鍧� + /// </summary> + /// <param name="serviceAddress">璇锋眰鐨勬湇鍔″湴鍧�</param> + /// <param name="contentType">璇锋眰鍐呭绫诲瀷锛岄粯璁や负application/json</param> + /// <param name="headers">璇锋眰澶村瓧鍏革紝鍙�夊弬鏁�</param> + /// <returns>杩斿洖鏈嶅姟鍝嶅簲瀛楃涓�</returns> + /// <exception cref="Exception">褰撹姹傚彂鐢熼敊璇椂鎶涘嚭寮傚父</exception> + /// /// <remarks> + /// 璇ユ柟娉曚細鑷姩璁板綍璇锋眰鏃ュ織锛屽寘鍚姹傚湴鍧�銆佽姹傛暟鎹�佸搷搴旀暟鎹拰鑰楁椂 + /// </remarks> + public static string Get(string serviceAddress, string contentType = "application/json", Dictionary<string, string>? headers = null) + { + string result = string.Empty; + DateTime beginDate = DateTime.Now; + try + { + using HttpClient httpClient = new HttpClient(); + httpClient.Timeout = new TimeSpan(0, 0, 60); + + if (headers != null) + { + foreach (var header in headers) + httpClient.DefaultRequestHeaders.Add(header.Key, header.Value); + } + + result = httpClient.GetStringAsync(serviceAddress).Result; + return result; + } + catch (Exception e) + { + throw new Exception(e.Message); + } + finally + { + Logger.Add(serviceAddress, "", result, beginDate); + } + } + + /// <summary> + /// 鍙戦�丠TTP POST璇锋眰鍒版寚瀹氭湇鍔″湴鍧� + /// </summary> + /// <param name="serviceAddress">鏈嶅姟鍦板潃URL</param> + /// <param name="requestJson">璇锋眰鐨凧SON鏁版嵁</param> + /// <param name="contentType">鍐呭绫诲瀷锛岄粯璁や负application/json</param> + /// <param name="headers">璇锋眰澶村瓧鍏�</param> + /// <returns>杩斿洖鏈嶅姟绔搷搴斿唴瀹�</returns> + /// <exception cref="Exception">褰撹姹傚彂鐢熷紓甯告椂鎶涘嚭</exception> + /// <remarks> + /// 璇ユ柟娉曚細鑷姩璁板綍璇锋眰鏃ュ織锛屽寘鍚姹傚湴鍧�銆佽姹傛暟鎹�佸搷搴旀暟鎹拰鑰楁椂 + /// </remarks> + public static string Post(string serviceAddress, string requestJson = null, string contentType = "application/json", Dictionary<string, string>? headers = null) + { + string result = string.Empty; + DateTime beginDate = DateTime.Now; + try + { + using (HttpContent httpContent = new StringContent(requestJson)) + { + httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + using HttpClient httpClient = new HttpClient(); + httpClient.Timeout = new TimeSpan(0, 0, 60); + + if (headers != null) + { + foreach (var header in headers) + httpClient.DefaultRequestHeaders.Add(header.Key, header.Value); + } + + result = httpClient.PostAsync(serviceAddress, httpContent).Result.Content.ReadAsStringAsync().Result; + } + return result; + } + catch (Exception e) + { + throw new Exception(e.Message); + } + finally + { + Logger.Add(serviceAddress, requestJson == null ? "" : requestJson, result, beginDate); + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/MD5Helper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/MD5Helper.cs" new file mode 100644 index 0000000..d4b2185 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/MD5Helper.cs" @@ -0,0 +1,101 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Helper +{ + public class MD5Helper + { + /// <summary> + /// 16浣峂D5鍔犲瘑 + /// </summary> + /// <param name="password"></param> + /// <returns></returns> + public static string MD5Encrypt16(string password) + { + var md5 = MD5.Create(); + string t2 = BitConverter.ToString(md5.ComputeHash(Encoding.Default.GetBytes(password)), 4, 8); + t2 = t2.Replace("-", string.Empty); + return t2; + } + + /// <summary> + /// 32浣峂D5鍔犲瘑 + /// </summary> + /// <param name="password"></param> + /// <returns></returns> + public static string MD5Encrypt32(string password = "") + { + string pwd = string.Empty; + try + { + if (!string.IsNullOrEmpty(password) && !string.IsNullOrWhiteSpace(password)) + { + MD5 md5 = MD5.Create(); //瀹炰緥鍖栦竴涓猰d5瀵瑰儚 + // 鍔犲瘑鍚庢槸涓�涓瓧鑺傜被鍨嬬殑鏁扮粍锛岃繖閲岃娉ㄦ剰缂栫爜UTF8/Unicode绛夌殑閫夋嫨銆� + byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(password)); + // 閫氳繃浣跨敤寰幆锛屽皢瀛楄妭绫诲瀷鐨勬暟缁勮浆鎹负瀛楃涓诧紝姝ゅ瓧绗︿覆鏄父瑙勫瓧绗︽牸寮忓寲鎵�寰� + foreach (var item in s) + { + // 灏嗗緱鍒扮殑瀛楃涓蹭娇鐢ㄥ崄鍏繘鍒剁被鍨嬫牸寮忋�傛牸寮忓悗鐨勫瓧绗︽槸灏忓啓鐨勫瓧姣嶏紝濡傛灉浣跨敤澶у啓锛圶锛夊垯鏍煎紡鍚庣殑瀛楃鏄ぇ鍐欏瓧绗� + pwd = string.Concat(pwd, item.ToString("X2")); + } + } + } + catch + { + throw new Exception($"閿欒鐨� password 瀛楃涓�:銆恵password}銆�"); + } + return pwd; + } + + /// <summary> + /// 64浣峂D5鍔犲瘑 + /// </summary> + /// <param name="password"></param> + /// <returns></returns> + public static string MD5Encrypt64(string password) + { + // 瀹炰緥鍖栦竴涓猰d5瀵瑰儚 + // 鍔犲瘑鍚庢槸涓�涓瓧鑺傜被鍨嬬殑鏁扮粍锛岃繖閲岃娉ㄦ剰缂栫爜UTF8/Unicode绛夌殑閫夋嫨銆� + MD5 md5 = MD5.Create(); + byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(password)); + return Convert.ToBase64String(s); + } + /// <summary> + /// Sha1鍔犲瘑 + /// </summary> + /// <param name="str">瑕佸姞瀵嗙殑瀛楃涓�</param> + /// <returns>鍔犲瘑鍚庣殑鍗佸叚杩涘埗鐨勫搱甯屾暎鍒楋紙瀛楃涓诧級</returns> + public static string Sha1(string str, string format = "x2") + { + var buffer = Encoding.UTF8.GetBytes(str); + var data = SHA1.Create().ComputeHash(buffer); + var sb = new StringBuilder(); + foreach (var t in data) + { + sb.Append(t.ToString(format)); + } + return sb.ToString(); + } + /// <summary> + /// Sha256鍔犲瘑 + /// </summary> + /// <param name="str">瑕佸姞瀵嗙殑瀛楃涓�</param> + /// <returns>鍔犲瘑鍚庣殑鍗佸叚杩涘埗鐨勫搱甯屾暎鍒楋紙瀛楃涓诧級</returns> + public static string Sha256(string str, string format = "x2") + { + var buffer = Encoding.UTF8.GetBytes(str); + var data = SHA256.Create().ComputeHash(buffer); + var sb = new StringBuilder(); + foreach (var t in data) + { + sb.Append(t.ToString(format)); + } + return sb.ToString(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/MethodInfoExtensions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/MethodInfoExtensions.cs" new file mode 100644 index 0000000..e1457b7 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/MethodInfoExtensions.cs" @@ -0,0 +1,27 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Helper +{ + public static class MethodInfoExtensions + { + /// <summary> + /// 鑾峰彇鏂规硶鐨勫畬鏁村悕绉帮紝鍖呮嫭澹版槑绫诲瀷鐨勫叏鍚嶅拰鏂规硶鍚� + /// </summary> + /// <param name="method">瑕佽幏鍙栧畬鏁村悕绉扮殑鏂规硶淇℃伅</param> + /// <returns>杩斿洖鏍煎紡涓�"澹版槑绫诲瀷鍏ㄥ悕.鏂规硶鍚�"鐨勫瓧绗︿覆锛屽鏋滃0鏄庣被鍨嬩负绌哄垯鍙繑鍥炴柟娉曞悕</returns> + public static string GetFullName(this MethodInfo method) + { + if (method.DeclaringType == null) + { + return $@"{method.Name}"; + } + + return $"{method.DeclaringType.FullName}.{method.Name}"; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ObjectExtension.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ObjectExtension.cs" new file mode 100644 index 0000000..ae0b212 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/ObjectExtension.cs" @@ -0,0 +1,89 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Helper +{ + public static class ObjectExtension + { + /// <summary> + /// 灏嗗瓧鍏稿垪琛ㄨ浆鎹负鎸囧畾绫诲瀷鐨勫璞″垪琛� + /// </summary> + /// <typeparam name="T">鐩爣瀵硅薄绫诲瀷</typeparam> + /// <param name="dicList">婧愬瓧鍏稿垪琛�</param> + /// <returns>杞崲鍚庣殑瀵硅薄鍒楄〃</returns> + public static List<T> DicToIEnumerable<T>(this List<Dictionary<string, object>> dicList) + { + List<T> list = new List<T>(); + foreach (Dictionary<string, object> dic in dicList) + { + list.Add(dic.DicToModel<T>()); + } + return list; + } + + /// <summary> + /// 灏嗗瓧鍏歌浆鎹负鎸囧畾绫诲瀷鐨勬ā鍨嬪璞� + /// </summary> + /// <typeparam name="T">鐩爣妯″瀷绫诲瀷</typeparam> + /// <param name="dic">鍖呭惈灞炴�у�肩殑瀛楀吀</param> + /// <returns>杞崲鍚庣殑妯″瀷瀵硅薄</returns> + /// <remarks> + /// 1. 鏀寔閫氳繃灞炴�у悕銆侀瀛楁瘝澶у啓鎴栧皬鍐欑殑灞炴�у悕浠庡瓧鍏镐腑鏌ユ壘鍊� + /// 2. 澶勭悊浜哠ugarColumn鐗规�х殑鐗规畩閫昏緫锛氫富閿�/鑷瀛楁璺宠繃锛岄潪绌哄瓧娈垫牎楠� + /// 3. 鑷姩杩涜绫诲瀷杞崲 + /// </remarks> + /// <exception cref="Exception">褰撻潪绌哄瓧娈靛�间负null鎴栫┖鏃舵姏鍑哄紓甯�</exception> + public static T DicToModel<T>(this Dictionary<string, object> dic) + { + T model = Activator.CreateInstance<T>(); + PropertyInfo[] propertyInfos = typeof(T).GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance); + foreach (var property in propertyInfos) + { + object? value = null; + if (!dic.TryGetValue(property.Name, out value)) + { + if (!dic.TryGetValue(property.Name.FirstLetterToUpper(), out value)) + { + if (!dic.TryGetValue(property.Name.FirstLetterToLower(), out value)) + { + continue; + } + } + } + + SugarColumn? sugarColumn = property.GetCustomAttribute<SugarColumn>(); + if (sugarColumn != null) + { + if ((value == null || value.Equals(""))) + { + if (sugarColumn.IsIdentity || sugarColumn.IsPrimaryKey) + continue; + else if (sugarColumn.IsNullable) + { + property.SetValue(model, value); + } + else + { + throw new Exception($"The value of {property.Name} is null or empty, but it is not allowed to be null or empty."); + } + } + else + { + property.SetValue(model, value.ChangeType(property.PropertyType)); + } + + if (sugarColumn.IsIdentity || sugarColumn.IsPrimaryKey) + continue; + } + if (value != null && sugarColumn != null && !sugarColumn.IsNullable) + property.SetValue(model, value.ChangeType(property.PropertyType)); + } + return model; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/RuntimeExtension.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/RuntimeExtension.cs" new file mode 100644 index 0000000..c3cc98e --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/RuntimeExtension.cs" @@ -0,0 +1,113 @@ +锘� +using Microsoft.Extensions.DependencyModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Helper +{ + public static class RuntimeExtension + { + /// <summary> + /// 鑾峰彇褰撳墠椤圭洰涓墍鏈夌殑绋嬪簭闆� + /// </summary> + /// <returns>杩斿洖椤圭洰涓墍鏈夐潪绯荤粺绋嬪簭闆嗙殑闆嗗悎</returns> + /// <remarks> + /// 璇ユ柟娉曚細杩囨护鎺夌郴缁熺▼搴忛泦鍜孨uGet鍖咃紝鍙姞杞介」鐩嚜韬殑绋嬪簭闆嗐�� + /// 鍔犺浇澶辫触鐨勭▼搴忛泦浼氳蹇界暐锛屼笉浼氭姏鍑哄紓甯搞�� + /// </remarks> + public static IList<Assembly> GetAllAssemblies() + { + var list = new List<Assembly>(); + var deps = DependencyContext.Default; + //鍙姞杞介」鐩腑鐨勭▼搴忛泦 + var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type == "project"); //鎺掗櫎鎵�鏈夌殑绯荤粺绋嬪簭闆嗐�丯uget涓嬭浇鍖� + foreach (var lib in libs) + { + try + { + var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name)); + list.Add(assembly); + } + catch (Exception e) + { + //Log.Debug(e, "GetAllAssemblies Exception:{ex}", e.Message); + } + } + + return list; + } + + /// <summary> + /// 鏍规嵁绋嬪簭闆嗗悕绉拌幏鍙栧搴旂殑绋嬪簭闆� + /// </summary> + /// <param name="assemblyName">瑕佹煡鎵剧殑绋嬪簭闆嗗悕绉�</param> + /// <returns>鎵惧埌鐨勭▼搴忛泦锛岃嫢鏈壘鍒板垯杩斿洖null</returns> + public static Assembly GetAssembly(string assemblyName) + { + return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName)); + } + + /// <summary> + /// 鑾峰彇褰撳墠搴旂敤绋嬪簭鍩熶腑鎵�鏈夌▼搴忛泦瀹氫箟鐨勭被鍨嬮泦鍚� + /// </summary> + /// <returns>鍖呭惈鎵�鏈夌被鍨嬬殑鍒楄〃</returns> + public static IList<Type> GetAllTypes() + { + var list = new List<Type>(); + foreach (var assembly in GetAllAssemblies()) + { + var typeInfos = assembly.DefinedTypes; + foreach (var typeInfo in typeInfos) + { + list.Add(typeInfo.AsType()); + } + } + + return list; + } + + /// <summary> + /// 閫氳繃绋嬪簭闆嗗悕绉拌幏鍙栬绋嬪簭闆嗕腑鐨勬墍鏈夌被鍨� + /// </summary> + /// <param name="assemblyName">瑕佸姞杞界殑绋嬪簭闆嗗悕绉�</param> + /// <returns>鍖呭惈绋嬪簭闆嗕腑鎵�鏈夌被鍨嬬殑鍒楄〃</returns> + public static IList<Type> GetTypesByAssembly(string assemblyName) + { + var list = new List<Type>(); + var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName)); + var typeInfos = assembly.DefinedTypes; + foreach (var typeInfo in typeInfos) + { + list.Add(typeInfo.AsType()); + } + + return list; + } + + /// <summary> + /// 鏍规嵁绫诲瀷鍚嶇О鍜屽熀鎺ュ彛绫诲瀷鑾峰彇瀹炵幇绫诲瀷 + /// </summary> + /// <param name="typeName">瑕佹煡鎵剧殑绫诲瀷鍚嶇О</param> + /// <param name="baseInterfaceType">鍩烘帴鍙g被鍨�</param> + /// <returns>绗﹀悎鏉′欢鐨勭涓�涓潪鎶借薄銆侀潪娉涘瀷鐨勭被绫诲瀷锛岃嫢鏈壘鍒板垯杩斿洖null</returns> + public static Type GetImplementType(string typeName, Type baseInterfaceType) + { + return GetAllTypes().FirstOrDefault(t => + { + if (t.Name == typeName && + t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name)) + { + var typeInfo = t.GetTypeInfo(); + return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType; + } + + return false; + }); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/SecurityEncDecryptHelper.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/SecurityEncDecryptHelper.cs" new file mode 100644 index 0000000..c44c9e2 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/SecurityEncDecryptHelper.cs" @@ -0,0 +1,93 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Const; +using WIDESEA_Core.DB; + +namespace WIDESEA_Core.Helper +{ + public static class SecurityEncDecryptHelper + { + private static byte[] Keys = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; + /// <summary> + /// DES鍔犲瘑瀛楃涓� + /// </summary> + /// <param name="encryptString">寰呭姞瀵嗙殑瀛楃涓�</param> + /// <param name="encryptKey">鍔犲瘑瀵嗛挜,瑕佹眰涓�16浣�</param> + /// <returns>鍔犲瘑鎴愬姛杩斿洖鍔犲瘑鍚庣殑瀛楃涓诧紝澶辫触杩斿洖婧愪覆</returns> + + public static string EncryptDES(this string encryptString, string encryptKey) + { + try + { + byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 16)); + byte[] rgbIV = Keys; + byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString); + + using (var DCSP = Aes.Create()) + { + using (MemoryStream mStream = new MemoryStream()) + { + using (CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write)) + { + cStream.Write(inputByteArray, 0, inputByteArray.Length); + cStream.FlushFinalBlock(); + return Convert.ToBase64String(mStream.ToArray()).Replace('+', '_').Replace('/', '~'); + } + } + } + } + catch (Exception ex) + { + throw new Exception("瀵嗙爜鍔犲瘑寮傚父" + ex.Message); + } + + } + + /// <summary> + /// DES瑙e瘑瀛楃涓� + /// </summary> + /// <param name="decryptString">寰呰В瀵嗙殑瀛楃涓�</param> + /// <param name="decryptKey">瑙e瘑瀵嗛挜,瑕佹眰涓�16浣�,鍜屽姞瀵嗗瘑閽ョ浉鍚�</param> + /// <returns>瑙e瘑鎴愬姛杩斿洖瑙e瘑鍚庣殑瀛楃涓诧紝澶辫触杩旀簮涓�</returns> + + public static string DecryptDES(this string decryptString, string decryptKey) + { + if (decryptKey == AppSecret.DB && !AppSettings.Get(MainDb.ConnectionStringsEncryption).ObjToBool()) + return decryptString; + + byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 16)); + byte[] rgbIV = Keys; + byte[] inputByteArray = Convert.FromBase64String(decryptString.Replace('_', '+').Replace('~', '/')); + using (var DCSP = Aes.Create()) + { + using (MemoryStream mStream = new MemoryStream()) + { + using (CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write)) + { + byte[] inputByteArrays = new byte[inputByteArray.Length]; + cStream.Write(inputByteArray, 0, inputByteArray.Length); + cStream.FlushFinalBlock(); + return Encoding.UTF8.GetString(mStream.ToArray()); + } + } + } + } + public static bool TryDecryptDES(this string decryptString, string decryptKey, out string result) + { + result = ""; + try + { + result = DecryptDES(decryptString, decryptKey); + return true; + } + catch + { + return false; + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/UtilConvert.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/UtilConvert.cs" new file mode 100644 index 0000000..8a2daf8 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Helper/UtilConvert.cs" @@ -0,0 +1,559 @@ +锘縰sing Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using WIDESEA_Core.Const; +using WIDESEA_Core.Enums; + +namespace WIDESEA_Core.Helper +{ + public static class UtilConvert + { + private static DateTime dateStart = new DateTime(1970, 1, 1, 8, 0, 0); + + private static long longTime = 621355968000000000; + + private static int samllTime = 10000000; + + /// <summary> + /// 灏嗘椂闂存埑杞崲涓烘湰鍦版棩鏈熸椂闂� + /// </summary> + /// <param name="timeStamp">瑕佽浆鎹㈢殑鏃堕棿鎴冲璞�</param> + /// <returns>杞崲鍚庣殑鏈湴DateTime瀵硅薄</returns> + /// <remarks>濡傛灉鍙傛暟涓簄ull锛屽垯杩斿洖榛樿璧峰鏃ユ湡</remarks> + public static DateTime GetTimeSpmpToDate(this object timeStamp) + { + if (timeStamp == null) return dateStart; + DateTime dateTime = new DateTime(longTime + Convert.ToInt64(timeStamp) * samllTime, DateTimeKind.Utc).ToLocalTime(); + return dateTime; + } + + /// <summary> + /// 灏嗗璞″簭鍒楀寲涓篔SON瀛楃涓� + /// </summary> + /// <param name="obj">瑕佸簭鍒楀寲鐨勫璞�</param> + /// <param name="formatDate">鏃ユ湡鏍煎紡鍖栬缃紝榛樿涓�"yyyy-MM-dd HH:mm:ss"鏍煎紡</param> + /// <returns>搴忓垪鍖栧悗鐨凧SON瀛楃涓诧紝濡傛灉瀵硅薄涓簄ull鍒欒繑鍥瀗ull</returns> + public static string Serialize(this object obj, JsonSerializerSettings formatDate = null) + { + if (obj == null) return null; + formatDate = formatDate ?? new JsonSerializerSettings + { + DateFormatString = "yyyy-MM-dd HH:mm:ss" + }; + return JsonConvert.SerializeObject(obj, formatDate); + } + + /// <summary> + /// 灏咼SON瀛楃涓插弽搴忓垪鍖栦负鎸囧畾绫诲瀷鐨勫璞� + /// </summary> + /// <typeparam name="T">鐩爣瀵硅薄绫诲瀷</typeparam> + /// <param name="json">瑕佸弽搴忓垪鍖栫殑JSON瀛楃涓�</param> + /// <returns>鍙嶅簭鍒楀寲鍚庣殑瀵硅薄瀹炰緥锛屽鏋滆緭鍏ヤ负绌哄垯杩斿洖榛樿鍊�</returns> + /// <remarks> + /// 褰撹緭鍏ヤ负"{}"鏃朵細鑷姩杞崲涓�"[]"澶勭悊 + /// </remarks> + public static T DeserializeObject<T>(this string json) + { + if (string.IsNullOrEmpty(json)) + { + return default(T); + } + if (json == "{}") + { + json = "[]"; + } + return JsonConvert.DeserializeObject<T>(json); + } + + /// <summary> + /// 灏嗗瓧绗︿覆鐨勯瀛楁瘝杞崲涓哄皬鍐� + /// </summary> + /// <param name="thisValue">瑕佸鐞嗙殑瀛楃涓�</param> + /// <returns>棣栧瓧姣嶅皬鍐欑殑瀛楃涓诧紝鑻ヨ緭鍏ヤ负绌哄垯杩斿洖绌哄瓧绗︿覆</returns> + public static string FirstLetterToLower(this string thisValue) + { + if (string.IsNullOrEmpty(thisValue)) return string.Empty; + string result = thisValue.Substring(0, 1).ToLower() + thisValue.Substring(1, thisValue.Length - 1); + return result; + } + + /// <summary> + /// 灏嗗瓧绗︿覆鐨勯瀛楁瘝杞崲涓哄ぇ鍐� + /// </summary> + /// <param name="thisValue">瑕佸鐞嗙殑瀛楃涓�</param> + /// <returns>棣栧瓧姣嶅ぇ鍐欑殑瀛楃涓诧紝鑻ヨ緭鍏ヤ负绌哄垯杩斿洖绌哄瓧绗︿覆</returns> + public static string FirstLetterToUpper(this string thisValue) + { + if (string.IsNullOrEmpty(thisValue)) return string.Empty; + string result = thisValue.Substring(0, 1).ToUpper() + thisValue.Substring(1, thisValue.Length - 1); + return result; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负鏁村瀷鍊� + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <returns>杞崲鍚庣殑鏁村瀷鍊硷紝杞崲澶辫触杩斿洖0</returns> + /// <remarks> + /// 鏀寔澶勭悊null鍊笺�丏BNull.Value鍜屾灇涓剧被鍨� + /// </remarks> + public static int ObjToInt(this object thisValue) + { + int reval = 0; + if (thisValue == null) return 0; + if (thisValue is Enum && thisValue != DBNull.Value && Enum.TryParse(thisValue.GetType(), thisValue.ToString(), out var val)) + { + return Convert.ToInt32(val.ChangeType(typeof(int))); + } + if (thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + + return reval; + } + + /// <summary> + /// 灏嗗弻绮惧害娴偣鏁拌浆鎹负32浣嶆湁绗﹀彿鏁存暟 + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑鍙岀簿搴︽诞鐐规暟</param> + /// <returns>杞崲鍚庣殑32浣嶆湁绗﹀彿鏁存暟</returns> + public static int DoubleToInt(this double thisValue) + { + int reval = 0; + + return Convert.ToInt32(thisValue); + } + + /// <summary> + /// 灏嗗璞¤浆鎹负鏁存暟锛岃嫢杞崲澶辫触鍒欒繑鍥炴寚瀹氱殑閿欒鍊� + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <param name="errorValue">杞崲澶辫触鏃惰繑鍥炵殑閿欒鍊�</param> + /// <returns>杞崲鍚庣殑鏁存暟鍊兼垨鎸囧畾鐨勯敊璇��</returns> + public static int ObjToInt(this object thisValue, int errorValue) + { + int reval = 0; + if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + + return errorValue; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负闀挎暣鍨�(long) + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <returns>杞崲鍚庣殑闀挎暣鍨嬪�硷紝杞崲澶辫触鎴栦负null鏃惰繑鍥�0</returns> + /// <remarks> + /// 澶勭悊DBNull.Value鎯呭喌锛屽苟灏濊瘯灏嗗璞¤浆鎹负long绫诲瀷 + /// </remarks> + public static long ObjToLong(this object thisValue) + { + long reval = 0; + if (thisValue == null) return 0; + if (thisValue != DBNull.Value && long.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + + return reval; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负閲戦(double绫诲瀷)銆傝嫢杞崲澶辫触鍒欒繑鍥�0銆� + /// </summary> + /// <param name="thisValue">寰呰浆鎹㈢殑瀵硅薄</param> + /// <returns>杞崲鍚庣殑閲戦鍊硷紝澶辫触杩斿洖0</returns> + public static double ObjToMoney(this object thisValue) + { + double reval = 0; + if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + + return 0; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负閲戦(double)绫诲瀷锛岃浆鎹㈠け璐ユ椂杩斿洖鎸囧畾鐨勯敊璇�� + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <param name="errorValue">杞崲澶辫触鏃惰繑鍥炵殑榛樿鍊�</param> + /// <returns>杞崲鎴愬姛鐨刣ouble鍊兼垨鎸囧畾鐨勯敊璇��</returns> + public static double ObjToMoney(this object thisValue, double errorValue) + { + double reval = 0; + if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + + return errorValue; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负瀛楃涓诧紝鑻ュ璞′负null鍒欒繑鍥炵┖瀛楃涓� + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <returns>鍘婚櫎鍓嶅悗绌烘牸鐨勫瓧绗︿覆缁撴灉</returns> + public static string ObjToString(this object thisValue) + { + if (thisValue != null) return thisValue.ToString().Trim(); + return ""; + } + + /// <summary> + /// 鍒ゆ柇瀵硅薄鏄惁涓嶄负绌烘垨null鍊� + /// </summary> + /// <param name="thisValue">瑕佸垽鏂殑瀵硅薄</param> + /// <returns>褰撳璞′笉涓虹┖涓斾笉绛変簬"undefined"鎴�"null"瀛楃涓叉椂杩斿洖true锛屽惁鍒欒繑鍥瀎alse</returns> + public static bool IsNotEmptyOrNull(this object thisValue) + { + return ObjToString(thisValue) != "" && ObjToString(thisValue) != "undefined" && ObjToString(thisValue) != "null"; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负瀛楃涓诧紝濡傛灉瀵硅薄涓簄ull鍒欒繑鍥炴寚瀹氱殑閿欒鍊� + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <param name="errorValue">褰撳璞′负null鏃惰繑鍥炵殑鍊�</param> + /// <returns>瀵硅薄鐨勫瓧绗︿覆琛ㄧず鎴栨寚瀹氱殑閿欒鍊�</returns> + public static string ObjToString(this object thisValue, string errorValue) + { + if (thisValue != null) return thisValue.ToString().Trim(); + return errorValue; + } + + /// <summary> + /// 鍒ゆ柇瀵硅薄鏄惁涓簄ull銆丏BNull鎴栫┖瀛楃涓� + /// </summary> + /// <param name="thisValue">瑕佹鏌ョ殑瀵硅薄</param> + /// <returns>濡傛灉瀵硅薄涓簄ull銆丏BNull鎴栫┖瀛楃涓插垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse</returns> + public static bool IsNullOrEmpty(this object thisValue) => thisValue == null || thisValue == DBNull.Value || string.IsNullOrWhiteSpace(thisValue.ToString()); + + /// <summary> + /// 灏嗗璞¤浆鎹负Decimal绫诲瀷 + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <returns>杞崲鍚庣殑Decimal鍊硷紝杞崲澶辫触杩斿洖0</returns> + public static Decimal ObjToDecimal(this object thisValue) + { + Decimal reval = 0; + if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + + return 0; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负Decimal绫诲瀷锛岃嫢杞崲澶辫触鍒欒繑鍥炴寚瀹氱殑榛樿鍊� + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <param name="errorValue">杞崲澶辫触鏃惰繑鍥炵殑榛樿鍊�</param> + /// <returns>杞崲鎴愬姛鐨凞ecimal鍊兼垨鎸囧畾鐨勯粯璁ゅ��</returns> + public static Decimal ObjToDecimal(this object thisValue, decimal errorValue) + { + Decimal reval = 0; + if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + + return errorValue; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负DateTime绫诲瀷 + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <returns>杞崲鍚庣殑DateTime鍊硷紝杞崲澶辫触杩斿洖DateTime.MinValue</returns> + public static DateTime ObjToDate(this object thisValue) + { + DateTime reval = DateTime.MinValue; + if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval)) + { + reval = Convert.ToDateTime(thisValue); + } + + return reval; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负DateTime绫诲瀷锛岃浆鎹㈠け璐ユ椂杩斿洖鎸囧畾鐨勯粯璁ゅ�� + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <param name="errorValue">杞崲澶辫触鏃惰繑鍥炵殑榛樿鍊�</param> + /// <returns>杞崲鎴愬姛鐨凞ateTime鍊兼垨鎸囧畾鐨勯粯璁ゅ��</returns> + public static DateTime ObjToDate(this object thisValue, DateTime errorValue) + { + DateTime reval = DateTime.MinValue; + if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + + return errorValue; + } + + /// <summary> + /// 灏嗗璞¤浆鎹负甯冨皵鍊� + /// </summary> + /// <param name="thisValue">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <returns>杞崲鍚庣殑甯冨皵鍊硷紝杞崲澶辫触鏃惰繑鍥瀎alse</returns> + public static bool ObjToBool(this object thisValue) + { + bool reval = false; + if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + + return reval; + } + + /// <summary> + /// 灏咲ateTime杞崲涓篣nix鏃堕棿鎴筹紙绉掔骇锛� + /// </summary> + /// <param name="thisValue">闇�瑕佽浆鎹㈢殑DateTime瀵硅薄</param> + /// <returns>杩斿洖琛ㄧずUnix鏃堕棿鎴崇殑瀛楃涓�</returns> + public static string DateToTimeStamp(this DateTime thisValue) + { + TimeSpan ts = thisValue - new DateTime(1970, 1, 1, 0, 0, 0, 0); + return Convert.ToInt64(ts.TotalSeconds).ToString(); + } + + /// <summary> + /// 灏嗗璞¤浆鎹负鎸囧畾绫诲瀷 + /// </summary> + /// <param name="value">瑕佽浆鎹㈢殑瀵硅薄</param> + /// <param name="type">鐩爣绫诲瀷</param> + /// <returns>杞崲鍚庣殑瀵硅薄</returns> + /// <remarks> + /// 鏀寔澶勭悊null鍊笺�佹灇涓剧被鍨嬨�佹硾鍨嬬被鍨嬨�丟uid銆乂ersion绛夌壒娈婄被鍨嬬殑杞崲銆� + /// 濡傛灉杞崲澶辫触鎴栫被鍨嬩笉鍖归厤锛屽皢杩斿洖鍘熷鍊兼垨鎶涘嚭寮傚父銆� + /// </remarks> + public static object ChangeType(this object value, Type type) + { + if (value == null && type.IsGenericType) return Activator.CreateInstance(type); + if (value == null) return null; + if (type == value.GetType()) return value; + if (type.IsEnum) + { + if (value is string) + return Enum.Parse(type, value as string); + else + return Enum.ToObject(type, value); + } + + if (!type.IsInterface && type.IsGenericType) + { + Type innerType = type.GetGenericArguments()[0]; + object innerValue = ChangeType(value, innerType); + return Activator.CreateInstance(type, new object[] { innerValue }); + } + + if (value is string && type == typeof(Guid)) return new Guid(value as string); + if (value is string && type == typeof(Version)) return new Version(value as string); + if (!(value is IConvertible)) return value; + return Convert.ChangeType(value, type); + } + + /// <summary> + /// 灏嗗璞″�艰浆鎹负鎸囧畾绫诲瀷鐨勬硾鍨嬪垪琛ㄣ�� + /// </summary> + /// <param name="value">寰呰浆鎹㈢殑瀵硅薄鍊�</param> + /// <param name="type">鐩爣鍒楄〃鍏冪礌绫诲瀷</param> + /// <returns>杞崲鍚庣殑娉涘瀷鍒楄〃瀵硅薄锛岃嫢杈撳叆涓簄ull鍒欒繑鍥為粯璁ゅ��</returns> + /// <remarks> + /// 鏀寔澶勭悊浠ユ嫭鍙峰寘瑁圭殑瀛楃涓叉牸寮忥紙濡�"(1,2,3)"鎴�"("a","b")"锛夛紝 + /// 鑷姩鍘婚櫎鍒嗛殧绗﹀苟灏嗗厓绱犺浆鎹负鐩爣绫诲瀷鍚庢坊鍔犲埌鍒楄〃銆� + /// </remarks> + public static object ChangeTypeList(this object value, Type type) + { + if (value == null) return default; + + var gt = typeof(List<>).MakeGenericType(type); + dynamic lis = Activator.CreateInstance(gt); + + var addMethod = gt.GetMethod("Add"); + string values = value.ToString(); + if (values != null && values.StartsWith("(") && values.EndsWith(")")) + { + string[] splits; + if (values.Contains("\",\"")) + { + splits = values.Remove(values.Length - 2, 2) + .Remove(0, 2) + .Split("\",\""); + } + else + { + splits = values.Remove(0, 1) + .Remove(values.Length - 2, 1) + .Split(","); + } + + foreach (var split in splits) + { + var str = split; + if (split.StartsWith("\"") && split.EndsWith("\"")) + { + str = split.Remove(0, 1) + .Remove(split.Length - 2, 1); + } + + addMethod.Invoke(lis, new object[] { ChangeType(str, type) }); + } + } + + return lis; + } + + /// <summary> + /// 灏嗗璞″簭鍒楀寲涓篔SON瀛楃涓� + /// </summary> + /// <param name="value">瑕佸簭鍒楀寲鐨勫璞�</param> + /// <returns>瀵硅薄鐨凧SON瀛楃涓茶〃绀�</returns> + public static string ToJson(this object value) + { + return JsonConvert.SerializeObject(value); + } + + /// <summary> + /// 鍒ゆ柇瀵硅薄鏄惁鍙互杞崲涓烘暣鏁� + /// </summary> + /// <param name="obj">瑕佸垽鏂殑瀵硅薄</param> + /// <returns>濡傛灉鍙互杞崲涓烘暣鏁拌繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse</returns> + public static bool IsInt(this object obj) + { + if (obj == null) + return false; + bool reslut = Int32.TryParse(obj.ToString(), out int _number); + return reslut; + + } + + /// <summary> + /// 鍒ゆ柇瀵硅薄鏄惁涓烘湁鏁堟棩鏈熸牸寮� + /// </summary> + /// <param name="str">寰呮娴嬬殑瀵硅薄</param> + /// <returns>true琛ㄧず鏄湁鏁堟棩鏈燂紝false鍒欎笉鏄�</returns> + /// <remarks>姝ゆ柟娉曟槸鎵╁睍鏂规硶锛岄�氳繃璋冪敤IsDate(out _)瀹炵幇</remarks> + public static bool IsDate(this object str) + { + return str.IsDate(out _); + } + + /// <summary> + /// 鍒ゆ柇瀵硅薄鏄惁鍙互杞崲涓烘湁鏁堢殑鏃ユ湡鏃堕棿 + /// </summary> + /// <param name="str">瑕佸垽鏂殑瀵硅薄</param> + /// <param name="dateTime">杈撳嚭杞崲鍚庣殑鏃ユ湡鏃堕棿鍊�</param> + /// <returns>濡傛灉杞崲鎴愬姛杩斿洖true锛屽惁鍒欒繑鍥瀎alse</returns> + public static bool IsDate(this object str, out DateTime dateTime) + { + dateTime = DateTime.Now; + if (str == null || str.ToString() == "") + { + return false; + } + return DateTime.TryParse(str.ToString(), out dateTime); + } + + /// <summary> + /// 鍒ゆ柇瀛楃涓叉槸鍚﹀彲浠ヨ浆鎹负鏁板瓧 + /// </summary> + /// <param name="str">瑕佹鏌ョ殑瀛楃涓�</param> + /// <param name="formatString">鏍煎紡瀛楃涓诧紙鏈娇鐢級</param> + /// <returns>濡傛灉瀛楃涓插彲浠ヨ浆鎹负鏁板瓧鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse</returns> + /// <remarks> + /// 浣跨敤姝e垯琛ㄨ揪寮忛獙璇佸瓧绗︿覆鏄惁涓烘暟瀛楁牸寮忥紝鏀寔姝h礋鍙峰拰灏忔暟鐐� + /// </remarks> + public static bool IsNumber(this string str, string formatString) + { + if (string.IsNullOrEmpty(str)) return false; + + return Regex.IsMatch(str, @"^[+-]?\d*[.]?\d*$"); + } + + /// <summary> + /// 鍒ゆ柇瀛楃涓叉槸鍚︿负鏈夋晥鐨凣uid鏍煎紡 + /// </summary> + /// <param name="guid">瑕侀獙璇佺殑瀛楃涓�</param> + /// <returns>濡傛灉瀛楃涓叉槸鏈夋晥鐨凣uid鏍煎紡鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse</returns> + public static bool IsGuid(this string guid) + { + Guid newId; + return guid.GetGuid(out newId); + } + + /// <summary> + /// 灏嗗瓧绗︿覆杞崲涓篏uid绫诲瀷 + /// </summary> + /// <param name="guid">瑕佽浆鎹㈢殑瀛楃涓�</param> + /// <param name="outId">杈撳嚭杞崲鍚庣殑Guid</param> + /// <returns>杞崲鎴愬姛杩斿洖true锛屽惁鍒欒繑鍥瀎alse</returns> + public static bool GetGuid(this string guid, out Guid outId) + { + Guid emptyId = Guid.Empty; + return Guid.TryParse(guid, out outId); + } + + /// <summary> + /// 灏嗗瓧绗︿覆绫诲瀷鐨勬潯浠惰浆鎹负瀵瑰簲鐨凩inq琛ㄨ揪寮忕被鍨� + /// </summary> + /// <param name="stringType">琛ㄧず鏉′欢鐨勫瓧绗︿覆</param> + /// <returns>瀵瑰簲鐨凩inq琛ㄨ揪寮忕被鍨嬫灇涓惧��</returns> + /// <remarks> + /// 璇ユ柟娉曠敤浜庡皢鍓嶇浼犻�掔殑鏉′欢瀛楃涓叉槧灏勪负鍚庣Linq鏌ヨ浣跨敤鐨勮〃杈惧紡绫诲瀷锛� + /// 鏀寔鍖呭惈銆佸ぇ浜庣瓑浜庛�佸皬浜庣瓑浜庛�佸ぇ浜庛�佸皬浜庛�佹ā绯婂尮閰嶇瓑甯歌鏉′欢绫诲瀷锛� + /// 榛樿杩斿洖绛変簬(Equal)绫诲瀷 + /// </remarks> + public static LinqExpressionType GetLinqCondition(this string stringType) + { + LinqExpressionType linqExpression; + switch (stringType) + { + case HtmlElementType.Contains: + case HtmlElementType.selectlist: + case nameof(HtmlElementType.Contains): + linqExpression = LinqExpressionType.In; + break; + case HtmlElementType.ThanOrEqual: + case nameof(HtmlElementType.ThanOrEqual): + case HtmlElementType.thanorequal: + linqExpression = LinqExpressionType.ThanOrEqual; + break; + case HtmlElementType.LessOrEqual: + case nameof(HtmlElementType.LessOrEqual): + case HtmlElementType.lessorequal: + linqExpression = LinqExpressionType.LessThanOrEqual; + break; + case HtmlElementType.GT: + case nameof(HtmlElementType.GT): + linqExpression = LinqExpressionType.GreaterThan; + break; + case HtmlElementType.lt: + linqExpression = LinqExpressionType.LessThan; + break; + case HtmlElementType.like: + linqExpression = LinqExpressionType.Contains; + break; + default: + linqExpression = LinqExpressionType.Equal; + break; + } + return linqExpression; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/HostedService/SeedDataHostedService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/HostedService/SeedDataHostedService.cs" new file mode 100644 index 0000000..5cd9dec --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/HostedService/SeedDataHostedService.cs" @@ -0,0 +1,71 @@ +锘縰sing Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; +using WIDESEA_Core.Seed; + +namespace WIDESEA_Core +{ + public sealed class SeedDataHostedService : IHostedService + { + private readonly DBContext _dbContext; + private readonly ILogger<SeedDataHostedService> _logger; + private readonly string _webRootPath; + private readonly IServiceProvider _serviceProvider; + + public SeedDataHostedService( + IServiceProvider serviceProvider, + IWebHostEnvironment webHostEnvironment, + ILogger<SeedDataHostedService> logger) + { + _serviceProvider = serviceProvider; + _logger = logger; + _webRootPath = webHostEnvironment.WebRootPath; + + using var scope = _serviceProvider.CreateScope(); + + var dbContext = scope.ServiceProvider.GetService<DBContext>(); + //dbContext.Db.Aop.DataExecuting = SqlSugarAop.DataExecuting; + _dbContext = dbContext; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + _logger.LogInformation("Start Initialization Db Seed Service!"); + await DoWork(); + } + + private async Task DoWork() + { + try + { + if (AppSettings.GetValue("DBSeedEnable").ObjToBool()) + { + + await DBSeed.SeedAsync(_dbContext, _webRootPath); + + //澶氱鎴� 鍚屾 + //await DBSeed.TenantSeedAsync(_dbContext); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured seeding the Database."); + throw; + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _logger.LogInformation("Stop Initialization Db Seed Service!"); + return Task.CompletedTask; + } + + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/HttpContextUser/AspNetUser.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/HttpContextUser/AspNetUser.cs" new file mode 100644 index 0000000..676433b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/HttpContextUser/AspNetUser.cs" @@ -0,0 +1,282 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Authorization; +using WIDESEA_Core.Const; +using WIDESEA_Core.DB; +using WIDESEA_Core.Extensions; +using WIDESEA_Core.Helper; +using WIDESEA_Core.Seed; +using ICacheService = WIDESEA_Core.Caches.ICacheService; + +namespace WIDESEA_Core.HttpContextUser +{ + /// <summary> + /// 鎻愪緵鍩轰簬ASP.NET Core HttpContext鐨勭敤鎴蜂俊鎭闂湇鍔� + /// </summary> + /// <remarks> + /// 瀹炵幇IUser鎺ュ彛锛岄�氳繃JWT Token瑙f瀽鐢ㄦ埛韬唤淇℃伅锛� + /// 鍖呮嫭鐢ㄦ埛鍚嶃�佺敤鎴稩D銆佺鎴稩D銆佽鑹睮D绛夋牳蹇冨睘鎬э紝 + /// 骞舵彁渚汿oken绠$悊銆佽韩浠介獙璇佸拰澹版槑淇℃伅鑾峰彇绛夊姛鑳� + /// </remarks> + public class AspNetUser : IUser + { + private readonly IHttpContextAccessor _accessor; + private readonly ICacheService _cacheService; + //private readonly ILogger<AspNetUser> _logger; + + public AspNetUser(IHttpContextAccessor accessor, ICacheService cacheService) + { + _accessor = accessor; + _cacheService = cacheService; + /*_logger = logger;*/ + } + + /// <summary> + /// 鑾峰彇褰撳墠鐢ㄦ埛鐨勭敤鎴峰悕锛堜粠JWT Token涓В鏋愶級 + /// </summary> + /// <returns>鐢ㄦ埛鍚嶅瓧绗︿覆锛岃嫢涓嶅瓨鍦ㄥ垯杩斿洖绌哄瓧绗︿覆</returns> + public string UserName => GetUserInfoFromToken(ClaimTypes.Name).FirstOrDefault() ?? ""; + + /// <summary> + /// 鑾峰彇褰撳墠鐢ㄦ埛鐨処D锛屼粠JWT浠ょ墝鐨凧TI澹版槑涓В鏋愩�傝嫢澹版槑涓嶅瓨鍦ㄦ垨瑙f瀽澶辫触鍒欒繑鍥�0銆� + /// </summary> + /// <returns>鐢ㄦ埛ID锛堟暣鏁帮級</returns> + public int UserId => GetClaimValueByType(JwtRegisteredClaimNames.Jti) == null ? 0 : GetClaimValueByType(JwtRegisteredClaimNames.Jti).FirstOrDefault()?.ObjToInt() ?? 0; + + /// <summary> + /// 浠庣敤鎴蜂护鐗屼腑鑾峰彇绉熸埛ID + /// </summary> + /// <returns>褰撳墠鐢ㄦ埛鐨勭鎴稩D锛岃嫢鑾峰彇澶辫触鍒欒繑鍥�-1</returns> + public long TenantId => GetUserInfoFromToken(nameof(TenantId)).FirstOrDefault()?.ObjToLong() ?? -1; + + /// <summary> + /// 鑾峰彇褰撳墠鐢ㄦ埛瑙掕壊ID锛堜粠Token涓В鏋愶級 + /// </summary> + /// <returns>瑙掕壊ID锛岃嫢涓嶅瓨鍦ㄥ垯杩斿洖0</returns> + public int RoleId => GetUserInfoFromToken(ClaimTypes.Role).FirstOrDefault()?.ObjToInt() ?? 0; + + /// <summary> + /// 鑾峰彇褰撳墠鐢ㄦ埛鐨凾oken + /// </summary> + public string Token => GetToken(); + + /// <summary> + /// 鑾峰彇鑿滃崟绫诲瀷锛屾牴鎹姹傚ご涓槸鍚﹀寘鍚�"uniapp"鏍囪瘑杩斿洖1鎴�0 + /// </summary> + public int MenuType => (_accessor.HttpContext?.Request.Headers.ContainsKey("uniapp") ?? false) ? 1 : 0; + + /// <summary> + /// 妫�鏌ュ綋鍓岺TTP涓婁笅鏂囩敤鎴锋槸鍚﹀凡璁よ瘉 + /// </summary> + /// <returns>濡傛灉鐢ㄦ埛宸茶璇佽繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse</returns> + public bool IsAuthenticated() + { + return _accessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false; + } + + /// <summary> + /// 鑾峰彇褰撳墠鐢ㄦ埛鐨凧WT Token + /// </summary> + /// <returns> + /// 杩斿洖褰撳墠璇锋眰鐨凙uthorization澶翠腑鐨凚earer Token锛� + /// 濡傛灉璇锋眰鏉ヨ嚜Swagger涓旈獙璇佹垚鍔熷垯杩斿洖Swagger鐨凧WT Token锛� + /// 鍚﹀垯灏濊瘯浠庣紦瀛樹腑鑾峰彇鐢ㄦ埛Token + /// </returns> + /// <remarks> + /// 1. 浼樺厛浠庤姹傚ごAuthorization涓幏鍙朆earer Token + /// 2. 濡傛灉鏄疭wagger璇锋眰涓旈獙璇佹垚鍔燂紝浣跨敤Swagger鐨凧WT Token + /// 3. 鏈�鍚庡皾璇曚粠缂撳瓨涓幏鍙栫敤鎴稵oken + /// </remarks> + public string GetToken() + { + string token = _accessor.HttpContext?.Request?.Headers["Authorization"].ObjToString().Replace("Bearer ", "") ?? ""; + if (!token.IsNullOrEmpty()) + { + return token; + } + if (_accessor.HttpContext?.IsSuccessSwagger() == true) + { + token = _accessor.HttpContext.GetSuccessSwaggerJwt(); + if (token.IsNotEmptyOrNull()) + { + //UserInfo userInfo = JwtHelper.SerializeJwt(token); + //if (userInfo.UserId > 0) + //{ + // return token; + //} + List<Claim> claims1 = _accessor.HttpContext.User.Claims.ToList(); + if (_accessor.HttpContext.User.Claims.Any(s => s.Type == JwtRegisteredClaimNames.Jti)) + { + return token; + } + + var claims = new ClaimsIdentity(GetClaimsIdentity(token)); + _accessor.HttpContext.User.AddIdentity(claims); + return token; + } + } + token = _cacheService.Get(UserId.ToString()); + if (!string.IsNullOrEmpty(token)) { return token; } + return token; + + // string token = _cacheService.Get(UserId.ToString()); + //if (!string.IsNullOrEmpty(token)) { return token; } + //return string.Empty; + //return _accessor.HttpContext?.Request?.Headers["Authorization"].ObjToString().Replace("Bearer ", "") ?? ""; + } + + /// <summary> + /// 鏇存柊鐢ㄦ埛浠ょ墝 + /// </summary> + /// <param name="token">鏂扮殑浠ょ墝瀛楃涓�</param> + /// <remarks> + /// 璇ユ柟娉曚細灏嗙敤鎴稩D涓庝护鐗屽叧鑱斿瓨鍌ㄥ埌缂撳瓨鏈嶅姟涓� + /// </remarks> + public void UpdateToke(string token) + { + _cacheService.AddOrUpdate(UserId.ToString(), token); + } + + /// <summary> + /// 鑾峰彇涓�涓�硷紝鎸囩ず褰撳墠鐢ㄦ埛鏄惁涓鸿秴绾х鐞嗗憳 + /// </summary> + /// <remarks> + /// 閫氳繃妫�鏌ヨ鑹睮D鏄惁涓鸿秴绾х鐞嗗憳瑙掕壊鏉ュ垽鏂� + /// </remarks> + public bool IsSuperAdmin => IsRoleIdSuperAdmin(RoleId); + + /// <summary> + /// 浠嶫WT浠ょ墝涓幏鍙栨寚瀹氱被鍨嬬殑鐢ㄦ埛澹版槑淇℃伅 + /// </summary> + /// <param name="ClaimType">瑕佽幏鍙栫殑澹版槑绫诲瀷</param> + /// <returns>鍖呭惈澹版槑鍊肩殑瀛楃涓插垪琛紝鑻ヤ护鐗屾棤鏁堟垨鏈壘鍒板0鏄庡垯杩斿洖绌哄垪琛�</returns> + public List<string> GetUserInfoFromToken(string ClaimType) + { + var jwtHandler = new JwtSecurityTokenHandler(); + var token = ""; + + token = GetToken(); + // token鏍¢獙 + if (token.IsNotEmptyOrNull() && jwtHandler.CanReadToken(token)) + { + JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(token); + + List<string> items = (from item in jwtToken.Claims + where item.Type == ClaimType + select item.Value).ToList(); + return items; + } + + return new List<string>() { }; + } + + /// <summary> + /// 鑾峰彇褰撳墠HTTP涓婁笅鏂囩殑韬唤澹版槑闆嗗悎锛屽寘鎷姹傚ご淇℃伅 + /// </summary> + /// <returns>鍖呭惈褰撳墠鐢ㄦ埛澹版槑鍜岃姹傚ご淇℃伅鐨勯泦鍚堬紝鑻ttpContext涓虹┖鍒欒繑鍥炵┖闆嗗悎</returns> + public IEnumerable<Claim> GetClaimsIdentity() + { + if (_accessor.HttpContext != null) + { + var claims = _accessor.HttpContext.User.Claims.ToList(); + var headers = _accessor.HttpContext.Request.Headers; + foreach (var header in headers) + { + claims.Add(new Claim(header.Key, header.Value)); + } + + return claims; + } + return ArraySegment<Claim>.Empty; + } + + /// <summary> + /// 浠嶫WT浠ょ墝涓幏鍙栬韩浠藉0鏄�(Claims) + /// </summary> + /// <param name="token">JWT浠ょ墝瀛楃涓�</param> + /// <returns>鍖呭惈澹版槑淇℃伅鐨勯泦鍚堬紝鑻ヤ护鐗屾棤鏁堝垯杩斿洖绌洪泦鍚�</returns> + public IEnumerable<Claim> GetClaimsIdentity(string token) + { + var jwtHandler = new JwtSecurityTokenHandler(); + // token鏍¢獙 + if (token.IsNotEmptyOrNull() && jwtHandler.CanReadToken(token)) + { + var jwtToken = jwtHandler.ReadJwtToken(token); + + return jwtToken.Claims; + } + + return new List<Claim>(); + } + + /// <summary> + /// 鏍规嵁澹版槑绫诲瀷鑾峰彇瀵瑰簲鐨勫0鏄庡�煎垪琛� + /// </summary> + /// <param name="ClaimType">瑕佹煡璇㈢殑澹版槑绫诲瀷</param> + /// <returns>鍖归厤鎸囧畾绫诲瀷鐨勫0鏄庡�煎垪琛�</returns> + public List<string> GetClaimValueByType(string ClaimType) + { + return (from item in GetClaimsIdentity() + where item.Type == ClaimType + select item.Value).ToList(); + } + + /// <summary> + /// 妫�鏌ヨ鑹睮D鏄惁涓鸿秴绾х鐞嗗憳 + /// </summary> + /// <param name="roleId">瑕佹鏌ョ殑瑙掕壊ID</param> + /// <returns>濡傛灉鏄秴绾х鐞嗗憳杩斿洖true锛屽惁鍒欒繑鍥瀎alse</returns> + public bool IsRoleIdSuperAdmin(int roleId) + { + return roleId == 1; + } + } + + /// <summary> + /// 鐢ㄦ埛淇℃伅瀹炰綋绫� + /// </summary> + /// <remarks> + /// 鍖呭惈鐢ㄦ埛鐨勫熀鏈俊鎭紝濡傜鎴稩D銆佽鑹睮D銆佺敤鎴峰悕绛� + /// </remarks> + public class UserInfo + { + /// <summary> + /// 鑾峰彇鎴栬缃鎴稩D + /// </summary> + public long TenantId { get; set; } + + /// <summary> + /// 鑾峰彇鎴栬缃敤鎴疯鑹睮D + /// </summary> + public int RoleId { get; set; } + + /// <summary> + /// 鑾峰彇鎴栬缃敤鎴风殑鍚嶇О + /// </summary> + public string UserName { get; set; } + + /// <summary> + /// 鑾峰彇鎴栬缃敤鎴稩D + /// </summary> + public int UserId { get; set; } + + /// <summary> + /// 鑾峰彇鎴栬缃敤鎴风殑鐪熷疄濮撳悕 + /// </summary> + public string UserTrueName { get; set; } + + /// <summary> + /// 鑾峰彇鎴栬缃敤鎴峰ご鍍忕殑URL + /// </summary> + public string HeadImageUrl { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/HttpContextUser/IUser.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/HttpContextUser/IUser.cs" new file mode 100644 index 0000000..b951b4c --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/HttpContextUser/IUser.cs" @@ -0,0 +1,80 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.HttpContextUser +{ + public interface IUser + { + /// <summary> + /// 鍚嶇О + /// </summary> + string UserName { get; } + + /// <summary> + /// UserId + /// </summary> + int UserId { get; } + + /// <summary> + /// 绉熸埛ID + /// </summary> + long TenantId { get; } + + int RoleId { get; } + + string Token { get; } + + int MenuType { get; } + + /// <summary> + /// 鏇存柊鐢ㄦ埛浠ょ墝 + /// </summary> + /// <param name="token">鏂扮殑浠ょ墝瀛楃涓�</param> + void UpdateToke(string token); + + /// <summary> + /// 鍒ゆ柇褰撳墠鐢ㄦ埛鏄惁宸茶璇� + /// </summary> + /// <returns>濡傛灉鐢ㄦ埛宸茶璇佽繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse</returns> + bool IsAuthenticated(); + + /// <summary> + /// 鑾峰彇鐢ㄦ埛韬唤澹版槑闆嗗悎 + /// </summary> + /// <returns>鍖呭惈鐢ㄦ埛韬唤澹版槑鐨勫彲鏋氫妇闆嗗悎</returns> + IEnumerable<Claim> GetClaimsIdentity(); + + /// <summary> + /// 鏍规嵁澹版槑绫诲瀷鑾峰彇澹版槑鍊煎垪琛� + /// </summary> + /// <param name="ClaimType">瑕佹煡璇㈢殑澹版槑绫诲瀷</param> + /// <returns>鍖归厤鎸囧畾绫诲瀷鐨勫0鏄庡�煎垪琛�</returns> + List<string> GetClaimValueByType(string ClaimType); + + /// <summary> + /// 鑾峰彇褰撳墠鐢ㄦ埛鐨勮璇佷护鐗� + /// </summary> + /// <returns>鐢ㄦ埛璁よ瘉浠ょ墝瀛楃涓�</returns> + string GetToken(); + + /// <summary> + /// 浠庝护鐗屼腑鑾峰彇鎸囧畾绫诲瀷鐨勭敤鎴蜂俊鎭� + /// </summary> + /// <param name="ClaimType">瑕佽幏鍙栫殑澹版槑绫诲瀷</param> + /// <returns>鍖呭惈鐢ㄦ埛淇℃伅鐨勫瓧绗︿覆鍒楄〃</returns> + List<string> GetUserInfoFromToken(string ClaimType); + + bool IsSuperAdmin { get; } + + /// <summary> + /// 鍒ゆ柇鎸囧畾瑙掕壊ID鏄惁涓鸿秴绾х鐞嗗憳 + /// </summary> + /// <param name="roleId">瑕佹鏌ョ殑瑙掕壊ID</param> + /// <returns>濡傛灉鏄秴绾х鐞嗗憳杩斿洖true锛屽惁鍒欒繑鍥瀎alse</returns> + bool IsRoleIdSuperAdmin(int roleId); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/IDependency.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/IDependency.cs" new file mode 100644 index 0000000..98e47b1 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/IDependency.cs" @@ -0,0 +1,12 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core +{ + public interface IDependency + { + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/LogLock.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/LogLock.cs" new file mode 100644 index 0000000..d7f9321 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/LogLock.cs" @@ -0,0 +1,110 @@ +锘� +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.LogHelper +{ + public class LogLock + { + static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim(); + static int WritedCount = 0; + static int FailedCount = 0; + static string _contentRoot = string.Empty; + + public LogLock(string contentPath) + { + _contentRoot = contentPath; + } + + /// <summary> + /// 杈撳嚭AOP鏃ュ織淇℃伅 + /// </summary> + /// <param name="prefix">鏃ュ織鍓嶇紑</param> + /// <param name="dataParas">鏃ュ織鍙傛暟鏁扮粍</param> + /// <param name="IsHeader">鏄惁鍖呭惈澶撮儴淇℃伅锛岄粯璁や负true</param> + public static void OutLogAOP(string prefix, string[] dataParas, bool IsHeader = true) + { + OutSql2LogToFile(prefix, dataParas, IsHeader); + } + + /// <summary> + /// 灏哠QL鏃ュ織杈撳嚭鍒版枃浠� + /// </summary> + /// <param name="prefix">鏃ュ織鏂囦欢鍓嶇紑鍚�</param> + /// <param name="dataParas">瑕佸啓鍏ョ殑SQL鍙傛暟鏁扮粍</param> + /// <param name="IsHeader">鏄惁娣诲姞鏃ュ織澶翠俊鎭�(榛樿true)</param> + /// <param name="isWrt">鏄惁瑕嗙洊鍐欏叆(榛樿false杩藉姞鍐欏叆)</param> + /// <remarks> + /// 浣跨敤鍐欏叆閿佷繚璇佺嚎绋嬪畨鍏紝闀挎椂闂存寔鏈夐攣鍙兘瀵艰嚧绾跨▼楗ラタ + /// 鑷姩鍒涘缓Log鐩綍锛屾寜鍓嶇紑鍜屽ぇ灏忕敓鎴愬彲鐢ㄦ枃浠跺悕 + /// 缁熻鎴愬姛鍜屽け璐ュ啓鍏ユ鏁� + /// </remarks> + public static void OutSql2LogToFile(string prefix, string[] dataParas, bool IsHeader = true, bool isWrt = false) + { + try + { + //璁剧疆璇诲啓閿佷负鍐欏叆妯″紡鐙崰璧勬簮锛屽叾浠栧啓鍏ヨ姹傞渶瑕佺瓑寰呮湰娆″啓鍏ョ粨鏉熶箣鍚庢墠鑳界户缁啓鍏� + //娉ㄦ剰锛氶暱鏃堕棿鎸佹湁璇荤嚎绋嬮攣鎴栧啓绾跨▼閿佷細浣垮叾浠栫嚎绋嬪彂鐢熼ゥ楗� (starve)銆� 涓轰簡寰楀埌鏈�濂界殑鎬ц兘锛岄渶瑕佽�冭檻閲嶆柊鏋勯�犲簲鐢ㄧ▼搴忎互灏嗗啓璁块棶鐨勬寔缁椂闂村噺灏戝埌鏈�灏忋�� + // 浠庢�ц兘鏂归潰鑰冭檻锛岃姹傝繘鍏ュ啓鍏ユā寮忓簲璇ョ揣璺熸枃浠舵搷浣滀箣鍓嶏紝鍦ㄦ澶勮繘鍏ュ啓鍏ユā寮忎粎鏄负浜嗛檷浣庝唬鐮佸鏉傚害 + // 鍥犺繘鍏ヤ笌閫�鍑哄啓鍏ユā寮忓簲鍦ㄥ悓涓�涓猼ry finally璇彞鍧楀唴锛屾墍浠ュ湪璇锋眰杩涘叆鍐欏叆妯″紡涔嬪墠涓嶈兘瑙﹀彂寮傚父锛屽惁鍒欓噴鏀炬鏁板ぇ浜庤姹傛鏁板皢浼氳Е鍙戝紓甯� + LogWriteLock.EnterWriteLock(); + + var folderPath = Path.Combine(_contentRoot, "Log"); + if (!Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + //string logFilePath = Path.Combine(path, $@"{filename}.log"); + var logFilePath = FileHelper.GetAvailableFileWithPrefixOrderSize(folderPath, prefix); + + var now = DateTime.Now; + string logContent = String.Join("\r\n", dataParas); + if (IsHeader) + { + logContent = ( + "--------------------------------\r\n" + + DateTime.Now + "|\r\n" + + String.Join("\r\n", dataParas) + "\r\n" + ); + } + else + { + logContent = ( + dataParas[1] + ",\r\n" + ); + } + + //if (logContent.IsNotEmptyOrNull() && logContent.Length > 500) + //{ + // logContent = logContent.Substring(0, 500) + "\r\n"; + //} + if (isWrt) + { + System.IO.File.WriteAllText(logFilePath, logContent); + } + else + { + System.IO.File.AppendAllText(logFilePath, logContent); + } + WritedCount++; + } + catch (Exception e) + { + //Console.Write(e.Message); + FailedCount++; + } + finally + { + //閫�鍑哄啓鍏ユā寮忥紝閲婃斁璧勬簮鍗犵敤 + //娉ㄦ剰锛氫竴娆¤姹傚搴斾竴娆¢噴鏀� + // 鑻ラ噴鏀炬鏁板ぇ浜庤姹傛鏁板皢浼氳Е鍙戝紓甯竅鍐欏叆閿佸畾鏈粡淇濇寔鍗宠閲婃斁] + // 鑻ヨ姹傚鐞嗗畬鎴愬悗鏈噴鏀惧皢浼氳Е鍙戝紓甯竅姝ゆā寮忎笉涓嬪厑璁镐互閫掑綊鏂瑰紡鑾峰彇鍐欏叆閿佸畾] + LogWriteLock.ExitWriteLock(); + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/Logger.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/Logger.cs" new file mode 100644 index 0000000..9a3e6cd --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/Logger.cs" @@ -0,0 +1,310 @@ +锘縰sing Microsoft.AspNetCore.Http; +using SqlSugar; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.DB; +using WIDESEA_Core.Helper; +using WIDESEA_Core.HttpContextUser; +using WIDESEA_Core.Seed; + +namespace WIDESEA_Core.LogHelper +{ + public static class Logger + { + public static ConcurrentQueue<dynamic> loggerQueueData = new ConcurrentQueue<dynamic>(); + static Logger() + { + Task.Run(() => + { + StartWriteLog(); + }); + + } + + /// <summary> + /// 鏃ュ織鍐欏叆绾跨▼鐨勫叆鍙f柟娉曪紝璐熻矗浠庨槦鍒椾腑鍙栧嚭鏃ュ織鏁版嵁骞舵壒閲忓啓鍏ユ暟鎹簱 + /// </summary> + /// <remarks> + /// 璇ユ柟娉曚細鎸佺画杩愯锛屾瘡5绉掓鏌ヤ竴娆℃棩蹇楅槦鍒楋細 + /// 1. 褰撻槦鍒楁湁鏁版嵁涓旂紦瀛樿〃琛屾暟灏忎簬500鏃讹紝灏嗘暟鎹Щ鍏ョ紦瀛樿〃 + /// 2. 褰撶紦瀛樿〃鏈夋暟鎹椂锛屼娇鐢⊿qlSugar杩涜鎵归噺鎻掑叆 + /// 3. 鍙戠敓寮傚父鏃朵細杈撳嚭閿欒淇℃伅浣嗕笉浼氱粓姝㈢嚎绋� + /// </remarks> + static void StartWriteLog() + { + DataTable queueTable = CreateEmptyTable(); + while (true) + { + try + { + //濡傛灉闃熷垪涓湁鏁版嵁涓旈槦鍒楄〃涓殑琛屾暟灏忎簬500锛屽垯灏嗛槦鍒椾腑鐨勬暟鎹啓鍏ラ槦鍒楄〃 + if (loggerQueueData.Count() > 0 && queueTable.Rows.Count < 500) + { + DequeueToTable(queueTable); continue; + } + //姣�5绉掑啓涓�娆℃暟鎹� + Thread.Sleep(5000); + + //濡傛灉闃熷垪琛ㄤ腑鐨勮鏁颁负0锛屽垯璺宠繃鏈寰幆 + if (queueTable.Rows.Count == 0) { continue; } + + string str = DBContext.GetMainConnectionDb().Connection; + //鍒涘缓SqlSugarClient瀵硅薄锛岀敤浜庤繛鎺ユ暟鎹簱 + SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig() + { + ConnectionString = DBContext.GetMainConnectionDb().Connection, + IsAutoCloseConnection = true, + DbType = DBContext.DbType, + }); + + //灏嗛槦鍒楄〃涓殑鏁版嵁鎵归噺鎻掑叆鏁版嵁搴� + int rows = sugarClient.Fastest<DataTable>().AS("Sys_Log").BulkCopy(queueTable); + + //娓呯┖闃熷垪琛� + queueTable.Clear(); + } + catch (Exception ex) + { + //鎵撳嵃寮傚父淇℃伅 + Console.WriteLine(ex.ToString()); + } + } + } + + /// <summary> + /// 浠庢棩蹇楅槦鍒椾腑鍙栧嚭鏃ュ織椤瑰苟娣诲姞鍒版暟鎹〃涓� + /// </summary> + /// <param name="queueTable">瑕佹坊鍔犳棩蹇楁暟鎹殑鐩爣鏁版嵁琛�</param> + /// <remarks> + /// 1. 澶勭悊鏃ュ織鏃ユ湡锛氬鏋淏eginDate涓虹┖鎴栨棭浜�2010骞达紝鍒欒涓哄綋鍓嶆椂闂达紱EndDate涓虹┖鍒欒涓哄綋鍓嶆椂闂� + /// 2. 娓呯悊RequestParam鍜孯esponseParam涓殑鎹㈣绗� + /// 3. 璁$畻璇锋眰鑰楁椂(EndDate - BeginDate鐨勬绉掓暟) + /// 4. 澶勭悊UserId涓虹┖鐨勬儏鍐碉紝榛樿璁句负-1 + /// </remarks> + private static void DequeueToTable(DataTable queueTable) + { + loggerQueueData.TryDequeue(out dynamic log); + if (log != null) + { + DataRow row = queueTable.NewRow(); + // 濡傛灉log鐨凚eginDate涓虹┖鎴栬�匓eginDate鐨勫勾浠藉皬浜�2010锛屽垯灏咮eginDate璁剧疆涓哄綋鍓嶆椂闂� + if (log.BeginDate == null || log.BeginDate?.Year < 2010) + { + log.BeginDate = DateTime.Now; + } + // 濡傛灉log鐨凟ndDate涓虹┖锛屽垯灏咵ndDate璁剧疆涓哄綋鍓嶆椂闂� + if (log.EndDate == null) + { + log.EndDate = DateTime.Now; + } + // row["Id"] = log.Id; + // 灏哛equestParam涓殑鎹㈣绗︽浛鎹负绌哄瓧绗︿覆 + row["RequestParam"] = log.RequestParam?.Replace("\r\n", ""); + // 灏哛esponseParam涓殑鎹㈣绗︽浛鎹负绌哄瓧绗︿覆 + row["ResponseParam"] = log.ResponseParam?.Replace("\r\n", ""); + //row["Success"] = log.Success ?? -1; + // 灏咮eginDate璁剧疆涓簂og鐨凚eginDate + row["BeginDate"] = log.BeginDate; + // 灏咵ndDate璁剧疆涓簂og鐨凟ndDate + row["EndDate"] = log.EndDate; + // 璁$畻ElapsedTime锛屽嵆EndDate鍑忓幓BeginDate鐨勬绉掓暟 + row["ElapsedTime"] = ((DateTime)log.EndDate - (DateTime)log.BeginDate).TotalMilliseconds; + // 灏哢serIP璁剧疆涓簂og鐨刄serIP + row["UserIP"] = log.UserIP; + // 灏哢rl璁剧疆涓簂og鐨刄rl + row["Url"] = log.Url; + // 濡傛灉log鐨刄serId涓虹┖锛屽垯灏哢serId璁剧疆涓�-1锛屽惁鍒欒缃负log鐨刄serId + row["UserId"] = log.UserId ?? -1; + // 灏哢serName璁剧疆涓簂og鐨刄serName + row["UserName"] = log.UserName; + // 灏唕ow娣诲姞鍒皅ueueTable涓� + queueTable.Rows.Add(row); + } + } + + /// <summary> + /// 鍒涘缓涓�涓┖鐨凞ataTable锛岀敤浜庡瓨鍌ㄦ棩蹇楁暟鎹� + /// </summary> + /// <returns>鍖呭惈鏃ュ織瀛楁缁撴瀯鐨勭┖DataTable</returns> + /// <remarks> + /// 鍖呭惈浠ヤ笅鍒楋細BeginDate, ElapsedTime, EndDate, RequestParam, ResponseParam, + /// Url, UserIP, UserName, UserId銆傚叾浠栨敞閲婃帀鐨勫垪涓洪鐣欏瓧娈点�� + /// </remarks> + private static DataTable CreateEmptyTable() + { + DataTable queueTable = new DataTable(); + queueTable.Columns.Add("BeginDate", Type.GetType("System.DateTime")); + queueTable.Columns.Add("ElapsedTime", Type.GetType("System.Int32")); + queueTable.Columns.Add("EndDate", Type.GetType("System.DateTime")); + queueTable.Columns.Add("RequestParam", typeof(string)); + queueTable.Columns.Add("ResponseParam", typeof(string)); + //queueTable.Columns.Add("Success", Type.GetType("System.Int32")); + queueTable.Columns.Add("Url", typeof(string)); + queueTable.Columns.Add("UserIP", typeof(string)); + queueTable.Columns.Add("UserName", typeof(string)); + queueTable.Columns.Add("UserId", Type.GetType("System.Int32")); + //queueTable.Columns.Add("LogType", typeof(string)); + //queueTable.Columns.Add("ExceptionInfo", typeof(string)); + //queueTable.Columns.Add("ServiceIP", typeof(string)); + //queueTable.Columns.Add("BrowserType", typeof(string)); + //queueTable.Columns.Add("Role_Id", Type.GetType("System.Int32")); + return queueTable; + } + + /// <summary> + /// 娣诲姞绯荤粺鏃ュ織璁板綍 + /// </summary> + /// <param name="url">璇锋眰URL鍦板潃</param> + /// <param name="requestParameter">璇锋眰鍙傛暟</param> + /// <param name="responseParameter">鍝嶅簲鍙傛暟</param> + /// <param name="beginDate">璇锋眰寮�濮嬫椂闂�</param> + /// <remarks> + /// 璇ユ柟娉曚細璁板綍璇锋眰鐨刄RL銆佸弬鏁般�佸搷搴斾互鍙婄敤鎴蜂俊鎭紝骞惰嚜鍔ㄨ绠楄姹傝�楁椂銆� + /// 濡傛灉鑾峰彇鐢ㄦ埛淇℃伅鏃跺彂鐢熷紓甯革紝浠嶄細璁板綍鍩烘湰璇锋眰淇℃伅銆� + /// </remarks> + public static void Add(string url, string requestParameter, string responseParameter, DateTime beginDate) + { + dynamic? log = null; + try + { + //鑾峰彇褰撳墠鐢ㄦ埛 + IUser? user = App.User; + //鍒涘缓鏃ュ織瀵硅薄 + log = new + { + //璇锋眰寮�濮嬫椂闂� + BeginDate = beginDate, + //璇锋眰缁撴潫鏃堕棿 + EndDate = DateTime.Now, + //璇锋眰鍙傛暟 + RequestParam = requestParameter, + //鍝嶅簲鍙傛暟 + ResponseParam = responseParameter, + //璇锋眰URL + Url = url, + //瀹㈡埛绔疘P + UserIP = "", + //鐢ㄦ埛ID + UserId = user?.UserId, + //鐢ㄦ埛鍚� + UserName = user?.UserName + }; + } + catch (Exception exception) + { + //濡傛灉鍙戠敓寮傚父锛屽垯鍒涘缓鏃ュ織瀵硅薄 + log = log ?? new + { + //璇锋眰寮�濮嬫椂闂� + BeginDate = DateTime.Now, + //璇锋眰缁撴潫鏃堕棿 + EndDate = DateTime.Now, + //璇锋眰鍙傛暟 + RequestParam = requestParameter, + //鍝嶅簲鍙傛暟 + ResponseParam = responseParameter, + }; + } + //娣诲姞绯荤粺鏃ュ織 + loggerQueueData.Enqueue(log); + } + + /// <summary> + /// 娣诲姞璇锋眰鍜屽搷搴旀棩蹇楄褰� + /// </summary> + /// <param name="requestParameter">璇锋眰鍙傛暟</param> + /// <param name="responseParameter">鍝嶅簲鍙傛暟</param> + /// <remarks> + /// 璇ユ柟娉曚細璁板綍HTTP璇锋眰鐨勮缁嗕俊鎭紝鍖呮嫭璇锋眰鏃堕棿銆佸搷搴旀椂闂淬�佽姹俇RL銆佸鎴风IP銆佺敤鎴蜂俊鎭瓑銆� + /// 濡傛灉鍙戠敓寮傚父锛屼粛浼氳褰曞熀鏈殑璇锋眰鍜屽搷搴斾俊鎭�� + /// 瀵逛簬OPTIONS璇锋眰鏂规硶鎴栫┖HttpContext鐨勬儏鍐典細鐩存帴杩斿洖涓嶅仛璁板綍銆� + /// </remarks> + public static void Add(string requestParameter, string responseParameter) + { + dynamic? log = null; + try + { + //鑾峰彇褰撳墠HttpContext + HttpContext? context = App.HttpContext; + //濡傛灉HttpContext涓虹┖锛屽垯杩斿洖 + if (context == null) + { + return; + } + //濡傛灉璇锋眰鏂规硶涓篛PTIONS锛屽垯杩斿洖 + if (context.Request.Method == "OPTIONS") return; + //鑾峰彇RequestLogModel瀹炰緥 + RequestLogModel logModel = (context.RequestServices.GetService(typeof(RequestLogModel)) as RequestLogModel) ?? new RequestLogModel { RequestDate = DateTime.Now }; + + //鑾峰彇褰撳墠鐢ㄦ埛 + IUser? user = App.User; + //鍒涘缓鏃ュ織瀵硅薄 + log = new + { + //璇锋眰寮�濮嬫椂闂� + BeginDate = logModel.RequestDate, + //璇锋眰缁撴潫鏃堕棿 + EndDate = DateTime.Now, + //璇锋眰鍙傛暟 + RequestParam = requestParameter, + //鍝嶅簲鍙傛暟 + ResponseParam = responseParameter, + //璇锋眰URL + Url = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Path, + //瀹㈡埛绔疘P + UserIP = GetClientIP(context)?.Replace("::ffff:", ""), + //鐢ㄦ埛ID + UserId = user?.UserId, + //鐢ㄦ埛鍚� + UserName = user?.UserName + }; + } + catch (Exception exception) + { + //濡傛灉鍙戠敓寮傚父锛屽垯鍒涘缓鏃ュ織瀵硅薄 + log = log ?? new + { + //璇锋眰寮�濮嬫椂闂� + BeginDate = DateTime.Now, + //璇锋眰缁撴潫鏃堕棿 + EndDate = DateTime.Now, + //璇锋眰鍙傛暟 + RequestParam = requestParameter, + //鍝嶅簲鍙傛暟 + ResponseParam = responseParameter, + }; + } + //娣诲姞绯荤粺鏃ュ織 + loggerQueueData.Enqueue(log); + } + + /// <summary> + /// 鑾峰彇瀹㈡埛绔殑IP鍦板潃 + /// </summary> + /// <param name="context">Http涓婁笅鏂囧璞�</param> + /// <returns>瀹㈡埛绔殑IP鍦板潃瀛楃涓�</returns> + /// <remarks> + /// 浼樺厛浠嶺-Forwarded-For璇锋眰澶翠腑鑾峰彇IP鍦板潃锛屽鏋滀笉瀛樺湪鍒欎粠杩炴帴杩滅▼IP鍦板潃鑾峰彇 + /// </remarks> + public static string GetClientIP(HttpContext context) + { + // 鑾峰彇璇锋眰澶翠腑鐨刋-Forwarded-For瀛楁锛屽苟灏嗗叾杞崲涓哄瓧绗︿覆 + var ip = context.Request.Headers["X-Forwarded-For"].ObjToString(); + // 濡傛灉X-Forwarded-For瀛楁涓虹┖锛屽垯鑾峰彇杩滅▼IP鍦板潃 + if (string.IsNullOrEmpty(ip)) + { + ip = context.Connection.RemoteIpAddress.ObjToString(); + } + + // 杩斿洖IP鍦板潃 + return ip; + } + + + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/QuartzLogger.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/QuartzLogger.cs" new file mode 100644 index 0000000..7ac06f4 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/QuartzLogger.cs" @@ -0,0 +1,117 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.LogHelper +{ + public class QuartzLogger + { + static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim(); + static string folderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Log\\{DateTime.Now.ToString("yyyy-MM-dd")}"); + + /// <summary> + /// 灏嗘棩蹇楀唴瀹瑰啓鍏ユ寚瀹氭枃浠� + /// </summary> + /// <param name="fileName">鏃ュ織鏂囦欢鍚�</param> + /// <param name="log">瑕佽褰曠殑鏃ュ織鍐呭</param> + /// <remarks> + /// 璇ユ柟娉曚細纭繚绾跨▼瀹夊叏鍦板啓鍏ユ棩蹇楋紝鑻ョ洰褰曚笉瀛樺湪浼氳嚜鍔ㄥ垱寤猴紝 + /// 鏃ュ織鍐呭浼氳嚜鍔ㄦ坊鍔犳椂闂存埑骞惰拷鍔犲埌鏂囦欢鏈熬 + /// </remarks> + public static void WriteLogToFile(string fileName, string log) + { + try + { + // 杩涘叆鍐欓攣 + LogWriteLock.EnterWriteLock(); + + // 濡傛灉鏂囦欢澶逛笉瀛樺湪锛屽垯鍒涘缓鏂囦欢澶� + if (!Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + // 鑾峰彇鏃ュ織鏂囦欢璺緞 + string logFilePath = Path.Combine(folderPath, GetLastAccessFileName(fileName)); + // 鑾峰彇褰撳墠鏃堕棿 + DateTime now = DateTime.Now; + // 鏋勯�犳棩蹇楀唴瀹� + string logContent = $"銆恵now}銆憑Environment.NewLine}{log}"; + + // 灏嗘棩蹇楀唴瀹硅拷鍔犲埌鏃ュ織鏂囦欢涓� + File.AppendAllText(logFilePath, logContent); + } + catch { } + finally + { + // 閫�鍑哄啓閿� + LogWriteLock.ExitWriteLock(); + } + } + static int size = 10 * 1024 * 1024; + static string ext = ".log"; + /// <summary> + /// 鑾峰彇鎸囧畾鏂囦欢澶逛笅绗﹀悎鏉′欢鐨勬棩蹇楁枃浠惰矾寰� + /// </summary> + /// <param name="folderPath">瑕佹悳绱㈢殑鏂囦欢澶硅矾寰�</param> + /// <param name="fileName">瑕佸尮閰嶇殑鏂囦欢鍚�</param> + /// <returns>濡傛灉鎵惧埌绗﹀悎鏉′欢鐨勬枃浠跺垯杩斿洖绗竴涓枃浠剁殑瀹屾暣璺緞锛屽惁鍒欒繑鍥炲甫鏃堕棿鎴崇殑鏂版枃浠惰矾寰�</returns> + /// <remarks> + /// 鏌ユ壘瑙勫垯锛氭枃浠跺悕鍖呭惈鎸囧畾鍚嶇О銆佹墿灞曞悕鍖归厤涓斿皬浜庢寚瀹氬ぇ灏忕殑鏂囦欢锛屾寜鏂囦欢鍚嶉檷搴忔帓鍒� + /// </remarks> + private static string GetLogFilePath(string folderPath, string fileName) + { + // 鑾峰彇鎸囧畾鏂囦欢澶逛笅鐨勬墍鏈夋枃浠� + var allFiles = new DirectoryInfo(folderPath); + // 鑾峰彇绗﹀悎鏉′欢鐨勬枃浠讹紝鎸夋枃浠跺悕闄嶅簭鎺掑垪 + var selectFiles = allFiles.GetFiles().Where(fi => fi.Name.ToLower().Contains(fileName.ToLower()) && fi.Extension.ToLower() == ext.ToLower() && fi.Length < size).OrderByDescending(d => d.Name).ToList(); + + FileInfo? file = selectFiles.FirstOrDefault(); + // 濡傛灉鏈夌鍚堟潯浠剁殑鏂囦欢锛岃繑鍥炵涓�涓枃浠剁殑瀹屾暣璺緞 + if (file != null) + { + return file.FullName; + } + + // 濡傛灉娌℃湁绗﹀悎鏉′欢鐨勬枃浠讹紝杩斿洖涓�涓柊鐨勬枃浠惰矾寰勶紝鏂囦欢鍚嶄负鍘熸枃浠跺悕鍔犱笂褰撳墠鏃堕棿 + return Path.Combine(folderPath, $@"{fileName}_{DateTime.Now.ToString("HH-mm-ss")}.log"); + } + + /// <summary> + /// 鑾峰彇鏈�鍚庝竴涓彲鐢ㄧ殑鏃ュ織鏂囦欢鍚� + /// </summary> + /// <param name="fileName">鏃ュ織鏂囦欢鍩虹鍚嶇О</param> + /// <returns>濡傛灉瀛樺湪鏈揪鍒板ぇ灏忛檺鍒剁殑鏃ュ織鏂囦欢鍒欒繑鍥炶鏂囦欢鍚嶏紝鍚﹀垯杩斿洖鍩轰簬褰撳墠鏃堕棿鐨勬柊鏃ュ織鏂囦欢鍚�</returns> + /// <remarks> + /// 璇ユ柟娉曚細閬嶅巻鎵�鏈夊凡瀛樺湪鐨勬棩蹇楁枃浠讹紝杩斿洖绗竴涓枃浠跺ぇ灏忔湭瓒呰繃闄愬埗鐨勬枃浠跺悕銆� + /// 濡傛灉娌℃湁绗﹀悎鏉′欢鐨勬枃浠讹紝鍒欑敓鎴愪竴涓互褰撳墠鏃堕棿鍛藉悕鐨勬柊鏃ュ織鏂囦欢鍚嶃�� + /// </remarks> + private static string GetLastAccessFileName(string fileName) + { + foreach (var m in GetExistLogFileNames(fileName)) + { + FileInfo fileInfo = new FileInfo(m); + if (fileInfo.Length < size) + { + return m; + } + } + + // 杩斿洖涓�涓柊鐨勯粯璁ゅ綋鍓嶆椂闂寸殑鏃ュ織鍚嶇О + return $@"{fileName}_{DateTime.Now.ToString("HH-mm-ss")}.log"; + } + + /// <summary> + /// 鑾峰彇鎸囧畾鏂囦欢鍚嶆ā寮忕殑鎵�鏈夋棩蹇楁枃浠� + /// </summary> + /// <param name="fileName">鏃ュ織鏂囦欢鍚嶅墠缂�</param> + /// <returns>鍖归厤鏂囦欢鍚嶆ā寮忕殑鎵�鏈夋棩蹇楁枃浠惰矾寰勬暟缁�</returns> + public static string[] GetExistLogFileNames(string fileName) + { + string[] fileNames = Directory.GetFiles(folderPath, fileName + "*.log"); + return fileNames; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/RequestLogModel.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/RequestLogModel.cs" new file mode 100644 index 0000000..05a6f65 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/LogHelper/RequestLogModel.cs" @@ -0,0 +1,13 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.LogHelper +{ + public class RequestLogModel + { + public DateTime RequestDate { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/AllServicesMiddleware.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/AllServicesMiddleware.cs" new file mode 100644 index 0000000..bf29f08 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/AllServicesMiddleware.cs" @@ -0,0 +1,72 @@ +锘縰sing Autofac.Core; +using Autofac.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Middlewares +{ + /// <summary> + /// 鏌ョ湅鎵�鏈夋敞鍏ョ殑鏈嶅姟 + /// </summary> + public static class AllServicesMiddleware + { + /// <summary> + /// 娉ㄥ唽涓�涓腑闂翠欢锛岀敤浜庢樉绀烘墍鏈夊凡娉ㄥ唽鐨勬湇鍔′俊鎭� + /// </summary> + /// <param name="app">搴旂敤绋嬪簭鏋勫缓鍣�</param> + /// <param name="_services">鏈嶅姟闆嗗悎</param> + /// <remarks> + /// 璇ヤ腑闂翠欢浼氬湪"/allservices"璺緞涓嬬敓鎴愪竴涓狧TML琛ㄦ牸锛� + /// 灞曠ず鎵�鏈夋敞鍐岀殑鏈嶅姟绫诲瀷銆佺敓鍛藉懆鏈熷拰瀹炵幇绫诲瀷淇℃伅锛� + /// 鍖呮嫭閫氳繃Autofac娉ㄥ唽鐨勬湇鍔� + /// </remarks> + public static void UseAllServicesMiddle(this IApplicationBuilder app, IServiceCollection _services) + { + if (app == null) throw new ArgumentNullException(nameof(app)); + + //List<Type> tsDIAutofac = new List<Type>(); + //tsDIAutofac.AddRange(Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, "Blog.Core.Services.dll")).GetTypes().ToList()); + //tsDIAutofac.AddRange(Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, "Blog.Core.Repository.dll")).GetTypes().ToList()); + + IEnumerable<IComponentRegistration> autofacContainers = (app.ApplicationServices.GetAutofacRoot())?.ComponentRegistry?.Registrations ?? new List<IComponentRegistration>(); + + + app.Map("/allservices", builder => builder.Run(async context => + { + context.Response.ContentType = "text/html; charset=utf-8"; + await context.Response.WriteAsync("<style>.table2_1 table {width:100%;margin:15px 0}.table2_1 th {background-color:#93DAFF;color:#000000}.table2_1,.table2_1 th,.table2_1 td{font-size:0.95em;text-align:center;padding:4px;border:1px solid #c1e9fe;border-collapse:collapse}.table2_1 tr:nth-child(odd){background-color:#dbf2fe;}.table2_1 tr:nth-child(even){background-color:#fdfdfd;}</style>"); + + await context.Response.WriteAsync($"<h3>鎵�鏈夋湇鍔_services.Count}涓�</h3><table class='table2_1'><thead><tr><th>绫诲瀷</th><th>鐢熷懡鍛ㄦ湡</th><th>Instance</th></tr></thead><tbody>"); + + foreach (var svc in _services) + { + await context.Response.WriteAsync("<tr>"); + await context.Response.WriteAsync($"<td>{svc.ServiceType.FullName}</td>"); + await context.Response.WriteAsync($"<td>{svc.Lifetime}</td>"); + await context.Response.WriteAsync($"<td>{svc.ImplementationType?.Name}</td>"); + await context.Response.WriteAsync("</tr>"); + } + foreach (var item in autofacContainers?.ToList()) + { + var interfaceType = item.Services; + foreach (var typeArray in interfaceType) + { + await context.Response.WriteAsync("<tr>"); + await context.Response.WriteAsync($"<td>{typeArray?.Description}</td>"); + await context.Response.WriteAsync($"<td>{item?.Lifetime}</td>"); + await context.Response.WriteAsync($"<td>{item?.Target.Activator.ObjToString().Replace("(ReflectionActivator)", "")}</td>"); + await context.Response.WriteAsync("</tr>"); + } + } + await context.Response.WriteAsync("</tbody></table>"); + })); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/ApiLogMiddleware.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/ApiLogMiddleware.cs" new file mode 100644 index 0000000..93df4a1 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/ApiLogMiddleware.cs" @@ -0,0 +1,144 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using StackExchange.Profiling.Internal; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; +using WIDESEA_Core.LogHelper; + +namespace WIDESEA_Core.Middlewares +{ + /// <summary> + /// 璁板綍璇锋眰鍜屽搷搴旀暟鎹� + /// </summary> + public class ApiLogMiddleware + { + /// <summary> + /// + /// </summary> + private readonly RequestDelegate _next; + + public ApiLogMiddleware(RequestDelegate next, ILogger<ApiLogMiddleware> logger) + { + _next = next; + } + + //todo + /// <summary> + /// API鏃ュ織涓棿浠讹紝鐢ㄤ簬澶勭悊HTTP璇锋眰鍜屽搷搴旂殑鏃ュ織璁板綍 + /// </summary> + /// <remarks> + /// 1. 妫�鏌ョ郴缁熻繃鏈熸椂闂达紝鑻ヨ繃鏈熷垯杩斿洖500閿欒 + /// 2. 浠呭鐞嗗寘鍚�"api"璺緞鐨勮姹� + /// 3. 璁板綍璇锋眰鍜屽搷搴旀暟鎹埌鏃ュ織绯荤粺 + /// 4. 鏀寔閫氳繃閰嶇疆蹇界暐鐗瑰畾URL鐨勬棩蹇楄褰� + /// </remarks> + /// <param name="context">褰撳墠HTTP涓婁笅鏂�</param> + /// <returns>寮傛浠诲姟</returns> + public async Task InvokeAsync(HttpContext context) + { + if (App.ExpDateTime != null && (DateTime.Now - App.ExpDateTime.GetValueOrDefault()).TotalSeconds > 0) + { + context.Response.StatusCode = HttpStatusCode.InternalServerError.ObjToInt(); + context.Response.ContentType = "application/json"; + + var json = new WebResponseContent(); + + json.Message = HttpStatusCode.InternalServerError.ToString();//閿欒淇℃伅 + json.Code = 500;//500寮傚父 + + StreamWriter streamWriter = new StreamWriter(context.Response.Body); + await streamWriter.WriteAsync(json.Serialize()); + return; + } + + // 杩囨护锛屽彧鏈夋帴鍙� + if (context.Request.Path.Value?.Contains("api") ?? false) + { + context.Request.EnableBuffering(); + Stream originalBody = context.Response.Body; + string requestParam = string.Empty; + string responseParam = string.Empty; + try + { + string? apiIgnore = AppSettings.GetValue("ApiLogIgnore")?.ToString(); + string[] ignoreUrls = !string.IsNullOrEmpty(apiIgnore) ? apiIgnore.Split(",") : new string[] { "get" }; + + (context.RequestServices.GetService(typeof(RequestLogModel)) as RequestLogModel).RequestDate = DateTime.Now; + try + { + // 瀛樺偍璇锋眰鏁版嵁 + requestParam = RequestDataLog(context); + context.Request.Body.Position = 0; + } + catch { } + using MemoryStream ms = new(); + context.Response.Body = ms; + + await _next(context); + + try + { + // 瀛樺偍鍝嶅簲鏁版嵁 + responseParam = ResponseDataLog(context.Response); + } + catch { } + + ms.Position = 0; + await ms.CopyToAsync(originalBody); + + if (!ignoreUrls.Any(x => context.Request.Path.Value?.Contains(x) ?? false)) + { + Logger.Add(requestParam, responseParam); + } + } + catch (Exception ex) + { + // 璁板綍寮傚父 + + } + finally + { + context.Response.Body = originalBody; + } + } + else + { + await _next(context); + } + } + + private string RequestDataLog(HttpContext context) + { + var request = context.Request; + var sr = new StreamReader(request.Body); + + object obj = new + { + QueryString = request.QueryString.ToString(), + BodyData = sr.ReadToEndAsync().Result + }; + + string data = JsonConvert.SerializeObject(obj); + + request.Body.Position = 0; + + return data; + } + + private string ResponseDataLog(HttpResponse response) + { + response.Body.Position = 0; + using StreamReader stream = new StreamReader(response.Body, leaveOpen: true); + string body = stream.ReadToEnd(); + response.Body.Position = 0; + return body; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/ExceptionHandlerMiddleware.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/ExceptionHandlerMiddleware.cs" new file mode 100644 index 0000000..6431571 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/ExceptionHandlerMiddleware.cs" @@ -0,0 +1,84 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.DirectoryServices.Protocols; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Middlewares +{ + public class ExceptionHandlerMiddleware + { + private readonly RequestDelegate _next; + + public ExceptionHandlerMiddleware(RequestDelegate next) + { + _next = next; + } + + /// <summary> + /// 澶勭悊HTTP璇锋眰骞舵崟鑾峰紓甯� + /// </summary> + /// <param name="context">HTTP涓婁笅鏂�</param> + /// <returns>琛ㄧず寮傛鎿嶄綔鐨勪换鍔�</returns> + /// <remarks> + /// 褰撹姹傚鐞嗚繃绋嬩腑鍙戠敓寮傚父鏃讹紝浼氳皟鐢℉andleExceptionAsync鏂规硶杩涜澶勭悊 + /// </remarks> + public async Task Invoke(HttpContext context) + { + try + { + await _next(context); + } + catch (Exception ex) + { + await HandleExceptionAsync(context, ex); + } + } + + /// <summary> + /// 寮傛澶勭悊寮傚父骞跺啓鍏ュ搷搴� + /// </summary> + /// <param name="context">HTTP涓婁笅鏂�</param> + /// <param name="e">寰呭鐞嗙殑寮傚父瀵硅薄</param> + /// <returns>琛ㄧず寮傛鎿嶄綔鐨勪换鍔�</returns> + private async Task HandleExceptionAsync(HttpContext context, Exception e) + { + if (e == null) return; + + await WriteExceptionAsync(context, e).ConfigureAwait(false); + } + + /// <summary> + /// 寮傛灏嗗紓甯镐俊鎭啓鍏TTP鍝嶅簲 + /// </summary> + /// <param name="context">HTTP涓婁笅鏂囧璞�</param> + /// <param name="e">鍙戠敓鐨勫紓甯�</param> + /// <remarks> + /// 鏍规嵁寮傚父绫诲瀷璁剧疆瀵瑰簲鐨凥TTP鐘舵�佺爜锛� + /// - UnauthorizedAccessException: 杩斿洖401鏈巿鏉冪姸鎬佺爜 + /// - 鍏朵粬寮傚父: 杩斿洖500鍐呴儴鏈嶅姟鍣ㄩ敊璇姸鎬佺爜 + /// 鍝嶅簲鍐呭涓篔SON鏍煎紡鐨勯敊璇俊鎭� + /// </remarks> + private static async Task WriteExceptionAsync(HttpContext context, Exception e) + { + var message = e.Message; + switch (e) + { + case UnauthorizedAccessException: + context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + break; + default: + context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + break; + } + context.Response.ContentType = "application/json"; + await context.Response + .WriteAsync(JsonConvert.SerializeObject(WebResponseContent.Instance.Error(message))) + .ConfigureAwait(false); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/HttpRequestMiddleware.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/HttpRequestMiddleware.cs" new file mode 100644 index 0000000..0d5aa39 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/HttpRequestMiddleware.cs" @@ -0,0 +1,31 @@ +锘縰sing Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Middlewares +{ + public class HttpRequestMiddleware + { + private readonly RequestDelegate _next; + + public HttpRequestMiddleware(RequestDelegate next) + { + _next = next; + } + + /// <summary> + /// 涓棿浠舵柟娉曪紝鐢ㄤ簬澶勭悊HTTP璇锋眰涓婁笅鏂囥�� + /// 鍚戝搷搴斿ご娣诲姞"Access-Control-Expose-Headers"瀛楁锛屽厑璁稿鎴风璁块棶鑷畾涔夊ご"WIDESEA_exp"銆� + /// </summary> + /// <param name="context">HTTP璇锋眰涓婁笅鏂囧璞�</param> + /// <returns>寮傛浠诲姟</returns> + public async Task InvokeAsync(HttpContext context) + { + context.Response.Headers.Add("Access-Control-Expose-Headers", "WIDESEA_exp"); + await _next(context); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/IpLimitMiddleware.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/IpLimitMiddleware.cs" new file mode 100644 index 0000000..279f7a4 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/IpLimitMiddleware.cs" @@ -0,0 +1,40 @@ +锘� +using Microsoft.AspNetCore.Builder; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Middlewares +{ + /// <summary> + /// ip 闄愭祦 + /// </summary> + public static class IpLimitMiddleware + { + /// <summary> + /// ip闄愭祦 + /// </summary> + /// <param name="app"></param> + /// <exception cref="ArgumentNullException"></exception> + public static void UseIpLimitMiddle(this IApplicationBuilder app) + { + if (app == null) throw new ArgumentNullException(nameof(app)); + + //try + //{ + // if (AppSettings.app("Middleware", "IpRateLimit", "Enabled").ObjToBool()) + // { + // app.UseIpRateLimiting(); + // } + //} + //catch (Exception e) + //{ + // Log.Error($"Error occured limiting ip rate.\n{e.Message}"); + // throw; + //} + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/JwtTokenAuthMiddleware.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/JwtTokenAuthMiddleware.cs" new file mode 100644 index 0000000..ef95892 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/JwtTokenAuthMiddleware.cs" @@ -0,0 +1,94 @@ +锘縰sing Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Authorization; +using WIDESEA_Core.HttpContextUser; + +namespace WIDESEA_Core.Middlewares +{ + /// <summary> + /// 涓棿浠� + /// 鍘熷仛涓鸿嚜瀹氫箟鎺堟潈涓棿浠� + /// 鍏堝仛妫�鏌� header token鐨勪娇鐢� + /// </summary> + public class JwtTokenAuthMiddleware + { + /// <summary> + /// + /// </summary> + private readonly RequestDelegate _next; + /// <summary> + /// + /// </summary> + /// <param name="next"></param> + public JwtTokenAuthMiddleware(RequestDelegate next) + { + _next = next; + } + + + private void PreProceed(HttpContext next) + { + //Console.WriteLine($"{DateTime.Now} middleware invoke preproceed"); + //... + } + private void PostProceed(HttpContext next) + { + //Console.WriteLine($"{DateTime.Now} middleware invoke postproceed"); + //.... + } + + /// <summary> + /// + /// </summary> + /// <param name="httpContext"></param> + /// <returns></returns> + public Task Invoke(HttpContext httpContext) + { + PreProceed(httpContext); + + + //妫�娴嬫槸鍚﹀寘鍚�'Authorization'璇锋眰澶� + if (!httpContext.Request.Headers.ContainsKey("Authorization")) + { + PostProceed(httpContext); + + return _next(httpContext); + } + //var tokenHeader = httpContext.Request.Headers["Authorization"].ToString(); + var tokenHeader = httpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", ""); + + try + { + if (tokenHeader.Length >= 128) + { + //Console.WriteLine($"{DateTime.Now} token :{tokenHeader}"); + UserInfo tm = JwtHelper.SerializeJwt(tokenHeader); + + //鎺堟潈 + //var claimList = new List<Claim>(); + //var claim = new Claim(ClaimTypes.Role, tm.Role); + //claimList.Add(claim); + //var identity = new ClaimsIdentity(claimList); + //var principal = new ClaimsPrincipal(identity); + //httpContext.User = principal; + } + + } + catch (Exception e) + { + Console.WriteLine($"{DateTime.Now} middleware wrong:{e.Message}"); + } + + + PostProceed(httpContext); + + + return _next(httpContext); + } + + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/MiddlewareHelpers.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/MiddlewareHelpers.cs" new file mode 100644 index 0000000..917faa5 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/MiddlewareHelpers.cs" @@ -0,0 +1,42 @@ +锘縰sing Microsoft.AspNetCore.Builder; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Middlewares +{ + public static class MiddlewareHelpers + { + /// <summary> + /// 璇锋眰鍝嶅簲涓棿浠� + /// </summary> + /// <param name="app"></param> + /// <returns></returns> + public static IApplicationBuilder UseApiLogMiddleware(this IApplicationBuilder app) + { + return app.UseMiddleware<ApiLogMiddleware>(); + } + + /// <summary> + /// 鑷畾涔夋巿鏉冧腑闂翠欢 + /// </summary> + /// <param name="app"></param> + /// <returns></returns> + public static IApplicationBuilder UseJwtTokenAuth(this IApplicationBuilder app) + { + return app.UseMiddleware<JwtTokenAuthMiddleware>(); + } + + /// <summary> + /// 寮傚父澶勭悊涓棿浠� + /// </summary> + /// <param name="app"></param> + /// <returns></returns> + public static IApplicationBuilder UseExceptionHandlerMiddle(this IApplicationBuilder app) + { + return app.UseMiddleware<ExceptionHandlerMiddleware>(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/SwaggerAuthMiddleware.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/SwaggerAuthMiddleware.cs" new file mode 100644 index 0000000..701af29 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/SwaggerAuthMiddleware.cs" @@ -0,0 +1,86 @@ +锘縰sing Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Extensions; + +namespace WIDESEA_Core.Middlewares +{ + public class SwaggerAuthMiddleware + { + + private readonly RequestDelegate next; + + public SwaggerAuthMiddleware(RequestDelegate next) + { + this.next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + // 涔熷彲浠ユ牴鎹槸鍚︽槸鏈湴鍋氬垽鏂� IsLocalRequest + if (context.Request.Path.Value?.ToLower().Contains("index.html") ?? false) + { + // 鍒ゆ柇鏉冮檺鏄惁姝g‘ + if (IsAuthorized(context)) + { + await next.Invoke(context); + return; + } + + // 鏃犳潈闄愶紝璺宠浆swagger鐧诲綍椤� + context.RedirectSwaggerLogin(); + } + else + { + await next.Invoke(context); + } + } + + /// <summary> + /// 妫�鏌ュ綋鍓岺TTP涓婁笅鏂囨槸鍚﹀凡閫氳繃Swagger璁よ瘉 + /// </summary> + /// <param name="context">HTTP涓婁笅鏂囧璞�</param> + /// <returns>杩斿洖true琛ㄧず宸查�氳繃璁よ瘉锛宖alse琛ㄧず鏈�氳繃</returns> + public bool IsAuthorized(HttpContext context) + { + // 浣跨敤session妯″紡 + // 鍙互浣跨敤鍏朵粬鐨� + return context.IsSuccessSwagger(); + } + + /// <summary> + /// 鍒ゆ柇鏄笉鏄湰鍦拌闂� + /// 鏈湴涓嶇敤swagger鎷︽埅 + /// </summary> + /// <param name="context"></param> + /// <returns></returns> + public bool IsLocalRequest(HttpContext context) + { + if (context.Connection.RemoteIpAddress == null && context.Connection.LocalIpAddress == null) + { + return true; + } + if (context.Connection.RemoteIpAddress?.Equals(context.Connection.LocalIpAddress) ?? false) + { + return true; + } + if (IPAddress.IsLoopback(context.Connection.RemoteIpAddress)) + { + return true; + } + return false; + } + } + public static class SwaggerAuthorizeExtensions + { + public static IApplicationBuilder UseSwaggerAuthorized(this IApplicationBuilder builder) + { + return builder.UseMiddleware<SwaggerAuthMiddleware>(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/SwaggerMiddleware.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/SwaggerMiddleware.cs" new file mode 100644 index 0000000..16c46ee --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Middlewares/SwaggerMiddleware.cs" @@ -0,0 +1,61 @@ +锘� +using Microsoft.AspNetCore.Builder; +using Swashbuckle.AspNetCore.SwaggerUI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Middlewares +{ + /// <summary> + /// Swagger涓棿浠� + /// </summary> + public static class SwaggerMiddleware + { + /// <summary> + /// 閰嶇疆搴旂敤绋嬪簭浣跨敤Swagger涓棿浠� + /// </summary> + /// <param name="app">搴旂敤绋嬪簭鏋勫缓鍣�</param> + /// <param name="streamHtml">鐢ㄤ簬鑾峰彇鑷畾涔塖wagger棣栭〉HTML娴佺殑鍑芥暟</param> + /// <remarks> + /// 姝ゆ墿灞曟柟娉曢厤缃甋wagger UI锛屽寘鎷細 + /// 1. 璁剧疆API鏂囨。绔偣 + /// 2. 鑷畾涔夋枃妗f爣棰樺拰鏍峰紡 + /// 3. 閰嶇疆鑷畾涔夐椤垫祦 + /// 4. 璁剧疆鏂囨。灞曞紑琛屼负鍜岃矾鐢卞墠缂� + /// 濡傛灉streamHtml杩斿洖null锛屽皢鎶涘嚭寮傚父鎻愮ず闇�瑕佸皢index.html璁剧疆涓哄祵鍏ヨ祫婧� + /// </remarks> + public static void UseSwaggerMiddle(this IApplicationBuilder app, Func<Stream> streamHtml) + { + if (app == null) throw new ArgumentNullException(nameof(app)); + + app.UseSwagger(); + app.UseSwaggerUI(c => + { + //鏍规嵁鐗堟湰鍚嶇О鍊掑簭 閬嶅巻灞曠ず + var apiName = AppSettings.Get(new string[] { "ApiName" }); + c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"{apiName} v1"); + + // 灏唖wagger棣栭〉锛岃缃垚鎴戜滑鑷畾涔夌殑椤甸潰锛岃寰楄繖涓瓧绗︿覆鐨勫啓娉曪細{椤圭洰鍚�.index.html} + if (streamHtml.Invoke() == null) + { + var msg = "index.html鐨勫睘鎬э紝蹇呴』璁剧疆涓哄祵鍏ョ殑璧勬簮"; + //Log.Error(msg); + throw new Exception(msg); + } + c.DocumentTitle = $"{apiName} 鍦ㄧ嚎璋冭瘯鏂囨。"; + + c.InjectStylesheet("/css/swaggerdoc.css"); + c.InjectJavascript("/js/swaggerdoc.js"); + c.IndexStream = streamHtml; + c.DocExpansion(DocExpansion.None); //->淇敼鐣岄潰鎵撳紑鏃惰嚜鍔ㄦ姌鍙� + + // 璺緞閰嶇疆锛岃缃负绌猴紝琛ㄧず鐩存帴鍦ㄦ牴鍩熷悕锛坙ocalhost:8001锛夎闂鏂囦欢,娉ㄦ剰localhost:8001/swagger鏄闂笉鍒扮殑锛屽幓launchSettings.json鎶妉aunchUrl鍘绘帀锛屽鏋滀綘鎯虫崲涓�涓矾寰勶紝鐩存帴鍐欏悕瀛楀嵆鍙紝姣斿鐩存帴鍐檆.RoutePrefix = "doc"; + c.RoutePrefix = ""; + }); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/DBContext.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/DBContext.cs" new file mode 100644 index 0000000..56ddd5f --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/DBContext.cs" @@ -0,0 +1,225 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Const; +using WIDESEA_Core.DB; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Seed +{ + public class DBContext + { + private static MutiDBOperate connectObject => GetMainConnectionDb(); + private static string _connectionString = connectObject.Connection; + private static DbType _dbType = (DbType)connectObject.DbType; + public static string ConnId = connectObject.ConnId; + private SqlSugarClient _db; + + /// <summary> + /// 杩炴帴瀛楃涓� + /// </summary> + public static MutiDBOperate GetMainConnectionDb() + { + string dbType = AppSettings.GetValue("DBType"); + if (Enum.TryParse(typeof(DbType), dbType, out object? result) && result != null) + { + DbType dataBaseType = (DbType)result; + MutiDBOperate mainDb = new MutiDBOperate() + { + Connection = AppSettings.Get(MainDb.ConnectionString).DecryptDES(AppSecret.DB), + ConnId = MainDb.CurrentDbConnId, + DbType = dataBaseType + }; + + return mainDb; + } + else + { + throw new Exception("鏁版嵁搴撶被鍨嬮厤缃敊璇�"); + } + } + /// <summary> + /// 杩炴帴瀛楃涓� + /// </summary> + public static string ConnectionString + { + get { return _connectionString; } + set { _connectionString = value; } + } + /// <summary> + /// 鏁版嵁搴撶被鍨� + /// </summary> + public static DbType DbType + { + get { return _dbType; } + set { _dbType = value; } + } + /// <summary> + /// 鏁版嵁杩炴帴瀵硅薄 + /// </summary> + public SqlSugarClient Db + { + get { return _db; } + private set { _db = value; } + } + + //public SqlSugarScope DbClient + //{ + // get { return _dbClient; } + // private set { _dbClient = value; } + //} + + /// <summary> + /// 鍔熻兘鎻忚堪:鏋勯�犲嚱鏁� + /// </summary> + public DBContext(ISqlSugarClient sqlSugarClient) + { + if (string.IsNullOrEmpty(_connectionString)) + throw new ArgumentNullException("鏁版嵁搴撹繛鎺ュ瓧绗︿覆涓虹┖"); + + _db = sqlSugarClient as SqlSugarClient; + //_db.Aop.DataExecuting = SqlSugarAop.DataExecuting; + } + + #region 瀹炰緥鏂规硶 + /// <summary> + /// 鍔熻兘鎻忚堪:鑾峰彇鏁版嵁搴撳鐞嗗璞� + /// </summary> + /// <returns>杩斿洖鍊�</returns> + public SimpleClient<T> GetEntityDB<T>() where T : class, new() + { + return new SimpleClient<T>(_db); + } + /// <summary> + /// 鍔熻兘鎻忚堪:鑾峰彇鏁版嵁搴撳鐞嗗璞� + /// </summary> + /// <param name="db">db</param> + /// <returns>杩斿洖鍊�</returns> + //public SimpleClient<T> GetEntityDB<T>(SqlSugarClient db) where T : class, new() + //{ + // return new SimpleClient<T>(db); + //} + + + + #endregion + + + #region 鏍规嵁瀹炰綋绫荤敓鎴愭暟鎹簱琛� + /// <summary> + /// 鍔熻兘鎻忚堪:鏍规嵁瀹炰綋绫荤敓鎴愭暟鎹簱琛� + /// </summary> + /// <param name="blnBackupTable">鏄惁澶囦唤琛�</param> + /// <param name="lstEntitys">鎸囧畾鐨勫疄浣�</param> + public void CreateTableByEntity<T>(bool blnBackupTable, params T[] lstEntitys) where T : class, new() + { + Type[] lstTypes = null; + if (lstEntitys != null) + { + lstTypes = new Type[lstEntitys.Length]; + for (int i = 0; i < lstEntitys.Length; i++) + { + T t = lstEntitys[i]; + lstTypes[i] = typeof(T); + } + } + CreateTableByEntity(blnBackupTable, lstTypes); + } + + /// <summary> + /// 鍔熻兘鎻忚堪:鏍规嵁瀹炰綋绫荤敓鎴愭暟鎹簱琛� + /// </summary> + /// <param name="blnBackupTable">鏄惁澶囦唤琛�</param> + /// <param name="lstEntitys">鎸囧畾鐨勫疄浣�</param> + public void CreateTableByEntity(bool blnBackupTable, params Type[] lstEntitys) + { + if (blnBackupTable) + { + _db.CodeFirst.BackupTable().InitTables(lstEntitys); //change entity backupTable + } + else + { + _db.CodeFirst.InitTables(lstEntitys); + } + } + #endregion + + + #region 闈欐�佹柟娉� + + ///// <summary> + ///// 鍔熻兘鎻忚堪:鑾峰緱涓�涓狣bContext + ///// </summary> + ///// <returns></returns> + //public static MyContext GetDbContext() + //{ + // return new MyContext(); + //} + + /// <summary> + /// 鍔熻兘鎻忚堪:璁剧疆鍒濆鍖栧弬鏁� + /// </summary> + /// <param name="strConnectionString">杩炴帴瀛楃涓�</param> + /// <param name="enmDbType">鏁版嵁搴撶被鍨�</param> + public static void Init(string strConnectionString, DbType enmDbType = SqlSugar.DbType.SqlServer) + { + _connectionString = strConnectionString; + _dbType = enmDbType; + } + + /// <summary> + /// 鍔熻兘鎻忚堪:鍒涘缓涓�涓摼鎺ラ厤缃� + /// </summary> + /// <param name="blnIsAutoCloseConnection">鏄惁鑷姩鍏抽棴杩炴帴</param> + /// <param name="blnIsShardSameThread">鏄惁澶哥被浜嬪姟</param> + /// <returns>ConnectionConfig</returns> + public static ConnectionConfig GetConnectionConfig(bool blnIsAutoCloseConnection = true, bool blnIsShardSameThread = false) + { + ConnectionConfig config = new ConnectionConfig() + { + ConnectionString = _connectionString, + DbType = _dbType, + IsAutoCloseConnection = blnIsAutoCloseConnection, + ConfigureExternalServices = new ConfigureExternalServices() + { + //DataInfoCacheService = new HttpRuntimeCache() + }, + //IsShardSameThread = blnIsShardSameThread + }; + return config; + } + + /// <summary> + /// 鍔熻兘鎻忚堪:鑾峰彇涓�涓嚜瀹氫箟鐨凞B + /// </summary> + /// <param name="config">config</param> + /// <returns>杩斿洖鍊�</returns> + public static SqlSugarClient GetCustomDB(ConnectionConfig config) + { + return new SqlSugarClient(config); + } + /// <summary> + /// 鍔熻兘鎻忚堪:鑾峰彇涓�涓嚜瀹氫箟鐨勬暟鎹簱澶勭悊瀵硅薄 + /// </summary> + /// <param name="sugarClient">sugarClient</param> + /// <returns>杩斿洖鍊�</returns> + public static SimpleClient<T> GetCustomEntityDB<T>(SqlSugarClient sugarClient) where T : class, new() + { + return new SimpleClient<T>(sugarClient); + } + /// <summary> + /// 鍔熻兘鎻忚堪:鑾峰彇涓�涓嚜瀹氫箟鐨勬暟鎹簱澶勭悊瀵硅薄 + /// </summary> + /// <param name="config">config</param> + /// <returns>杩斿洖鍊�</returns> + public static SimpleClient<T> GetCustomEntityDB<T>(ConnectionConfig config) where T : class, new() + { + SqlSugarClient sugarClient = GetCustomDB(config); + return GetCustomEntityDB<T>(sugarClient); + } + #endregion + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/DBSeed.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/DBSeed.cs" new file mode 100644 index 0000000..8121e38 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/DBSeed.cs" @@ -0,0 +1,354 @@ +锘縰sing Castle.Components.DictionaryAdapter.Xml; +using Microsoft.AspNetCore.Mvc.Rendering; +using Newtonsoft.Json; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Text; +using SkiaSharp; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Attributes; +using WIDESEA_Core.Const; +using WIDESEA_Core.DB; +using WIDESEA_Core.Helper; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Core.Seed +{ + public class DBSeed + { + private static string SeedDataFolder = "WIDESEA_DB.DBSeed.Json/{0}.tsv"; + + /// <summary> + /// 寮傛娣诲姞绉嶅瓙鏁版嵁 + /// </summary> + /// <param name="myContext"></param> + /// <param name="WebRootPath"></param> + /// <returns></returns> + public static async Task SeedAsync(DBContext dbContext, string WebRootPath) + { + try + { + if (string.IsNullOrEmpty(WebRootPath)) + { + throw new Exception("鑾峰彇wwwroot璺緞鏃讹紝寮傚父锛�"); + } + + SeedDataFolder = Path.Combine(WebRootPath, SeedDataFolder); + + Console.WriteLine("************ WIDESEA DataBase Set *****************"); + + //Console.WriteLine($"Master DB ConId: {DBContext.ConnId}"); + Console.WriteLine($"Master DB Type: {DBContext.DbType}"); + //Console.WriteLine($"Master DB ConnectString: {DBContext.ConnectionString}"); + + Console.WriteLine(); + + // 鍒涘缓鏁版嵁搴� + Console.WriteLine($"Create Database(The Db Id:{DBContext.ConnId})..."); + + if (DBContext.DbType != SqlSugar.DbType.Oracle) + { + dbContext.Db.DbMaintenance.CreateDatabase(); + ConsoleHelper.WriteSuccessLine($"Database Created Successfully!"); + } + else + { + //Oracle 鏁版嵁搴撲笉鏀寔璇ユ搷浣� + ConsoleHelper.WriteSuccessLine($"Oracle 鏁版嵁搴撲笉鏀寔璇ユ搷浣滐紝鍙墜鍔ㄥ垱寤篛racle鏁版嵁搴�!"); + } + + // 鍒涘缓鏁版嵁搴撹〃锛岄亶鍘嗘寚瀹氬懡鍚嶇┖闂翠笅鐨刢lass锛� + // 娉ㄦ剰涓嶈鎶婂叾浠栧懡鍚嶇┖闂翠笅鐨勪篃娣诲姞杩涙潵銆� + Console.WriteLine("Create Tables..."); + + string path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory; + Assembly[] referencedAssemblies = System.IO.Directory.GetFiles(path, MainDb.AssemblyName).Select(Assembly.LoadFrom).ToArray(); + + List<Type> modelTypes = referencedAssemblies + .SelectMany(a => a.DefinedTypes) + .Select(type => type.AsType()) + .Where(x => x.IsClass && x.Namespace is MainDb.EntityNameSpace && x.GetCustomAttribute<SugarTable>() != null) + .ToList(); + + modelTypes.ForEach(t => + { + //var diffString = dbContext.Db.CodeFirst.GetDifferenceTables(t).ToDiffString(); + // 杩欓噷鍙敮鎸佹坊鍔犺〃锛屼笉鏀寔鍒犻櫎 + // 濡傛灉鎯宠鍒犻櫎锛屾暟鎹簱鐩存帴鍙抽敭鍒犻櫎锛屾垨鑰呰仈绯籗qlSugar浣滆�咃紱 + IDbMaintenance dbMaintenance = dbContext.Db.DbMaintenance; + if (!dbMaintenance.IsAnyTable(t.Name, false)) + { + ConsoleHelper.WriteSuccessLine($"Table [{t.Name}] Created Successfully"); + dbContext.Db.CodeFirst.InitTables(t); + + string seedData = FileHelper.ReadFile(string.Format(SeedDataFolder, t.Name), Encoding.UTF8); + + #region AddSeedData + if (seedData != "涓嶅瓨鍦ㄧ浉搴旂殑鐩綍") + { + List<Dictionary<string, object>> dicFile = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(seedData); + + if (dicFile.Count > 0) + { + List<Dictionary<string, object>> dic = new List<Dictionary<string, object>>(); + + List<string> columnNames = dbContext.Db.DbMaintenance.GetColumnInfosByTableName(t.Name, false).Select(x => x.DbColumnName).ToList(); + var a = t.GetProperties().FirstOrDefault(x => !columnNames.Contains(x.Name)); + + List<PropertyInfo> propertyInfos = t.GetProperties().Where(x => columnNames.Contains(x.Name)).ToList(); + for (int j = 0; j < dicFile.Count; j++) + { + Dictionary<string, object> keyValuePairs = new Dictionary<string, object>(); + for (int i = 0; i < propertyInfos.Count; i++) + { + PropertyInfo propertyInfo = propertyInfos[i]; + + SequenceAttribute? sequenceAttirbute = propertyInfo.GetCustomAttribute<SequenceAttribute>(); + if (sequenceAttirbute != null) + { + int count = dbContext.Db.Ado.GetScalar($"SELECT COUNT(*) FROM sys.sequences WHERE name = '{sequenceAttirbute.SequenceName}'").ObjToInt(); + if (count == 0) + { + string sql = $"CREATE SEQUENCE {sequenceAttirbute.SequenceName} AS [int] START WITH {sequenceAttirbute.StartWith} INCREMENT BY {sequenceAttirbute.Increment} MINVALUE {sequenceAttirbute.SeqMinValue} MAXVALUE {sequenceAttirbute.SeqMaxValue} {(sequenceAttirbute.IsCycle ? "CYCLE" : "")} CACHE"; + dbContext.Db.Ado.ExecuteCommand(sql); + } + } + + SugarColumn? sugarColumn = propertyInfo.GetCustomAttribute<SugarColumn>(); + if (sugarColumn != null) + { + if (!sugarColumn.IsIgnore) + { + keyValuePairs.Add(propertyInfo.Name, dicFile[j][propertyInfo.Name]); + } + } + } + dic.Add(keyValuePairs); + } + + if (dic.Count > 0) + { + for (int i = 0; i < dic.Count; i++) + { + if (dic[i].ContainsKey("CreateDate")) + dic[i]["CreateDate"] = DateTime.Now; + else + dic[i].Add("CreateDate", DateTime.Now); + } + string str = ""; + if (DBContext.DbType == SqlSugar.DbType.SqlServer) + { + str += $"SET IDENTITY_INSERT {t.Name} ON;"; + + str += dbContext.Db.Insertable(dic).AS(t.Name).ToSqlString(); + + str += ($"SET IDENTITY_INSERT {t.Name} OFF;"); + + dbContext.Db.Ado.ExecuteCommand(str); + } + else + { + dbContext.Db.Insertable(dic).AS(t.Name).ExecuteCommand(); + } + + ConsoleHelper.WriteSuccessLine($"Table [{t.Name}] SeedData Added Successfully"); + } + } + } + #endregion + } + else + { + List<string> columnNames = dbContext.Db.DbMaintenance.GetColumnInfosByTableName(t.Name, false).Select(x => x.DbColumnName).ToList(); + if (t.GetProperties().FirstOrDefault(x => !columnNames.Contains(x.Name)) != null) + { + bool isChange = true; + List<PropertyInfo> propertyInfos = t.GetProperties().Where(x => !columnNames.Contains(x.Name)).ToList(); + for (int i = 0; i < propertyInfos.Count; i++) + { + PropertyInfo propertyInfo = propertyInfos[i]; + + SequenceAttribute? sequenceAttirbute = propertyInfo.GetCustomAttribute<SequenceAttribute>(); + if (sequenceAttirbute != null) + { + int count = dbContext.Db.Ado.GetScalar($"SELECT COUNT(*) FROM sys.sequences WHERE name = '{sequenceAttirbute.SequenceName}'").ObjToInt(); + if (count == 0) + { + string sql = $"CREATE SEQUENCE {sequenceAttirbute.SequenceName} AS [int] START WITH {sequenceAttirbute.StartWith} INCREMENT BY {sequenceAttirbute.Increment} MINVALUE {sequenceAttirbute.SeqMinValue} MAXVALUE {sequenceAttirbute.SeqMaxValue} {(sequenceAttirbute.IsCycle ? "CYCLE" : "")} CACHE"; + dbContext.Db.Ado.ExecuteCommand(sql); + } + } + SugarColumn? sugarColumn = propertyInfo.GetCustomAttribute<SugarColumn>(); + if (sugarColumn != null) + { + if (!sugarColumn.IsIgnore) + { + if (!sugarColumn.IsNullable) + { + isChange = false; + break; + } + } + } + } + if (isChange) + dbContext.Db.CodeFirst.InitTables(t); + } + } + }); + ConsoleHelper.WriteSuccessLine($"Tables Created Successfully!"); + Console.WriteLine(); + + + } + catch (Exception ex) + { + // 1銆佽嫢鏄疢ysql,鏌ョ湅甯歌闂:https://github.com/anjoy8/Blog.Core/issues/148#issue-776281770 + //2銆佽嫢鏄疧racle,鏌ョ湅甯歌闂:https://github.com/anjoy8/Blog.Core/issues/148#issuecomment-752340231 + throw new Exception("閿欒锛�" + ex.Message); + } + } + + /// <summary> + /// 鍒濆鍖� 澶氱鎴� + /// </summary> + /// <param name="dbContext"></param> + /// <returns></returns> + public static async Task TenantSeedAsync(DBContext dbContext) + { + + if (BaseDBConfig.MutiConnectionString.Where(x => x.ConnId != MainDb.CurrentDbConnId).Any()) + { + Console.WriteLine($@"Init Multi Tenant Db"); + foreach (MutiDBOperate tenant in BaseDBConfig.MutiConnectionString.Where(x => x.ConnId != MainDb.CurrentDbConnId)) + { + + Console.WriteLine($@"Init Multi Tenant Db : {tenant.ConnId}"); + ConnectionConfig connectionConfig = new ConnectionConfig() + { + ConfigId = tenant.ConnId, + ConnectionString = tenant.Connection, + IsAutoCloseConnection = true, + MoreSettings = new ConnMoreSettings() + { + IsAutoRemoveDataCache = true + }, + DbType = (DbType)tenant.DbType, + }; + await InitTenantSeedAsync(dbContext.Db.AsTenant(), connectionConfig); + } + + Console.WriteLine(DateTime.Now + $@"Init Multi Tenant Db Finish"); + } + + //tenants = await myContext.Db.Queryable<SysTenant>().Where(s => s.TenantType == TenantTypeEnum.Tables).ToListAsync(); + //if (tenants.Any()) + //{ + // await InitTenantSeedAsync(myContext, tenants); + //} + } + + #region 澶氱鎴� 澶氬簱 鍒濆鍖� + + /// <summary> + /// 鍒濆鍖栧搴� + /// </summary> + /// <param name="itenant"></param> + /// <param name="config"></param> + /// <returns></returns> + public static async Task InitTenantSeedAsync(ITenant itenant, ConnectionConfig config) + { + Console.WriteLine(DateTime.Now + $@"Init Multi Tenant Db"); + //itenant.RemoveConnection(config.ConfigId); + itenant.AddConnection(config); + + var db = itenant.GetConnectionScope(config.ConfigId); + + db.DbMaintenance.CreateDatabase(); + ConsoleHelper.WriteSuccessLine($"Init Multi Tenant Db : {config.ConfigId} Database created successfully!"); + + Console.WriteLine($@"Init Multi Tenant Db : {config.ConfigId} Create Tables"); + + // 鑾峰彇鎵�鏈夊疄浣撹〃-鍒濆鍖栫鎴蜂笟鍔¤〃 + var entityTypes = TenantUtil.GetTenantEntityTypes(TenantTypeEnum.Db); + if (!entityTypes.Any()) return; + foreach (var entityType in entityTypes) + { + //var splitTable = entityType.GetCustomAttribute<SplitTableAttribute>(); + //if (splitTable == null) + db.CodeFirst.InitTables(entityType); + //else + // db.CodeFirst.SplitTables().InitTables(entityType); + + Console.WriteLine(entityType.Name); + } + Console.WriteLine(DateTime.Now + $@"Init Multi Tenant Db Finish"); + //澶氱鎴峰垵濮嬪寲绉嶅瓙鏁版嵁 + //await TenantSeedDataAsync(db, TenantTypeEnum.Db); + } + + #endregion + + //private static async Task TenantSeedDataAsync(ISqlSugarClient db, TenantTypeEnum tenantType) + //{ + // // 鑾峰彇鎵�鏈夌瀛愰厤缃�-鍒濆鍖栨暟鎹� + // var seedDataTypes = AssemblysExtensions.GetAllAssemblies().SelectMany(s => s.DefinedTypes) + // .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass) + // .Where(u => + // { + // var esd = u.GetInterfaces().FirstOrDefault(i => i.HasImplementedRawGeneric(typeof(IEntitySeedData<>))); + // if (esd is null) + // { + // return false; + // } + + // var eType = esd.GenericTypeArguments[0]; + // return eType.IsTenantEntity(tenantType); + // }); + // if (!seedDataTypes.Any()) return; + // foreach (var seedType in seedDataTypes) + // { + // dynamic instance = Activator.CreateInstance(seedType); + // //鍒濆鍖栨暟鎹� + // { + // var seedData = instance.InitSeedData(); + // if (seedData != null && Enumerable.Any(seedData)) + // { + // var entityType = seedType.GetInterfaces().First().GetGenericArguments().First(); + // var entity = db.EntityMaintenance.GetEntityInfo(entityType); + + // if (!await db.Queryable(entity.DbTableName, "").AnyAsync()) + // { + // await db.Insertable(Enumerable.ToList(seedData)).ExecuteCommandAsync(); + // Console.WriteLine($"Table:{entity.DbTableName} init success!"); + // } + // } + // } + + // //绉嶅瓙鏁版嵁 + // { + // var seedData = instance.SeedData(); + // if (seedData != null && Enumerable.Any(seedData)) + // { + // var entityType = seedType.GetInterfaces().First().GetGenericArguments().First(); + // var entity = db.EntityMaintenance.GetEntityInfo(entityType); + + // await db.Storageable(Enumerable.ToList(seedData)).ExecuteCommandAsync(); + // Console.WriteLine($"Table:{entity.DbTableName} seedData success!"); + // } + // } + + // //鑷畾涔夊鐞� + // { + // await instance.CustomizeSeedData(db); + // } + // } + //} + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/FrameSeed.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/FrameSeed.cs" new file mode 100644 index 0000000..4711bda --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Seed/FrameSeed.cs" @@ -0,0 +1,582 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Seed +{ + public class FrameSeed + { + + /// <summary> + /// 鐢熸垚Controller灞� + /// </summary> + /// <param name="sqlSugarClient">sqlsugar瀹炰緥</param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="tableNames">鏁版嵁搴撹〃鍚嶆暟缁勶紝榛樿绌猴紝鐢熸垚鎵�鏈夎〃</param> + /// <param name="isMuti"></param> + /// <returns></returns> + public static bool CreateControllers(SqlSugarScope sqlSugarClient, string ConnId = null, bool isMuti = false, string[] tableNames = null) + { + Create_Controller_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Blog.Core.Api.Controllers", "Blog.Core.Api.Controllers", tableNames, "", isMuti); + return true; + } + + /// <summary> + /// 鐢熸垚Model灞� + /// </summary> + /// <param name="sqlSugarClient">sqlsugar瀹炰緥</param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="tableNames">鏁版嵁搴撹〃鍚嶆暟缁勶紝榛樿绌猴紝鐢熸垚鎵�鏈夎〃</param> + /// <param name="isMuti"></param> + /// <returns></returns> + public static bool CreateModels(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) + { + Create_Model_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Blog.Core.Model", "Blog.Core.Model.Models", tableNames, "", isMuti); + return true; + } + + /// <summary> + /// 鐢熸垚IRepository灞� + /// </summary> + /// <param name="sqlSugarClient">sqlsugar瀹炰緥</param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="isMuti"></param> + /// <param name="tableNames">鏁版嵁搴撹〃鍚嶆暟缁勶紝榛樿绌猴紝鐢熸垚鎵�鏈夎〃</param> + /// <returns></returns> + public static bool CreateIRepositorys(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) + { + Create_IRepository_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Blog.Core.IRepository", "Blog.Core.IRepository", tableNames, "", isMuti); + return true; + } + + + + /// <summary> + /// 鐢熸垚 IService 灞� + /// </summary> + /// <param name="sqlSugarClient">sqlsugar瀹炰緥</param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="isMuti"></param> + /// <param name="tableNames">鏁版嵁搴撹〃鍚嶆暟缁勶紝榛樿绌猴紝鐢熸垚鎵�鏈夎〃</param> + /// <returns></returns> + public static bool CreateIServices(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) + { + Create_IServices_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Blog.Core.IServices", "Blog.Core.IServices", tableNames, "", isMuti); + return true; + } + + + + /// <summary> + /// 鐢熸垚 Repository 灞� + /// </summary> + /// <param name="sqlSugarClient">sqlsugar瀹炰緥</param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="isMuti"></param> + /// <param name="tableNames">鏁版嵁搴撹〃鍚嶆暟缁勶紝榛樿绌猴紝鐢熸垚鎵�鏈夎〃</param> + /// <returns></returns> + public static bool CreateRepository(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) + { + Create_Repository_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Blog.Core.Repository", "Blog.Core.Repository", tableNames, "", isMuti); + return true; + } + + + + /// <summary> + /// 鐢熸垚 Service 灞� + /// </summary> + /// <param name="sqlSugarClient">sqlsugar瀹炰緥</param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="isMuti"></param> + /// <param name="tableNames">鏁版嵁搴撹〃鍚嶆暟缁勶紝榛樿绌猴紝鐢熸垚鎵�鏈夎〃</param> + /// <returns></returns> + public static bool CreateServices(SqlSugarScope sqlSugarClient, string ConnId, bool isMuti = false, string[] tableNames = null) + { + Create_Services_ClassFileByDBTalbe(sqlSugarClient, ConnId, $@"C:\my-file\Blog.Core.Services", "Blog.Core.Services", tableNames, "", isMuti); + return true; + } + + + #region 鏍规嵁鏁版嵁搴撹〃鐢熶骇Controller灞� + + /// <summary> + /// 鍔熻兘鎻忚堪:鏍规嵁鏁版嵁搴撹〃鐢熶骇Controller灞� + /// 浣溿��銆�鑰�:Blog.Core + /// </summary> + /// <param name="sqlSugarClient"></param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="strPath">瀹炰綋绫诲瓨鏀捐矾寰�</param> + /// <param name="strNameSpace">鍛藉悕绌洪棿</param> + /// <param name="lstTableNames">鐢熶骇鎸囧畾鐨勮〃</param> + /// <param name="strInterface">瀹炵幇鎺ュ彛</param> + /// <param name="isMuti"></param> + /// <param name="blnSerializable">鏄惁搴忓垪鍖�</param> + private static void Create_Controller_ClassFileByDBTalbe( + SqlSugarScope sqlSugarClient, + string ConnId, + string strPath, + string strNameSpace, + string[] lstTableNames, + string strInterface, + bool isMuti = false, + bool blnSerializable = false) + { + var IDbFirst = sqlSugarClient.DbFirst; + if (lstTableNames != null && lstTableNames.Length > 0) + { + IDbFirst = IDbFirst.Where(lstTableNames); + } + var ls = IDbFirst.IsCreateDefaultValue().IsCreateAttribute() + + .SettingClassTemplate(p => p = +@"using Blog.Core.IServices; +using Blog.Core.Model; +using Blog.Core.Model.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace " + strNameSpace + @" +{ + [Route(""api/[controller]/[action]"")] + [ApiController] + [Authorize(Permissions.Name)] + public class {ClassName}Controller : ControllerBase + { + /// <summary> + /// 鏈嶅姟鍣ㄦ帴鍙o紝鍥犱负鏄ā鏉跨敓鎴愶紝鎵�浠ラ瀛楁瘝鏄ぇ鍐欑殑锛岃嚜宸卞彲浠ラ噸鏋勪笅 + /// </summary> + private readonly I{ClassName}Services _{ClassName}Services; + + public {ClassName}Controller(I{ClassName}Services {ClassName}Services) + { + _{ClassName}Services = {ClassName}Services; + } + + [HttpGet] + public async Task<MessageModel<PageModel<{ClassName}>>> Get(int page = 1, string key = """",int intPageSize = 50) + { + if (string.IsNullOrEmpty(key) || string.IsNullOrWhiteSpace(key)) + { + key = """"; + } + + Expression<Func<{ClassName}, bool>> whereExpression = a => true; + + return new MessageModel<PageModel<{ClassName}>>() + { + msg = ""鑾峰彇鎴愬姛"", + success = true, + response = await _{ClassName}Services.QueryPage(whereExpression, page, intPageSize) + }; + + } + + [HttpGet(""{id}"")] + public async Task<MessageModel<{ClassName}>> Get(string id) + { + return new MessageModel<{ClassName}>() + { + msg = ""鑾峰彇鎴愬姛"", + success = true, + response = await _{ClassName}Services.QueryById(id) + }; + } + + [HttpPost] + public async Task<MessageModel<string>> Post([FromBody] {ClassName} request) + { + var data = new MessageModel<string>(); + + var id = await _{ClassName}Services.Add(request); + data.success = id > 0; + if (data.success) + { + data.response = id.ObjToString(); + data.msg = ""娣诲姞鎴愬姛""; + } + + return data; + } + + [HttpPut] + public async Task<MessageModel<string>> Put([FromBody] {ClassName} request) + { + var data = new MessageModel<string>(); + data.success = await _{ClassName}Services.Update(request); + if (data.success) + { + data.msg = ""鏇存柊鎴愬姛""; + data.response = request?.id.ObjToString(); + } + + return data; + } + + [HttpDelete] + public async Task<MessageModel<string>> Delete(int id) + { + var data = new MessageModel<string>(); + var model = await _{ClassName}Services.QueryById(id); + model.IsDeleted = true; + data.success = await _departmentServices.Update(model); + if (data.success) + { + data.msg = ""鍒犻櫎鎴愬姛""; + data.response = model?.Id.ObjToString(); + } + + return data; + } + } +}") + + .ToClassStringList(strNameSpace); + + Dictionary<string, string> newdic = new Dictionary<string, string>(); + //寰幆澶勭悊 棣栧瓧姣嶅皬鍐� 骞舵彃鍏ユ柊鐨� Dictionary + foreach (KeyValuePair<string, string> item in ls) + { + string newkey = "_" + item.Key.First().ToString().ToLower() + item.Key.Substring(1); + string newvalue = item.Value.Replace("_" + item.Key, newkey); + newdic.Add(item.Key, newvalue); + } + CreateFilesByClassStringList(newdic, strPath, "{0}Controller"); + } + #endregion + + + #region 鏍规嵁鏁版嵁搴撹〃鐢熶骇Model灞� + + /// <summary> + /// 鍔熻兘鎻忚堪:鏍规嵁鏁版嵁搴撹〃鐢熶骇Model灞� + /// 浣溿��銆�鑰�:Blog.Core + /// </summary> + /// <param name="sqlSugarClient"></param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="strPath">瀹炰綋绫诲瓨鏀捐矾寰�</param> + /// <param name="strNameSpace">鍛藉悕绌洪棿</param> + /// <param name="lstTableNames">鐢熶骇鎸囧畾鐨勮〃</param> + /// <param name="strInterface">瀹炵幇鎺ュ彛</param> + /// <param name="isMuti"></param> + /// <param name="blnSerializable">鏄惁搴忓垪鍖�</param> + private static void Create_Model_ClassFileByDBTalbe( + SqlSugarScope sqlSugarClient, + string ConnId, + string strPath, + string strNameSpace, + string[] lstTableNames, + string strInterface, + bool isMuti = false, + bool blnSerializable = false) + { + //澶氬簱鏂囦欢鍒嗙 + if (isMuti) + { + strPath = strPath + @"\Models\" + ConnId; + strNameSpace = strNameSpace + "." + ConnId; + } + + var IDbFirst = sqlSugarClient.DbFirst; + if (lstTableNames != null && lstTableNames.Length > 0) + { + IDbFirst = IDbFirst.Where(lstTableNames); + } + var ls = IDbFirst.IsCreateDefaultValue().IsCreateAttribute() + + .SettingClassTemplate(p => p = +@"{using} + +namespace " + strNameSpace + @" +{ +{ClassDescription} + [SugarTable( ""{ClassName}"", """ + ConnId + @""")]" + (blnSerializable ? "\n [Serializable]" : "") + @" + public class {ClassName}" + (string.IsNullOrEmpty(strInterface) ? "" : (" : " + strInterface)) + @" + { + public {ClassName}() + { + } +{PropertyName} + } +}") + //.SettingPropertyDescriptionTemplate(p => p = string.Empty) + .SettingPropertyTemplate(p => p = +@"{SugarColumn} + public {PropertyType} {PropertyName} { get; set; }") + + //.SettingConstructorTemplate(p => p = " this._{PropertyName} ={DefaultValue};") + + .ToClassStringList(strNameSpace); + CreateFilesByClassStringList(ls, strPath, "{0}"); + } + #endregion + + + #region 鏍规嵁鏁版嵁搴撹〃鐢熶骇IRepository灞� + + /// <summary> + /// 鍔熻兘鎻忚堪:鏍规嵁鏁版嵁搴撹〃鐢熶骇IRepository灞� + /// 浣溿��銆�鑰�:Blog.Core + /// </summary> + /// <param name="sqlSugarClient"></param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="strPath">瀹炰綋绫诲瓨鏀捐矾寰�</param> + /// <param name="strNameSpace">鍛藉悕绌洪棿</param> + /// <param name="lstTableNames">鐢熶骇鎸囧畾鐨勮〃</param> + /// <param name="strInterface">瀹炵幇鎺ュ彛</param> + /// <param name="isMuti"></param> + private static void Create_IRepository_ClassFileByDBTalbe( + SqlSugarScope sqlSugarClient, + string ConnId, + string strPath, + string strNameSpace, + string[] lstTableNames, + string strInterface, + bool isMuti = false + ) + { + //澶氬簱鏂囦欢鍒嗙 + if (isMuti) + { + strPath = strPath + @"\" + ConnId; + strNameSpace = strNameSpace + "." + ConnId; + } + + var IDbFirst = sqlSugarClient.DbFirst; + if (lstTableNames != null && lstTableNames.Length > 0) + { + IDbFirst = IDbFirst.Where(lstTableNames); + } + var ls = IDbFirst.IsCreateDefaultValue().IsCreateAttribute() + + .SettingClassTemplate(p => p = +@"using Blog.Core.IRepository.Base; +using Blog.Core.Model.Models" + (isMuti ? "." + ConnId + "" : "") + @"; + +namespace " + strNameSpace + @" +{ + /// <summary> + /// I{ClassName}Repository + /// </summary> + public interface I{ClassName}Repository : IBaseRepository<{ClassName}>" + (string.IsNullOrEmpty(strInterface) ? "" : (" , " + strInterface)) + @" + { + } +}") + + .ToClassStringList(strNameSpace); + CreateFilesByClassStringList(ls, strPath, "I{0}Repository"); + } + #endregion + + + #region 鏍规嵁鏁版嵁搴撹〃鐢熶骇IServices灞� + + /// <summary> + /// 鍔熻兘鎻忚堪:鏍规嵁鏁版嵁搴撹〃鐢熶骇IServices灞� + /// 浣溿��銆�鑰�:Blog.Core + /// </summary> + /// <param name="sqlSugarClient"></param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="strPath">瀹炰綋绫诲瓨鏀捐矾寰�</param> + /// <param name="strNameSpace">鍛藉悕绌洪棿</param> + /// <param name="lstTableNames">鐢熶骇鎸囧畾鐨勮〃</param> + /// <param name="strInterface">瀹炵幇鎺ュ彛</param> + /// <param name="isMuti"></param> + private static void Create_IServices_ClassFileByDBTalbe( + SqlSugarScope sqlSugarClient, + string ConnId, + string strPath, + string strNameSpace, + string[] lstTableNames, + string strInterface, + bool isMuti = false) + { + //澶氬簱鏂囦欢鍒嗙 + if (isMuti) + { + strPath = strPath + @"\" + ConnId; + strNameSpace = strNameSpace + "." + ConnId; + } + + var IDbFirst = sqlSugarClient.DbFirst; + if (lstTableNames != null && lstTableNames.Length > 0) + { + IDbFirst = IDbFirst.Where(lstTableNames); + } + var ls = IDbFirst.IsCreateDefaultValue().IsCreateAttribute() + + .SettingClassTemplate(p => p = +@"using Blog.Core.IServices.BASE; +using Blog.Core.Model.Models" + (isMuti ? "." + ConnId + "" : "") + @"; + +namespace " + strNameSpace + @" +{ + /// <summary> + /// I{ClassName}Services + /// </summary> + public interface I{ClassName}Services :IBaseServices<{ClassName}>" + (string.IsNullOrEmpty(strInterface) ? "" : (" , " + strInterface)) + @" + { + } +}") + + .ToClassStringList(strNameSpace); + CreateFilesByClassStringList(ls, strPath, "I{0}Services"); + } + #endregion + + + + #region 鏍规嵁鏁版嵁搴撹〃鐢熶骇 Repository 灞� + + /// <summary> + /// 鍔熻兘鎻忚堪:鏍规嵁鏁版嵁搴撹〃鐢熶骇 Repository 灞� + /// 浣溿��銆�鑰�:Blog.Core + /// </summary> + /// <param name="sqlSugarClient"></param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="strPath">瀹炰綋绫诲瓨鏀捐矾寰�</param> + /// <param name="strNameSpace">鍛藉悕绌洪棿</param> + /// <param name="lstTableNames">鐢熶骇鎸囧畾鐨勮〃</param> + /// <param name="strInterface">瀹炵幇鎺ュ彛</param> + /// <param name="isMuti"></param> + private static void Create_Repository_ClassFileByDBTalbe( + SqlSugarScope sqlSugarClient, + string ConnId, + string strPath, + string strNameSpace, + string[] lstTableNames, + string strInterface, + bool isMuti = false) + { + //澶氬簱鏂囦欢鍒嗙 + if (isMuti) + { + strPath = strPath + @"\" + ConnId; + strNameSpace = strNameSpace + "." + ConnId; + } + + var IDbFirst = sqlSugarClient.DbFirst; + if (lstTableNames != null && lstTableNames.Length > 0) + { + IDbFirst = IDbFirst.Where(lstTableNames); + } + var ls = IDbFirst.IsCreateDefaultValue().IsCreateAttribute() + + .SettingClassTemplate(p => p = +@"using Blog.Core.IRepository" + (isMuti ? "." + ConnId + "" : "") + @"; +using Blog.Core.IRepository.UnitOfWork; +using Blog.Core.Model.Models" + (isMuti ? "." + ConnId + "" : "") + @"; +using Blog.Core.Repository.Base; + +namespace " + strNameSpace + @" +{ + /// <summary> + /// {ClassName}Repository + /// </summary> + public class {ClassName}Repository : BaseRepository<{ClassName}>, I{ClassName}Repository" + (string.IsNullOrEmpty(strInterface) ? "" : (" , " + strInterface)) + @" + { + public {ClassName}Repository(IUnitOfWork unitOfWork) : base(unitOfWork) + { + } + } +}") + .ToClassStringList(strNameSpace); + + + CreateFilesByClassStringList(ls, strPath, "{0}Repository"); + } + #endregion + + + #region 鏍规嵁鏁版嵁搴撹〃鐢熶骇 Services 灞� + + /// <summary> + /// 鍔熻兘鎻忚堪:鏍规嵁鏁版嵁搴撹〃鐢熶骇 Services 灞� + /// 浣溿��銆�鑰�:Blog.Core + /// </summary> + /// <param name="sqlSugarClient"></param> + /// <param name="ConnId">鏁版嵁搴撻摼鎺D</param> + /// <param name="strPath">瀹炰綋绫诲瓨鏀捐矾寰�</param> + /// <param name="strNameSpace">鍛藉悕绌洪棿</param> + /// <param name="lstTableNames">鐢熶骇鎸囧畾鐨勮〃</param> + /// <param name="strInterface">瀹炵幇鎺ュ彛</param> + /// <param name="isMuti"></param> + private static void Create_Services_ClassFileByDBTalbe( + SqlSugarScope sqlSugarClient, + string ConnId, + string strPath, + string strNameSpace, + string[] lstTableNames, + string strInterface, + bool isMuti = false) + { + //澶氬簱鏂囦欢鍒嗙 + if (isMuti) + { + strPath = strPath + @"\" + ConnId; + strNameSpace = strNameSpace + "." + ConnId; + } + + var IDbFirst = sqlSugarClient.DbFirst; + if (lstTableNames != null && lstTableNames.Length > 0) + { + IDbFirst = IDbFirst.Where(lstTableNames); + } + var ls = IDbFirst.IsCreateDefaultValue().IsCreateAttribute() + + .SettingClassTemplate(p => p = +@" +using Blog.Core.IServices" + (isMuti ? "." + ConnId + "" : "") + @"; +using Blog.Core.Model.Models" + (isMuti ? "." + ConnId + "" : "") + @"; +using Blog.Core.Services.BASE; +using Blog.Core.IRepository.Base; + +namespace " + strNameSpace + @" +{ + public class {ClassName}Services : BaseServices<{ClassName}>, I{ClassName}Services" + (string.IsNullOrEmpty(strInterface) ? "" : (" , " + strInterface)) + @" + { + private readonly IBaseRepository<{ClassName}> _dal; + public {ClassName}Services(IBaseRepository<{ClassName}> dal) + { + this._dal = dal; + base.BaseDal = dal; + } + } +}") + .ToClassStringList(strNameSpace); + + CreateFilesByClassStringList(ls, strPath, "{0}Services"); + } + #endregion + + + #region 鏍规嵁妯℃澘鍐呭鎵归噺鐢熸垚鏂囦欢 + /// <summary> + /// 鏍规嵁妯℃澘鍐呭鎵归噺鐢熸垚鏂囦欢 + /// </summary> + /// <param name="ls">绫绘枃浠跺瓧绗︿覆list</param> + /// <param name="strPath">鐢熸垚璺緞</param> + /// <param name="fileNameTp">鏂囦欢鍚嶆牸寮忔ā鏉�</param> + private static void CreateFilesByClassStringList(Dictionary<string, string> ls, string strPath, string fileNameTp) + { + + foreach (var item in ls) + { + var fileName = $"{string.Format(fileNameTp, item.Key)}.cs"; + var fileFullPath = Path.Combine(strPath, fileName); + if (!Directory.Exists(strPath)) + { + Directory.CreateDirectory(strPath); + } + File.WriteAllText(fileFullPath, item.Value, Encoding.UTF8); + } + } + #endregion + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/ITenantEntity.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/ITenantEntity.cs" new file mode 100644 index 0000000..ca499c4 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/ITenantEntity.cs" @@ -0,0 +1,21 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Tenants +{ + /// <summary> + /// 绉熸埛妯″瀷鎺ュ彛 + /// </summary> + public interface ITenantEntity + { + /// <summary> + /// 绉熸埛Id + /// </summary> + [SugarColumn(DefaultValue = "0")] + public long TenantId { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/MultiTenantAttribute.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/MultiTenantAttribute.cs" new file mode 100644 index 0000000..a0927c3 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/MultiTenantAttribute.cs" @@ -0,0 +1,56 @@ +锘縰sing System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Tenants +{ + /// <summary> + /// 鏍囪瘑 澶氱鎴� 鐨勪笟鍔¤〃 <br/> + /// 榛樿璁剧疆鏄搴� <br/> + /// 鍏叡琛ㄦ棤闇�鍖哄垎 鐩存帴浣跨敤涓诲簱 鍚勮嚜涓氬姟鍦ㄥ悇鑷簱涓� <br/> + /// </summary> + [AttributeUsage(AttributeTargets.Class)] + public class MultiTenantAttribute : Attribute + { + public MultiTenantAttribute() + { + } + + public MultiTenantAttribute(TenantTypeEnum tenantType) + { + TenantType = tenantType; + } + + + public TenantTypeEnum TenantType { get; set; } = TenantTypeEnum.Db; + } + + /// <summary> + /// 绉熸埛闅旂鏂规 + /// </summary> + public enum TenantTypeEnum + { + None = 0, + + /// <summary> + /// Id闅旂 + /// </summary> + [Description("Id闅旂")] + Id = 1, + + /// <summary> + /// 搴撻殧绂� + /// </summary> + [Description("搴撻殧绂�")] + Db = 2, + + /// <summary> + /// 琛ㄩ殧绂� + /// </summary> + [Description("琛ㄩ殧绂�")] + Tables = 3, + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/TenantUtil.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/TenantUtil.cs" new file mode 100644 index 0000000..a0a9755 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Tenants/TenantUtil.cs" @@ -0,0 +1,127 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.DB; + +namespace WIDESEA_Core.Tenants +{ + public static class TenantUtil + { + //public static SysTenant DefaultTenantConfig(this SysTenant tenant) + //{ + // tenant.DbType ??= DbType.Sqlite; + + // //濡傛灉娌℃湁閰嶇疆杩炴帴 + // if (tenant.Connection.IsNullOrEmpty()) + // { + // //姝ゅ榛樿閰嶇疆 Sqlite 鍦板潃 + // //瀹為檯涓氬姟涓� 涔熶細鏈夎繍缁淬�佺郴缁熺鐞嗗憳绛夋潵缁存姢 + // switch (tenant.DbType.Value) + // { + // case DbType.Sqlite: + // tenant.Connection = $"DataSource={Path.Combine(Environment.CurrentDirectory, tenant.ConfigId)}.db"; + // break; + // } + // } + + // return tenant; + //} + + //public static ConnectionConfig GetConnectionConfig(this SysTenant tenant) + //{ + // if (tenant.DbType is null) + // { + // throw new ArgumentException("Tenant DbType Must"); + // } + + + // return new ConnectionConfig() + // { + // ConfigId = tenant.ConfigId, + // DbType = tenant.DbType.Value, + // ConnectionString = tenant.Connection, + // IsAutoCloseConnection = true, + // MoreSettings = new ConnMoreSettings() + // { + // IsAutoRemoveDataCache = true + // }, + // }; + //} + + public static List<Type> GetTenantEntityTypes(TenantTypeEnum? tenantType = null) + { + List<Type> types = RepositorySetting.Entitys.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass).ToList(); + + List<Type> returnTypes = types.Where(s => IsTenantEntity(s, tenantType)).ToList(); + return returnTypes; + } + + public static bool IsTenantEntity(this Type u, TenantTypeEnum? tenantType = null) + { + var mta = u.GetCustomAttribute<MultiTenantAttribute>(); + if (mta is null) + { + return false; + } + + if (tenantType != null) + { + if (mta.TenantType != tenantType) + { + return false; + } + } + + return true; + } + + public static string GetTenantTableName(this Type type, ISqlSugarClient db, string id) + { + var entityInfo = db.EntityMaintenance.GetEntityInfo(type); + return $@"{entityInfo.DbTableName}_{id}"; + } + + //public static string GetTenantTableName(this Type type, ISqlSugarClient db, SysTenant tenant) + //{ + // return GetTenantTableName(type, db, tenant.Id.ToString()); + //} + + public static void SetTenantTable(this ISqlSugarClient db, string id) + { + var types = GetTenantEntityTypes(TenantTypeEnum.Tables); + + foreach (var type in types) + { + db.MappingTables.Add(type.Name, type.GetTenantTableName(db, id)); + } + } + + public static List<SelectModel> GetTenantSelectModels() + { + List<SelectModel> selectModels = new List<SelectModel>() + { + new SelectModel + { + FieldName = MainDb.TenantId + }, + //new SelectModel + //{ + // FieldName = MainDb.TenantName + //}, + new SelectModel + { + FieldName = MainDb.ConnectionString, + }, + new SelectModel + { + FieldName = MainDb.TenantDbType + } + }; + return selectModels; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/EntityProperties.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/EntityProperties.cs" new file mode 100644 index 0000000..1290655 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/EntityProperties.cs" @@ -0,0 +1,404 @@ +锘縰sing SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Const; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Utilities +{ + public static class EntityProperties + { + + /// <summary> + /// 楠岃瘉灞炴�у�兼槸鍚︾鍚堟暟鎹簱瀛楁绫诲瀷瑕佹眰 + /// </summary> + /// <param name="propertyInfo">灞炴�т俊鎭�</param> + /// <param name="value">寰呴獙璇佺殑鍊�</param> + /// <returns> + /// 鍏冪粍鍖呭惈涓変釜鍊硷細 + /// Item1 - 楠岃瘉鏄惁閫氳繃锛坱rue/false锛� + /// Item2 - 楠岃瘉澶辫触鏃剁殑閿欒淇℃伅 + /// Item3 - 鍘熷杈撳叆鍊� + /// </returns> + /// <remarks> + /// 鏀寔楠岃瘉浠ヤ笅鏁版嵁搴撶被鍨嬶細 + /// - 鏁存暟绫诲瀷锛圛nt/BigInt锛� + /// - 鏃ユ湡鏃堕棿绫诲瀷锛圖ateTime/Date绛夛級 + /// - 娴偣绫诲瀷锛團loat/Double/Decimal锛� + /// - GUID绫诲瀷锛圲niqueIdentifier锛� + /// - 瀛楃涓茬被鍨嬶紙VarChar/NVarChar绛夛級鐨勯暱搴﹂檺鍒� + /// </remarks> + public static (bool, string, object) ValidationVal(this PropertyInfo propertyInfo, object value) + { + string dbType = ""; + SugarColumn sugarColumn = null; + if (propertyInfo != null) + { + sugarColumn = propertyInfo.GetCustomAttribute<SugarColumn>(); + dbType = propertyInfo.PropertyType != null ? propertyInfo.GetProperWithDbType() : SqlDbTypeName.NVarChar; + } + dbType = dbType.ToLower(); + string val = value?.ToString(); + //楠岃瘉闀垮害 + string reslutMsg = string.Empty; + if (dbType == SqlDbTypeName.Int) + { + if (!value.IsInt()) + reslutMsg = "鍙兘涓烘湁鏁堟暣鏁�"; + } //2021.10.12澧炲姞灞炴�ф牎楠宭ong绫诲瀷鐨勬敮鎸� + else if (dbType == SqlDbTypeName.BigInt) + { + if (!long.TryParse(val, out _)) + { + reslutMsg = "鍙兘涓烘湁鏁堟暣鏁�"; + } + } + else if (dbType == SqlDbTypeName.DateTime + || dbType == SqlDbTypeName.Date + || dbType == SqlDbTypeName.SmallDateTime + || dbType == SqlDbTypeName.SmallDate + ) + { + if (!value.IsDate()) + reslutMsg = "蹇呴』涓烘棩鏈熸牸寮�"; + } + else if (dbType == SqlDbTypeName.Float || dbType == SqlDbTypeName.Decimal || dbType == SqlDbTypeName.Double) + { + + if (!val.IsNumber(null)) + { + reslutMsg = "涓嶆槸鏈夋晥鏁板瓧"; + } + } + else if (dbType == SqlDbTypeName.UniqueIdentifier) + { + if (!val.IsGuid()) + { + reslutMsg = propertyInfo.Name + "Guid涓嶆纭�"; + } + } + else if (propertyInfo != null + && (dbType == SqlDbTypeName.VarChar + || dbType == SqlDbTypeName.NVarChar + || dbType == SqlDbTypeName.NChar + || dbType == SqlDbTypeName.Char + || dbType == SqlDbTypeName.Text)) + { + + //榛樿nvarchar(max) 銆乼ext 闀垮害涓嶈兘瓒呰繃20000 + if (val.Length > 200000) + { + reslutMsg = $"瀛楃闀垮害鏈�澶氥��200000銆�"; + } + else + { + int length = sugarColumn.Length; + if (length == 0) { return (true, null, value); } + //鍒ゆ柇鍙屽瓧鑺備笌鍗曞瓧娈� + else if (length < 8000 && + ((dbType.Substring(0, 1) != "n" + && Encoding.UTF8.GetBytes(val.ToCharArray()).Length > length) + || val.Length > length) + ) + { + reslutMsg = $"鏈�澶氬彧鑳姐�恵length}銆戜釜瀛楃銆�"; + } + } + } + if (!string.IsNullOrEmpty(reslutMsg) && propertyInfo != null) + { + reslutMsg = sugarColumn.ColumnDescription + reslutMsg; + } + return (reslutMsg == "" ? true : false, reslutMsg, value); + } + + /// <summary> + /// 楠岃瘉灞炴�у�兼槸鍚︾鍚堟暟鎹簱绫诲瀷瑕佹眰 + /// </summary> + /// <param name="propertyInfo">瑕侀獙璇佺殑灞炴�т俊鎭�</param> + /// <param name="values">瑕侀獙璇佺殑鍊兼暟缁�</param> + /// <returns>杩斿洖楠岃瘉缁撴灉鍒楄〃锛屾瘡涓粨鏋滃寘鍚槸鍚︽垚鍔熴�侀敊璇俊鎭拰楠岃瘉鍚庣殑鍊�</returns> + public static List<(bool, string, object)> ValidationValueForDbType(this PropertyInfo propertyInfo, params object[] values) + { + List<(bool, string, object)> result = new List<(bool, string, object)>(); + foreach (object value in values) + { + result.Add(propertyInfo.ValidationVal(value)); + } + return result; + } + + private static readonly Dictionary<Type, string> ProperWithDbType = new Dictionary<Type, string>() { + { typeof(string), SqlDbTypeName.NVarChar }, + { typeof(DateTime), SqlDbTypeName.DateTime}, + { typeof(long), SqlDbTypeName.BigInt }, + { typeof(int), SqlDbTypeName.Int}, + { typeof(decimal), SqlDbTypeName.Decimal }, + { typeof(float), SqlDbTypeName.Float }, + { typeof(double), SqlDbTypeName.Double }, + { typeof(byte), SqlDbTypeName.Int },//绫诲瀷寰呭畬 + { typeof(Guid), SqlDbTypeName.UniqueIdentifier} + }; + + /// <summary> + /// 鑾峰彇灞炴�у搴旂殑鏁版嵁搴撶被鍨� + /// </summary> + /// <param name="propertyInfo">灞炴�т俊鎭�</param> + /// <returns>濡傛灉鎵惧埌鍖归厤鍒欒繑鍥炲搴旂殑鏁版嵁搴撶被鍨嬶紝鍚﹀垯杩斿洖榛樿鐨凬VarChar绫诲瀷</returns> + public static string GetProperWithDbType(this PropertyInfo propertyInfo) + { + bool result = ProperWithDbType.TryGetValue(propertyInfo.PropertyType, out string value); + if (result) + { + return value; + } + return SqlDbTypeName.NVarChar; + } + + /// <summary> + /// 楠岃瘉瀛楀吀涓殑瀛楁鏄惁鍖归厤瀹炰綋灞炴�э紝骞惰繘琛屽繀瑕佺殑娓呯悊鍜岄獙璇� + /// </summary> + /// <param name="typeinfo">瀹炰綋绫诲瀷淇℃伅</param> + /// <param name="dic">寰呴獙璇佺殑瀛楁瀛楀吀</param> + /// <param name="removerKey">鏄惁绉婚櫎涓婚敭瀛楁</param> + /// <param name="propertyInfo">瀹炰綋灞炴�ч泦鍚�</param> + /// <param name="ignoreFields">闇�瑕佸拷鐣ョ殑瀛楁鍚嶆暟缁�</param> + /// <returns>楠岃瘉閫氳繃杩斿洖绌哄瓧绗︿覆锛屽惁鍒欒繑鍥為敊璇俊鎭�</returns> + /// <remarks> + /// 1. 绉婚櫎瀛楀吀涓笉瀛樺湪鐨勫疄浣撳瓧娈� + /// 2. 鏍规嵁閰嶇疆鍐冲畾鏄惁绉婚櫎涓婚敭瀛楁 + /// 3. 妫�鏌ュ繀濉瓧娈垫槸鍚︿负绌� + /// 4. 灏嗙┖瀛楃涓插�艰浆涓簄ull + /// </remarks> + public static string ValidateDicInEntity(this Type typeinfo, Dictionary<string, object> dic, bool removerKey, PropertyInfo[] propertyInfo, string[] ignoreFields = null) + { + if (dic == null || dic.Count == 0) { return "鍙傛暟鏃犳晥"; } + + // 涓嶅瓨鍦ㄧ殑瀛楁鐩存帴绉婚櫎 + dic.Where(x => !propertyInfo.Any(p => p.Name == x.Key.FirstLetterToUpper())).Select(s => s.Key).ToList().ForEach(f => + { + dic.Remove(f); + }); + + string keyName = typeinfo.GetKeyName(); + //绉婚櫎涓婚敭 + if (removerKey) + dic.Remove(keyName); + //else + //{ + // if (!dic.ContainsKey(keyName)) + // return "璇蜂紶鍏ヤ富閿弬鏁�"; + //} + + foreach (PropertyInfo property in propertyInfo) + { + SugarColumn sugarColumn = property.GetCustomAttribute<SugarColumn>(); + if (sugarColumn == null) + return "璇烽厤缃甋ugarColumn灞炴��"; + //蹇界暐涓庝富閿殑瀛楁涓嶅仛楠岃瘉 + if (property.Name == keyName.FirstLetterToUpper() || (ignoreFields != null && ignoreFields.Contains(property.Name)) || sugarColumn.IsOnlyIgnoreInsert || sugarColumn.IsOnlyIgnoreUpdate || sugarColumn.IsIgnore) + continue; + + //涓嶅湪缂栬緫涓殑鍒楋紝鏄惁涔熻蹇呭~ + if (!dic.ContainsKey(property.Name.FirstLetterToLower())) + { + if (!sugarColumn.IsNullable) + { + if (sugarColumn.DefaultValue == null) + return sugarColumn.ColumnDescription + "涓哄繀椤绘彁浜ら」"; + continue; + } + continue; + } + if(dic[property.Name.FirstLetterToLower()] != null) + { + string str = dic[property.Name.FirstLetterToLower()].ToString(); + //灏嗘墍鏈夌┖鍊艰缃负null + if (str == string.Empty) + dic[property.Name.FirstLetterToLower()] = null; + } + + } + return string.Empty; + } + + /// <summary> + /// 楠岃瘉瀛楀吀鍒楄〃涓殑瀛楁鏄惁涓庡疄浣撶被鍨嬪睘鎬у尮閰� + /// </summary> + /// <param name="typeinfo">瀹炰綋绫诲瀷</param> + /// <param name="dicList">瑕侀獙璇佺殑瀛楀吀鍒楄〃</param> + /// <param name="removerKey">鏄惁绉婚櫎涓嶅尮閰嶇殑閿�</param> + /// <param name="ignoreFields">瑕佸拷鐣ョ殑瀛楁鍚嶆暟缁�</param> + /// <returns>杩斿洖楠岃瘉缁撴灉娑堟伅锛岃嫢涓虹┖琛ㄧず楠岃瘉閫氳繃</returns> + public static string ValidateDicInEntity(this Type typeinfo, List<Dictionary<string, object>> dicList, bool removerKey, string[] ignoreFields = null) + { + PropertyInfo[] propertyInfo = typeinfo.GetProperties(); + string reslutMsg = string.Empty; + foreach (Dictionary<string, object> dic in dicList) + { + reslutMsg = typeinfo.ValidateDicInEntity(dic, removerKey, propertyInfo, ignoreFields); + if (!string.IsNullOrEmpty(reslutMsg)) + return reslutMsg; + } + return reslutMsg; + } + + /// <summary> + /// 鑾峰彇鎸囧畾绫诲瀷鐨勯敭鍚嶇О + /// </summary> + /// <param name="typeinfo">瑕佽幏鍙栭敭鍚嶇О鐨勭被鍨�</param> + /// <returns>杩斿洖璇ョ被鍨嬬殑閿悕绉�</returns> + public static string GetKeyName(this Type typeinfo) + { + return typeinfo.GetProperties().GetKeyName(); + } + + /// <summary> + /// 浠庡睘鎬ч泦鍚堜腑鑾峰彇涓婚敭灞炴�х殑鍚嶇О + /// </summary> + /// <param name="properties">瑕佹悳绱㈢殑灞炴�ч泦鍚�</param> + /// <returns>濡傛灉鎵惧埌涓婚敭灞炴�у垯杩斿洖鍏跺悕绉帮紝鍚﹀垯杩斿洖null</returns> + /// <remarks>閫氳繃鏌ユ壘甯︽湁[SugarColumn(IsPrimaryKey = true)]鐗规�х殑灞炴�ф潵纭畾涓婚敭</remarks> + public static string GetKeyName(this PropertyInfo[] properties) + { + foreach (PropertyInfo property in properties) + { + SugarColumn sugarColumn = property.GetCustomAttribute<SugarColumn>(); + if (sugarColumn.IsPrimaryKey) + return property.Name; + } + return null; + } + + /// <summary> + /// 鑾峰彇鎸囧畾绫诲瀷鐨勪富閿睘鎬� + /// </summary> + /// <param name="typeinfo">瑕佹鏌ョ殑绫诲瀷</param> + /// <returns>濡傛灉鎵惧埌鏍囪涓篬SugarColumn(IsPrimaryKey = true)]鐨勫睘鎬у垯杩斿洖璇ュ睘鎬э紝鍚﹀垯杩斿洖null</returns> + public static PropertyInfo GetKeyProperty(this Type typeinfo) + { + PropertyInfo[] properties = typeinfo.GetProperties(); + foreach (PropertyInfo property in properties) + { + SugarColumn sugarColumn = property.GetCustomAttribute<SugarColumn>(); + if (sugarColumn?.IsPrimaryKey ?? false) + { + return property; + } + } + return null; + } + + /// <summary> + /// 鑾峰彇绫诲瀷鐨勫鑸睘鎬ц缁嗙被鍨� + /// </summary> + /// <param name="typeinfo">瑕佹鏌ョ殑绫诲瀷</param> + /// <returns> + /// 濡傛灉鎵惧埌OneToOne瀵艰埅灞炴�у垯杩斿洖灞炴�х被鍨嬶紝 + /// 濡傛灉鏄叾浠栧鑸被鍨嬪垯杩斿洖娉涘瀷鍙傛暟绫诲瀷锛� + /// 鏈壘鍒板鑸睘鎬у垯杩斿洖null + /// </returns> + public static Type GetDetailType(this Type typeinfo) + { + PropertyInfo[] properties = typeinfo.GetProperties(); + foreach (PropertyInfo property in properties) + { + Navigate? navigate = property.GetCustomAttribute<Navigate>(); + if (navigate is not null) + { + if (navigate.GetNavigateType() == NavigateType.OneToOne) + return property.PropertyType; + else + return property.PropertyType.GenericTypeArguments[0]; + } + } + return null; + } + + /// <summary> + /// 閫氳繃瀹炰綋绫诲瀷鑾峰彇鍏朵富閿睘鎬у悕绉� + /// </summary> + /// <param name="typeinfo">瀹炰綋绫诲瀷</param> + /// <returns>涓婚敭灞炴�у悕绉帮紝濡傛灉鏈壘鍒板垯杩斿洖null</returns> + /// <remarks> + /// 璇ユ柟娉曢�氳繃鏌ユ壘瀹炰綋绫诲瀷涓婃爣璁颁簡[Navigate]鐗规�х殑灞炴�ф潵鑾峰彇涓婚敭鍚嶇О + /// </remarks> + public static string GetMainIdByDetail(this Type typeinfo) + { + PropertyInfo[] properties = typeinfo.GetProperties(); + foreach (PropertyInfo property in properties) + { + Navigate? navigate = property.GetCustomAttribute<Navigate>(); + if (navigate is not null) + { + return navigate.GetName(); + } + } + return null; + } + + /// <summary> + /// 涓哄疄浣撳璞¤缃寚瀹氬悕绉扮殑灞炴�у�� + /// </summary> + /// <typeparam name="T">瀹炰綋绫诲瀷</typeparam> + /// <param name="typeinfo">瀹炰綋绫诲瀷淇℃伅</param> + /// <param name="enetiy">鐩爣瀹炰綋瀵硅薄</param> + /// <param name="id">瑕佽缃殑灞炴�у��</param> + /// <param name="name">灞炴�у悕绉�</param> + public static void SetDetailId<T>(this Type typeinfo, T enetiy, object id, string name) + { + PropertyInfo property = typeinfo.GetProperty(name); + if (property != null) + { + property.SetValue(enetiy, id); + } + } + + /// <summary> + /// 鑾峰彇鎸囧畾绫诲瀷涓爣璁颁簡[Navigate]鐗规�х殑灞炴�� + /// </summary> + /// <param name="typeinfo">瑕佹悳绱㈢殑鐩爣绫诲瀷</param> + /// <returns>鎵惧埌鐨凱ropertyInfo瀵硅薄锛岃嫢鏈壘鍒板垯杩斿洖null</returns> + public static PropertyInfo? GetNavigatePro(this Type typeinfo) + { + PropertyInfo[] properties = typeinfo.GetProperties(); + foreach (PropertyInfo property in properties) + { + Navigate? navigate = property.GetCustomAttribute<Navigate>(); + if (navigate is not null) + { + return property; + } + } + return null; + } + + /// <summary> + /// 鑾峰彇鎸囧畾瀵硅薄鐨勫睘鎬у�� + /// </summary> + /// <typeparam name="T">瀵硅薄绫诲瀷</typeparam> + /// <param name="typeinfo">绫诲瀷淇℃伅</param> + /// <param name="data">鐩爣瀵硅薄</param> + /// <param name="propertyName">灞炴�у悕绉�</param> + /// <returns>灞炴�у�硷紝濡傛灉灞炴�т笉瀛樺湪鍒欒繑鍥瀗ull</returns> + public static object GetPropertyValue<T>(this Type typeinfo, T data, string propertyName) + { + if (typeinfo != typeof(T)) + return null; + + PropertyInfo? property = typeinfo.GetProperty(propertyName); + if (property != null) + { + return property.GetValue(data); + } + return null; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/LambdaExtensions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/LambdaExtensions.cs" new file mode 100644 index 0000000..459408a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/LambdaExtensions.cs" @@ -0,0 +1,183 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Enums; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Utilities +{ + public static class LambdaExtensions + { + /// <summary> + /// + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="propertyName">瀛楁鍚�</param> + /// <param name="propertyValue">琛ㄨ揪寮忕殑鍊�</param> + /// <param name="expressionType">鍒涘缓琛ㄨ揪寮忕殑绫诲瀷,濡�:p=>p.propertyName != propertyValue + /// p=>p.propertyName.Contains(propertyValue)</param> + /// <returns></returns> + public static Expression<Func<T, bool>> CreateExpression<T>(this string propertyName, object propertyValue, LinqExpressionType expressionType) + { + return propertyName.CreateExpression<T>(propertyValue, null, expressionType); + } + + /// <summary> + /// + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="propertyName">瀛楁鍚�</param> + /// <param name="propertyValue">琛ㄨ揪寮忕殑鍊�</param> + /// <param name="expressionType">鍒涘缓琛ㄨ揪寮忕殑绫诲瀷,濡�:p=>p.propertyName != propertyValue + /// p=>p.propertyName.Contains(propertyValue)</param> + /// <returns></returns> + private static Expression<Func<T, bool>> CreateExpression<T>( + this string propertyName, + object propertyValue, + ParameterExpression parameter, + LinqExpressionType expressionType) + { + Type proType = null; + PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName); + if (propertyInfo != null) + proType = propertyInfo.PropertyType; + else + { + propertyInfo = typeof(T).GetProperty(propertyName.FirstLetterToLower()); + if (propertyInfo != null) + proType = propertyInfo.PropertyType; + else + { + propertyInfo = typeof(T).GetProperty(propertyName.FirstLetterToUpper()); + if (propertyInfo != null) + proType = propertyInfo.PropertyType; + else + { + throw new Exception($"鏈壘鍒拌灞炴��,type:{typeof(T)}"); + } + } + } + //鍒涘缓鑺傜偣鍙橀噺濡俻=>鐨勮妭鐐筽 + // parameter ??= Expression.Parameter(typeof(T), "p");//鍒涘缓鍙傛暟p + parameter = parameter ?? Expression.Parameter(typeof(T), "p"); + + //鍒涘缓鑺傜偣鐨勫睘鎬=>p.name 灞炴�ame + MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyName); + if (expressionType == LinqExpressionType.In) + { + if (!(propertyValue is System.Collections.IList list) || list.Count == 0) throw new Exception("灞炴�у�肩被鍨嬩笉姝g‘"); + + bool isStringValue = true; + List<object> objList = new List<object>(); + + if (proType.ToString() != "System.String") + { + isStringValue = false; + foreach (var value in list) + { + objList.Add(value.ToString().ChangeType(proType)); + } + list = objList; + } + + if (isStringValue) + { + //string 绫诲瀷鐨勫瓧娈碉紝濡傛灉鍊煎甫鏈�'鍗曞紩鍙�,EF浼氶粯璁ゅ彉鎴�''涓や釜鍗曞紩鍙� + MethodInfo method = typeof(System.Collections.IList).GetMethod("Contains"); + //鍒涘缓闆嗗悎甯搁噺骞惰缃负甯搁噺鐨勫�� + ConstantExpression constantCollection = Expression.Constant(list); + //鍒涘缓涓�涓〃绀鸿皟鐢ㄥ甫鍙傛暟鐨勬柟娉曠殑锛歯ew string[]{"1","a"}.Contains("a"); + MethodCallExpression methodCall = Expression.Call(constantCollection, method, memberProperty); + return Expression.Lambda<Func<T, bool>>(methodCall, parameter); + } + //闈瀞tring瀛楁锛屾寜涓婇潰鏂瑰紡澶勭悊鎶ュ紓甯窷ull TypeMapping in Sql Tree + BinaryExpression body = null; + foreach (var value in list) + { + ConstantExpression constantExpression = Expression.Constant(value); + UnaryExpression unaryExpression = Expression.Convert(memberProperty, constantExpression.Type); + + body = body == null + ? Expression.Equal(unaryExpression, constantExpression) + : Expression.OrElse(body, Expression.Equal(unaryExpression, constantExpression)); + } + return Expression.Lambda<Func<T, bool>>(body, parameter); + } + + // object value = propertyValue; + ConstantExpression constant = proType.ToString() == "System.String" + ? Expression.Constant(propertyValue) : Expression.Constant(propertyValue.ToString().ChangeType(proType)); + + // DateTime鍙�夋嫨浜嗘棩鏈熺殑鏃跺�欒嚜鍔ㄥ湪缁撴潫鏃ユ湡鍔犱竴澶╋紝淇DateTime绫诲瀷浣跨敤鏃ユ湡鍖洪棿鏌ヨ鏃犳硶鏌ヨ鍒扮粨鏉熸棩鏈熺殑闂 + if ((proType == typeof(DateTime) || proType == typeof(DateTime?)) && expressionType == LinqExpressionType.LessThanOrEqual && propertyValue.ToString().Length == 10) + { + constant = Expression.Constant(Convert.ToDateTime(propertyValue.ToString()).AddDays(1)); + } + + UnaryExpression member = Expression.Convert(memberProperty, constant.Type); + Expression<Func<T, bool>> expression; + switch (expressionType) + { + //p=>p.propertyName == propertyValue + case LinqExpressionType.Equal: + expression = Expression.Lambda<Func<T, bool>>(Expression.Equal(member, constant), parameter); + break; + //p=>p.propertyName != propertyValue + case LinqExpressionType.NotEqual: + expression = Expression.Lambda<Func<T, bool>>(Expression.NotEqual(member, constant), parameter); + break; + // p => p.propertyName > propertyValue + case LinqExpressionType.GreaterThan: + expression = Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(member, constant), parameter); + break; + // p => p.propertyName < propertyValue + case LinqExpressionType.LessThan: + expression = Expression.Lambda<Func<T, bool>>(Expression.LessThan(member, constant), parameter); + break; + // p => p.propertyName >= propertyValue + case LinqExpressionType.ThanOrEqual: + expression = Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter); + break; + // p => p.propertyName <= propertyValue + case LinqExpressionType.LessThanOrEqual: + expression = Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(member, constant), parameter); + break; + // p => p.propertyName.Contains(propertyValue) + // p => !p.propertyName.Contains(propertyValue) + case LinqExpressionType.Contains: + case LinqExpressionType.NotContains: + MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); + constant = Expression.Constant(propertyValue, typeof(string)); + if (expressionType == LinqExpressionType.Contains) + { + expression = Expression.Lambda<Func<T, bool>>(Expression.Call(member, method, constant), parameter); + } + else + { + expression = Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter); + } + break; + default: + // p => p.false + expression = False<T>(); + break; + } + return expression; + } + + /// <summary> + /// 鍒涘缓lambda琛ㄨ揪寮忥細p=>false + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + public static Expression<Func<T, bool>> False<T>() + { + + return p => false; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/ModelValidate.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/ModelValidate.cs" new file mode 100644 index 0000000..c3b174d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/ModelValidate.cs" @@ -0,0 +1,229 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.Attributes; +using WIDESEA_Core.Helper; + +namespace WIDESEA_Core.Utilities +{ + public class ModelValidate + { + /// <summary> + /// 楠岃瘉妯″瀷鏁版嵁鏄惁绗﹀悎瀹氫箟鐨勯獙璇佽鍒� + /// </summary> + /// <typeparam name="T">瑕侀獙璇佺殑妯″瀷绫诲瀷</typeparam> + /// <param name="data">瑕侀獙璇佺殑妯″瀷鏁版嵁</param> + /// <returns>鍖呭惈楠岃瘉缁撴灉銆侀敊璇俊鎭拰鍘熷鏁版嵁鐨勫厓缁�</returns> + /// <remarks> + /// 杩斿洖鍊艰鏄庯細 + /// Item1 - 楠岃瘉鏄惁閫氳繃 (true/false) + /// Item2 - 楠岃瘉澶辫触鏃剁殑閿欒淇℃伅 + /// Item3 - 鍘熷浼犲叆鐨勬暟鎹璞� + /// </remarks> + public static (bool, string, object?) ValidateModelData<T>(T data) where T : class, new() + { + Type modelType = typeof(T); + if (data == null) return (false, "浼犲叆鍙傛暟涓嶅彲涓簄ull", data); + ModelValidateAttribute? modelAttribute = modelType.GetCustomAttribute<ModelValidateAttribute>(); + if (modelAttribute == null) return (false, $"{modelType.Name}鏈畾涔夈�怣odelValidateAttribute銆戠壒鎬�", data); + PropertyInfo[] propertyInfos = modelType.GetProperties(); + return SimpleValidate(propertyInfos, data); + } + + /// <summary> + /// 楠岃瘉妯″瀷鏁版嵁闆嗗悎鐨勬湁鏁堟�� + /// </summary> + /// <typeparam name="T">妯″瀷绫诲瀷</typeparam> + /// <param name="datas">寰呴獙璇佺殑妯″瀷鏁版嵁闆嗗悎</param> + /// <returns> + /// 鍏冪粍鍖呭惈涓変釜鍊硷細 + /// Item1 - 楠岃瘉缁撴灉(true/false) + /// Item2 - 楠岃瘉澶辫触鏃剁殑閿欒淇℃伅 + /// Item3 - 楠岃瘉澶辫触鏃剁殑閿欒鏁版嵁瀵硅薄 + /// </returns> + /// <remarks> + /// 璇ユ柟娉曚細妫�鏌ラ泦鍚堟槸鍚︿负null/绌猴紝骞堕獙璇佹瘡涓暟鎹」鐨凪odelValidateAttribute鐗规�у拰灞炴�у�� + /// </remarks> + public static (bool, string, object?) ValidateModelData<T>(List<T> datas) where T : class, new() + { + Type modelType = typeof(T); + if (datas == null) return (false, "浼犲叆鍙傛暟涓嶅彲涓簄ull", datas); + if (datas.Count == 0) return (false, "闆嗗悎涓暟涓嶅彲绛変簬0", datas); + foreach (T data in datas) + { + if (data == null) return (false, "浼犲叆鍙傛暟涓嶅彲涓簄ull", data); + ModelValidateAttribute? modelAttribute = modelType.GetCustomAttribute<ModelValidateAttribute>(); + if (modelAttribute == null) return (false, $"{modelType.Name}鏈畾涔夈�怣odelValidateAttribute銆戠壒鎬�", data); + PropertyInfo[] propertyInfos = modelType.GetProperties(); + (bool, string, object?) result = SimpleValidate(propertyInfos, data); + if (!result.Item1) return result; + } + + return (true, $"鎴愬姛", datas); + } + + //private static (bool, string, object?) CustomMethodValidate<T>(ModelValidateAttribute modelAttribute, T data) where T : class, new() + //{ + // try + // { + // if (modelAttribute.CustomValidateMethodTypeName == null) return (false, $"鑷畾涔夐獙璇佹柟娉曢渶瑕佹彁渚涙柟娉曟墍鍦ㄧ被鐨勭被鍨嬪璞�", data); + // if (modelAttribute.CustomValidateMethodName == null) return (false, $"鑷畾涔夐獙璇佹柟娉曢渶瑕佹彁渚涙柟娉曞悕", data); + + // string path = Path.Combine(AppContext.BaseDirectory, $"{modelAttribute.CustomValidateAssemblyName}.dll"); + // Assembly assembly = Assembly.LoadFrom(path); + + // Type t = assembly.GetType(modelAttribute.CustomValidateAssemblyName + "." + modelAttribute.CustomValidateMethodTypeName); + // object bbb = App.GetService(t); + // MethodInfo? methodInfo = t.GetMethod(modelAttribute.CustomValidateMethodName); + // var result = methodInfo.Invoke(bbb, new object[] { data }); + // //MethodInfo? methodInfo = modelAttribute.CustomValidateMethodType.GetMethod(modelAttribute.CustomValidateMethodName); + // //if (methodInfo == null) return (false, $"鏈湪璇ョ被鍨嬪璞°�恵modelAttribute.CustomValidateMethodType.Name}銆戜腑鎵惧埌璇ユ柟娉曘�恵modelAttribute.CustomValidateMethodName}銆�", data); + // //methodInfo.GetGenericArguments() + // return (true, "鎴愬姛", data); + // } + // catch(Exception ex) + // { + // throw new Exception(); + // } + + //} + + /// <summary> + /// 鎵ц绠�鍗曠殑妯″瀷灞炴�ч獙璇� + /// </summary> + /// <typeparam name="T">瑕侀獙璇佺殑妯″瀷绫诲瀷</typeparam> + /// <param name="propertyInfos">妯″瀷鐨勫睘鎬т俊鎭泦鍚�</param> + /// <param name="data">瑕侀獙璇佺殑妯″瀷瀹炰緥</param> + /// <returns>楠岃瘉缁撴灉鍏冪粍锛�(鏄惁楠岃瘉閫氳繃, 楠岃瘉娑堟伅, 鍘熷鏁版嵁)</returns> + /// <remarks> + /// 璇ユ柟娉曚細鏍规嵁灞炴�т笂鐨凱ropertyValidateAttribute鐗规�ц繘琛屼互涓嬮獙璇侊細 + /// 1. 闈炵┖楠岃瘉(NotNullAndEmpty) + /// 2. 鏈�灏忓�奸獙璇�(MinValue) + /// 3. 鏈�澶у�奸獙璇�(MaxValue) + /// 4. 鍏宠仈灞炴�ч潪绌洪獙璇�(NotNullAndEmptyWithProperty) + /// 5. 鍏宠仈灞炴�х壒瀹氬�奸獙璇�(NotNullAndEmptyWithPropertyAndValue) + /// </remarks> + private static (bool, string, object?) SimpleValidate<T>(PropertyInfo[] propertyInfos, T data) where T : class, new() + { + try + { + foreach (PropertyInfo propertyInfo in propertyInfos) + { + PropertyValidateAttribute? propertyAttribute = propertyInfo.GetCustomAttribute<PropertyValidateAttribute>(); + if (propertyAttribute == null) continue; + + object? value = propertyInfo.GetValue(data, null); + if (propertyAttribute.NotNullAndEmpty) + { + if (value == null) return (false, $"{(string.IsNullOrEmpty(propertyAttribute.Description) ? propertyInfo.Name : propertyAttribute.Description)}涓嶅彲涓簄ull", data); + if (string.IsNullOrEmpty(value.ToString())) return (false, $"{(string.IsNullOrEmpty(propertyAttribute.Description) ? propertyInfo.Name : propertyAttribute.Description)}涓嶅彲涓虹┖瀛楃涓�", data); + } + + if (propertyAttribute.MinValue > int.MinValue) + { + if (value == null) return (false, $"{(string.IsNullOrEmpty(propertyAttribute.Description) ? propertyInfo.Name : propertyAttribute.Description)}涓嶅彲涓簄ull", data); + if (propertyAttribute.IsContainMinValue) + { + if (Convert.ToInt32(value.ToString()) < propertyAttribute.MinValue) return (false, $"{(string.IsNullOrEmpty(propertyAttribute.Description) ? propertyInfo.Name : propertyAttribute.Description)}鐨勫�笺�恵value}銆戜笉鍙皬浜庛�恵propertyAttribute.MinValue}銆�", data); + } + else + { + if (Convert.ToInt32(value.ToString()) <= propertyAttribute.MinValue) return (false, $"{(string.IsNullOrEmpty(propertyAttribute.Description) ? propertyInfo.Name : propertyAttribute.Description)}鐨勫�笺�恵value}銆戣澶т簬銆恵propertyAttribute.MinValue}銆�", data); + } + } + + if (propertyAttribute.MaxValue < int.MaxValue) + { + if (value == null) return (false, $"{(string.IsNullOrEmpty(propertyAttribute.Description) ? propertyInfo.Name : propertyAttribute.Description)}涓嶅彲涓簄ull", data); + if (propertyAttribute.IsContainMaxValue) + { + if (Convert.ToInt32(value.ToString()) >= propertyAttribute.MaxValue) return (false, $"{(string.IsNullOrEmpty(propertyAttribute.Description) ? propertyInfo.Name : propertyAttribute.Description)}鐨勫�笺�恵value}銆戜笉鍙ぇ浜庛�恵propertyAttribute.MaxValue}銆�", data); + } + else + { + if (Convert.ToInt32(value.ToString()) > propertyAttribute.MaxValue) return (false, $"{(string.IsNullOrEmpty(propertyAttribute.Description) ? propertyInfo.Name : propertyAttribute.Description)}鐨勫�笺�恵value}銆戣灏忎簬銆恵propertyAttribute.MaxValue}銆�", data); + } + } + + if (!string.IsNullOrEmpty(propertyAttribute.NotNullAndEmptyWithProperty)) + { + PropertyInfo? property = propertyInfos.FirstOrDefault(x => x.Name == propertyAttribute.NotNullAndEmptyWithProperty); + if (property != null) + { + object? tempValue = property.GetValue(data); + if (tempValue != null && !string.IsNullOrEmpty(tempValue.ToString())) + { + Type[] types = propertyInfo.PropertyType.GenericTypeArguments; + if (types.Length == 1) + { + string str = value.Serialize(); + if (str == "[]") + { + return (false, $"銆恵property.Name}銆戝睘鎬х殑鍊奸潪绌烘椂銆恵propertyInfo.Name}銆戝睘鎬х殑鍊间篃涓嶅彲涓虹┖", data); + } + } + else if (types.Length == 0) + { + if (value == null) + { + return (false, $"銆恵property.Name}銆戝睘鎬х殑鍊奸潪绌烘椂銆恵propertyInfo.Name}銆戝睘鎬х殑鍊间篃涓嶅彲涓虹┖", data); + } + } + + } + } + else + { + return (false, $"鏈壘鍒般�恵propertyInfo.Name}銆戠壒鎬у睘鎬с�恵propertyAttribute.NotNullAndEmptyWithProperty}銆�", data); + } + } + + if (propertyAttribute.NotNullAndEmptyWithPropertyAndValue != null && propertyAttribute.NotNullAndEmptyWithPropertyAndValue.Length == 2) + { + PropertyInfo? property = propertyInfos.FirstOrDefault(x => x.Name == propertyAttribute.NotNullAndEmptyWithPropertyAndValue[0]); + if (property != null) + { + object? tempValue = property.GetValue(data); + if (tempValue != null && !string.IsNullOrEmpty(tempValue.ToString())) + { + Type[] types = propertyInfo.PropertyType.GenericTypeArguments; + if (types.Length == 1) + { + if (tempValue.ChangeType(property.PropertyType).ToString() == propertyAttribute.NotNullAndEmptyWithPropertyAndValue[1].ChangeType(property.PropertyType).ToString()) + { + string str = value.Serialize(); + if (str == "[]") + { + return (false, $"銆恵property.Name}銆戝睘鎬х殑鍊间负銆恵propertyAttribute.NotNullAndEmptyWithPropertyAndValue[1]}銆戞椂銆恵propertyInfo.Name}銆戝睘鎬х殑鍊间笉鍙负绌�", data); + } + } + + } + else if (types.Length == 0) + { + if (tempValue.ChangeType(property.PropertyType).ToString() == propertyAttribute.NotNullAndEmptyWithPropertyAndValue[1].ChangeType(property.PropertyType).ToString() && value == null && string.IsNullOrEmpty(value.ToString())) + { + return (false, $"銆恵property.Name}銆戝睘鎬х殑鍊间负銆恵propertyAttribute.NotNullAndEmptyWithPropertyAndValue[1]}銆戞椂銆恵propertyInfo.Name}銆戝睘鎬х殑鍊间笉鍙负绌�", data); + } + } + + } + } + else + { + return (false, $"鏈壘鍒板睘鎬с�恵propertyAttribute.NotNullAndEmptyWithProperty}銆�", data); + } + } + } + } + catch (Exception ex) + { + return (false, $"鏁版嵁楠岃瘉寮傚父,寮傚父淇℃伅:{ex.Message}", data); + } + return (true, "楠岃瘉鎴愬姛", data); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/VierificationCode.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/VierificationCode.cs" new file mode 100644 index 0000000..b0cdec4 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/Utilities/VierificationCode.cs" @@ -0,0 +1,122 @@ +锘縰sing SkiaSharp; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Core.Utilities +{ + public static class VierificationCode + { + private static readonly string[] _chars = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; + + private static readonly SKColor[] colors = { SKColors.Black, SKColors.Green, SKColors.Brown }; + + private static readonly string[] fonts = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "瀹嬩綋" }; + public static string RandomText() + { + string code = "";//浜х敓鐨勯殢鏈烘暟 + int temp = -1; + Random rand = new Random(); + for (int i = 1; i < 5; i++) + { + if (temp != -1) + { + rand = new Random(i * temp * unchecked((int)DateTime.Now.Ticks)); + } + int t = rand.Next(61); + if (temp != -1 && temp == t) + { + return RandomText(); + } + temp = t; + code += _chars[t]; + } + return code; + } + public static string CreateBase64Imgage(string code) + { + var random = new Random(); + var info = new SKImageInfo((int)code.Length * 18, 32); + using var bitmap = new SKBitmap(info); + using var canvas = new SKCanvas(bitmap); + + canvas.Clear(SKColors.White); + + using var pen = new SKPaint(); + pen.FakeBoldText = true; + pen.Style = SKPaintStyle.Fill; + pen.TextSize = 20;// 0.6f * info.Width * pen.TextSize / pen.MeasureText(code); + + //缁樺埗闅忔満瀛楃 + for (int i = 0; i < code.Length; i++) + { + pen.Color = random.GetRandom(colors);//闅忔満棰滆壊绱㈠紩鍊� + + pen.Typeface = SKTypeface.FromFamilyName(random.GetRandom(fonts), 700, 20, SKFontStyleSlant.Italic);//閰嶇疆瀛椾綋 + var point = new SKPoint() + { + X = i * 16, + Y = 22// info.Height - ((i + 1) % 2 == 0 ? 2 : 4), + + }; + canvas.DrawText(code.Substring(i, 1), point, pen);//缁樺埗涓�涓獙璇佸瓧绗� + + } + + // 缁樺埗鍣偣 + var points = Enumerable.Range(0, 100).Select( + _ => new SKPoint(random.Next(bitmap.Width), random.Next(bitmap.Height)) + ).ToArray(); + canvas.DrawPoints( + SKPointMode.Points, + points, + pen); + + //缁樺埗璐濆灏旂嚎鏉� + for (int i = 0; i < 2; i++) + { + var p1 = new SKPoint(0, 0); + var p2 = new SKPoint(0, 0); + var p3 = new SKPoint(0, 0); + var p4 = new SKPoint(0, 0); + + var touchPoints = new SKPoint[] { p1, p2, p3, p4 }; + + using var bPen = new SKPaint(); + bPen.Color = random.GetRandom(colors); + bPen.Style = SKPaintStyle.Stroke; + + using var path = new SKPath(); + path.MoveTo(touchPoints[0]); + path.CubicTo(touchPoints[1], touchPoints[2], touchPoints[3]); + canvas.DrawPath(path, bPen); + } + return bitmap.ToBase64String(SKEncodedImageFormat.Png); + } + + public static T GetRandom<T>(this Random random, T[] tArray) + { + if (random == null) random = new Random(); + return tArray[random.Next(tArray.Length)]; + } + + /// <summary> + /// SKBitmap杞珺ase64String + /// </summary> + /// <param name="bitmap"></param> + /// <param name="format"></param> + /// <returns></returns> + public static string ToBase64String(this SKBitmap bitmap, SKEncodedImageFormat format) + { + using var memStream = new MemoryStream(); + using var wstream = new SKManagedWStream(memStream); + bitmap.Encode(wstream, format, 32); + memStream.TryGetBuffer(out ArraySegment<byte> buffer); + return $"{Convert.ToBase64String(buffer.Array, 0, (int)memStream.Length)}"; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/WIDESEA_Core.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/WIDESEA_Core.csproj" new file mode 100644 index 0000000..ccc52c8 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Core/WIDESEA_Core.csproj" @@ -0,0 +1,35 @@ +锘�<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Autofac" Version="8.3.0" /> + <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" /> + <PackageReference Include="Autofac.Extras.DynamicProxy" Version="7.1.0" /> + <PackageReference Include="AutoMapper" Version="15.0.1" /> + <PackageReference Include="Magicodes.IE.EPPlus" Version="2.7.6" /> + <PackageReference Include="Magicodes.IE.Excel" Version="2.7.6" /> + <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.18" /> + <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.5.4" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> + <PackageReference Include="OfficeOpenXml.Core.ExcelPackage" Version="1.0.0" /> + <PackageReference Include="SkiaSharp" Version="3.119.0" /> + <PackageReference Include="SqlSugarCore" Version="5.1.4.198" /> + <PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" /> + <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="9.0.0" /> + <PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="9.0.3" /> + <PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.7" /> + <PackageReference Include="System.Net.Http" Version="4.3.4" /> + <PackageReference Include="System.Security.Cryptography.Pkcs" Version="9.0.7" /> + <PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" /> + </ItemGroup> + + <ItemGroup> + <Folder Include="ServiceExtensions\" /> + </ItemGroup> + +</Project> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/ActivationCodeDTO.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/ActivationCodeDTO.cs" new file mode 100644 index 0000000..3302712 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/ActivationCodeDTO.cs" @@ -0,0 +1,17 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_DTO.BasicInfo +{ + public class ActivationCodeDTO + { + public string RuntimeCode { get; set; } = null!; + + public string DeviceId { get; set; } = null!; + + public string ProductName { get; set; } = null!; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/ActivationDTO.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/ActivationDTO.cs" new file mode 100644 index 0000000..8985919 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/ActivationDTO.cs" @@ -0,0 +1,19 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_DTO.BasicInfo +{ + public class ActivationDTO + { + public string RuntimeCode { get; set; } = null!; + + public string DeviceId { get; set; } = null!; + + public string ProductName { get; set; } = null!; + + public string ActivationCode { get; set; } = null!; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/DeviceInfoDTO.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/DeviceInfoDTO.cs" new file mode 100644 index 0000000..db218a7 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/BasicInfo/DeviceInfoDTO.cs" @@ -0,0 +1,17 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_DTO.BasicInfo +{ + public class DeviceInfoDTO + { + public string DeviceId { get; set; } = null!; + + public string DeviceInfoJson { get; set; } = null!; + + public string ProductName { get; set; } = null!; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/ActionDTO.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/ActionDTO.cs" new file mode 100644 index 0000000..57ed299 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/ActionDTO.cs" @@ -0,0 +1,16 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_DTO.System +{ + public class ActionDTO + { + public int ActionId { get; set; } + public int MenuId { get; set; } + public string Text { get; set; } + public string Value { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/MenuDTO.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/MenuDTO.cs" new file mode 100644 index 0000000..00ec87a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/MenuDTO.cs" @@ -0,0 +1,14 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Model.Models; + +namespace WIDESEA_DTO.System +{ + public class MenuDTO : Sys_Menu + { + public List<ActionDTO>? Actions { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/UserPermissions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/UserPermissions.cs" new file mode 100644 index 0000000..9c892bb --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/UserPermissions.cs" @@ -0,0 +1,17 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_DTO.System +{ + public class UserPermissionDTO + { + public int Id { get; set; } + public int Pid { get; set; } + public string Text { get; set; } + public bool IsApp { get; set; } + public List<ActionDTO> Actions { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/VueDictionaryDTO.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/VueDictionaryDTO.cs" new file mode 100644 index 0000000..c7598c7 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/System/VueDictionaryDTO.cs" @@ -0,0 +1,19 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_DTO.System +{ + public class VueDictionaryDTO + { + public string DicNo { get; set; } + + public string Config { get; set; } + + public object Data { get; set; } + + public bool SaveCache { get; set; } = true; + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/WIDESEA_DTO.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/WIDESEA_DTO.csproj" new file mode 100644 index 0000000..f9651fd --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_DTO/WIDESEA_DTO.csproj" @@ -0,0 +1,13 @@ +锘�<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\WIDESEA_Model\WIDESEA_Model.csproj" /> + </ItemGroup> + +</Project> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IActivationCodeService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IActivationCodeService.cs" new file mode 100644 index 0000000..87b9671 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IActivationCodeService.cs" @@ -0,0 +1,16 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseServices; +using WIDESEA_DTO.BasicInfo; +using WIDESEA_Model.Models; + +namespace WIDESEA_IBasicInfoServices +{ + public interface IActivationCodeService : IService<Dt_ActivationCode> + { + string GenerateActivationCode(ActivationCodeDTO activationDTO); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IProductsService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IProductsService.cs" new file mode 100644 index 0000000..6a97935 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IProductsService.cs" @@ -0,0 +1,19 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core; +using WIDESEA_Core.BaseServices; +using WIDESEA_DTO.BasicInfo; +using WIDESEA_Model.Models; + +namespace WIDESEA_IBasicInfoServices +{ + public interface IProductsService : IService<Dt_Products> + { + WebResponseContent ValidateActivation(ActivationDTO activationModel); + + WebResponseContent GetActivationInfo(string deviceId, string productName); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IRuntimeCodeService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IRuntimeCodeService.cs" new file mode 100644 index 0000000..a664d01 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IRuntimeCodeService.cs" @@ -0,0 +1,17 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core; +using WIDESEA_Core.BaseServices; +using WIDESEA_DTO.BasicInfo; +using WIDESEA_Model.Models; + +namespace WIDESEA_IBasicInfoServices +{ + public interface IRuntimeCodeService : IService<Dt_RuntimeCode> + { + WebResponseContent GenerateRuntimeCode(DeviceInfoDTO deviceInfo); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IVersionsService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IVersionsService.cs" new file mode 100644 index 0000000..a29b1ea --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/IVersionsService.cs" @@ -0,0 +1,14 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_IBasicInfoServices +{ + public interface IVersionsService : IService<Dt_Versions> + { + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/WIDESEA_IBasicInfoServices.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/WIDESEA_IBasicInfoServices.csproj" new file mode 100644 index 0000000..8376ea7 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_IBasicInfoServices/WIDESEA_IBasicInfoServices.csproj" @@ -0,0 +1,13 @@ +锘�<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\WIDESEA_DTO\WIDESEA_DTO.csproj" /> + </ItemGroup> + +</Project> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_DictionaryListService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_DictionaryListService.cs" new file mode 100644 index 0000000..1b87c73 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_DictionaryListService.cs" @@ -0,0 +1,14 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_ISystemServices +{ + public interface ISys_DictionaryListService : IService<Sys_DictionaryList> + { + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_DictionaryService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_DictionaryService.cs" new file mode 100644 index 0000000..00e63e9 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_DictionaryService.cs" @@ -0,0 +1,16 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseServices; +using WIDESEA_DTO.System; +using WIDESEA_Model.Models; + +namespace WIDESEA_ISystemServices +{ + public interface ISys_DictionaryService : IService<Sys_Dictionary> + { + List<VueDictionaryDTO> GetVueDictionary(string[] dicNos); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_LogService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_LogService.cs" new file mode 100644 index 0000000..b3e7b81 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_LogService.cs" @@ -0,0 +1,14 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_ISystemServices +{ + public interface ISys_LogService : IService<Sys_Log> + { + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_MenuService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_MenuService.cs" new file mode 100644 index 0000000..4370552 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_MenuService.cs" @@ -0,0 +1,32 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_DTO.System; +using WIDESEA_Core; +using WIDESEA_Core.BaseServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_ISystemServices +{ + public interface ISys_MenuService : IService<Sys_Menu> + { + object GetCurrentMenuActionList(); + object GetMenuActionList(int roleId); + + List<MenuDTO> GetUserMenuList(int roleId); + + List<Permissions> GetPermissions(int roleId); + + List<ActionDTO> GetActions(int menuId, List<ActionDTO> menuActions, List<Permissions> permissions, int roleId); + + object GetMenu(); + + object GetTreeItem(int menuId); + + WebResponseContent Save(Sys_Menu menu); + + WebResponseContent DelMenu(int menuId); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_RoleAuthService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_RoleAuthService.cs" new file mode 100644 index 0000000..f9994c9 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_RoleAuthService.cs" @@ -0,0 +1,14 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_ISystemServices +{ + public interface ISys_RoleAuthService : IService<Sys_RoleAuth> + { + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_RoleService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_RoleService.cs" new file mode 100644 index 0000000..e87d93d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_RoleService.cs" @@ -0,0 +1,23 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_DTO.System; +using WIDESEA_Core; +using WIDESEA_Core.BaseServices; +using WIDESEA_Model.Models; +using WIDESEA_Model.Models.System; + +namespace WIDESEA_ISystemServices +{ + public interface ISys_RoleService : IService<Sys_Role> + { + List<RoleNodes> GetAllChildren(int roleId); + WebResponseContent GetCurrentTreePermission(); + + WebResponseContent GetUserTreePermission(int role_Id); + + WebResponseContent SavePermission(List<UserPermissionDTO> userPermissions, int roleId); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_TenantService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_TenantService.cs" new file mode 100644 index 0000000..761c667 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_TenantService.cs" @@ -0,0 +1,16 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core; +using WIDESEA_Core.BaseServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_ISystemServices +{ + public interface ISys_TenantService : IService<Sys_Tenant> + { + WebResponseContent InitTenantInfo(string tenantName, int tenantType); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_UserService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_UserService.cs" new file mode 100644 index 0000000..754e3da --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/ISys_UserService.cs" @@ -0,0 +1,22 @@ +锘縰sing Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core; +using WIDESEA_Core.BaseServices; +using WIDESEA_Model; +using WIDESEA_Model.Models; + +namespace WIDESEA_ISystemServices +{ + public interface ISys_UserService : IService<Sys_User> + { + WebResponseContent Login(LoginInfo loginInfo); + + WebResponseContent GetCurrentUserInfo(); + + WebResponseContent ModifyPwd(string oldPwd, string newPwd); + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/WIDESEA_ISystemServices.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/WIDESEA_ISystemServices.csproj" new file mode 100644 index 0000000..240fcbd --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ISystemServices/WIDESEA_ISystemServices.csproj" @@ -0,0 +1,14 @@ +锘�<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\WIDESEA_Common\WIDESEA_Common.csproj" /> + <ProjectReference Include="..\WIDESEA_DTO\WIDESEA_DTO.csproj" /> + </ItemGroup> + +</Project> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/LoginInfo.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/LoginInfo.cs" new file mode 100644 index 0000000..678745b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/LoginInfo.cs" @@ -0,0 +1,15 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Model +{ + public class LoginInfo + { + public string UserName { get; set; } + + public string Password { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_ActivationCode.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_ActivationCode.cs" new file mode 100644 index 0000000..4e99715 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_ActivationCode.cs" @@ -0,0 +1,70 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; + +namespace WIDESEA_Model.Models +{ + /// <summary> + /// 婵�娲荤爜琛� + /// </summary> + [SugarTable(nameof(Dt_ActivationCode), TableDescription = "婵�娲荤爜琛�")] + public class Dt_ActivationCode + { + /// <summary> + /// 涓婚敭 + /// </summary> + [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "涓婚敭")] + public int Id { get; set; } + + /// <summary> + /// 婵�娲荤爜 + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "婵�娲荤爜")] + public string ActivationCode { get; set; } = null!; + + /// <summary> + /// 鏄犲皠鐨勯殢鏈虹爜 + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "鏄犲皠鐨勯殢鏈虹爜")] + public string MappedRandom { get; set; } = null!; + + /// <summary> + /// 婵�娲绘椂闂� + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "婵�娲绘椂闂�")] + public DateTime? ExpiresTime { get; set; } + + /// <summary> + /// 鏄惁宸蹭娇鐢� + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鏄惁宸蹭娇鐢�")] + public bool IsUsed { get; set; } + + /// <summary> + /// 浣跨敤鏃堕棿 + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "浣跨敤鏃堕棿")] + public DateTime? UsedTime { get; set; } + + /// <summary> + /// 杩愯鏃朵唬鐮� + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "杩愯鏃朵唬鐮�")] + public string RuntimeCode { get; set; } = null!; + + /// <summary> + /// 璁惧鍞竴鏍囪瘑 + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "璁惧鍞竴鏍囪瘑")] + public string DeviceId { get; set; } = null!; + + /// <summary> + /// 浜у搧涓婚敭 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "浜у搧涓婚敭")] + public int ProductId { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_CharMapping.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_CharMapping.cs" new file mode 100644 index 0000000..92f78c1 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_CharMapping.cs" @@ -0,0 +1,40 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; + +namespace WIDESEA_Model.Models +{ + /// <summary> + /// 瀛楃鏄犲皠琛� + /// </summary> + [SugarTable(nameof(Dt_CharMapping), TableDescription = "瀛楃鏄犲皠琛�")] + public class Dt_CharMapping + { + /// <summary> + /// 涓婚敭 + /// </summary> + [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "涓婚敭")] + public int Id { get; set; } + + /// <summary> + /// 杈撳叆瀛楃 + /// </summary> + [SugarColumn(IsNullable = false, Length = 1, ColumnDescription = "杈撳叆瀛楃")] + public string InputChar { get; set; } = null!; + + /// <summary> + /// 鏄犲皠瀛楃 + /// </summary> + [SugarColumn(IsNullable = false, Length = 1, ColumnDescription = "鏄犲皠瀛楃")] + public string OutputChar { get; set; } = null!; + + /// <summary> + /// 鏄犲皠鍋忕Щ閲� + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鏄犲皠鍋忕Щ閲�")] + public int ShiftFactor { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_Products.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_Products.cs" new file mode 100644 index 0000000..7bed861 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_Products.cs" @@ -0,0 +1,47 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; +using WIDESEA_Core.DB.Models; + +namespace WIDESEA_Model.Models +{ + /// <summary> + /// 浜у搧淇℃伅琛� + /// </summary> + [SugarTable(nameof(Dt_Products), TableDescription = "浜у搧淇℃伅琛�")] + public class Dt_Products : BaseEntity + { + /// <summary> + /// 涓婚敭 + /// </summary> + [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "涓婚敭")] + public int Id { get; set; } + + /// <summary> + /// 浜у搧鍚嶇О + /// </summary> + [SugarColumn(IsNullable = false, Length = 100, ColumnDescription = "浜у搧鍚嶇О")] + public string ProductName { get; set; } = null!; + + /// <summary> + /// 浜у搧鎻忚堪 + /// </summary> + [SugarColumn(IsNullable = true, Length = 2000, ColumnDescription = "浜у搧鎻忚堪")] + public string? ProductDescription { get; set; } + + /// <summary> + /// 鍒嗙被锛堟闈�/绉诲姩/涓棿浠剁瓑锛� + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "鍒嗙被锛堟闈�/绉诲姩/涓棿浠剁瓑锛�")] + public string ProductCategory { get; set; } = null!; + + /// <summary> + /// 鏄惁鍚敤 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鏄惁鍚敤")] + public bool IsEnable { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_RuntimeCode.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_RuntimeCode.cs" new file mode 100644 index 0000000..b3b5acb --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_RuntimeCode.cs" @@ -0,0 +1,59 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; +using WIDESEA_Core.DB.Models; + +namespace WIDESEA_Model.Models +{ + /// <summary> + /// 璁惧杩愯鐮佽〃 + /// </summary> + [SugarTable(nameof(Dt_RuntimeCode), TableDescription = "璁惧杩愯鐮佽〃")] + public class Dt_RuntimeCode : BaseEntity + { + /// <summary> + /// 涓婚敭 + /// </summary> + [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "涓婚敭")] + public int Id { get; set; } + + /// <summary> + /// 璁惧鍞竴鏍囪瘑 + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "璁惧鍞竴鏍囪瘑")] + public string DeviceId { get; set; } = null!; + + /// <summary> + /// 杩愯鏃朵唬鐮� + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "杩愯鏃朵唬鐮�")] + public string RuntimeCode { get; set; } = null!; + + /// <summary> + /// 闅忔満鐮� + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "闅忔満鐮�")] + public string BaseRandom { get; set; } = null!; + + /// <summary> + /// 璁惧淇℃伅 + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "璁惧淇℃伅")] + public string DeviceInfo { get; set; } = null!; + + /// <summary> + /// 鏍¢獙浣� + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "鏍¢獙浣�")] + public string CheckDigit { get; set; } = null!; + + /// <summary> + /// 浜у搧涓婚敭 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "浜у搧涓婚敭")] + public int ProductId { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_Versions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_Versions.cs" new file mode 100644 index 0000000..94490ab --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/BasicInfo/Dt_Versions.cs" @@ -0,0 +1,65 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; +using WIDESEA_Core.DB.Models; + +namespace WIDESEA_Model.Models +{ + /// <summary> + /// 鐗堟湰淇℃伅琛� + /// </summary> + [SugarTable(nameof(Dt_Versions), TableDescription = "鐗堟湰淇℃伅琛�")] + public class Dt_Versions : BaseEntity + { + /// <summary> + /// 涓婚敭 + /// </summary> + [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "涓婚敭")] + public int Id { get; set; } + + /// <summary> + /// 璇箟鍖栫増鏈彿锛堝2.1.0锛� + /// </summary> + [SugarColumn(IsNullable = false, Length = 20, ColumnDescription = "璇箟鍖栫増鏈彿锛堝2.1.0锛�")] + public string VersionNumber { get; set; } = null!; + + /// <summary> + /// 鍙戝竷鏃ユ湡 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鍙戝竷鏃ユ湡")] + public DateTime ReleaseDate { get; set; } + + /// <summary> + /// 鏇存柊鏃ュ織 + /// </summary> + [SugarColumn(IsNullable = true, Length = 2000, ColumnDescription = "鏇存柊鏃ュ織")] + public string? ReleaseNotes { get; set; } + + /// <summary> + /// 鏂囦欢瀛樺偍璺緞/URL + /// </summary> + [SugarColumn(IsNullable = false, Length = 200, ColumnDescription = "鏂囦欢瀛樺偍璺緞/URL")] + public string? DownloadUrl { get; set; } = null!; + + /// <summary> + /// 鐘舵�侊紙宸插彂甯�/鏈彂甯冿級 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鐘舵�侊紙宸插彂甯�/鏈彂甯冿級")] + public string Status { get; set; } = null!; + + /// <summary> + /// 鐗堟湰绫诲瀷锛堟寮忕増/娴嬭瘯鐗�/鍐呮祴鐗堢瓑锛� + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "鐗堟湰绫诲瀷锛堟寮忕増/娴嬭瘯鐗�/鍐呮祴鐗堢瓑锛�")] + public string VersionType { get; set; } = null!; + + /// <summary> + /// 鍏宠仈鐨勪骇鍝両D + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鍏宠仈鐨勪骇鍝両D")] + public int ProductId { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/RoleAuthor.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/RoleAuthor.cs" new file mode 100644 index 0000000..4cd4407 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/RoleAuthor.cs" @@ -0,0 +1,14 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Model +{ + public class RoleAuthor + { + public int menuId { get; set; } + public string actions { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/RoleNodes.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/RoleNodes.cs" new file mode 100644 index 0000000..25b6b51 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/RoleNodes.cs" @@ -0,0 +1,15 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Model.Models.System +{ + public class RoleNodes + { + public int Id { get; set; } + public int ParentId { get; set; } + public string RoleName { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Actions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Actions.cs" new file mode 100644 index 0000000..2b56a08 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Actions.cs" @@ -0,0 +1,16 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Model.Models +{ + public class Sys_Actions + { + public int ActionId { get; set; } + public int MenuId { get; set; } + public string Text { get; set; } + public string Value { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Department.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Department.cs" new file mode 100644 index 0000000..1ac637a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Department.cs" @@ -0,0 +1,57 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Model.Models +{ + [SugarTable("Sys_Department", "缁勭粐鏋舵瀯"), MultiTenant] + public class Sys_Department : BaseEntity + { + /// <summary> + /// 缁勭粐ID + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true, ColumnDescription = "缁勭粐ID")] + public int DepartmentId { get; set; } + + /// <summary> + /// 缁勭粐鍚嶇О + /// </summary> + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "缁勭粐鍚嶇О")] + public string DepartmentName { get; set; } + + /// <summary> + /// 缁勭粐缂栧彿 + /// </summary> + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "缁勭粐缂栧彿")] + public string DepartmentCode { get; set; } + + /// <summary> + /// 涓婄骇缁勭粐 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "涓婄骇缁勭粐")] + public int ParentId { get; set; } + + /// <summary> + /// 閮ㄩ棬绫诲瀷 + /// </summary> + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "閮ㄩ棬绫诲瀷")] + public string DepartmentType { get; set; } + + /// <summary> + /// 鏄惁鍙敤 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鏄惁鍙敤")] + public int Enable { get; set; } + + /// <summary> + /// 澶囨敞 + /// </summary> + [SugarColumn(IsNullable = true, Length = 2000, ColumnDescription = "澶囨敞")] + public string Remark { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Dictionary.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Dictionary.cs" new file mode 100644 index 0000000..ea9724b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Dictionary.cs" @@ -0,0 +1,95 @@ +锘縰sing Magicodes.ExporterAndImporter.Core; +using SqlSugar; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Filter; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Model.Models +{ + [MultiTenant] + [Exporter(ExporterHeaderFilter = typeof(ExporterHeaderFilter))] + [SugarTable("Sys_Dictionary", "瀛楀吀鏁版嵁")] + public class Sys_Dictionary : BaseEntity + { + /// <summary> + /// 瀛楀吀ID + /// </summary> + [ExporterHeader(DisplayName = "瀛楀吀ID")] + [SugarColumn(IsIdentity = true, IsPrimaryKey = true, ColumnDescription = "瀛楀吀ID")] + public int DicId { get; set; } + + /// <summary> + /// 閰嶇疆椤� + /// </summary> + [ExporterHeader(DisplayName = "閰嶇疆椤�")] + [SugarColumn(IsNullable = true, Length = 200, ColumnDescription = "閰嶇疆椤�")] + public string Config { get; set; } + + /// <summary> + /// 鏁版嵁搴撴湇鍔� + /// </summary> + [ExporterHeader(DisplayName = "鏁版嵁搴撴湇鍔�")] + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "鏁版嵁搴撴湇鍔�")] + public string DBServer { get; set; } + + /// <summary> + /// Sql璇彞 + /// </summary> + [ExporterHeader(DisplayName = "Sql璇彞")] + [SugarColumn(IsNullable = true, Length = 500, ColumnDescription = "Sql璇彞")] + public string DBSql { get; set; } + + /// <summary> + /// 瀛楀吀鍚嶇О + /// </summary> + [ExporterHeader(DisplayName = "瀛楀吀鍚嶇О")] + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "瀛楀吀鍚嶇О")] + public string DicName { get; set; } + + /// <summary> + /// 瀛楀吀缂栧彿 + /// </summary> + [ExporterHeader(DisplayName = "瀛楀吀缂栧彿")] + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "瀛楀吀缂栧彿")] + public string DicNo { get; set; } + + /// <summary> + /// 鏄惁鍚敤 + /// </summary> + [ExporterHeader(DisplayName = "鏄惁鍚敤")] + [SugarColumn(IsNullable = true, ColumnDescription = "鏄惁鍚敤")] + public byte? Enable { get; set; } + + /// <summary> + /// 鎺掑簭鍙� + /// </summary> + [ExporterHeader(DisplayName = "鎺掑簭鍙�")] + [SugarColumn(IsNullable = true, ColumnDescription = "鎺掑簭鍙�")] + public int? OrderNo { get; set; } + + /// <summary> + /// 鐖剁骇ID + /// </summary> + [ExporterHeader(DisplayName = "鐖剁骇ID")] + [SugarColumn(IsNullable = true, ColumnDescription = "鐖剁骇ID")] + public int ParentId { get; set; } + + /// <summary> + /// 澶囨敞 + /// </summary> + [ExporterHeader(DisplayName = "澶囨敞")] + [SugarColumn(IsNullable = true, Length = 2000, ColumnDescription = "澶囨敞")] + public string Remark { get; set; } + + /// <summary> + /// 绯荤粺绫诲瀷 + /// </summary> + [ExporterHeader(DisplayName = "绯荤粺绫诲瀷")] + [SugarColumn(IsNullable = false, ColumnDescription = "绯荤粺绫诲瀷")] + public int SystemType { get; set; } + + [ExporterHeader(IsIgnore = true)] + [Navigate(NavigateType.OneToMany, nameof(DicId),nameof(DicId)), SugarColumn(IsIgnore = true, IsNullable = true)] + public List<Sys_DictionaryList> DicList { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_DictionaryList.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_DictionaryList.cs" new file mode 100644 index 0000000..e29f6fc --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_DictionaryList.cs" @@ -0,0 +1,57 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.DB.Models; +using SqlSugar; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Model.Models +{ + [SugarTable("Sys_DictionaryList", "瀛楀吀鏄庣粏"), MultiTenant] + public class Sys_DictionaryList : BaseEntity + { + /// <summary> + /// 瀛楀吀鍒楄〃ID + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true, ColumnDescription = "瀛楀吀鍒楄〃ID")] + public int DicListId { get; set; } + + /// <summary> + /// 鏁版嵁婧怲ext + /// </summary> + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "鏁版嵁婧怲ext")] + public string DicName { get; set; } + + /// <summary> + /// 鏁版嵁婧怴alue + /// </summary> + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "鏁版嵁婧怴alue")] + public string DicValue { get; set; } + + /// <summary> + /// 鏁版嵁婧怚D + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鏁版嵁婧怚D")] + public int DicId { get; set; } + + /// <summary> + /// 鏄惁鍙敤 + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "鏄惁鍙敤")] + public byte? Enable { get; set; } + + /// <summary> + /// 鎺掑簭鍙� + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "鎺掑簭鍙�")] + public int? OrderNo { get; set; } + + /// <summary> + /// 澶囨敞 + /// </summary> + [SugarColumn(IsNullable = true, Length = 2000, ColumnDescription = "澶囨敞")] + public string Remark { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Log.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Log.cs" new file mode 100644 index 0000000..1254b5a --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Log.cs" @@ -0,0 +1,80 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SqlSugar; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Model.Models +{ + [SugarTable, MultiTenant] + public class Sys_Log + { + /// <summary> + /// 涓婚敭 + /// </summary> + [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "涓婚敭")] + public int Id { get; set; } + + /// <summary> + /// 寮�濮嬫椂闂� + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "寮�濮嬫椂闂�")] + public DateTime? BeginDate { get; set; } + + /// <summary> + /// 鏃堕暱 + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "鏃堕暱")] + public int? ElapsedTime { get; set; } + + /// <summary> + /// 缁撴潫鏃堕棿 + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "缁撴潫鏃堕棿")] + public DateTime EndDate { get; set; } + + /// <summary> + /// 鏃ュ織绫诲瀷 + /// </summary> + //[SugarColumn(IsNullable = true, ColumnDescription = "鏃ュ織绫诲瀷")] + //public DateTime LogType { get; set; } + + /// <summary> + /// 璇锋眰鍙傛暟 + /// </summary> + [SugarColumn(IsNullable = true, Length = int.MaxValue, ColumnDescription = "璇锋眰鍙傛暟")] + public string RequestParam { get; set; } + + /// <summary> + /// 鍝嶅簲鍙傛暟 + /// </summary> + [SugarColumn(IsNullable = true, Length = int.MaxValue, ColumnDescription = "鍝嶅簲鍙傛暟")] + public string ResponseParam { get; set; } + + /// <summary> + /// 璇锋眰鍦板潃 + /// </summary> + [SugarColumn(IsNullable = true, Length = 2000, ColumnDescription = "璇锋眰鍦板潃")] + public string Url { get; set; } + + /// <summary> + /// 鐢ㄦ埛IP + /// </summary> + [SugarColumn(IsNullable = true, Length = 20, ColumnDescription = "鐢ㄦ埛IP")] + public string UserIP { get; set; } + + /// <summary> + /// 鐢ㄦ埛鍚嶇О + /// </summary> + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "鐢ㄦ埛鍚嶇О")] + public string? UserName { get; set; } + + /// <summary> + /// 鐢ㄦ埛涓婚敭 + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "鐢ㄦ埛涓婚敭")] + public int? UserId { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Menu.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Menu.cs" new file mode 100644 index 0000000..9a268ba --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Menu.cs" @@ -0,0 +1,81 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Model.Models +{ + [SugarTable("Sys_Menu", "鑿滃崟閰嶇疆"), MultiTenant] + public class Sys_Menu : BaseEntity + { + /// <summary> + /// 鑿滃崟ID + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true, ColumnDescription = "鑿滃崟ID")] + public int MenuId { get; set; } + + /// <summary> + /// 鑿滃崟鍚嶇О + /// </summary> + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "鑿滃崟鍚嶇О")] + public string MenuName { get; set; } + + /// <summary> + /// 鏉冮檺 + /// </summary> + [SugarColumn(IsNullable = true, Length = 2000, ColumnDescription = "鏉冮檺")] + public string Auth { get; set; } + + /// <summary> + /// 鍥炬爣 + /// </summary> + [SugarColumn(IsNullable = true, Length = 200, ColumnDescription = "鍥炬爣")] + public string Icon { get; set; } + + /// <summary> + /// 鎻忚堪 + /// </summary> + [SugarColumn(IsNullable = true, Length = 2000, ColumnDescription = "鎻忚堪")] + public string Description { get; set; } + + /// <summary> + /// 鏄惁鍚敤 + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "鏄惁鍚敤")] + public byte? Enable { get; set; } + + /// <summary> + /// 琛ㄥ悕 + /// </summary> + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "琛ㄥ悕")] + public string TableName { get; set; } + + /// <summary> + /// 鐖剁骇ID + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鐖剁骇ID")] + public int ParentId { get; set; } + + /// <summary> + /// 璺緞 + /// </summary> + [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "璺緞")] + public string Url { get; set; } + + /// <summary> + /// 鎺掑簭鍙� + /// </summary> + [SugarColumn(IsNullable = true,ColumnDescription ="鎺掑簭鍙�")] + public int? OrderNo { get; set; } + + /// <summary> + /// 鑿滃崟绫诲瀷 + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "鑿滃崟绫诲瀷")] + public int? MenuType { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Role.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Role.cs" new file mode 100644 index 0000000..b64dcb1 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Role.cs" @@ -0,0 +1,54 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Model.Models +{ + [SugarTable("Sys_Role", "瑙掕壊琛�"), MultiTenant] + public class Sys_Role : BaseEntity + { + /// <summary> + /// 涓婚敭 + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true, ColumnDescription = "涓婚敭")] + public int RoleId { get; set; } + + /// <summary> + /// 閮ㄩ棬鍚嶇О + /// </summary> + [SugarColumn(IsNullable = true, IsIgnore = true, Length = 50, ColumnDescription = "閮ㄩ棬鍚嶇О")] + public string DeptName { get; set; } + + /// <summary> + /// 閮ㄩ棬涓婚敭 + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "閮ㄩ棬涓婚敭")] + public int? DeptId { get; set; } + + /// <summary> + /// 鏄惁鍚敤 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鏄惁鍚敤")] + public byte Enable { get; set; } + + /// <summary> + /// 鐖禝D + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鐖禝D")] + public int ParentId { get; set; } + + /// <summary> + /// 瑙掕壊鍚嶇О + /// </summary> + [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "瑙掕壊鍚嶇О")] + public string RoleName { get; set; } + + //[Navigate(NavigateType.OneToMany, nameof(ParentId), nameof(RoleId)), SugarColumn(IsIgnore = true, IsNullable = true)] + //public List<Sys_Role> Roles { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_RoleAuth.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_RoleAuth.cs" new file mode 100644 index 0000000..1d9c5ff --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_RoleAuth.cs" @@ -0,0 +1,48 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SqlSugar; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Model.Models +{ + /// <summary> + /// 瑙掕壊韬唤楠岃瘉绠$悊琛� + /// </summary> + [SugarTable("Sys_RoleAuth", "瑙掕壊韬唤楠岃瘉绠$悊"), MultiTenant] + public class Sys_RoleAuth : BaseEntity + { + /// <summary> + /// 瑙掕壊韬唤楠岃瘉ID + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true, ColumnDescription = "瑙掕壊韬唤楠岃瘉ID")] + public int AuthId { get; set; } + + /// <summary> + /// 鐢ㄦ埛鏉冮檺 + /// </summary> + [SugarColumn(IsNullable = true, Length = 500, ColumnDescription = "鐢ㄦ埛鏉冮檺")] + public string AuthValue { get; set; } + + /// <summary> + /// 鑿滃崟ID + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鑿滃崟ID")] + public int MenuId { get; set; } + + /// <summary> + /// 瑙掕壊ID + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "瑙掕壊ID")] + public int? RoleId { get; set; } + + /// <summary> + /// 鐢ㄦ埛ID + /// </summary> + [SugarColumn(IsNullable = true, ColumnDescription = "鐢ㄦ埛ID")] + public int? UserId { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Tenant.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Tenant.cs" new file mode 100644 index 0000000..33836b0 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_Tenant.cs" @@ -0,0 +1,57 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Model.Models +{ + [SugarTable("Sys_Tenant", "绉熸埛")] + public class Sys_Tenant : BaseEntity + { + /// <summary> + /// 绉熸埛ID + /// </summary> + [SugarColumn(IsIdentity = true, IsPrimaryKey = true, ColumnDescription = "绉熸埛ID")] + public int TenantId { get; set; } + + /// <summary> + /// 绉熸埛鍚嶇О + /// </summary> + [SugarColumn(Length = 200, IsNullable = false, ColumnDescription = "绉熸埛鍚嶇О")] + public string TenantName { get; set; } + + /// <summary> + /// 绉熸埛绫诲瀷 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "绉熸埛绫诲瀷")] + public int TenantType { get; set; } + + /// <summary> + /// 鏁版嵁搴撶被鍨� + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鏁版嵁搴撶被鍨�")] + public int DbType { get; set; } + + /// <summary> + /// 杩炴帴瀛楃涓� + /// </summary> + [SugarColumn(Length = 1000, IsNullable = false, ColumnDescription = "杩炴帴瀛楃涓�")] + public string ConnectionString { get; set; } + + /// <summary> + /// 鐘舵�� + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鐘舵��")] + public int Status { get; set; } + + /// <summary> + /// 澶囨敞 + /// </summary> + [SugarColumn(Length = 2000, IsNullable = true, ColumnDescription = "澶囨敞")] + public string Remark { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_User.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_User.cs" new file mode 100644 index 0000000..d17ee0b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/Sys_User.cs" @@ -0,0 +1,84 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.DB.Models; +using WIDESEA_Core.Tenants; + +namespace WIDESEA_Model.Models +{ + /// <summary> + /// 鐢ㄦ埛淇℃伅琛� + /// </summary> + [SugarTable("Sys_User", "鐢ㄦ埛琛�")] //('鏁版嵁搴撹〃鍚�'锛�'鏁版嵁搴撹〃澶囨敞') + public class Sys_User : BaseEntity + { + /// <summary> + /// 鐢ㄦ埛ID + /// </summary> + [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "鐢ㄦ埛ID")] + public int User_Id { get; set; } + + /// <summary> + ///甯愬彿 + /// </summary> + [SugarColumn(Length = 100, IsNullable = false, ColumnDescription = "甯愬彿")] + public string UserName { get; set; } = null!; // 闈炵┖瀛楃涓诧紝涓嶈兘涓虹┖ + + /// <summary> + /// 瑙掕壊ID + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "瑙掕壊ID")] + public int Role_Id { get; set; } + + /// <summary> + /// 瑙掕壊鍚嶇О + /// </summary> + [SugarColumn(Length = 100, IsNullable = true, ColumnDescription = "瑙掕壊鍚嶇О")] + public string RoleName { get; set; } = null!; // 闈炵┖瀛楃涓诧紝涓嶈兘涓虹┖ + + /// <summary> + /// 澶囨敞 + /// </summary> + [SugarColumn(Length = 200, IsNullable = true, ColumnDescription = "澶囨敞")] + public string? Remark { get; set; } + + /// <summary> + /// 瀵嗙爜 + /// </summary> + [SugarColumn(Length = 200, IsNullable = false, ColumnDescription = "瀵嗙爜")] + public string UserPwd { get; set; } = null!; // 闈炵┖瀛楃涓诧紝涓嶈兘涓虹┖ + + /// <summary> + /// 鐪熷疄濮撳悕 + /// </summary> + [SugarColumn(Length = 100, IsNullable = false, ColumnDescription = "鐪熷疄濮撳悕")] + public string UserTrueName { get; set; } = null!; // 闈炵┖瀛楃涓诧紝涓嶈兘涓虹┖ + + /// <summary> + /// 鏄惁鍙敤 + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "鏄惁鍙敤")] + public byte Enable { get; set; } + + /// <summary> + /// 澶村儚 + /// </summary> + [SugarColumn(Length = 500, IsNullable = true, ColumnDescription = "澶村儚")] + public string? HeadImageUrl { get; set; } + + /// <summary> + /// 鏈�鍚庡瘑鐮佷慨鏀规椂闂� + /// </summary> + [SugarColumn(IsNullable = true, IsOnlyIgnoreInsert = true, ColumnDescription = "鏈�鍚庡瘑鐮佷慨鏀规椂闂�")] + public DateTime? LastModifyPwdDate { get; set; } + + /// <summary> + /// 绉熸埛ID + /// </summary> + [SugarColumn(IsNullable = false, ColumnDescription = "绉熸埛ID",DefaultValue = "0")] + public long TenantId { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/UserPermissions.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/UserPermissions.cs" new file mode 100644 index 0000000..7f2ed24 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/Models/System/UserPermissions.cs" @@ -0,0 +1,17 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_Model.Models.System +{ + public class UserPermissions + { + public int Id { get; set; } + public int Pid { get; set; } + public string Text { get; set; } + public bool IsApp { get; set; } + public List<Sys_Actions> Actions { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/WIDESEA_Model.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/WIDESEA_Model.csproj" new file mode 100644 index 0000000..4741606 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_Model/WIDESEA_Model.csproj" @@ -0,0 +1,13 @@ +锘�<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\WIDESEA_Core\WIDESEA_Core.csproj" /> + </ItemGroup> + +</Project> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.sln" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.sln" new file mode 100644 index 0000000..ba02313 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.sln" @@ -0,0 +1,87 @@ +锘� +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36202.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_ProductMgmtServer", "WIDESEA_ProductMgmtServer\WIDESEA_ProductMgmtServer.csproj", "{35C3B7BB-5C1A-4E47-822B-9C641379CF63}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_Core", "WIDESEA_Core\WIDESEA_Core.csproj", "{B6079216-9BD5-4608-87EC-228C27822B97}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_DTO", "WIDESEA_DTO\WIDESEA_DTO.csproj", "{DBB18687-01D6-4A9F-9501-6DE02D5E821F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_Model", "WIDESEA_Model\WIDESEA_Model.csproj", "{1F993B17-6603-46F6-87EA-3065264C208D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_Common", "WIDESEA_Common\WIDESEA_Common.csproj", "{06657FA3-D8EA-4D67-80D2-9D827BFED067}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_ISystemServices", "WIDESEA_ISystemServices\WIDESEA_ISystemServices.csproj", "{0C0C8DCC-F688-4EE2-888D-95C68E05844F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_SystemServices", "WIDESEA_SystemServices\WIDESEA_SystemServices.csproj", "{F42FD5E8-FAF6-4A1B-B59E-52BC70DF58DA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "System", "System", "{730690AF-5A08-4647-97A1-8C116E4D5FBB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BasicInfo", "BasicInfo", "{84EC6AC7-4271-418D-AAB8-CEF7CA1C7930}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_IBasicInfoServices", "WIDESEA_IBasicInfoServices\WIDESEA_IBasicInfoServices.csproj", "{3F755E47-AFB4-413D-9FC3-D0DB9C148E18}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_BasicInfoServices", "WIDESEA_BasicInfoServices\WIDESEA_BasicInfoServices.csproj", "{D0828E29-93D1-4556-9209-AFCDA4C4F3EF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {35C3B7BB-5C1A-4E47-822B-9C641379CF63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35C3B7BB-5C1A-4E47-822B-9C641379CF63}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35C3B7BB-5C1A-4E47-822B-9C641379CF63}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35C3B7BB-5C1A-4E47-822B-9C641379CF63}.Release|Any CPU.Build.0 = Release|Any CPU + {B6079216-9BD5-4608-87EC-228C27822B97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6079216-9BD5-4608-87EC-228C27822B97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6079216-9BD5-4608-87EC-228C27822B97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6079216-9BD5-4608-87EC-228C27822B97}.Release|Any CPU.Build.0 = Release|Any CPU + {DBB18687-01D6-4A9F-9501-6DE02D5E821F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DBB18687-01D6-4A9F-9501-6DE02D5E821F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DBB18687-01D6-4A9F-9501-6DE02D5E821F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DBB18687-01D6-4A9F-9501-6DE02D5E821F}.Release|Any CPU.Build.0 = Release|Any CPU + {1F993B17-6603-46F6-87EA-3065264C208D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F993B17-6603-46F6-87EA-3065264C208D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F993B17-6603-46F6-87EA-3065264C208D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F993B17-6603-46F6-87EA-3065264C208D}.Release|Any CPU.Build.0 = Release|Any CPU + {06657FA3-D8EA-4D67-80D2-9D827BFED067}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {06657FA3-D8EA-4D67-80D2-9D827BFED067}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06657FA3-D8EA-4D67-80D2-9D827BFED067}.Release|Any CPU.ActiveCfg = Release|Any CPU + {06657FA3-D8EA-4D67-80D2-9D827BFED067}.Release|Any CPU.Build.0 = Release|Any CPU + {0C0C8DCC-F688-4EE2-888D-95C68E05844F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C0C8DCC-F688-4EE2-888D-95C68E05844F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C0C8DCC-F688-4EE2-888D-95C68E05844F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C0C8DCC-F688-4EE2-888D-95C68E05844F}.Release|Any CPU.Build.0 = Release|Any CPU + {F42FD5E8-FAF6-4A1B-B59E-52BC70DF58DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F42FD5E8-FAF6-4A1B-B59E-52BC70DF58DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F42FD5E8-FAF6-4A1B-B59E-52BC70DF58DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F42FD5E8-FAF6-4A1B-B59E-52BC70DF58DA}.Release|Any CPU.Build.0 = Release|Any CPU + {3F755E47-AFB4-413D-9FC3-D0DB9C148E18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F755E47-AFB4-413D-9FC3-D0DB9C148E18}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F755E47-AFB4-413D-9FC3-D0DB9C148E18}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F755E47-AFB4-413D-9FC3-D0DB9C148E18}.Release|Any CPU.Build.0 = Release|Any CPU + {D0828E29-93D1-4556-9209-AFCDA4C4F3EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D0828E29-93D1-4556-9209-AFCDA4C4F3EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D0828E29-93D1-4556-9209-AFCDA4C4F3EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D0828E29-93D1-4556-9209-AFCDA4C4F3EF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {0C0C8DCC-F688-4EE2-888D-95C68E05844F} = {730690AF-5A08-4647-97A1-8C116E4D5FBB} + {F42FD5E8-FAF6-4A1B-B59E-52BC70DF58DA} = {730690AF-5A08-4647-97A1-8C116E4D5FBB} + {730690AF-5A08-4647-97A1-8C116E4D5FBB} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {84EC6AC7-4271-418D-AAB8-CEF7CA1C7930} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {3F755E47-AFB4-413D-9FC3-D0DB9C148E18} = {84EC6AC7-4271-418D-AAB8-CEF7CA1C7930} + {D0828E29-93D1-4556-9209-AFCDA4C4F3EF} = {84EC6AC7-4271-418D-AAB8-CEF7CA1C7930} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EFC7C874-F540-4F5E-B340-B0AF84765FBB} + EndGlobalSection +EndGlobal diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/ActivationCodeController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/ActivationCodeController.cs" new file mode 100644 index 0000000..60800ea --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/ActivationCodeController.cs" @@ -0,0 +1,32 @@ +锘縰sing Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WIDESEA_BasicInfoServices; +using WIDESEA_Core.BaseController; +using WIDESEA_DTO.BasicInfo; +using WIDESEA_IBasicInfoServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_ProductMgmtServer.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class ActivationCodeController : ApiBaseController<IActivationCodeService, Dt_ActivationCode> + { + public ActivationCodeController(IActivationCodeService service) : base(service) + { + } + + /// <summary> + /// 鐢熸垚婵�娲荤爜 + /// </summary> + /// <param name="activationDTO">鍖呭惈鐢熸垚婵�娲荤爜鎵�闇�淇℃伅鐨凞TO瀵硅薄</param> + /// <returns>鐢熸垚鐨勬縺娲荤爜瀛楃涓�</returns> + [HttpPost("GenerateActivationCode"), AllowAnonymous] + public string GenerateActivationCode([FromBody] ActivationCodeDTO activationDTO) + { + return Service.GenerateActivationCode(activationDTO); + } + + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/ProductsController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/ProductsController.cs" new file mode 100644 index 0000000..4a0df02 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/ProductsController.cs" @@ -0,0 +1,43 @@ +锘縰sing Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WIDESEA_Core; +using WIDESEA_Core.BaseController; +using WIDESEA_DTO.BasicInfo; +using WIDESEA_IBasicInfoServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_ProductMgmtServer.Controllers.BasicInfo +{ + [Route("api/[controller]")] + [ApiController] + public class ProductsController : ApiBaseController<IProductsService, Dt_Products> + { + public ProductsController(IProductsService service) : base(service) + { + } + + /// <summary> + /// 楠岃瘉婵�娲昏姹傜殑API鎺ュ彛 + /// </summary> + /// <param name="activationModel">鍖呭惈婵�娲讳俊鎭殑DTO瀵硅薄</param> + /// <returns>鍖呭惈楠岃瘉缁撴灉鐨刉ebResponseContent瀵硅薄</returns> + [HttpPost("ValidateActivation"), AllowAnonymous] + public WebResponseContent ValidateActivation([FromBody] ActivationDTO activationModel) + { + return Service.ValidateActivation(activationModel); + } + + /// <summary> + /// 鑾峰彇鎸囧畾浜у搧鍚嶇О鍜岃澶嘔D鐨勬縺娲讳俊鎭�� + /// </summary> + /// <param name="productName">浜у搧鍚嶇О銆�</param> + /// <param name="deviceId">璁惧ID銆�</param> + /// <returns>鍖呭惈婵�娲讳俊鎭殑WebResponseContent瀵硅薄銆�</returns> + [HttpGet("GetActivationInfo/{productName}/{deviceId}"), AllowAnonymous] + public WebResponseContent GetActivationInfo(string deviceId, string productName) + { + return Service.GetActivationInfo(deviceId, productName); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/RuntimeCodeController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/RuntimeCodeController.cs" new file mode 100644 index 0000000..23fc68d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/BasicInfo/RuntimeCodeController.cs" @@ -0,0 +1,31 @@ +锘縰sing Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WIDESEA_Core; +using WIDESEA_Core.BaseController; +using WIDESEA_DTO.BasicInfo; +using WIDESEA_IBasicInfoServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_ProductMgmtServer.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class RuntimeCodeController : ApiBaseController<IRuntimeCodeService, Dt_RuntimeCode> + { + public RuntimeCodeController(IRuntimeCodeService service) : base(service) + { + } + + /// <summary> + /// 澶勭悊HTTP POST璇锋眰浠ョ敓鎴愯繍琛屾椂浠g爜銆� + /// </summary> + /// <param name="deviceInfo">鍖呭惈璁惧淇℃伅鐨凞TO瀵硅薄锛岄�氳繃璇锋眰涓讳綋浼犻�掋��</param> + /// <returns>鍖呭惈鐢熸垚杩愯鏃朵唬鐮佺粨鏋滅殑WebResponseContent瀵硅薄銆�</returns> + [HttpPost("GenerateRuntimeCode"), AllowAnonymous] + public WebResponseContent GenerateRuntimeCode([FromBody] DeviceInfoDTO deviceInfo) + { + return Service.GenerateRuntimeCode(deviceInfo); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_DictionaryController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_DictionaryController.cs" new file mode 100644 index 0000000..aa071b0 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_DictionaryController.cs" @@ -0,0 +1,119 @@ +锘縰sing Autofac.Core; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyModel; +using Newtonsoft.Json; +using System.Reflection; +using WIDESEA_Core.BaseController; +using WIDESEA_Core.Helper; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; +using System.IO; +using WIDESEA_DTO.System; +using System.ComponentModel; +using System.Collections.Generic; +using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime; +using WIDESEA_Core.Caches; +using WIDESEA_Core.Enums; + +namespace WIDESEA_WCSServer.Controllers.System +{ + [Route("api/Sys_Dictionary")] + [ApiController] + public class Sys_DictionaryController : ApiBaseController<ISys_DictionaryService, Sys_Dictionary> + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ICacheService _cacheService; + + public Sys_DictionaryController(ISys_DictionaryService service, IHttpContextAccessor httpContextAccessor, ICacheService cacheService) : base(service) + { + _httpContextAccessor = httpContextAccessor; + _cacheService = cacheService; + } + + [HttpPost, Route("GetVueDictionary"), AllowAnonymous] + public IActionResult GetVueDictionary([FromBody] string[] dicNos) + { + List<VueDictionaryDTO> vueDictionaryDTOs = Service.GetVueDictionary(dicNos); + try + { + List<string> cacheDicNos = new List<string>(); + foreach (string n in dicNos) + { + if (vueDictionaryDTOs.Where(x => x.DicNo == n).Count() > 0) + { + continue; + } + string str = _cacheService.Get(n); + if (!string.IsNullOrEmpty(str)) + { + VueDictionaryDTO? vueDictionary = JsonConvert.DeserializeObject<VueDictionaryDTO>(str); + + if (vueDictionary != null) + { + vueDictionaryDTOs.Add(vueDictionary); + cacheDicNos.Add(n); + } + } + } + List<string> dicList = dicNos.ToList(); + if (dicNos.Where(x => !cacheDicNos.Contains(x)).Count() > 0) + { + string str = AppSettings.Configuration["dics"]; + if (!string.IsNullOrEmpty(str)) + { + List<string> cusDics = new List<string>(); + + List<string> dics = str.Split(",").ToList(); + + foreach (var item in dics) + { + dicList.Remove(item); + cusDics.Add(item); + } + + foreach (var item in cusDics) + { + if (vueDictionaryDTOs.Where(x => x.DicNo == item).Count() > 0) + { + continue; + } + VueDictionaryDTO vueDictionaryDTO = GetVueDictionary(item.Trim()); + if (vueDictionaryDTO != null) + { + vueDictionaryDTOs.Add(vueDictionaryDTO); + if (!_cacheService.Exists(item) && vueDictionaryDTO.SaveCache) + { + _cacheService.Add(item, vueDictionaryDTO.Serialize()); + } + } + } + } + } + } + catch + { + + } + return Json(vueDictionaryDTOs); + } + + private VueDictionaryDTO? GetVueDictionary(string key) + { + VueDictionaryDTO? result = null; + try + { + switch (key) + { + + } + return result; + } + catch (Exception ex) + { + return null; + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_DictionaryListController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_DictionaryListController.cs" new file mode 100644 index 0000000..e1aebe9 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_DictionaryListController.cs" @@ -0,0 +1,17 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WIDESEA_Core.BaseController; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_Server.Controllers.System +{ + [Route("api/Sys_DictionaryList")] + [ApiController] + public class Sys_DictionaryListController : ApiBaseController<ISys_DictionaryListService, Sys_DictionaryList> + { + public Sys_DictionaryListController(ISys_DictionaryListService service) : base(service) + { + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_LogController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_LogController.cs" new file mode 100644 index 0000000..c4a5971 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_LogController.cs" @@ -0,0 +1,17 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WIDESEA_Core.BaseController; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_Server.Controllers.System +{ + [Route("api/[controller]")] + [ApiController] + public class Sys_LogController : ApiBaseController<ISys_LogService, Sys_Log> + { + public Sys_LogController(ISys_LogService service) : base(service) + { + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_MenuController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_MenuController.cs" new file mode 100644 index 0000000..9530bfd --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_MenuController.cs" @@ -0,0 +1,55 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WIDESEA_Core; +using WIDESEA_Core.BaseController; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_WCSServer.Controllers +{ + [Route("api/Sys_Menu")] + [ApiController] + public class Sys_MenuController : ApiBaseController<ISys_MenuService, Sys_Menu> + { + private readonly IHttpContextAccessor _httpContextAccessor; + public Sys_MenuController(ISys_MenuService menuService, IHttpContextAccessor httpContextAccessor) : base(menuService) + { + _httpContextAccessor = httpContextAccessor; + } + [HttpGet, HttpPost, Route("getTreeMenu")] + public IActionResult GetTreeMenu() + { + return Json(Service.GetCurrentMenuActionList()); + } + + [HttpPost, Route("getMenu")] + public IActionResult GetMenu() + { + return Json(Service.GetMenu()); + } + + [HttpPost, Route("getTreeItem")] + public IActionResult GetTreeItem(int menuId) + { + return Json(Service.GetTreeItem(menuId)); + } + + [HttpPost, Route("save")] + public ActionResult Save([FromBody] Sys_Menu menu) + { + if (App.User.UserId == 1) + { + return Json(Service.Save(menu)); + } + else + { + return Json(WebResponseContent.Instance.Error("浠呴檺瓒呯骇绠$悊鍛樹慨鏀规暟鎹�")); + } + } + [HttpPost, Route("delMenu")] + public WebResponseContent DelMenu(int menuId) + { + return Service.DelMenu(menuId); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_RoleAuthController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_RoleAuthController.cs" new file mode 100644 index 0000000..296ac92 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_RoleAuthController.cs" @@ -0,0 +1,17 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WIDESEA_Core.BaseController; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_Server.Controllers.System +{ + [Route("api/Sys_RoleAuth")] + [ApiController] + public class Sys_RoleAuthController : ApiBaseController<ISys_RoleAuthService, Sys_RoleAuth> + { + public Sys_RoleAuthController(ISys_RoleAuthService service) : base(service) + { + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_RoleController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_RoleController.cs" new file mode 100644 index 0000000..fe46367 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_RoleController.cs" @@ -0,0 +1,64 @@ +锘縰sing Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using WIDESEA_DTO.System; +using WIDESEA_Core; +using WIDESEA_Core.BaseController; +using WIDESEA_Core.BaseRepository; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; +using WIDESEA_Model.Models.System; + +namespace WIDESEA_WCSServer.Controllers.System +{ + [Route("api/Sys_Role")] + [ApiController] + public class Sys_RoleController : ApiBaseController<ISys_RoleService, Sys_Role> + { + private readonly IHttpContextAccessor _httpContextAccessor; + public Sys_RoleController(ISys_RoleService service, IHttpContextAccessor httpContextAccessor) : base(service) + { + _httpContextAccessor = httpContextAccessor; + } + + [HttpPost, Route("getUserChildRoles")] + public IActionResult GetUserChildRoles() + { + int roleId = App.User.RoleId; + var data = Service.GetAllChildren(roleId); + + if (App.User.IsSuperAdmin) + { + return Json(WebResponseContent.Instance.OK(null, data)); + } + //涓嶆槸瓒呯骇绠$悊锛屽皢鑷繁鐨勮鑹叉煡鍑烘潵锛屽湪鏍戝舰鑿滃崟涓婁綔涓烘牴鑺傜偣 + var self = data.Where(x => x.Id == roleId) + .Select(s => new RoleNodes() + { + Id = s.Id, + ParentId = 0,//灏嗚嚜宸辩殑瑙掕壊浣滀负root鑺傜偣 + RoleName = s.RoleName + }).ToList(); + data.AddRange(self); + return Json(WebResponseContent.Instance.OK(null, data)); + } + + [HttpPost, Route("getCurrentTreePermission")] + public IActionResult GetCurrentTreePermission() + { + return Json(Service.GetCurrentTreePermission()); + } + + [HttpPost, Route("getUserTreePermission")] + public IActionResult GetUserTreePermission(int roleId) + { + return Json(Service.GetUserTreePermission(roleId)); + } + + [HttpPost, Route("savePermission")] + public IActionResult SavePermission([FromBody] List<UserPermissionDTO> userPermissions, int roleId) + { + return Json(Service.SavePermission(userPermissions, roleId)); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_TenantController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_TenantController.cs" new file mode 100644 index 0000000..24922b5 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_TenantController.cs" @@ -0,0 +1,33 @@ +锘� +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WIDESEA_Core; +using WIDESEA_Core.BaseController; +using WIDESEA_Core.Const; +using WIDESEA_Core.Helper; +using WIDESEA_Core.HttpContextUser; +using WIDESEA_ISystemServices; +using WIDESEA_Model; +using WIDESEA_Model.Models; + +namespace WIDESEA_WCSServer.Controllers +{ + [Route("api/tenant")] + [ApiController] + public class Sys_TenantController : ApiBaseController<ISys_TenantService, Sys_Tenant> + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public Sys_TenantController(ISys_TenantService tenantService, IHttpContextAccessor httpContextAccessor) : base(tenantService) + { + _httpContextAccessor = httpContextAccessor; + } + + [HttpGet, Route("initTenantInfo"), AllowAnonymous] + public WebResponseContent InitTenantInfo(string tenantName, int tenantType) + { + return Service.InitTenantInfo(tenantName, tenantType); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_UserController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_UserController.cs" new file mode 100644 index 0000000..f9dd563 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Controllers/System/Sys_UserController.cs" @@ -0,0 +1,174 @@ +锘� +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json; +using StackExchange.Profiling; +using WIDESEA_Core; +using WIDESEA_Core.Authorization; +using WIDESEA_Core.BaseController; +using WIDESEA_Core.Caches; +using WIDESEA_Core.CodeGenerator; +using WIDESEA_Core.Const; +using WIDESEA_Core.Extensions; +using WIDESEA_Core.Helper; +using WIDESEA_Core.HttpContextUser; +using WIDESEA_Core.Utilities; +using WIDESEA_ISystemServices; +using WIDESEA_Model; +using WIDESEA_Model.Models; + +namespace WIDESEA_WCSServer.Controllers +{ + [Route("api/User")] + [ApiController] + public class Sys_UserController : ApiBaseController<ISys_UserService, Sys_User> + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ICacheService _cacheService; + + public Sys_UserController(ISys_UserService userService, IHttpContextAccessor httpContextAccessor, ICacheService cacheService) : base(userService) + { + _httpContextAccessor = httpContextAccessor; + _cacheService = cacheService; + } + + [HttpPost, Route("swgLogin"), AllowAnonymous] + public dynamic SwgLogin([FromBody] SwaggerLoginRequest loginRequest) + { + if (loginRequest is null) + { + return new { result = false }; + } + + try + { + LoginInfo loginInfo = new LoginInfo + { + Password = loginRequest.pwd, + UserName = loginRequest.name + }; + + if (loginInfo.Password == "<PASSWORD>" && loginInfo.UserName == "admin") + { + HttpContext.SuccessSwagger(); + + string token = JwtHelper.IssueJwt(new TokenModelJwt + { + RoleId = 1, + TenantId = 1, + UserId = 1, + UserName = "admin" + }); + + _cacheService.AddOrUpdate(1.ToString(), token); + + HttpContext.SuccessSwaggerJwt(token); + + string str = HttpContext.GetSuccessSwaggerJwt(); + return new { result = true }; + } + + var result = Service.Login(loginInfo); + if (result.Status) + { + HttpContext.SuccessSwagger(); + Dictionary<string, object>? dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Data.Serialize()); + if (dict != null) + { + HttpContext.SuccessSwaggerJwt((dict.ContainsKey("token") ? dict["token"].ToString() : "") ?? ""); + } + string str = HttpContext.GetSuccessSwaggerJwt(); + return new { result = true }; + } + } + catch (Exception ex) + { + + } + + return new { result = false }; + } + + [HttpPost, Route("login"), AllowAnonymous] + public IActionResult Login([FromBody] LoginInfo loginInfo) + { + return Json(Service.Login(loginInfo)); + } + [HttpPost, Route("getCurrentUserInfo")] + public WebResponseContent GetCurrentUser() + { + return Service.GetCurrentUserInfo(); + } + + [HttpPost, Route("modifyPwd")] + public IActionResult ModifyPwd(string oldPwd, string newPwd) + { + return Json(Service.ModifyPwd(oldPwd, newPwd)); + } + + [HttpGet, Route("getVierificationCode"), AllowAnonymous] + public IActionResult GetVierificationCode() + { + //var html = MiniProfiler.Current.RenderIncludes(_httpContextAccessor.HttpContext); + string code = "1234" /*VierificationCode.RandomText()*/; + var data = new + { + img = VierificationCode.CreateBase64Imgage(code), + uuid = Guid.NewGuid() + }; + + return Json(data); + } + [HttpGet, Route("SerializeJwt"), AllowAnonymous] + public WebResponseContent SerializeJwt(string code) + { + return WebResponseContent.Instance.OK(data: JwtHelper.SerializeJwt(code)); + } + [HttpPost, Route("replaceToken")] + public WebResponseContent ReplaceToken() + { + WebResponseContent responseContent = new WebResponseContent(); + try + { + string token = App.User.GetToken(); + if (string.IsNullOrEmpty(token)) + { + return responseContent = WebResponseContent.Instance.Error("token鏃犳晥锛岃閲嶆柊鐧诲綍锛�"); + } + TokenModelJwt tokenModelJwt = new TokenModelJwt() + { + RoleId = App.User.RoleId, + TenantId = App.User.TenantId, + UserId = App.User.UserId, + UserName = App.User.UserName + }; + string newToken = JwtHelper.IssueJwt(tokenModelJwt); + return responseContent = WebResponseContent.Instance.OK(data: newToken); + } + catch (Exception ex) + { + return responseContent.Error(ex.Message); + } + + } + + [HttpPost, Route("CreateIRepository"), AllowAnonymous] + public WebResponseContent CreateIRepository(string tableName, string nameSpace) + { + CodeGenertors.CreateIRepository(tableName, nameSpace); + CodeGenertors.CreateRepository(tableName, nameSpace); + CodeGenertors.CreateIService(tableName, nameSpace); + CodeGenertors.CreateService(tableName, nameSpace); + CodeGenertors.CreateController(tableName, nameSpace); + return WebResponseContent.Instance.OK(); + } + } + + public class SwaggerLoginRequest + { + public string name { get; set; } + public string pwd { get; set; } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/AutoMapperSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/AutoMapperSetup.cs" new file mode 100644 index 0000000..da78c06 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/AutoMapperSetup.cs" @@ -0,0 +1,20 @@ +锘� + +namespace WIDESEA_ProductMgmtServer.Filter +{ + /// <summary> + /// Automapper 鍚姩鏈嶅姟 + /// </summary> + public static class AutoMapperSetup + { + public static void AddAutoMapperSetup(this IServiceCollection services) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + services.AddAutoMapper(cfg => + { + cfg.AddProfile(new CustomProfile()); + }); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/AutofacPropertityModuleReg.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/AutofacPropertityModuleReg.cs" new file mode 100644 index 0000000..4005b48 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/AutofacPropertityModuleReg.cs" @@ -0,0 +1,17 @@ +锘縰sing Autofac; +using Microsoft.AspNetCore.Mvc; + +namespace WIDESEA_ProductMgmtServer.Filter +{ + public class AutofacPropertityModuleReg : Autofac.Module + { + protected override void Load(ContainerBuilder builder) + { + var controllerBaseType = typeof(ControllerBase); + builder.RegisterAssemblyTypes(typeof(Program).Assembly) + .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType) + .PropertiesAutowired(); + + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/CustomAuthorizeFilter.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/CustomAuthorizeFilter.cs" new file mode 100644 index 0000000..ee9c0de --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/CustomAuthorizeFilter.cs" @@ -0,0 +1,20 @@ +锘縰sing Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc; + +namespace WIDESEA_ProductMgmtServer.Filter +{ + public class CustomAuthorizeFilter : IAuthorizationFilter + { + public void OnAuthorization(AuthorizationFilterContext context) + { + + // 浣犵殑鑷畾涔夋巿鏉冮�昏緫 + // 渚嬪锛屸�屾鏌ョ敤鎴锋槸鍚﹀凡鐧诲綍锛屸�屾垨鑰呬粬浠槸鍚︽湁鐗瑰畾鐨勮鑹叉垨鏉冮檺 + //if (!context.HttpContext.User.Identity.IsAuthenticated) + //{ + // // 鐢ㄦ埛鏈櫥褰曪紝鈥岄噸瀹氬悜鍒扮櫥褰曢〉闈㈡垨杩斿洖401鐘舵�佺爜 + // context.Result = new ChallengeResult(); + //} + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/CustomProfile.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/CustomProfile.cs" new file mode 100644 index 0000000..e67fc37 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/CustomProfile.cs" @@ -0,0 +1,20 @@ +锘縰sing AutoMapper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WIDESEA_ProductMgmtServer.Filter +{ + public class CustomProfile : Profile + { + /// <summary> + /// 閰嶇疆鏋勯�犲嚱鏁帮紝鐢ㄦ潵鍒涘缓鍏崇郴鏄犲皠 + /// </summary> + public CustomProfile() + { + //CreateMap<Sys_Menu, MenuDTO>(); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/WebSocketSetup.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/WebSocketSetup.cs" new file mode 100644 index 0000000..296793b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Filter/WebSocketSetup.cs" @@ -0,0 +1,29 @@ +锘�//using HslCommunication.WebSocket; +//using WIDESEA_Core.Helper; + +//namespace WIDESEA_ProductMgmtServer.HostedService +//{ +// public static class WebSocketSetup +// { +// public static void AddWebSocketSetup(this IServiceCollection services) +// { +// if (services == null) throw new ArgumentNullException(nameof(services)); + +// if(AppSettings.Get("WebSocketEnable").ObjToBool()) +// { +// int port = AppSettings.Get("WebSocketPort").ObjToInt(); +// if (port == 0) +// { +// port = 9296; +// } + +// services.AddSingleton(x => +// { +// WebSocketServer socketServer = new WebSocketServer(); +// socketServer.ServerStart(port); +// return socketServer; +// }); +// } +// } +// } +//} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Program.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Program.cs" new file mode 100644 index 0000000..d899288 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Program.cs" @@ -0,0 +1,144 @@ +using System.Reflection; +using System.Text; +using Autofac; +using Autofac.Core; +using Autofac.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.FileProviders; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; +using WIDESEA_Core; +using WIDESEA_Core.Authorization; +using WIDESEA_Core.BaseServices; +using WIDESEA_Core.Core; +using WIDESEA_Core.Extensions; +using WIDESEA_Core.Filter; +using WIDESEA_Core.Helper; +using WIDESEA_Core.Middlewares; +using WIDESEA_ProductMgmtServer.Filter; + +var builder = WebApplication.CreateBuilder(args); + + +builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()).ConfigureContainer<ContainerBuilder>(builder => +{ + builder.RegisterModule(new AutofacModuleRegister());//带有接口层的服务注入 + builder.RegisterModule<AutofacPropertityModuleReg>();// +}).ConfigureAppConfiguration((hostingContext, config) => +{ + hostingContext.Configuration.ConfigureApplication(); + config.Sources.Clear(); + config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); +}); +builder.ConfigureApplication(); + +// 2、配置服务 +builder.Services.AddSingleton(new AppSettings(builder.Configuration));//注册 +builder.Services.AddAllOptionRegister();//读取配置文件 +builder.Services.AddMemoryCacheSetup();//缓存 +builder.Services.AddSqlsugarSetup();//SqlSugar 启动服务 +builder.Services.AddHostedService<SeedDataHostedService>();//初始化数据库 + +builder.Services.AddDbSetup();//Db 启动服务 +//builder.Services.AddWebSocketSetup(); + +builder.Services.AddAutoMapperSetup(); + +builder.Services.AddCorsSetup(); + +builder.Services.AddMiniProfilerSetup(); + +builder.Services.AddSwaggerSetup(); + +builder.Services.AddHttpContextSetup(); + +builder.Services.AddAuthorizationSetup(); + +builder.Services.AddIpPolicyRateLimitSetup(builder.Configuration);//IPLimit限流 启动服务 + +builder.Services.AddScoped<UseServiceDIAttribute>(); + +builder.Services.AddSession(); + +builder.Services.AddHttpClient(); + +builder.Services.AddControllers(o => +{ + o.Filters.Add(typeof(GlobalExceptionsFilter));//全局异常 +}) +.AddNewtonsoftJson(options => +{ + options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; + //options.SerializerSettings.ContractResolver = new DefaultContractResolver(); + options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(); + options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; + options.SerializerSettings.NullValueHandling = NullValueHandling.Include; + options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local; + options.SerializerSettings.Converters.Add(new StringEnumConverter()); +}); + + +builder.Services.AddMvc(options => +{ + options.Filters.Add(typeof(ApiAuthorizeFilter)); + options.Filters.Add(typeof(ActionExecuteFilter)); + options.Filters.Add(typeof(CustomAuthorizeFilter)); +}); + + +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); + +builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>()); +Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + + +var app = builder.Build(); + +// 3、配置中间件 +app.UseMiniProfiler();//性能分析器 +app.ConfigureApplication();//配置文件 +app.UseApplicationSetup();//启动配置 + +app.UseAllServicesMiddle(builder.Services); + +app.UseSession(); + +//if(app.Environment.IsProduction()) +{ + app.UseSwaggerAuthorized(); +} + +app.UseSwaggerMiddle(() => Assembly.GetExecutingAssembly().GetManifestResourceStream("WIDESEA_ProductMgmtServer.index.html") ?? throw new Exception("WIDESEA_ProductMgmtServer.index.html文件")); + +app.UseIpLimitMiddle(); +app.UseApiLogMiddleware(); + +app.UseCors(AppSettings.Get(new string[] { "Cors", "PolicyName" })); + +DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions(); +defaultFilesOptions.DefaultFileNames.Clear(); +defaultFilesOptions.DefaultFileNames.Add("index.html"); +app.UseDefaultFiles(defaultFilesOptions); +app.UseMiddleware<HttpRequestMiddleware>(); +app.UseStaticFiles(); + +app.UseStaticFiles(new StaticFileOptions +{ + FileProvider = new PhysicalFileProvider(App.WebHostEnvironment.WebRootPath) +}); +app.UseCookiePolicy(); +app.UseStatusCodePages(); + +app.UseRouting(); + +app.UseAuthentication(); +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Properties/launchSettings.json" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Properties/launchSettings.json" new file mode 100644 index 0000000..7cd3d74 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/Properties/launchSettings.json" @@ -0,0 +1,31 @@ +锘縶 + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:64469", + "sslPort": 0 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5206", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.csproj" new file mode 100644 index 0000000..2f3df73 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.csproj" @@ -0,0 +1,29 @@ +锘�<Project Sdk="Microsoft.NET.Sdk.Web"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <Nullable>enable</Nullable> + <ImplicitUsings>enable</ImplicitUsings> + </PropertyGroup> + + <ItemGroup> + <None Remove="index.html" /> + </ItemGroup> + + <ItemGroup> + <EmbeddedResource Include="index.html"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </EmbeddedResource> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\WIDESEA_BasicInfoServices\WIDESEA_BasicInfoServices.csproj" /> + <ProjectReference Include="..\WIDESEA_Core\WIDESEA_Core.csproj" /> + <ProjectReference Include="..\WIDESEA_SystemServices\WIDESEA_SystemServices.csproj" /> + </ItemGroup> + +</Project> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.http" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.http" new file mode 100644 index 0000000..5ef62b9 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer.http" @@ -0,0 +1,15 @@ +@WIDESEA_ProductMgmtServer_HostAddress = http://localhost:5206 + + +GET {{WIDESEA_ProductMgmtServer_HostAddress}}/api/User/getVierificationCode + +### + +POST {{WIDESEA_ProductMgmtServer_HostAddress}}/api/User/login +Content-Type: application/json + +{ + //LoginInfo +} + +### diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/appsettings.Development.json" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/appsettings.Development.json" new file mode 100644 index 0000000..0c208ae --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/appsettings.Development.json" @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/appsettings.json" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/appsettings.json" new file mode 100644 index 0000000..3909838 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/appsettings.json" @@ -0,0 +1,37 @@ +{ + "urls": "http://*:9291", //web鏈嶅姟绔彛锛屽鏋滅敤IIS閮ㄧ讲锛屾妸杩欎釜鍘绘帀 + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "dics": "", + "AllowedHosts": "*", + "ConnectionStringsEncryption": false, + "MainDB": "DB_WIDESEA", //褰撳墠椤圭洰鐨勪富搴擄紝鎵�瀵瑰簲鐨勮繛鎺ュ瓧绗︿覆鐨凟nabled蹇呴』涓簍rue + //1.MySql + //2.SqlServer + //3.Sqlite + //4.Oracle + //5.PostgreSQL + "DBType": "SqlServer", + //杩炴帴瀛楃涓� + "ConnectionString": "Data Source=.;Initial Catalog=WIDESEA_PM;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", + + //璺ㄥ煙 + "Cors": { + "PolicyName": "CorsIpAccess", //绛栫暐鍚嶇О + "EnableAllIPs": true, //褰撲负true鏃讹紝寮�鏀炬墍鏈塈P鍧囧彲璁块棶銆� + // 鏀寔澶氫釜鍩熷悕绔彛锛屾敞鎰忕鍙e彿鍚庝笉瑕佸甫/鏂滄潌锛氭瘮濡俵ocalhost:8000/锛屾槸閿欑殑 + // 娉ㄦ剰锛宧ttp://127.0.0.1:1818 鍜� http://localhost:1818 鏄笉涓�鏍风殑 + "IPs": "http://127.0.0.1:8080,http://localhost:8080" + }, + "ApiLogIgnore": "", //蹇界暐鐨凙PI鍚嶇О锛屽涓敤閫楀彿鍒嗛殧 + "ApiName": "WIDESEA", + "ExpMinutes": 120, + "DBSeedEnable": true, + "LogDeubgEnable": true, //鏄惁璁板綍璋冭瘯鏃ュ織 + "PrintSql": true, //鎵撳嵃SQL璇彞 + "LogAOPEnable": true //鏄惁璁板綍AOP鏃ュ織 +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/index.html" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/index.html" new file mode 100644 index 0000000..557d027 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/index.html" @@ -0,0 +1,188 @@ +锘�<!--1銆佺増鏈彿瑕佷笌nuget鍖呬竴鑷达紱2銆乮d涓嶈兘涓虹┖--> +<script async="async" id="mini-profiler" src="/profiler/includes.min.js?v=4.3.8+1120572909" data-version="4.3.8+1120572909" data-path="/profiler/" data-current-id="0d7e468e-0bb5-4c81-90fc-91fd1543640a" data-ids="0d7e468e-0bb5-4c81-90fc-91fd1543640a" data-position="Left" data-scheme="Light" data-authorized="true" data-children="true" data-max-traces="15" data-toggle-shortcut="Alt+P" data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync"></script> + +<!-- HTML for static distribution bundle build --> +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <!--鏋侀�熸ā寮�--> + <meta name="renderer" content="webkit" /> + <meta name="force-rendering" content="webkit" /> + <title>%(DocumentTitle)</title> + <link href="./swagger-ui.css" rel="stylesheet"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="./swagger-ui.css"> + <link rel="icon" type="image/png" href="./logo/favicon-32x32.png" sizes="32x32" /> + <script src="js/jquery-3.3.1.min.js"></script> + <style> + .swagger-ui .opblock-summary-control:focus { + outline: none + } + + .swagger-ui .topbar .download-url-wrapper { + display: flex; + flex: 3; + margin-bottom: 0px; + justify-content: flex-end; + } + + .swagger-ui .auth-container input[type=password], .swagger-ui .auth-container input[type=text] { + min-width: 565px; + } + + html { + box-sizing: border-box; + overflow-y: scroll; + } + + *, + *:before, + *:after { + box-sizing: inherit; + } + + body { + margin: 0; + background: #fafafa; + } + + .qqgroup { + position: absolute; + right: 0px; + top: 0px; + } + + .info { + float: left; + position: relative; + width: 100%; + } + + .download-contents { + display: none; + } + /* 婊氬姩妲� */ + ::-webkit-scrollbar { + width: 9px; + height: 9px; + } + + ::-webkit-scrollbar-track { + border-radius: 3px; + background: rgba(0,0,0,0.06); + -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.08); + } + /* 婊氬姩鏉℃粦鍧� */ + ::-webkit-scrollbar-thumb { + border-radius: 3px; + background: rgba(0,0,0,0.12); + -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.2); + } + </style> + %(HeadContent) +</head> +<body style=" user-select: text;"> + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0"> + <defs> + <symbol viewBox="0 0 20 20" id="unlocked"> + <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path> + </symbol> + <symbol viewBox="0 0 20 20" id="locked"> + <path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z" /> + </symbol> + <symbol viewBox="0 0 20 20" id="close"> + <path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z" /> + </symbol> + <symbol viewBox="0 0 20 20" id="large-arrow"> + <path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z" /> + </symbol> + <symbol viewBox="0 0 20 20" id="large-arrow-down"> + <path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z" /> + </symbol> + + <symbol viewBox="0 0 24 24" id="jump-to"> + <path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z" /> + </symbol> + <symbol viewBox="0 0 24 24" id="expand"> + <path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" /> + </symbol> + </defs> + </svg> + <div id="swagger-ui"></div> + <div id="footer" style="text-align: center;margin-bottom: 10px;"> + + + <br><span id="poweredby"></span> + </div> + <!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 --> + <script> + if (window.navigator.userAgent.indexOf("Edge") > -1) { + console.log("Removing native Edge fetch in favor of swagger-ui's polyfill") + window.fetch = undefined; + } + </script> + <script src="./swagger-ui-bundle.js"></script> + <script src="./swagger-ui-standalone-preset.js"></script> + <script> + var int = null; + + window.onload = function () { + var configObject = JSON.parse('%(ConfigObject)'); + var oauthConfigObject = JSON.parse('%(OAuthConfigObject)'); + + //鑾峰彇token鍦ㄦ鐩存帴璧嬪�硷紝鑳界洿鎺ュ簲鐢╯wagger鐨勬牱寮� + //configObject.onComplete = function () { + // ui.preauthorizeApiKey("oauth2", ""); + //}; + + // Apply mandatory parameters + configObject.dom_id = "#swagger-ui"; + configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset]; + configObject.layout = "StandaloneLayout"; + + // If oauth2RedirectUrl isn't specified, use the built-in default + if (!configObject.hasOwnProperty("oauth2RedirectUrl")) + configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html"); + + // Build a system + const ui = SwaggerUIBundle(configObject); + + // Apply OAuth config + ui.initOAuth(oauthConfigObject); + + //娓呯┖鍏冪礌鍐呭锛岃繖閲屾竻绌轰簡閫夋嫨鐗堟湰鐨勮嫳鏂� + $(".select-label span").empty(); + + myOnload(); + + //淇敼鐗堟湰鐨勭炕璇戜负涓枃 + function myOnload() { + $(document).ready(function () { + $(".select-label span").each(function () { + var myvalue = '閫夋嫨涓�涓帴鍙g増鏈�'; + $(this).html(myvalue); + }); + }); + } + setTimeout(() => { + + //浜岀淮鐮� + $('.info').append("<div class='qqgroup'><div style=\"color: #4990e2;\"><a href=\"../allservices\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"link\">路 鏌ョ湅鎵�鏈変緷璧栨敞鍐岀殑鏈嶅姟</a><br></div><div style=\"color: #4990e2;\"><a href=\"http.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"link\">路 HTTP Test</a><br></div></div><div style='clear: both;'></div>"); + + //淇敼 token鎺堟潈鎸夐挳涓轰腑鏂� + //$(".auth-wrapper span").empty(); + //$(document).ready(function () { + // $('.auth-wrapper span').each(function () { + // var myvalue = '鎺堟潈璁よ瘉'; + // $(this).html(myvalue); + // }); + //}); + + }, 1000) + // 鏂囨。logo + $(".link img").attr("src", "./logo/favicon-32x32.png"); + } + </script> +</body> +</html> diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseController.txt" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseController.txt" new file mode 100644 index 0000000..f28a803 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseController.txt" @@ -0,0 +1,16 @@ +锘縰sing Microsoft.AspNetCore.Mvc; +using [StartName]_Core.BaseController; +using [StartName]_I[Module]Service; +using [StartName]_Model.Models; + +namespace [StartName]_Server.Controllers.[Module] +{ + [Route("api/[TableShortName]")] + [ApiController] + public class [TableShortName]Controller : ApiBaseController<I[TableShortName]Service, [TableName]> + { + public [TableShortName]Controller(I[TableShortName]Service service) : base(service) + { + } + } +} \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseIRepository.txt" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseIRepository.txt" new file mode 100644 index 0000000..c298465 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseIRepository.txt" @@ -0,0 +1,10 @@ +锘� +using [StartName]_Core.BaseRepository; +using [StartName]_Model.Models; + +namespace [NameSpace] +{ + public interface I[TableShortName]Repository : IRepository<[TableName]> + { + } +} \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseIService.txt" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseIService.txt" new file mode 100644 index 0000000..ce4a0d9 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseIService.txt" @@ -0,0 +1,11 @@ +锘縰sing [StartName]_Core.BaseServices; +using [StartName]_I[Module]Repository; +using [StartName]_Model.Models; + +namespace [NameSpace] +{ + public interface I[TableShortName]Service : IService<[TableName]> + { + I[TableShortName]Repository Repository { get; } + } +} \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseRepository.txt" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseRepository.txt" new file mode 100644 index 0000000..733fe98 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseRepository.txt" @@ -0,0 +1,13 @@ +锘縰sing [StartName]_Core.BaseRepository; +using [StartName]_I[Module]Repository; +using [StartName]_Model.Models; + +namespace [NameSpace] +{ + public class [TableShortName]Repository : RepositoryBase<[TableName]>, I[TableShortName]Repository + { + public [TableShortName]Repository(IUnitOfWorkManage unitOfWorkManage) : base(unitOfWorkManage) + { + } + } +} \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseService.txt" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseService.txt" new file mode 100644 index 0000000..a200a70 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/BaseService.txt" @@ -0,0 +1,16 @@ +锘縰sing [StartName]_I[Module]Service; +using [StartName]_Core.BaseServices; +using [StartName]_I[Module]Repository; +using [StartName]_Model.Models; + +namespace [NameSpace] +{ + public class [TableShortName]Service : ServiceBase<[TableName], I[TableShortName]Repository>, I[TableShortName]Service + { + public I[TableShortName]Repository Repository => BaseDal; + + public [TableShortName]Service(I[TableShortName]Repository BaseDal) : base(BaseDal) + { + } + } +} \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/VuePage.txt" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/VuePage.txt" new file mode 100644 index 0000000..a8f48f9 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/CodeTemplate/VuePage.txt" @@ -0,0 +1,50 @@ +锘�<template> + <view-grid ref="grid" + :columns="columns" + :detail="detail" + :editFormFields="editFormFields" + :editFormOptions="editFormOptions" + :searchFormFields="searchFormFields" + :searchFormOptions="searchFormOptions" + :table="table" + :extend="extend"> + </view-grid> +</template> +<script> + import extend from "@/extension/[Module]/[TableShortName].js"; + import { ref, defineComponent } from "vue"; + export default defineComponent({ + setup() { + const table = ref({ + key: '[key]', + footer: "Foots", + cnName: '{Description}', + name: '[TableName]', + url: "[Url]", + sortName: "[SortBy]" + }); + const editFormFields = ref([EditFormFileds]); + const editFormOptions = ref([EditFormOptions]); + const searchFormFields = ref([SearchFormFileds]); + const searchFormOptions = ref([SearchFormOptions]); + const columns = ref([[Columns]]); + const detail = ref({ + cnName: "#detailCnName", + table: "#detailTable", + columns: [#detailColumns], + sortName: "#detailSortName", + key: "#detailKey" + }); + return { + table, + extend, + editFormFields, + editFormOptions, + searchFormFields, + searchFormOptions, + columns, + detail, + }; + }, + }); +</script> \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Dictionary.tsv" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Dictionary.tsv" new file mode 100644 index 0000000..b4a525e --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Dictionary.tsv" @@ -0,0 +1,254 @@ +锘縖 + { + "DicId": 3, + "Config": "{valueField: 'Enable',\r\ntextField: 'Enable',\r\n containField: null,\r\n handler: null }", + "DBServer": "1", + "DBSql": null, + "DicName": "鏄惁鍊�", + "DicNo": "enable", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-01-03T18:30:18.113" + }, + { + "DicId": 30, + "Config": "{valueField: 'Success',\r\n textField: 'Success', \r\n containField: null,\r\n handler: null }\r\n", + "DBServer": null, + "DBSql": null, + "DicName": "鍝嶅簲鐘舵��", + "DicNo": "restatus", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": "娴嬭瘯瓒呯骇绠$悊鍛�", + "ModifyDate": "2018-06-12T10:21:48" + }, + { + "DicId": 31, + "Config": "{valueField: 'LogType',\r\n textField: 'LogType', \r\n containField: null,\r\n handler: null }\r\n", + "DBServer": null, + "DBSql": null, + "DicName": "鏃ュ織绫诲瀷", + "DicNo": "log", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-04-04T13:21:54.927" + }, + { + "DicId": 32, + "Config": "{valueField: 'Role_Id',\r\n textField: 'RoleName', \r\n containField: ['Role_Id','RoleName'],\r\n handler: null }\r\n", + "DBServer": null, + "DBSql": "SELECT RoleId as 'key',RoleName as 'value' FROM Sys_Role WHERE Enable=1", + "DicName": "瑙掕壊鍒楄〃", + "DicNo": "roles", + "Enable": 1, + "OrderNo": 123, + "ParentId": 0, + "Remark": "sql璇彞闇�瑕乲ey,value鍒楋紝鐣岄潰鎵嶈兘缁戝畾鏁版嵁婧�", + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": "娴嬭瘯瓒呯骇绠$悊鍛�", + "ModifyDate": "2018-07-13T15:03:53" + }, + { + "DicId": 35, + "Config": "{\r\n valueField: 'AuditStatus',\r\n textField: 'AuditStatus',\r\n containField:null \r\n}", + "DBServer": null, + "DBSql": null, + "DicName": "瀹℃牳鐘舵��", + "DicNo": "audit", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2023-05-08T01:05:44.193" + }, + { + "DicId": 49, + "Config": "{\r\n valueField: 'Gender',\r\n textField: 'Gender',\r\n containField:null \r\n}", + "DBServer": null, + "DBSql": null, + "DicName": "鎬у埆", + "DicNo": "gender", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": "娴嬭瘯瓒呯骇绠$悊鍛�", + "ModifyDate": "2018-07-23T11:10:28" + }, + { + "DicId": 50, + "Config": "{\r\n valueField: 'Enable',\r\n textField: 'Enable',\r\n containField:null \r\n}", + "DBServer": null, + "DBSql": null, + "DicName": "鍚敤鐘舵��", + "DicNo": "status", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": null, + "ModifyDate": null + }, + { + "DicId": 59, + "Config": "{\r\n valueField: 'IsRegregisterPhone',\r\n textField: 'IsRegregisterPhone',\r\n containField:null \r\n}", + "DBServer": null, + "DBSql": null, + "DicName": "鎵嬫満鐢ㄦ埛", + "DicNo": "isphone", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2020-11-20T23:05:48.303" + }, + { + "DicId": 66, + "Config": null, + "DBServer": null, + "DBSql": "SELECT RoleId AS id,parentId,RoleId AS [key],RoleName AS value FROM Sys_Role", + "DicName": "绾ц仈瑙掕壊", + "DicNo": "tree_roles", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2020-11-20T23:08:03.217" + }, + { + "DicId": 67, + "Config": null, + "DBServer": null, + "DBSql": null, + "DicName": "nav", + "DicNo": "nav", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": null, + "ModifyDate": null + }, + { + "DicId": 70, + "Config": null, + "DBServer": null, + "DBSql": null, + "DicName": "璇锋眰鏂瑰紡", + "DicNo": "璇锋眰鏂瑰紡", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": null, + "ModifyDate": null + }, + { + "DicId": 71, + "Config": null, + "DBServer": null, + "DBSql": null, + "DicName": "瀹氭椂浠诲姟鐘舵��", + "DicNo": "瀹氭椂浠诲姟鐘舵��", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": null, + "ModifyDate": null + }, + { + "DicId": 72, + "Config": null, + "DBServer": null, + "DBSql": "SELECT DepartmentId AS 'key',DepartmentId AS 'id',ParentId AS parentId,DepartmentName as 'value' FROM Sys_Department", + "DicName": "缁勭粐鏈烘瀯", + "DicNo": "缁勭粐鏈烘瀯", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 10, + "DicList": null, + "Creater": "system", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": null, + "ModifyDate": null + }, + { + "DicId": 75, + "Config": null, + "DBServer": null, + "DBSql": null, + "DicName": "鏃ュ織鐘舵��", + "DicNo": "LogState", + "Enable": 1, + "OrderNo": null, + "ParentId": 0, + "Remark": null, + "SystemType": 1, + "DicList": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.233", + "Modifier": null, + "ModifyDate": null + } +] \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_DictionaryList.tsv" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_DictionaryList.tsv" new file mode 100644 index 0000000..0a8ad2e --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_DictionaryList.tsv" @@ -0,0 +1,548 @@ +锘縖 + { + "DicListId": 3, + "DicName": "鍚�", + "DicValue": "0", + "DicId": "3", + "Enable": null, + "OrderNo": 2, + "Remark": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-01-03T18:30:18.113" + }, + { + "DicListId": 4, + "DicName": "鏄�", + "DicValue": "1", + "DicId": "3", + "Enable": null, + "OrderNo": 1, + "Remark": null, + "Creater": "xxx", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-01-03T18:30:18.113" + }, + { + "DicListId": 22, + "DicName": "鍏朵粬", + "DicValue": "0", + "DicId": "30", + "Enable": null, + "OrderNo": 10, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2019-08-21T16:49:43" + }, + { + "DicListId": 23, + "DicName": "鎴愬姛", + "DicValue": "1", + "DicId": "30", + "Enable": null, + "OrderNo": 100, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2019-08-21T16:49:43" + }, + { + "DicListId": 24, + "DicName": "寮傚父", + "DicValue": "2", + "DicId": "30", + "Enable": null, + "OrderNo": 50, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2019-08-21T16:49:43" + }, + { + "DicListId": 25, + "DicName": "绯荤粺", + "DicValue": "System", + "DicId": "31", + "Enable": null, + "OrderNo": 100, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-04-04T13:21:54.947" + }, + { + "DicListId": 26, + "DicName": "鐧婚檰", + "DicValue": "Login", + "DicId": "31", + "Enable": null, + "OrderNo": 90, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-04-04T13:21:54.947" + }, + { + "DicListId": 27, + "DicName": "鏂板缓", + "DicValue": "Add", + "DicId": "31", + "Enable": null, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-04-04T13:21:54.943" + }, + { + "DicListId": 28, + "DicName": "鍒犻櫎", + "DicValue": "Del", + "DicId": "31", + "Enable": 1, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-04-04T13:21:54.943" + }, + { + "DicListId": 29, + "DicName": "缂栬緫", + "DicValue": "Edit", + "DicId": "31", + "Enable": 1, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-04-04T13:21:54.943" + }, + { + "DicListId": 37, + "DicName": "寰呭鏍�", + "DicValue": "0", + "DicId": "35", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2023-05-08T01:05:44.193" + }, + { + "DicListId": 38, + "DicName": "瀹℃牳閫氳繃", + "DicValue": "1", + "DicId": "35", + "Enable": null, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2023-05-08T01:05:44.193" + }, + { + "DicListId": 39, + "DicName": "瀹℃牳涓�", + "DicValue": "2", + "DicId": "35", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2023-05-08T01:05:44.193" + }, + { + "DicListId": 71, + "DicName": "寮傚父", + "DicValue": "Exception", + "DicId": "31", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-04-04T13:21:54.943" + }, + { + "DicListId": 90, + "DicName": "鐢�", + "DicValue": "0", + "DicId": "49", + "Enable": null, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "娴嬭瘯瓒呯骇绠$悊鍛�", + "ModifyDate": "2018-07-23T11:10:28" + }, + { + "DicListId": 91, + "DicName": "濂�", + "DicValue": "1", + "DicId": "49", + "Enable": null, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "娴嬭瘯瓒呯骇绠$悊鍛�", + "ModifyDate": "2018-07-23T11:10:28" + }, + { + "DicListId": 96, + "DicName": "鏈惎鐢�", + "DicValue": "0", + "DicId": "50", + "Enable": 1, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2019-08-16T18:17:47" + }, + { + "DicListId": 97, + "DicName": "宸插惎鐢�", + "DicValue": "1", + "DicId": "50", + "Enable": 1, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2019-08-16T18:17:47" + }, + { + "DicListId": 98, + "DicName": "宸插垹闄�", + "DicValue": "2", + "DicId": "50", + "Enable": 1, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2019-08-16T18:17:47" + }, + { + "DicListId": 128, + "DicName": "鏄�", + "DicValue": "1", + "DicId": "59", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2020-11-20T23:05:48.303" + }, + { + "DicListId": 129, + "DicName": "鍚�", + "DicValue": "0", + "DicId": "59", + "Enable": 1, + "OrderNo": null, + "Remark": null, + "Creater": "娴嬭瘯瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2020-11-20T23:05:48.303" + }, + { + "DicListId": 144, + "DicName": "鍒锋柊Token", + "DicValue": "ReplaceToeken", + "DicId": "31", + "Enable": null, + "OrderNo": 110, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2022-04-04T13:21:54.937" + }, + { + "DicListId": 145, + "DicName": "Info", + "DicValue": "3", + "DicId": "30", + "Enable": null, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 423, + "DicName": "鏄�", + "DicValue": "1", + "DicId": "67", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 424, + "DicName": "鍚�", + "DicValue": "0", + "DicId": "67", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 435, + "DicName": "瀹℃牳鏈�氳繃", + "DicValue": "3", + "DicId": "35", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2023-05-08T01:05:44.193" + }, + { + "DicListId": 436, + "DicName": "get", + "DicValue": "get", + "DicId": "70", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 437, + "DicName": "post", + "DicValue": "post", + "DicId": "70", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 438, + "DicName": "姝e父", + "DicValue": "0", + "DicId": "71", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 439, + "DicName": "鏆傚仠", + "DicValue": "1", + "DicId": "71", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 442, + "DicName": "椹冲洖", + "DicValue": "4", + "DicId": "35", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 443, + "DicName": "绂佺敤", + "DicValue": "DisEnable", + "DicId": "73", + "Enable": 1, + "OrderNo": 1, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "寮�鍙�", + "ModifyDate": "2023-07-14T14:17:01.037" + }, + { + "DicListId": 444, + "DicName": "鍚敤", + "DicValue": "Enable", + "DicId": "73", + "Enable": 1, + "OrderNo": 0, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "寮�鍙�", + "ModifyDate": "2023-07-14T14:17:01.017" + }, + { + "DicListId": 449, + "DicName": "淇℃伅", + "DicValue": "Info", + "DicId": "75", + "Enable": 0, + "OrderNo": 1, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 450, + "DicName": "鎴愬姛", + "DicValue": "Sucess", + "DicId": "75", + "Enable": 0, + "OrderNo": 2, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 451, + "DicName": "澶辫触", + "DicValue": "Error", + "DicId": "75", + "Enable": 0, + "OrderNo": 3, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 452, + "DicName": "1", + "DicValue": "1", + "DicId": "80", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2023-12-12T10:28:05.55" + }, + { + "DicListId": 453, + "DicName": "2", + "DicValue": "2", + "DicId": "80", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2023-12-12T10:28:05.55" + }, + { + "DicListId": 454, + "DicName": "3", + "DicValue": "3", + "DicId": "80", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2023-12-12T10:28:05.55" + }, + { + "DicListId": 455, + "DicName": "4", + "DicValue": "4", + "DicId": "80", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": "瓒呯骇绠$悊鍛�", + "ModifyDate": "2023-12-12T10:28:05.55" + }, + { + "DicListId": 456, + "DicName": "鏈鏍�", + "DicValue": "OrderState_Unaudited", + "DicId": "84", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + }, + { + "DicListId": 457, + "DicName": "宸插鏍�", + "DicValue": "OrderState_Audited", + "DicId": "84", + "Enable": 0, + "OrderNo": null, + "Remark": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:22.553", + "Modifier": null, + "ModifyDate": null + } +] \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Menu.tsv" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Menu.tsv" new file mode 100644 index 0000000..8a6eba7 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Menu.tsv" @@ -0,0 +1,173 @@ +锘縖 + { + "MenuId": 1, + "MenuName": "鐢ㄦ埛绠$悊", + "Auth": "[{\"text\":\"鏌ヨ\",\"value\":\"Search\"},{\"text\":\"鏂板缓\",\"value\":\"Add\"},{\"text\":\"鍒犻櫎\",\"value\":\"Delete\"},{\"text\":\"缂栬緫\",\"value\":\"Update\"},{\"text\":\"瀵煎叆\",\"value\":\"Import\"},{\"text\":\"瀵煎嚭\",\"value\":\"Export\"}]", + "Icon": "el-icon-user", + "Description": null, + "Enable": 1, + "TableName": ".", + "ParentId": 0, + "Url": null, + "OrderNo": 4000, + "MenuType": 99, + "Menus": null, + "Actions": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.907", + "Modifier": "admin", + "ModifyDate": "2024-05-09T15:50:07.567" + }, + { + "MenuId": 2, + "MenuName": "鐢ㄦ埛绠$悊", + "Auth": "[{\"text\":\"鏌ヨ\",\"value\":\"Search\"},{\"text\":\"鏂板缓\",\"value\":\"Add\"},{\"text\":\"鍒犻櫎\",\"value\":\"Delete\"},{\"text\":\"缂栬緫\",\"value\":\"Update\"},{\"text\":\"瀵煎叆\",\"value\":\"Import\"},{\"text\":\"瀵煎嚭\",\"value\":\"Export\"}]", + "Icon": null, + "Description": null, + "Enable": 1, + "TableName": "Sys_User", + "ParentId": 1, + "Url": "/Sys_User", + "OrderNo": 2000, + "MenuType": 99, + "Menus": null, + "Actions": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.907", + "Modifier": "admin", + "ModifyDate": "2024-05-09T15:50:14.03" + }, + { + "MenuId": 3, + "MenuName": "鏉冮檺绠$悊", + "Auth": "[{\"text\":\"鏌ヨ\",\"value\":\"Search\"},{\"text\":\"鏂板缓\",\"value\":\"Add\"},{\"text\":\"鍒犻櫎\",\"value\":\"Delete\"},{\"text\":\"缂栬緫\",\"value\":\"Update\"},{\"text\":\"瀵煎叆\",\"value\":\"Import\"},{\"text\":\"瀵煎嚭\",\"value\":\"Export\"}]", + "Icon": "ivu-icon ivu-icon-ios-boat", + "Description": null, + "Enable": 1, + "TableName": ",", + "ParentId": 1, + "Url": "/permission", + "OrderNo": 1000, + "MenuType": 99, + "Menus": null, + "Actions": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.907", + "Modifier": "admin", + "ModifyDate": "2024-05-09T15:50:20.727" + }, + { + "MenuId": 4, + "MenuName": "瑙掕壊绠$悊", + "Auth": "[{\"text\":\"鏌ヨ\",\"value\":\"Search\"},{\"text\":\"鏂板缓\",\"value\":\"Add\"},{\"text\":\"鍒犻櫎\",\"value\":\"Delete\"},{\"text\":\"缂栬緫\",\"value\":\"Update\"},{\"text\":\"瀵煎叆\",\"value\":\"Import\"},{\"text\":\"瀵煎嚭\",\"value\":\"Export\"}]", + "Icon": null, + "Description": null, + "Enable": 1, + "TableName": "Sys_Role", + "ParentId": 1, + "Url": "/Sys_Role", + "OrderNo": 900, + "MenuType": 99, + "Menus": null, + "Actions": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.907", + "Modifier": "admin", + "ModifyDate": "2024-05-09T15:50:23.177" + }, + { + "MenuId": 5, + "MenuName": "绯荤粺璁剧疆", + "Auth": "[{\"text\":\"鏌ヨ\",\"value\":\"Search\"},{\"text\":\"鏂板缓\",\"value\":\"Add\"},{\"text\":\"鍒犻櫎\",\"value\":\"Delete\"},{\"text\":\"缂栬緫\",\"value\":\"Update\"},{\"text\":\"瀵煎叆\",\"value\":\"Import\"},{\"text\":\"瀵煎嚭\",\"value\":\"Export\"}]", + "Icon": "el-icon-setting", + "Description": null, + "Enable": 1, + "TableName": "绯荤粺璁剧疆", + "ParentId": 0, + "Url": "/", + "OrderNo": 0, + "MenuType": 99, + "Menus": null, + "Actions": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.907", + "Modifier": "admin", + "ModifyDate": "2024-05-09T15:50:38.703" + }, + { + "MenuId": 6, + "MenuName": "鑿滃崟璁剧疆", + "Auth": "[{\"text\":\"鏌ヨ\",\"value\":\"Search\"},{\"text\":\"鏂板缓\",\"value\":\"Add\"},{\"text\":\"鍒犻櫎\",\"value\":\"Delete\"},{\"text\":\"缂栬緫\",\"value\":\"Update\"},{\"text\":\"瀵煎叆\",\"value\":\"Import\"},{\"text\":\"瀵煎嚭\",\"value\":\"Export\"}]", + "Icon": null, + "Description": null, + "Enable": 1, + "TableName": "Sys_Menu", + "ParentId": 5, + "Url": "/sysmenu", + "OrderNo": 10, + "MenuType": 99, + "Menus": null, + "Actions": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.907", + "Modifier": "admin", + "ModifyDate": "2024-05-09T15:50:42.007" + }, + { + "MenuId": 7, + "MenuName": "涓嬫媺妗嗙粦瀹氳缃�", + "Auth": "[{\"text\":\"鏌ヨ\",\"value\":\"Search\"},{\"text\":\"鏂板缓\",\"value\":\"Add\"},{\"text\":\"鍒犻櫎\",\"value\":\"Delete\"},{\"text\":\"缂栬緫\",\"value\":\"Update\"},{\"text\":\"瀵煎叆\",\"value\":\"Import\"},{\"text\":\"瀵煎嚭\",\"value\":\"Export\"}]", + "Icon": null, + "Description": null, + "Enable": 1, + "TableName": "Sys_Dictionary", + "ParentId": 5, + "Url": "/Sys_Dictionary", + "OrderNo": 10, + "MenuType": 99, + "Menus": null, + "Actions": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.907", + "Modifier": null, + "ModifyDate": null + }, + { + "MenuId": 8, + "MenuName": "鏃ュ織绠$悊", + "Auth": "[{\"text\":\"鏌ヨ\",\"value\":\"Search\"},{\"text\":\"鏂板缓\",\"value\":\"Add\"},{\"text\":\"鍒犻櫎\",\"value\":\"Delete\"},{\"text\":\"缂栬緫\",\"value\":\"Update\"},{\"text\":\"瀵煎叆\",\"value\":\"Import\"},{\"text\":\"瀵煎嚭\",\"value\":\"Export\"}]", + "Icon": "el-icon-date", + "Description": null, + "Enable": 1, + "TableName": "xxx", + "ParentId": 0, + "Url": "/", + "OrderNo": 500, + "MenuType": 99, + "Menus": null, + "Actions": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.907", + "Modifier": "admin", + "ModifyDate": "2024-05-09T15:50:30.557" + }, + { + "MenuId": 9, + "MenuName": "鎺ュ彛鏃ュ織", + "Auth": "[{\"text\":\"鏌ヨ\",\"value\":\"Search\"},{\"text\":\"鏂板缓\",\"value\":\"Add\"},{\"text\":\"鍒犻櫎\",\"value\":\"Delete\"},{\"text\":\"缂栬緫\",\"value\":\"Update\"},{\"text\":\"瀵煎叆\",\"value\":\"Import\"},{\"text\":\"瀵煎嚭\",\"value\":\"Export\"}]", + "Icon": null, + "Description": null, + "Enable": 1, + "TableName": "Sys_Log", + "ParentId": 8, + "Url": "/Sys_Log/Manager", + "OrderNo": 0, + "MenuType": 99, + "Menus": null, + "Actions": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:22.907", + "Modifier": "admin", + "ModifyDate": "2024-05-09T15:50:34.273" + } +] \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Role.tsv" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Role.tsv" new file mode 100644 index 0000000..1322331 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_Role.tsv" @@ -0,0 +1,15 @@ +锘縖 + { + "RoleId": 1, + "DeptName": null, + "DeptId": 111, + "Enable": 1, + "ParentId": 0, + "RoleName": "瓒呯骇绠$悊鍛�", + "Roles": null, + "Creater": "瓒呯骇绠$悊鍛�", + "CreateDate": "2024-08-23T11:32:23.227", + "Modifier": "admin", + "ModifyDate": "2024-04-29T13:53:44.717" + } +] \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_RoleAuth.tsv" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_RoleAuth.tsv" new file mode 100644 index 0000000..a85708b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_RoleAuth.tsv" @@ -0,0 +1,167 @@ +锘縖 + { + "AuthId": 136, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 1, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": "admin", + "ModifyDate": "2024-02-22T09:31:16.363" + }, + { + "AuthId": 137, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 2, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": "admin", + "ModifyDate": "2024-04-29T15:04:07.83" + }, + { + "AuthId": 138, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 3, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": "admin", + "ModifyDate": "2024-02-22T09:31:16.363" + }, + { + "AuthId": 140, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 4, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": "admin", + "ModifyDate": "2024-02-22T09:31:16.363" + }, + { + "AuthId": 141, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 5, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": "admin", + "ModifyDate": "2024-02-22T09:31:16.363" + }, + { + "AuthId": 143, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 6, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": "admin", + "ModifyDate": "2024-02-22T09:31:16.363" + }, + { + "AuthId": 144, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 7, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": "admin", + "ModifyDate": "2024-04-29T15:00:47.033" + }, + { + "AuthId": 146, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 8, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": "admin", + "ModifyDate": "2024-04-29T15:04:07.83" + }, + { + "AuthId": 148, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 9, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": "admin", + "ModifyDate": "2024-02-22T09:31:16.363" + }, + { + "AuthId": 153, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 10, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": null, + "ModifyDate": null + }, + { + "AuthId": 154, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 12, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": null, + "ModifyDate": null + }, + { + "AuthId": 155, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 13, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": null, + "ModifyDate": null + }, + { + "AuthId": 156, + "AuthValue": "Search", + "MenuId": 11, + "RoleId": 1, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": null, + "ModifyDate": null + }, + { + "AuthId": 157, + "AuthValue": "Search", + "MenuId": 11, + "RoleId": 2, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": null, + "ModifyDate": null + }, + { + "AuthId": 158, + "AuthValue": "Search,Add,Delete,Update,Import,Export", + "MenuId": 10, + "RoleId": 2, + "UserId": null, + "Creater": "admin", + "CreateDate": "2024-08-23T11:32:23.527", + "Modifier": null, + "ModifyDate": null + } +] \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_User.tsv" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_User.tsv" new file mode 100644 index 0000000..674b099 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/WIDESEAWCS_DB.DBSeed.Json/Sys_User.tsv" @@ -0,0 +1,29 @@ +锘縖 + { + "User_Id": 1, + "UserName": "admin", + "Role_Id": 1, + "RoleName": "瓒呯骇绠$悊鍛�", + "PhoneNo": "", + "Remark": "", + "UserPwd": "j79rYYvCz4vdhcboB1Ausg==", + "UserTrueName": "瓒呯骇绠$悊鍛�", + "DeptName": "", + "Dept_Id": 0, + "Email": "", + "Enable": 1, + "Gender": 1, + "HeadImageUrl": "", + "LastModifyPwdDate": "2024-04-16T19:58:55", + "Address": "绯荤粺鏈嶅姟鍣�", + "AuditDate": "2024-04-16T00:54:06", + "AuditStatus": 1, + "Auditor": "瓒呯骇绠$悊鍛�", + "Token": "", + "TenantId": 0, + "Creater": "绯荤粺", + "CreateDate": "2024-08-23T11:32:24.367", + "Modifier": null, + "ModifyDate": null + } +] \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/site.css" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/site.css" new file mode 100644 index 0000000..e679a8e --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/site.css" @@ -0,0 +1,71 @@ +锘�/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification +for details on configuring this project to bundle and minify static web assets. */ + +a.navbar-brand { + white-space: normal; + text-align: center; + word-break: break-all; +} + +/* Provide sufficient contrast against white background */ +a { + color: #0366d6; +} + +.btn-primary { + color: #fff; + background-color: #1b6ec2; + border-color: #1861ac; +} + +.nav-pills .nav-link.active, .nav-pills .show > .nav-link { + color: #fff; + background-color: #1b6ec2; + border-color: #1861ac; +} + +/* Sticky footer styles +-------------------------------------------------- */ +html { + font-size: 14px; +} +@media (min-width: 768px) { + html { + font-size: 16px; + } +} + +.border-top { + border-top: 1px solid #e5e5e5; +} +.border-bottom { + border-bottom: 1px solid #e5e5e5; +} + +.box-shadow { + box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); +} + +button.accept-policy { + font-size: 1rem; + line-height: inherit; +} + +/* Sticky footer styles +-------------------------------------------------- */ +html { + position: relative; + min-height: 100%; +} + +body { + /* Margin bottom by footer height */ + margin-bottom: 60px; +} +.footer { + position: absolute; + bottom: 0; + width: 100%; + white-space: nowrap; + line-height: 60px; /* Vertically center the text there */ +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/style.css" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/style.css" new file mode 100644 index 0000000..f8fe18d --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/style.css" @@ -0,0 +1,132 @@ +@charset "utf-8"; +::selection { + background: #2D2F36; +} +::-webkit-selection { + background: #2D2F36; +} +::-moz-selection { + background: #2D2F36; +} +body { + background: white; + font-family: 'Inter UI', sans-serif; + margin: 0; + padding: 20px; +} +.page { + background: #e2e2e5; + display: flex; + flex-direction: column; + height: calc(100% - 40px); + position: absolute; + place-content: center; + width: calc(100% - 40px); +} +@media (max-width: 767px) { + .page { + height: auto; + margin-bottom: 20px; + padding-bottom: 20px; + } +} +.container { + display: flex; + height: 320px; + margin: 0 auto; + width: 640px; +} +@media (max-width: 767px) { + .container { + flex-direction: column; + height: 630px; + width: 320px; + } +} +.left { + background: white; + height: calc(100% - 40px); + top: 20px; + position: relative; + width: 50%; +} +@media (max-width: 767px) { + .left { + height: 100%; + left: 20px; + width: calc(100% - 40px); + max-height: 270px; + } +} +.login { + font-size: 33px; + font-weight: 900; + margin: 50px 40px 40px; +} +.eula { + color: #999; + font-size: 14px; + line-height: 1.5; + margin: 40px; +} +.right { + background: #474A59; + box-shadow: 0px 0px 40px 16px rgba(0,0,0,0.22); + color: #F1F1F2; + position: relative; + width: 50%; +} +@media (max-width: 767px) { + .right { + flex-shrink: 0; + height: 100%; + width: 100%; + max-height: 350px; + } +} +svg { + position: absolute; + width: 320px; +} +path { + fill: none; + stroke: url(#linearGradient);; + stroke-width: 4; + stroke-dasharray: 240 1386; +} +.form { + margin: 40px; + position: absolute; +} +label { + color: #c2c2c5; + display: block; + font-size: 14px; + height: 16px; + margin-top: 20px; + margin-bottom: 5px; +} +input { + background: transparent; + border: 0; + color: #f2f2f2; + font-size: 20px; + height: 30px; + line-height: 30px; + outline: none !important; + width: 100%; +} +input::-moz-focus-inner { + border: 0; +} +#submit { + color: #707075; + margin-top: 40px; + transition: color 300ms; +} +#submit:focus { + color: #f2f2f2; +} +#submit:active { + color: #d0d0d2; +} \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/swaggerdoc.css" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/swaggerdoc.css" new file mode 100644 index 0000000..1a05ca2 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/css/swaggerdoc.css" @@ -0,0 +1,109 @@ +.selectBox { + margin: 50px auto; /*灞呬腑*/ + width: 150px; + text-align: center; +} + + .selectBox a { + color: #1b1b1b; + text-decoration: none; + } + + .selectBox ul, .selectBox li { + list-style: none; + } + + .selectBox span { + line-height: 46px; + background-color: #85ea2d; + display: block; + margin-bottom: 20px; + position: relative; + z-index: 2; + border-radius: 5px; + -webkit-transition: all .2s ease-in; + transition: all .2s ease-in; + } + +.drop { + left: 0; + right: 0; + top: -9999px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2); + border-radius: 5px; + position: absolute; + z-index: 1; + -webkit-transform: translateY(-50px); /*y杞存柟鍚戝钩绉�*/ + transform: translateY(-50px); + opacity: 0; + -webkit-transition: all .2s ease-in; /*骞崇Щ鏃堕棿0.2s*/ + transition: all .2s ease-in; +} +/*缁欓�佷釜涓嬫媺鍔╂敾*/ +.selectBox:hover span { + background-color: #74ea0d; +} + + .selectBox:hover span a:after { + -webkit-transform: rotate(180deg); /*鏃嬭浆180搴�*/ + transform: rotate(180deg); + } + +.selectBox:hover .drop { + position: static; + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); +} +.drop li:first-child:before { + content: " "; + font-size: 0; + line-height: 0; + margin: 0 auto; /*灞呬腑*/ + display: block; /*鐙崰涓�琛�*/ + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2); /*閰嶅悎鏁翠綋涓�鏍风殑鎶曞奖*/ + background-color: #fff; + width: 10px; + height: 10px; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); /*涓�涓鏂瑰舰鍊炬枩鍥涘崄浜斿害灏辨槸涓夎浜嗕絾鏄鎶婁笅鍗婇儴鍒嗚棌璧锋潵*/ + position: relative; + top: -5px; /*鏋滄柇鐨勯湶鍑轰笂鍗婇儴鍒�*/ + z-index: 1; /*鏋滄柇鐨勯殣钘忎笅鍗婇儴鍒�*/ + -webkit-transition: all .2s ease-in; + transition: all .2s ease-in; +} + +.drop li a { + color: #888; + line-height: 46px; + border-bottom: solid 1px #eee; + font-size: 14px; + display: block; + background-color: #fff; /*瑕佹湁鑳屾櫙鑹叉墠鑳界洊浣忓憖*/ + position: relative; + z-index: 2; /*杩欓噷寰堥噸瑕� 瑕佹尅浣忎笁瑙掑舰鐨勪笅鍗婇儴鍒�*/ + -webkit-transition: all .2s ease-in; + transition: all .2s ease-in; +} +.drop li:first-child a { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + margin-top: -10px; +} + +.drop li:last-child a { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + border-bottom: none; +} +.drop li:hover:before { + background-color: #85ea2d; +} + +.drop li:hover a { + background-color: #85ea2d; + color: #fff; +} + + diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/favicon.ico" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/favicon.ico" new file mode 100644 index 0000000..a3a7999 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/favicon.ico" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/http.html" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/http.html" new file mode 100644 index 0000000..d11c5d0 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/http.html" @@ -0,0 +1,2337 @@ +<!DOCTYPE html> +<html lang="zh-CN"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>API娴嬭瘯宸ュ叿</title> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/theme/dracula.min.css"> + <style> + :root { + --primary-color: #ff6b6b; + --secondary-color: #48dbfb; + --dark-color: #2d3436; + --light-color: #f5f6fa; + --success-color: #1dd1a1; + --warning-color: #feca57; + --error-color: #ff6b6b; + --sidebar-width: 280px; + --header-height: 60px; + --footer-height: 40px; + } + + * { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + } + + body { + background-color: #1e272e; + color: #f5f6fa; + height: 100vh; + display: flex; + flex-direction: column; + } + + /* 鐐叿娓愬彉鑳屾櫙 */ + .gradient-bg { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient(-45deg, #1e272e, #2d3436, #3d3d3d, #2d3436); + background-size: 400% 400%; + animation: gradientBG 15s ease infinite; + z-index: -1; + } + + @keyframes gradientBG { + 0% { + background-position: 0% 50%; + } + + 50% { + background-position: 100% 50%; + } + + 100% { + background-position: 0% 50%; + } + } + + /* 澶撮儴鏍峰紡 */ + .header { + height: var(--header-height); + background-color: rgba(45, 52, 54, 0.9); + display: flex; + align-items: center; + padding: 0 20px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); + z-index: 100; + } + + .logo { + display: flex; + align-items: center; + font-size: 22px; + font-weight: bold; + color: var(--primary-color); + } + + .logo i { + margin-right: 10px; + font-size: 24px; + } + + .header-actions { + margin-left: auto; + display: flex; + gap: 15px; + } + + /* 涓诲唴瀹瑰尯 */ + .main-container { + display: flex; + flex: 1; + overflow: hidden; + } + + /* 渚ц竟鏍� */ + .sidebar { + width: var(--sidebar-width); + background-color: rgba(45, 52, 54, 0.8); + border-right: 1px solid rgba(255, 255, 255, 0.1); + display: flex; + flex-direction: column; + transition: all 0.3s ease; + overflow-y: auto; + } + + .sidebar-header { + padding: 15px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + display: flex; + justify-content: space-between; + align-items: center; + } + + .sidebar-title { + font-size: 16px; + font-weight: 600; + color: var(--secondary-color); + } + + .sidebar-content { + flex: 1; + padding: 10px 0; + overflow-y: auto; + } + + /* 璇锋眰鍘嗗彶椤� */ + .history-item { + padding: 12px 15px; + border-bottom: 1px solid rgba(255, 255, 255, 0.05); + cursor: pointer; + transition: all 0.2s ease; + display: flex; + align-items: center; + } + + .history-item:hover { + background-color: rgba(255, 255, 255, 0.05); + } + + .history-method { + width: 50px; + padding: 3px 6px; + border-radius: 3px; + font-size: 12px; + font-weight: bold; + text-align: center; + margin-right: 10px; + } + + .history-method.get { + background-color: rgba(72, 219, 251, 0.2); + color: var(--secondary-color); + border: 1px solid var(--secondary-color); + } + + .history-method.post { + background-color: rgba(29, 209, 161, 0.2); + color: var(--success-color); + border: 1px solid var(--success-color); + } + + .history-method.put { + background-color: rgba(254, 202, 87, 0.2); + color: var(--warning-color); + border: 1px solid var(--warning-color); + } + + .history-method.delete { + background-color: rgba(255, 107, 107, 0.2); + color: var(--error-color); + border: 1px solid var(--error-color); + } + + .history-method.patch { + background-color: rgba(155, 89, 182, 0.2); + color: #9b59b6; + border: 1px solid #9b59b6; + } + + .history-url { + flex: 1; + font-size: 13px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + /* 涓诲伐浣滃尯 */ + .workspace { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + } + + /* 璇锋眰鎺у埗闈㈡澘 */ + .request-panel { + padding: 20px; + background-color: rgba(45, 52, 54, 0.7); + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + } + + .request-controls { + display: flex; + margin-bottom: 15px; + align-items: center; + } + + /* 鏂板璇锋眰鍔ㄧ敾鏁堟灉 */ + .request-animation { + position: relative; + overflow: hidden; + } + + .request-animation::after { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, + transparent, + rgba(72, 219, 251, 0.4), + transparent); + animation: loading 1.5s infinite; + } + + /* 鍝嶅簲鐘舵�佸姩鐢� */ + .response-status { + display: flex; + align-items: center; + } + + .status-pulse { + width: 12px; + height: 12px; + border-radius: 50%; + margin-right: 8px; + animation: pulse 2s infinite; + } + + @keyframes pulse { + 0% { + box-shadow: 0 0 0 0 rgba(72, 219, 251, 0.7); + } + + 70% { + box-shadow: 0 0 0 10px rgba(72, 219, 251, 0); + } + + 100% { + box-shadow: 0 0 0 0 rgba(72, 219, 251, 0); + } + } + + /* 鏇村鍔熻兘闈㈡澘鏍峰紡 */ + .advanced-panel { + margin-top: 15px; + padding: 15px; + background-color: rgba(0, 0, 0, 0.2); + border-radius: 4px; + display: none; + } + + .advanced-panel.active { + display: block; + animation: fadeIn 0.3s ease; + } + + @keyframes loading { + 100% { + left: 100%; + } + } + + .method-select { + width: 120px; + margin-right: 10px; + background-color: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + color: white; + padding: 10px 35px 10px 15px; + border-radius: 4px; + font-size: 14px; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3e%3cpath d='M7 10l5 5 5-5z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 10px center; + background-size: 12px; + cursor: pointer; + transition: all 0.3s ease; + } + + .method-select:focus { + background-color: rgba(45, 52, 54, 0.9); + border-color: var(--secondary-color); + outline: none; + box-shadow: 0 0 0 2px rgba(72, 219, 251, 0.3); + } + + .method-select option { + background-color: #2d3436; + color: white; + padding: 10px; + } + + .method-select option:checked { + background-color: rgba(72, 219, 251, 0.3); + } + + @-moz-document url-prefix() { + .method-select { + color: white !important; + text-shadow: 0 0 0 white; + } + + .method-select option { + background-color: #2d3436; + } + } + + .url-input { + flex: 1; + padding: 10px 15px; + background-color: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + color: white; + border-radius: 4px; + font-size: 14px; + transition: all 0.3s ease; + } + + .url-input:focus { + border-color: var(--secondary-color); + outline: none; + box-shadow: 0 0 0 2px rgba(72, 219, 251, 0.3); + } + + .send-btn { + margin-left: 10px; + padding: 10px 20px; + background-color: var(--primary-color); + color: white; + border: none; + border-radius: 4px; + font-weight: bold; + cursor: pointer; + transition: all 0.2s ease; + display: flex; + align-items: center; + gap: 8px; + } + + .send-btn i { + font-size: 16px; + } + + .send-btn:hover { + background-color: #ff5252; + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(255, 107, 107, 0.3); + } + + .send-btn:active { + transform: translateY(0); + box-shadow: none; + } + + /* 鏍囩椤靛鑸� */ + .tabs { + display: flex; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + margin-bottom: 15px; + } + + .tab { + padding: 10px 20px; + cursor: pointer; + border-bottom: 2px solid transparent; + transition: all 0.2s ease; + font-size: 14px; + position: relative; + } + + .tab.active { + border-bottom-color: var(--primary-color); + color: var(--primary-color); + } + + .tab:hover:not(.active) { + background-color: rgba(255, 255, 255, 0.05); + } + + .tab-badge { + position: absolute; + top: -5px; + right: 5px; + background-color: var(--secondary-color); + color: var(--dark-color); + border-radius: 50%; + width: 18px; + height: 18px; + font-size: 10px; + display: flex; + align-items: center; + justify-content: center; + } + + /* 鏍囩鍐呭鍖� */ + .tab-content { + display: none; + animation: fadeIn 0.3s ease; + } + + @keyframes fadeIn { + from { + opacity: 0; + transform: translateY(5px); + } + + to { + opacity: 1; + transform: translateY(0); + } + } + + .tab-content.active { + display: block; + } + + /* 鍙傛暟琛ㄦ牸鏍峰紡 */ + .params-table { + width: 100%; + border-collapse: collapse; + margin-bottom: 15px; + } + + .params-table th, + .params-table td { + padding: 10px; + text-align: left; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + } + + .params-table th { + font-weight: 500; + color: var(--secondary-color); + font-size: 13px; + } + + .params-table tr:last-child td { + border-bottom: none; + } + + .params-table input { + width: 100%; + padding: 8px; + background-color: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + color: white; + border-radius: 3px; + font-size: 13px; + transition: all 0.2s ease; + } + + .params-table input:focus { + border-color: var(--secondary-color); + outline: none; + box-shadow: 0 0 0 2px rgba(72, 219, 251, 0.2); + } + + .params-table select { + width: 100%; + padding: 8px; + background-color: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + color: white; + border-radius: 3px; + font-size: 13px; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3e%3cpath d='M7 10l5 5 5-5z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 8px center; + background-size: 10px; + cursor: pointer; + } + + .params-actions { + display: flex; + gap: 5px; + } + + .param-action-btn { + width: 28px; + height: 28px; + display: flex; + align-items: center; + justify-content: center; + background-color: rgba(255, 255, 255, 0.1); + border: none; + border-radius: 3px; + color: white; + cursor: pointer; + transition: all 0.2s ease; + } + + .param-action-btn:hover { + background-color: rgba(255, 255, 255, 0.2); + } + + .param-action-btn.delete:hover { + background-color: rgba(255, 107, 107, 0.3); + color: var(--error-color); + } + + .add-param-btn { + margin-top: 5px; + padding: 8px 15px; + background-color: rgba(72, 219, 251, 0.2); + color: var(--secondary-color); + border: 1px dashed var(--secondary-color); + border-radius: 4px; + cursor: pointer; + transition: all 0.2s ease; + font-size: 13px; + display: inline-flex; + align-items: center; + gap: 8px; + } + + .add-param-btn:hover { + background-color: rgba(72, 219, 251, 0.3); + } + + /* 璇锋眰浣撶紪杈戝櫒 */ + .body-editor { + width: 100%; + height: 200px; + background-color: rgba(0, 0, 0, 0.3); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 4px; + padding: 10px; + color: white; + font-family: 'Courier New', Courier, monospace; + font-size: 14px; + resize: vertical; + transition: all 0.3s ease; + } + + .body-editor:focus { + border-color: var(--secondary-color); + outline: none; + box-shadow: 0 0 0 2px rgba(72, 219, 251, 0.3); + } + + .body-type-selector { + margin: 12px 0; + padding: 0; + } + + .button-group { + display: flex; + flex-wrap: wrap; + gap: 6px; + background: transparent; + padding: 0; + } + + .type-button { + position: relative; + cursor: pointer; + } + + .type-button input[type="radio"] { + position: absolute; + opacity: 0; + width: 0; + height: 0; + } + + .type-button span { + display: block; + padding: 6px 12px; + font-size: 13px; + color: rgba(255, 255, 255, 0.7); + background-color: rgba(255, 255, 255, 0.1); + border-radius: 4px; + transition: all 0.2s ease; + white-space: nowrap; + } + + .type-button:hover span { + box-shadow: 0 0 0 2px rgba(72, 219, 251, 0.3); + } + + .type-button input[type="radio"]:checked+span { + background-color: rgba(72, 219, 251, 0.3); + color: var(--secondary-color); + } + + .type-button input[type="radio"]:focus+span { + outline: none; + box-shadow: 0 0 0 2px rgba(72, 219, 251, 0.3); + } + + .body-type-btn { + padding: 6px 12px; + background-color: rgba(255, 255, 255, 0.1); + border: none; + border-radius: 3px; + color: rgba(255, 255, 255, 0.7); + cursor: pointer; + font-size: 13px; + transition: all 0.2s ease; + } + + body-type-btn.active { + background-color: rgba(72, 219, 251, 0.3); + color: var(--secondary-color); + } + + /* 鍝嶅簲鍖哄煙 */ + .response-panel { + flex: 1; + padding: 20px; + overflow-y: auto; + background-color: rgba(45, 52, 54, 0.5); + } + + .response-header { + display: flex; + align-items: center; + margin-bottom: 20px; + padding-bottom: 10px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + } + + .status-code { + padding: 5px 10px; + border-radius: 3px; + font-weight: bold; + margin-right: 15px; + font-size: 14px; + } + + .status-code.success { + background-color: rgba(29, 209, 161, 0.2); + color: var(--success-color); + border: 1px solid var(--success-color); + } + + .status-code.error { + background-color: rgba(255, 107, 107, 0.2); + color: var(--error-color); + border: 1px solid var(--error-color); + } + + .response-time { + color: var(--secondary-color); + margin-right: 15px; + font-size: 13px; + } + + .response-size { + color: var(--secondary-color); + font-size: 13px; + } + + /* 鍝嶅簲鏍囩椤� */ + .response-tabs { + display: flex; + margin-bottom: 15px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + } + + .response-tab { + padding: 8px 15px; + cursor: pointer; + border-bottom: 2px solid transparent; + transition: all 0.2s ease; + font-size: 13px; + } + + .response-tab.active { + border-bottom-color: var(--primary-color); + color: var(--primary-color); + } + + /* 鍝嶅簲鍐呭鍖哄煙 */ + .response-content { + background-color: rgba(0, 0, 0, 0.3); + border-radius: 5px; + padding: 15px; + font-family: 'Courier New', Courier, monospace; + font-size: 14px; + white-space: pre-wrap; + overflow-x: auto; + min-height: 200px; + max-height: 400px; + overflow-y: auto; + } + + .response-content { + display: none; + animation: fadeIn 0.3s ease; + } + + .response-content.active { + display: block; + } + + /* JSON楂樹寒鏍峰紡 */ + .json-key { + color: #48dbfb; + } + + .json-string { + color: #1dd1a1; + } + + .json-number { + color: #feca57; + } + + .json-boolean { + color: #ff6b6b; + } + + .json-null { + color: #a55eea; + } + + /* 鍝嶅簲澶磋〃鏍� */ + .headers-table { + width: 100%; + border-collapse: collapse; + margin-bottom: 20px; + } + + .headers-table th, + .headers-table td { + padding: 8px 10px; + text-align: left; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + font-size: 13px; + } + + .headers-table th { + font-weight: 500; + color: var(--secondary-color); + } + + /* 搴曢儴鐘舵�佹爮 */ + .footer { + height: var(--footer-height); + background-color: rgba(45, 52, 54, 0.9); + display: flex; + align-items: center; + padding: 0 20px; + font-size: 13px; + color: rgba(255, 255, 255, 0.7); + border-top: 1px solid rgba(255, 255, 255, 0.1); + } + + .footer-item { + margin-right: 20px; + display: flex; + align-items: center; + } + + .footer-item i { + margin-right: 5px; + font-size: 14px; + } + + /* 鍔犺浇鍔ㄧ敾 */ + .loader { + display: inline-block; + width: 16px; + height: 16px; + border: 2px solid rgba(255, 255, 255, 0.3); + border-radius: 50%; + border-top-color: var(--secondary-color); + animation: spin 1s ease-in-out infinite; + margin-right: 8px; + } + + @keyframes spin { + to { + transform: rotate(360deg); + } + } + + /* 鍝嶅簲鍥剧墖棰勮 */ + .image-preview { + max-width: 100%; + max-height: 300px; + border-radius: 4px; + margin-top: 10px; + } + + /* 鍝嶅簲HTML棰勮 */ + .html-preview { + width: 100%; + height: 300px; + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 4px; + background-color: white; + } + + /* 鍝嶅簲鍘熷鏁版嵁 */ + .raw-response { + white-space: pre-wrap; + font-family: 'Courier New', Courier, monospace; + font-size: 14px; + } + + /* 宸ュ叿鎻愮ず */ + .tooltip { + position: relative; + display: inline-block; + } + + .tooltip .tooltip-text { + visibility: hidden; + width: 120px; + background-color: rgba(0, 0, 0, 0.8); + color: #fff; + text-align: center; + border-radius: 6px; + padding: 5px; + position: absolute; + z-index: 1; + bottom: 125%; + left: 50%; + margin-left: -60px; + opacity: 0; + transition: opacity 0.3s; + font-size: 12px; + } + + .tooltip:hover .tooltip-text { + visibility: visible; + opacity: 1; + } + + /* 鍝嶅簲cookie琛ㄦ牸 */ + .cookies-table { + width: 100%; + border-collapse: collapse; + margin-bottom: 20px; + } + + .cookies-table th, + .cookies-table td { + padding: 8px 10px; + text-align: left; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + font-size: 13px; + } + + .cookies-table th { + font-weight: 500; + color: var(--secondary-color); + } + + /* 鍝嶅簲娴嬭瘯缁撴灉 */ + .test-results { + margin-top: 20px; + } + + .test-result { + padding: 10px; + margin-bottom: 10px; + border-radius: 4px; + font-size: 13px; + } + + .test-result.pass { + background-color: rgba(29, 209, 161, 0.2); + color: var(--success-color); + border-left: 3px solid var(--success-color); + } + + .test-result.fail { + background-color: rgba(255, 107, 107, 0.2); + color: var(--error-color); + border-left: 3px solid var(--error-color); + } + + .test-result-name { + font-weight: bold; + margin-bottom: 5px; + } + + /* 鏆楄壊婊氬姩鏉� */ + ::-webkit-scrollbar { + width: 8px; + height: 8px; + } + + ::-webkit-scrollbar-track { + background: rgba(255, 255, 255, 0.05); + } + + ::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.2); + border-radius: 4px; + } + + ::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.3); + } + + /* 鍝嶅簲寮忚璁� */ + @media (max-width: 768px) { + .main-container { + flex-direction: column; + } + + .sidebar { + width: 100%; + height: 200px; + } + + .request-controls { + flex-direction: column; + } + + .method-select, + .url-input, + .send-btn { + width: 100%; + margin: 5px 0; + } + + .response-content { + max-height: 300px; + } + } + + /* 鏂板鏍峰紡 */ + .request-loading { + position: relative; + overflow: hidden; + } + + .request-loading::after { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, + transparent, + rgba(72, 219, 251, 0.4), + transparent); + animation: loading 1.5s infinite; + } + + @keyframes loading { + 100% { + left: 100%; + } + } + + .error-message { + display: flex; + align-items: center; + gap: 10px; + color: #ff6b6b; + padding: 15px; + background-color: rgba(255, 107, 107, 0.1); + border-radius: 4px; + } + + .error-message i { + font-size: 24px; + } + + .cm-s-dracula span.cm-string { + color: #f1fa8c; + } + + .cm-s-dracula span.cm-number { + color: #bd93f9; + } + + .cm-s-dracula span.cm-key { + color: #ff79c6; + } + + .cm-s-dracula span.cm-boolean { + color: #bd93f9; + } + + .cm-s-dracula span.cm-null { + color: #bd93f9; + } + </style> +</head> + +<body> + <div class="gradient-bg"></div> + <div class="header"> + <div class="logo"> + <i class="fas fa-bolt"></i> + <span>API娴嬭瘯宸ュ叿</span> + </div> + <div class="header-actions"> + <button id="new-request-btn" class="tooltip"> + <i class="fas fa-plus"></i> + <span class="tooltip-text">鏂板缓璇锋眰</span> + </button> + <button id="save-request-btn" class="tooltip"> + <i class="fas fa-save"></i> + <span class="tooltip-text">淇濆瓨璇锋眰</span> + </button> + <button id="import-request-btn" class="tooltip"> + <i class="fas fa-file-import"></i> + <span class="tooltip-text">瀵煎叆璇锋眰</span> + </button> + <button id="export-request-btn" class="tooltip"> + <i class="fas fa-file-export"></i> + <span class="tooltip-text">瀵煎嚭璇锋眰</span> + </button> + <button id="settings-btn" class="tooltip"> + <i class="fas fa-cog"></i> + <span class="tooltip-text">璁剧疆</span> + </button> + </div> + </div> + + <div class="main-container"> + <!-- 渚ц竟鏍� - 璇锋眰鍘嗗彶 --> + <div class="sidebar"> + <div class="sidebar-header"> + <div class="sidebar-title">璇锋眰鍘嗗彶</div> + <button id="clear-history-btn" class="tooltip"> + <i class="fas fa-trash"></i> + <span class="tooltip-text">娓呯┖鍘嗗彶</span> + </button> + </div> + <div class="sidebar-content" id="history-list"> + <!-- 鍘嗗彶璇锋眰灏嗗湪杩欓噷鍔ㄦ�佺敓鎴� --> + </div> + </div> + + <!-- 涓诲伐浣滃尯 --> + <div class="workspace"> + <!-- 璇锋眰闈㈡澘 --> + <div class="request-panel"> + <div class="request-controls"> + <select class="method-select" id="method-select"> + <option value="GET">GET</option> + <option value="POST">POST</option> + <option value="PUT">PUT</option> + <option value="DELETE">DELETE</option> + <option value="PATCH">PATCH</option> + <option value="HEAD">HEAD</option> + <option value="OPTIONS">OPTIONS</option> + </select> + <input type="text" class="url-input" id="url-input" + placeholder="杈撳叆璇锋眰URL (渚嬪: https://api.example.com/data)"> + <button class="send-btn" id="send-btn"> + <i class="fas fa-paper-plane"></i> + <span>鍙戦��</span> + </button> + </div> + + <!-- 璇锋眰鍙傛暟鏍囩椤� --> + <div class="tabs"> + <div class="tab active" data-tab="params">鍙傛暟</div> + <div class="tab" data-tab="headers">璇锋眰澶�</div> + <div class="tab" data-tab="body">璇锋眰浣�</div> + <div class="tab" data-tab="auth">璁よ瘉</div> + <div class="tab" data-tab="tests">娴嬭瘯</div> + </div> + + <!-- 鍙傛暟鏍囩鍐呭 --> + <div class="tab-content active" id="params-tab"> + <table class="params-table" id="params-table"> + <thead> + <tr> + <th>鍙傛暟鍚�</th> + <th>鍊�</th> + <th>鎻忚堪</th> + <th>鎿嶄綔</th> + </tr> + </thead> + <tbody> + <tr> + <td><input type="text" placeholder="鍙傛暟鍚�"></td> + <td><input type="text" placeholder="鍊�"></td> + <td><input type="text" placeholder="鎻忚堪"></td> + <td class="params-actions"> + <button class="param-action-btn delete"><i class="fas fa-trash"></i></button> + </td> + </tr> + </tbody> + </table> + <button class="add-param-btn" id="add-param-btn"> + <i class="fas fa-plus"></i> + <span>娣诲姞鍙傛暟</span> + </button> + </div> + + <!-- 璇锋眰澶存爣绛惧唴瀹� --> + <div class="tab-content" id="headers-tab"> + <table class="params-table" id="headers-table"> + <thead> + <tr> + <th>璇锋眰澶村悕</th> + <th>鍊�</th> + <th>鎻忚堪</th> + <th>鎿嶄綔</th> + </tr> + </thead> + <tbody> + <tr> + <td><input type="text" placeholder="渚嬪: Content-Type"></td> + <td><input type="text" placeholder="渚嬪: application/json"></td> + <td><input type="text" placeholder="鎻忚堪"></td> + <td class="params-actions"> + <button class="param-action-btn delete"><i class="fas fa-trash"></i></button> + </td> + </tr> + </tbody> + </table> + <button class="add-param-btn" id="add-header-btn"> + <i class="fas fa-plus"></i> + <span>娣诲姞璇锋眰澶�</span> + </button> + </div> + + <!-- 璇锋眰浣撴爣绛惧唴瀹� --> + <div class="tab-content" id="body-tab"> + <div class="body-type-selector"> + <div class="button-group"> + <label class="type-button"> + <input type="radio" name="body-type" value="none" checked> + <span>鏃�</span> + </label> + <label class="type-button"> + <input type="radio" name="body-type" value="form-data"> + <span>琛ㄥ崟鏁版嵁</span> + </label> + <label class="type-button"> + <input type="radio" name="body-type" value="x-www-form-urlencoded"> + <span>x-www-form-urlencoded</span> + </label> + <label class="type-button"> + <input type="radio" name="body-type" value="raw"> + <span>鍘熷鏁版嵁</span> + </label> + <label class="type-button"> + <input type="radio" name="body-type" value="binary"> + <span>浜岃繘鍒�</span> + </label> + </div> + </div> + + <!-- 琛ㄥ崟鏁版嵁 --> + <div class="body-content" id="form-data-content"> + <table class="params-table"> + <thead> + <tr> + <th>閿�</th> + <th>鍊�</th> + <th>鎻忚堪</th> + <th>鎿嶄綔</th> + </tr> + </thead> + <tbody> + <tr> + <td><input type="text" placeholder="閿�"></td> + <td><input type="text" placeholder="鍊�"></td> + <td><input type="text" placeholder="鎻忚堪"></td> + <td class="params-actions"> + <button class="param-action-btn delete"><i class="fas fa-trash"></i></button> + </td> + </tr> + </tbody> + </table> + <button class="add-param-btn"> + <i class="fas fa-plus"></i> + <span>娣诲姞琛ㄥ崟鏁版嵁</span> + </button> + </div> + + <!-- 鍘熷鏁版嵁 --> + <div class="body-content" id="raw-content"> + <textarea class="body-editor" id="body-editor" placeholder='渚嬪: {"key": "value"}'></textarea> + </div> + </div> + + <!-- 璁よ瘉鏍囩鍐呭 --> + <div class="tab-content" id="auth-tab"> + <select class="method-select" id="auth-type"> + <option value="none">鏃犺璇�</option> + <option value="basic">Basic Auth</option> + <option value="bearer">Bearer Token</option> + <option value="api-key">API Key</option> + <option value="oauth2">OAuth 2.0</option> + </select> + + <div id="auth-fields"> + <!-- 璁よ瘉瀛楁灏嗘牴鎹�夋嫨鐨勮璇佺被鍨嬪姩鎬佺敓鎴� --> + </div> + </div> + + <!-- 娴嬭瘯鏍囩鍐呭 --> + <div class="tab-content" id="tests-tab"> + <textarea class="body-editor" id="tests-editor" placeholder="// 缂栧啓JavaScript娴嬭瘯鑴氭湰 + // 渚嬪: pm.test('鐘舵�佺爜鏄�200', function() { + // pm.response.to.have.status(200); + // });"></textarea> + </div> + </div> + + <!-- 鍝嶅簲闈㈡澘 --> + <div class="response-panel" id="response-panel"> + <div class="response-header"> + <div class="status-code" id="status-code">绛夊緟璇锋眰...</div> + <div class="response-time" id="response-time"></div> + <div class="response-size" id="response-size"></div> + </div> + + <div class="response-tabs"> + <div class="response-tab active" data-response-tab="body">鍝嶅簲浣�</div> + <div class="response-tab" data-response-tab="headers">鍝嶅簲澶�</div> + <div class="response-tab" data-response-tab="cookies">Cookies</div> + <div class="response-tab" data-response-tab="tests">娴嬭瘯缁撴灉</div> + </div> + + <div class="response-content active" id="response-body"> + <pre id="response-body-content">鍙戦�佽姹備互鏌ョ湅鍝嶅簲</pre> + </div> + + <div class="response-content" id="response-headers"> + <table class="headers-table" id="headers-table"> + <thead> + <tr> + <th>鍚嶇О</th> + <th>鍊�</th> + </tr> + </thead> + <tbody> + <!-- 鍝嶅簲澶村皢鍦ㄨ繖閲屽姩鎬佺敓鎴� --> + </tbody> + </table> + </div> + + <div class="response-content" id="response-cookies"> + <table class="cookies-table" id="cookies-table"> + <thead> + <tr> + <th>鍚嶇О</th> + <th>鍊�</th> + <th>鍩�</th> + <th>璺緞</th> + <th>杩囨湡鏃堕棿</th> + </tr> + </thead> + <tbody> + <!-- Cookies灏嗗湪杩欓噷鍔ㄦ�佺敓鎴� --> + </tbody> + </table> + </div> + + <div class="response-content" id="response-tests"> + <div class="test-results" id="test-results"> + <!-- 娴嬭瘯缁撴灉灏嗗湪杩欓噷鍔ㄦ�佺敓鎴� --> + </div> + </div> + </div> + </div> + </div> + + <!-- 搴曢儴鐘舵�佹爮 --> + <div class="footer"> + <div class="footer-item"> + <i class="fas fa-circle"></i> + <span id="connection-status">宸茶繛鎺�</span> + </div> + <div class="footer-item"> + <i class="fas fa-code-branch"></i> + <span>v1.0.0</span> + </div> + <div class="footer-item"> + <i class="fas fa-info-circle"></i> + <span>API娴嬭瘯宸ュ叿</span> + </div> + </div> + + <!-- JavaScript 瀹炵幇 --> + <script> + // JavaScript 瀹炵幇 + document.addEventListener('DOMContentLoaded', function () { + // 鍏ㄥ眬鐘舵�佺鐞� + const state = { + currentRequest: { + method: 'GET', + url: '', + params: [], + headers: [ + { key: 'Content-Type', value: 'application/json', enabled: true } + ], + body: '{}', + auth: { type: 'none', basic: { username: '', password: '' }, bearer: { token: '' } }, + tests: '' + }, + requestHistory: JSON.parse(localStorage.getItem('requestHistory')) || [], + isRequestInProgress: false, + activeResponseTab: 'body', + activeRequestTab: 'params' + }; + + // DOM鍏冪礌缂撳瓨 + const elements = { + methodSelect: document.getElementById('method-select'), + urlInput: document.getElementById('url-input'), + sendBtn: document.getElementById('send-btn'), + saveBtn: document.getElementById('save-request-btn'), + historyList: document.getElementById('history-list'), + clearHistoryBtn: document.getElementById('clear-history-btn'), + statusCode: document.getElementById('status-code'), + responseTime: document.getElementById('response-time'), + responseSize: document.getElementById('response-size'), + responseBodyContent: document.getElementById('response-body-content'), + headersTableBody: document.querySelector('#headers-table tbody'), + cookiesTableBody: document.querySelector('#cookies-table tbody'), + testResults: document.getElementById('test-results'), + paramsTableBody: document.querySelector('#params-table tbody'), + headersTableBodyReq: document.querySelector('#headers-table tbody'), + bodyEditor: document.getElementById('body-editor'), + authTypeSelect: document.getElementById('auth-type'), + authBasicSection: document.getElementById('auth-basic'), + authBearerSection: document.getElementById('auth-bearer'), + testsEditor: document.getElementById('tests-editor') + }; + + // 鍒濆鍖栧簲鐢� + init(); + + function init() { + renderRequestHistory(); + setupUIEventListeners(); + setupRequestTabs(); + setupResponseTabs(); + loadDefaultRequest(); + setupBodyEditor(); + setupTestsEditor(); + } + + // 1. 璇锋眰鍙戦�佸姛鑳� + async function sendRequest() { + if (state.isRequestInProgress) return; + + try { + state.isRequestInProgress = true; + updateUIForRequestStart(); + + // 鍑嗗璇锋眰鏁版嵁 + const { url, method, headers, body } = prepareRequestData(); + + // 鍙戦�佽姹� + const startTime = performance.now(); + const response = await fetch(url, { + method, + headers: prepareRequestHeaders(headers), + body: method !== 'GET' ? body : null + }); + const duration = (performance.now() - startTime).toFixed(2); + + // 澶勭悊鍝嶅簲 + await processResponse(response, duration); + + // 淇濆瓨鍒板巻鍙茶褰� + saveToHistory(); + + } catch (error) { + handleRequestError(error); + } finally { + state.isRequestInProgress = false; + updateUIForRequestEnd(); + } + } + + function prepareRequestData() { + // 鏀堕泦褰撳墠璇锋眰鐨勬墍鏈夋暟鎹� + const method = elements.methodSelect.value; + let url = elements.urlInput.value.trim(); + + // 澶勭悊鏌ヨ鍙傛暟 + const params = collectParams(); + if (params.length > 0) { + const urlObj = new URL(url); + params.forEach(param => { + if (param.key && param.enabled) { + urlObj.searchParams.append(param.key, param.value); + } + }); + url = urlObj.toString(); + } + + // 澶勭悊璇锋眰澶� + const headers = collectHeaders(); + + // 澶勭悊璁よ瘉 + handleAuthentication(headers); + + // 澶勭悊璇锋眰浣� + const body = getRequestBody(); + + // 鏇存柊褰撳墠璇锋眰鐘舵�� + state.currentRequest = { + ...state.currentRequest, + method, + url, + params, + headers, + body + }; + + return { url, method, headers, body }; + } + + function prepareRequestHeaders(headers) { + const headerObj = {}; + headers + .filter(h => h.enabled && h.key) + .forEach(h => { + headerObj[h.key] = h.value; + }); + return headerObj; + } + + function handleAuthentication(headers) { + const authType = elements.authTypeSelect.value; + + if (authType === 'basic') { + const username = document.getElementById('basic-username').value; + const password = document.getElementById('basic-password').value; + if (username && password) { + const token = btoa(`${username}:${password}`); + headers.push({ + key: 'Authorization', + value: `Basic ${token}`, + enabled: true + }); + } + } + else if (authType === 'bearer') { + const token = document.getElementById('bearer-token').value; + if (token) { + headers.push({ + key: 'Authorization', + value: `Bearer ${token}`, + enabled: true + }); + } + } + } + + // 2. 鍙傛暟绠$悊鍔熻兘 + function collectParams() { + const params = []; + const rows = elements.paramsTableBody.querySelectorAll('tr'); + + rows.forEach(row => { + const key = row.querySelector('.param-key').value.trim(); + const value = row.querySelector('.param-value').value.trim(); + const enabled = row.querySelector('.param-enabled').checked; + + if (key) { + params.push({ key, value, enabled }); + } + }); + + return params; + } + + function collectHeaders() { + const headers = []; + const rows = elements.headersTableBodyReq.querySelectorAll('tr'); + + rows.forEach(row => { + const key = row.querySelector('.header-key').value.trim(); + const value = row.querySelector('.header-value').value.trim(); + const enabled = row.querySelector('.header-enabled').checked; + + if (key) { + headers.push({ key, value, enabled }); + } + }); + + return headers; + } + + function getRequestBody() { + const bodyType = document.querySelector('.body-type-selector input:checked').value; + + switch (bodyType) { + case 'json': + return elements.bodyEditor.value; + case 'form-data': + return prepareFormData(); + case 'x-www-form-urlencoded': + return prepareUrlEncodedData(); + default: + return ''; + } + } + + function prepareFormData() { + const formData = new FormData(); + document.querySelectorAll('#form-data-table tbody tr').forEach(row => { + const key = row.querySelector('.form-data-key').value; + const value = row.querySelector('.form-data-value').value; + const type = row.querySelector('.form-data-type').value; + + if (key) { + if (type === 'file') { + const file = row.querySelector('.form-data-file').files[0]; + if (file) formData.append(key, file); + } else { + formData.append(key, value); + } + } + }); + return formData; + } + + function prepareUrlEncodedData() { + const params = new URLSearchParams(); + document.querySelectorAll('#urlencoded-table tbody tr').forEach(row => { + const key = row.querySelector('.urlencoded-key').value; + const value = row.querySelector('.urlencoded-value').value; + if (key) params.append(key, value); + }); + return params.toString(); + } + + // 3. 鍝嶅簲澶勭悊鍔熻兘 + async function processResponse(response, duration) { + // 鏇存柊鍝嶅簲鐘舵�� + updateResponseStatus(response, duration); + + // 澶勭悊鍝嶅簲鏁版嵁 + const contentType = response.headers.get('content-type') || ''; + let responseData; + + if (contentType.includes('application/json')) { + responseData = await response.json(); + displayJsonResponse(responseData); + } + else if (contentType.includes('text/')) { + responseData = await response.text(); + displayTextResponse(responseData); + } + else if (contentType.includes('image/')) { + responseData = await response.blob(); + displayImageResponse(responseData); + } + else { + responseData = await response.text(); + displayRawResponse(responseData); + } + + // 鏄剧ず鍝嶅簲澶� + displayResponseHeaders(response.headers); + + // 鏄剧ずCookies + displayResponseCookies(response.headers); + + // 璁$畻骞舵樉绀哄搷搴斿ぇ灏� + displayResponseSize(response, responseData); + + // 杩愯娴嬭瘯 + runTests(response, responseData); + } + + function updateResponseStatus(response, duration) { + elements.statusCode.className = response.ok ? 'status-code success' : 'status-code error'; + elements.statusCode.textContent = `${response.status} ${response.statusText}`; + elements.responseTime.textContent = `${duration}ms`; + } + + function displayJsonResponse(data) { + elements.responseBodyContent.innerHTML = syntaxHighlight(JSON.stringify(data, null, 2)); + } + + function displayTextResponse(text) { + elements.responseBodyContent.textContent = text; + } + + function displayImageResponse(blob) { + const url = URL.createObjectURL(blob); + elements.responseBodyContent.innerHTML = `<img src="${url}" style="max-width: 100%;">`; + } + + function displayRawResponse(data) { + elements.responseBodyContent.textContent = data; + } + + // 4. 鍝嶅簲澶存樉绀哄姛鑳� + function displayResponseHeaders(headers) { + elements.headersTableBody.innerHTML = ''; + + headers.forEach((value, key) => { + const row = document.createElement('tr'); + row.innerHTML = ` + <td>${key}</td> + <td>${value}</td> + `; + elements.headersTableBody.appendChild(row); + }); + } + + // 5. Cookie鏄剧ず鍔熻兘 + function displayResponseCookies(headers) { + elements.cookiesTableBody.innerHTML = ''; + + const cookieHeader = headers.get('set-cookie'); + if (!cookieHeader) return; + + // 瑙f瀽澶氫釜Set-Cookie澶� + const cookies = Array.isArray(cookieHeader) ? cookieHeader : [cookieHeader]; + + cookies.forEach(cookie => { + const parts = cookie.split(';')[0].split('='); + const key = parts[0]; + const value = parts.slice(1).join('='); + + const row = document.createElement('tr'); + row.innerHTML = ` + <td>${key}</td> + <td>${value}</td> + `; + elements.cookiesTableBody.appendChild(row); + }); + } + + // 6. 鍝嶅簲澶у皬璁$畻 + function displayResponseSize(response, responseData) { + let size = '0 B'; + + // 浠嶤ontent-Length澶磋幏鍙栧ぇ灏� + const contentLength = response.headers.get('content-length'); + if (contentLength) { + size = formatBytes(parseInt(contentLength)); + } + // 濡傛灉娌℃湁Content-Length锛岃绠楀疄闄呮暟鎹ぇ灏� + else if (responseData) { + if (typeof responseData === 'string') { + size = formatBytes(new Blob([responseData]).size); + } else if (responseData instanceof Blob) { + size = formatBytes(responseData.size); + } else { + const jsonStr = JSON.stringify(responseData); + size = formatBytes(new Blob([jsonStr]).size); + } + } + + elements.responseSize.textContent = size; + } + + function formatBytes(bytes) { + if (bytes === 0) return '0 B'; + + const k = 1024; + const sizes = ['B', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + } + + // 7. 娴嬭瘯鑴氭湰鎵ц + function runTests(response, responseData) { + const tests = elements.testsEditor.getValue(); + if (!tests.trim()) return; + + try { + // 鍒涘缓娴嬭瘯鐜 + const testEnv = { + status: response.status, + statusText: response.statusText, + headers: Object.fromEntries(response.headers), + response: responseData, + tests: [], + assertions: 0, + failures: 0 + }; + + // 娣诲姞娴嬭瘯宸ュ叿鍑芥暟 + testEnv.expect = function (value) { + this.assertions++; + return { + to: { + be: expected => { + if (value !== expected) { + this.failures++; + this.tests.push({ + passed: false, + message: `Expected ${value} to be ${expected}` + }); + } else { + this.tests.push({ + passed: true, + message: `Expected ${value} to be ${expected}` + }); + } + }, + contain: expected => { + if (!value.includes(expected)) { + this.failures++; + this.tests.push({ + passed: false, + message: `Expected ${value} to contain ${expected}` + }); + } else { + this.tests.push({ + passed: true, + message: `Expected ${value} to contain ${expected}` + }); + } + } + } + }; + }; + + // 鎵ц娴嬭瘯浠g爜 + new Function('pm', tests)(testEnv); + + // 鏄剧ず娴嬭瘯缁撴灉 + displayTestResults(testEnv); + + } catch (error) { + elements.testResults.innerHTML = ` + <div class="test-error"> + <i class="fas fa-exclamation-circle"></i> + Test script error: ${error.message} + </div> + `; + } + } + + function displayTestResults(testEnv) { + let html = ` + <div class="test-summary"> + Tests: ${testEnv.tests.length}, + Passed: ${testEnv.tests.length - testEnv.failures}, + Failed: ${testEnv.failures} + </div> + `; + + testEnv.tests.forEach(test => { + html += ` + <div class="test-result ${test.passed ? 'passed' : 'failed'}"> + <i class="fas ${test.passed ? 'fa-check-circle' : 'fa-times-circle'}"></i> + ${test.message} + </div> + `; + }); + + elements.testResults.innerHTML = html; + } + + // 8. 璇锋眰鍘嗗彶绠$悊 + function saveToHistory() { + // 妫�鏌ユ槸鍚﹀凡瀛樺湪鐩稿悓璇锋眰 + const existingIndex = state.requestHistory.findIndex( + req => req.method === state.currentRequest.method && + req.url === state.currentRequest.url + ); + + if (existingIndex >= 0) { + // 鏇存柊鐜版湁璁板綍 + state.requestHistory[existingIndex] = { ...state.currentRequest }; + } else { + // 娣诲姞鍒板巻鍙茶褰� + state.requestHistory.unshift({ ...state.currentRequest }); + + // 闄愬埗鍘嗗彶璁板綍鏁伴噺 + if (state.requestHistory.length > 50) { + state.requestHistory.pop(); + } + } + + // 淇濆瓨鍒版湰鍦板瓨鍌� + localStorage.setItem('requestHistory', JSON.stringify(state.requestHistory)); + + // 閲嶆柊娓叉煋鍘嗗彶鍒楄〃 + renderRequestHistory(); + } + + function renderRequestHistory() { + elements.historyList.innerHTML = ''; + + state.requestHistory.forEach((request, index) => { + const item = document.createElement('div'); + item.className = 'history-item'; + item.innerHTML = ` + <span class="method ${request.method.toLowerCase()}">${request.method}</span> + <span class="url">${request.url}</span> + <button class="load-btn" data-index="${index}"> + <i class="fas fa-upload"></i> + </button> + <button class="delete-btn" data-index="${index}"> + <i class="fas fa-trash"></i> + </button> + `; + + elements.historyList.appendChild(item); + }); + + // 娣诲姞鍘嗗彶椤逛簨浠剁洃鍚� + document.querySelectorAll('.history-item .load-btn').forEach(btn => { + btn.addEventListener('click', () => loadFromHistory(parseInt(btn.dataset.index))); + }); + + document.querySelectorAll('.history-item .delete-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + e.stopPropagation(); + deleteFromHistory(parseInt(btn.dataset.index)); + }); + }); + } + + function loadFromHistory(index) { + const request = state.requestHistory[index]; + if (!request) return; + + // 鏇存柊UI + elements.methodSelect.value = request.method; + elements.urlInput.value = request.url; + + // 鍔犺浇鍙傛暟 + renderParamsTable(request.params); + + // 鍔犺浇璇锋眰澶� + renderHeadersTable(request.headers); + + // 鍔犺浇璇锋眰浣� + elements.bodyEditor.setValue(request.body || ''); + + // 鏇存柊褰撳墠璇锋眰鐘舵�� + state.currentRequest = { ...request }; + } + + function deleteFromHistory(index) { + state.requestHistory.splice(index, 1); + localStorage.setItem('requestHistory', JSON.stringify(state.requestHistory)); + renderRequestHistory(); + } + + // 9. UI浜や簰鍔熻兘 + function setupUIEventListeners() { + // 鍙戦�佽姹傛寜閽� + elements.sendBtn.addEventListener('click', sendRequest); + + // 淇濆瓨璇锋眰鎸夐挳 + elements.saveBtn.addEventListener('click', saveToHistory); + + // 娓呯┖鍘嗗彶鎸夐挳 + elements.clearHistoryBtn.addEventListener('click', () => { + state.requestHistory = []; + localStorage.removeItem('requestHistory'); + renderRequestHistory(); + }); + + // 璁よ瘉绫诲瀷鍒囨崲 + elements.authTypeSelect.addEventListener('change', () => { + updateAuthUI(); + }); + + // 璇锋眰浣撶被鍨嬪垏鎹� + document.querySelectorAll('.body-type-selector input').forEach(radio => { + radio.addEventListener('change', () => { + updateBodyTypeUI(); + }); + }); + } + + function updateAuthUI() { + const authType = elements.authTypeSelect.value; + + // 闅愯棌鎵�鏈夎璇侀儴鍒� + elements.authBasicSection.style.display = 'none'; + elements.authBearerSection.style.display = 'none'; + + // 鏄剧ず閫変腑鐨勮璇侀儴鍒� + if (authType === 'basic') { + elements.authBasicSection.style.display = 'block'; + } else if (authType === 'bearer') { + elements.authBearerSection.style.display = 'block'; + } + } + + function updateBodyTypeUI() { + const bodyType = document.querySelector('.body-type-selector input:checked').value; + + // 闅愯棌鎵�鏈塨ody缂栬緫鍣� + document.querySelectorAll('.body-editor-container').forEach(el => { + el.style.display = 'none'; + }); + + // 鏄剧ず閫変腑鐨刡ody缂栬緫鍣� + const activeEditor = document.getElementById(`${bodyType}-editor`); + if (activeEditor) { + activeEditor.style.display = 'block'; + + // 濡傛灉鏄疛SON缂栬緫鍣紝閲嶆柊鏍煎紡鍖栧唴瀹� + if (bodyType === 'json') { + try { + const json = JSON.parse(elements.bodyEditor.getValue()); + elements.bodyEditor.setValue(JSON.stringify(json, null, 2)); + } catch (e) { + // 涓嶆槸鏈夋晥鐨凧SON锛屼繚鎸佸師鏍� + } + } + } + } + + // 10. 琛ㄦ牸琛屾搷浣滃姛鑳� + function setupTableRowOperations() { + // 鍙傛暟琛ㄦ牸鎿嶄綔 + setupDynamicTable('#params-table', 'params', { + keyClass: 'param-key', + valueClass: 'param-value', + enabledClass: 'param-enabled' + }); + + // 璇锋眰澶磋〃鏍兼搷浣� + setupDynamicTable('#headers-table', 'headers', { + keyClass: 'header-key', + valueClass: 'header-value', + enabledClass: 'header-enabled' + }); + + // FormData琛ㄦ牸鎿嶄綔 + setupDynamicTable('#form-data-table', 'form-data', { + keyClass: 'form-data-key', + valueClass: 'form-data-value', + typeClass: 'form-data-type' + }); + + // URL缂栫爜琛ㄦ牸鎿嶄綔 + setupDynamicTable('#urlencoded-table', 'urlencoded', { + keyClass: 'urlencoded-key', + valueClass: 'urlencoded-value' + }); + } + + function setupDynamicTable(tableId, type, classes) { + const table = document.querySelector(tableId); + const tbody = table.querySelector('tbody'); + const addBtn = table.querySelector('.add-row-btn'); + + // 娣诲姞琛� + addBtn.addEventListener('click', () => { + addTableRow(tbody, type, classes); + }); + + // 鍒濆鍖栬 + if (tbody.children.length === 0) { + addTableRow(tbody, type, classes); + } + + // 琛屽唴鍒犻櫎鎸夐挳 + tbody.addEventListener('click', (e) => { + if (e.target.classList.contains('delete-row-btn')) { + const row = e.target.closest('tr'); + if (row && tbody.children.length > 1) { + row.remove(); + } + } + }); + } + + function addTableRow(tbody, type, classes) { + const row = document.createElement('tr'); + + let rowHtml = ` + <td> + <input type="text" class="${classes.keyClass}" placeholder="Key"> + </td> + <td> + <input type="text" class="${classes.valueClass}" placeholder="Value"> + </td> + `; + + // 娣诲姞鍚敤/绂佺敤寮�鍏� + if (classes.enabledClass) { + rowHtml += ` + <td> + <label class="switch"> + <input type="checkbox" class="${classes.enabledClass}" checked> + <span class="slider"></span> + </label> + </td> + `; + } + + // 娣诲姞绫诲瀷閫夋嫨鍣� (鐢ㄤ簬FormData) + if (classes.typeClass) { + rowHtml += ` + <td> + <select class="${classes.typeClass}"> + <option value="text">Text</option> + <option value="file">File</option> + </select> + </td> + `; + } + + // 娣诲姞鍒犻櫎鎸夐挳 + rowHtml += ` + <td> + <button class="delete-row-btn"> + <i class="fas fa-trash"></i> + </button> + </td> + `; + + row.innerHTML = rowHtml; + tbody.appendChild(row); + + // 澶勭悊鏂囦欢閫夋嫨鍣ㄧ殑鏄剧ず/闅愯棌 + if (classes.typeClass) { + const typeSelect = row.querySelector(`.${classes.typeClass}`); + const valueInput = row.querySelector(`.${classes.valueClass}`); + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.className = 'form-data-file'; + fileInput.style.display = 'none'; + + valueInput.parentNode.insertBefore(fileInput, valueInput.nextSibling); + + typeSelect.addEventListener('change', () => { + if (typeSelect.value === 'file') { + valueInput.style.display = 'none'; + fileInput.style.display = 'block'; + } else { + valueInput.style.display = 'block'; + fileInput.style.display = 'none'; + } + }); + } + } + + // 11. 璇锋眰鍜屽搷搴旀爣绛鹃〉鍒囨崲 + function setupRequestTabs() { + const tabs = document.querySelectorAll('.tab'); + tabs.forEach(tab => { + tab.addEventListener('click', () => { + tabs.forEach(t => t.classList.remove('active')); + tab.classList.add('active'); + + const tabId = tab.getAttribute('data-tab'); + document.querySelectorAll('.tab-content').forEach(content => { + content.classList.remove('active'); + }); + document.getElementById(`${tabId}-tab`).classList.add('active'); + + // 濡傛灉鏄疊ody鏍囩锛屽埛鏂扮紪杈戝櫒 + if (tabId === 'body') { + setTimeout(() => { + elements.bodyEditor.refresh(); + }, 0); + } + }); + }); + } + + function setupResponseTabs() { + const responseTabs = document.querySelectorAll('.response-tab'); + responseTabs.forEach(tab => { + tab.addEventListener('click', () => { + responseTabs.forEach(t => t.classList.remove('active')); + tab.classList.add('active'); + + const tabId = tab.getAttribute('data-response-tab'); + document.querySelectorAll('#response-panel .response-content').forEach(content => { + content.classList.remove('active'); + }); + document.getElementById(`response-${tabId}`).classList.add('active'); + }); + }); + } + + // 12. 缂栬緫鍣ㄥ垵濮嬪寲 + function setupBodyEditor() { + var a = document.getElementById('body-editor'); + elements.bodyEditor = CodeMirror.fromTextArea( + document.getElementById('body-editor'), + { + mode: 'application/json', + lineNumbers: true, + lineWrapping: true, + indentUnit: 2, + tabSize: 2, + theme: 'dracula', + autoCloseBrackets: true, + matchBrackets: true, + extraKeys: { + 'Ctrl-Enter': sendRequest, + 'Cmd-Enter': sendRequest + } + } + ); + + // 鍒濆鍐呭 + elements.bodyEditor.setValue('{\n \n}'); + } + + function setupTestsEditor() { + elements.testsEditor = CodeMirror.fromTextArea( + document.getElementById('tests-editor'), + { + mode: 'javascript', + lineNumbers: true, + lineWrapping: true, + indentUnit: 2, + tabSize: 2, + theme: 'dracula', + autoCloseBrackets: true, + matchBrackets: true + } + ); + + // 鍒濆鍐呭 + elements.testsEditor.setValue('// 浣跨敤pm瀵硅薄缂栧啓娴嬭瘯\n// 绀轰緥:\npm.expect(pm.response.status).to.be(200);'); + } + + // 13. 鍔犺浇榛樿璇锋眰 + function loadDefaultRequest() { + // 璁剧疆榛樿鏂规硶 + elements.methodSelect.value = 'GET'; + + // 璁剧疆榛樿URL + elements.urlInput.value = ''; + + // 娣诲姞绀轰緥璇锋眰澶� + renderHeadersTable([ + + ]); + + // 娣诲姞绀轰緥鍙傛暟 + renderParamsTable([ + + ]); + } + + function renderHeadersTable(headers) { + const tbody = elements.headersTableBodyReq; + tbody.innerHTML = ''; + + headers.forEach(header => { + addTableRow(tbody, 'headers', { + keyClass: 'header-key', + valueClass: 'header-value', + enabledClass: 'header-enabled' + }); + + const lastRow = tbody.lastChild; + lastRow.querySelector('.header-key').value = header.key; + lastRow.querySelector('.header-value').value = header.value; + lastRow.querySelector('.header-enabled').checked = header.enabled; + }); + } + + function renderParamsTable(params) { + const tbody = elements.paramsTableBody; + tbody.innerHTML = ''; + + params.forEach(param => { + addTableRow(tbody, 'params', { + keyClass: 'param-key', + valueClass: 'param-value', + enabledClass: 'param-enabled' + }); + + const lastRow = tbody.lastChild; + lastRow.querySelector('.param-key').value = param.key; + lastRow.querySelector('.param-value').value = param.value; + lastRow.querySelector('.param-enabled').checked = param.enabled; + }); + + // 纭繚鑷冲皯鏈変竴琛� + if (tbody.children.length === 0) { + addTableRow(tbody, 'params', { + keyClass: 'param-key', + valueClass: 'param-value', + enabledClass: 'param-enabled' + }); + } + } + + // 14. 璇锋眰鐘舵�佺鐞� + function updateUIForRequestStart() { + // 绂佺敤鍙戦�佹寜閽� + elements.sendBtn.disabled = true; + elements.sendBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 璇锋眰涓�...'; + + // 娣诲姞鍔犺浇鍔ㄧ敾 + document.querySelector('.request-panel').classList.add('request-loading'); + + // 娓呯┖涔嬪墠鐨勫搷搴� + elements.responseBodyContent.innerHTML = ''; + elements.headersTableBody.innerHTML = ''; + elements.cookiesTableBody.innerHTML = ''; + elements.testResults.innerHTML = ''; + elements.statusCode.textContent = '--'; + elements.responseTime.textContent = '--'; + elements.responseSize.textContent = '--'; + } + + function updateUIForRequestEnd() { + // 鎭㈠鍙戦�佹寜閽� + elements.sendBtn.disabled = false; + elements.sendBtn.innerHTML = '<i class="fas fa-paper-plane"></i> 鍙戦��'; + + // 绉婚櫎鍔犺浇鍔ㄧ敾 + document.querySelector('.request-panel').classList.remove('request-loading'); + } + + // 15. 閿欒澶勭悊 + function handleRequestError(error) { + console.error('璇锋眰澶辫触:', error); + + // 鏇存柊UI鏄剧ず閿欒 + elements.statusCode.className = 'status-code error'; + elements.statusCode.textContent = 'Error'; + elements.responseTime.textContent = '--'; + elements.responseSize.textContent = '--'; + + // 鏄剧ず閿欒淇℃伅 + elements.responseBodyContent.innerHTML = ` + <div class="error-message"> + <i class="fas fa-exclamation-triangle"></i> + <div> + <h4>璇锋眰澶辫触</h4> + <p>${error.message || '鏈煡閿欒'}</p> + </div> + </div> + `; + + // 鏄剧ず鍦ㄦ祴璇曠粨鏋滃尯鍩� + elements.testResults.innerHTML = ` + <div class="test-error"> + <i class="fas fa-exclamation-circle"></i> + Request failed: ${error.message} + </div> + `; + } + + // 16. 杈呭姪鍑芥暟 + function syntaxHighlight(json) { + if (typeof json !== 'string') { + json = JSON.stringify(json, null, 2); + } + + json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); + + return json.replace( + /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, + function (match) { + let cls = 'number'; + if (/^"/.test(match)) { + if (/:$/.test(match)) { + cls = 'key'; + } else { + cls = 'string'; + } + } else if (/true|false/.test(match)) { + cls = 'boolean'; + } else if (/null/.test(match)) { + cls = 'null'; + } + return '<span class="' + cls + '">' + match + '</span>'; + } + ); + } + + // 17. 蹇嵎閿敮鎸� + function setupKeyboardShortcuts() { + // Ctrl+Enter 鍙戦�佽姹� + document.addEventListener('keydown', (e) => { + if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { + e.preventDefault(); + sendRequest(); + } + }); + + // URL杈撳叆妗嗗洖杞﹀彂閫佽姹� + elements.urlInput.addEventListener('keydown', (e) => { + if (e.key === 'Enter') { + sendRequest(); + } + }); + } + + // 18. 鍒濆鍖栧畬鎴� + console.log('HTTP璇锋眰宸ュ叿宸插垵濮嬪寲'); + }); + + </script> + + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/javascript/javascript.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/xml/xml.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/edit/matchbrackets.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/edit/closebrackets.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/selection/active-line.min.js"></script> + +</body> + +</html> \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/anime.min.js" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/anime.min.js" new file mode 100644 index 0000000..c399324 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/anime.min.js" @@ -0,0 +1,33 @@ +/* + 2017 Julian Garnier + Released under the MIT license +*/ +var $jscomp={scope:{}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(e,r,p){if(p.get||p.set)throw new TypeError("ES3 does not support getters and setters.");e!=Array.prototype&&e!=Object.prototype&&(e[r]=p.value)};$jscomp.getGlobal=function(e){return"undefined"!=typeof window&&window===e?e:"undefined"!=typeof global&&null!=global?global:e};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_"; +$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(e){return $jscomp.SYMBOL_PREFIX+(e||"")+$jscomp.symbolCounter_++}; +$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var e=$jscomp.global.Symbol.iterator;e||(e=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[e]&&$jscomp.defineProperty(Array.prototype,e,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(e){var r=0;return $jscomp.iteratorPrototype(function(){return r<e.length?{done:!1,value:e[r++]}:{done:!0}})}; +$jscomp.iteratorPrototype=function(e){$jscomp.initSymbolIterator();e={next:e};e[$jscomp.global.Symbol.iterator]=function(){return this};return e};$jscomp.array=$jscomp.array||{};$jscomp.iteratorFromArray=function(e,r){$jscomp.initSymbolIterator();e instanceof String&&(e+="");var p=0,m={next:function(){if(p<e.length){var u=p++;return{value:r(u,e[u]),done:!1}}m.next=function(){return{done:!0,value:void 0}};return m.next()}};m[Symbol.iterator]=function(){return m};return m}; +$jscomp.polyfill=function(e,r,p,m){if(r){p=$jscomp.global;e=e.split(".");for(m=0;m<e.length-1;m++){var u=e[m];u in p||(p[u]={});p=p[u]}e=e[e.length-1];m=p[e];r=r(m);r!=m&&null!=r&&$jscomp.defineProperty(p,e,{configurable:!0,writable:!0,value:r})}};$jscomp.polyfill("Array.prototype.keys",function(e){return e?e:function(){return $jscomp.iteratorFromArray(this,function(e){return e})}},"es6-impl","es3");var $jscomp$this=this; +(function(e,r){"function"===typeof define&&define.amd?define([],r):"object"===typeof module&&module.exports?module.exports=r():e.anime=r()})(this,function(){function e(a){if(!h.col(a))try{return document.querySelectorAll(a)}catch(c){}}function r(a,c){for(var d=a.length,b=2<=arguments.length?arguments[1]:void 0,f=[],n=0;n<d;n++)if(n in a){var k=a[n];c.call(b,k,n,a)&&f.push(k)}return f}function p(a){return a.reduce(function(a,d){return a.concat(h.arr(d)?p(d):d)},[])}function m(a){if(h.arr(a))return a; +h.str(a)&&(a=e(a)||a);return a instanceof NodeList||a instanceof HTMLCollection?[].slice.call(a):[a]}function u(a,c){return a.some(function(a){return a===c})}function C(a){var c={},d;for(d in a)c[d]=a[d];return c}function D(a,c){var d=C(a),b;for(b in a)d[b]=c.hasOwnProperty(b)?c[b]:a[b];return d}function z(a,c){var d=C(a),b;for(b in c)d[b]=h.und(a[b])?c[b]:a[b];return d}function T(a){a=a.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,function(a,c,d,k){return c+c+d+d+k+k});var c=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(a); +a=parseInt(c[1],16);var d=parseInt(c[2],16),c=parseInt(c[3],16);return"rgba("+a+","+d+","+c+",1)"}function U(a){function c(a,c,b){0>b&&(b+=1);1<b&&--b;return b<1/6?a+6*(c-a)*b:.5>b?c:b<2/3?a+(c-a)*(2/3-b)*6:a}var d=/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(a)||/hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(a);a=parseInt(d[1])/360;var b=parseInt(d[2])/100,f=parseInt(d[3])/100,d=d[4]||1;if(0==b)f=b=a=f;else{var n=.5>f?f*(1+b):f+b-f*b,k=2*f-n,f=c(k,n,a+1/3),b=c(k,n,a);a=c(k,n,a-1/3)}return"rgba("+ +255*f+","+255*b+","+255*a+","+d+")"}function y(a){if(a=/([\+\-]?[0-9#\.]+)(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(a))return a[2]}function V(a){if(-1<a.indexOf("translate")||"perspective"===a)return"px";if(-1<a.indexOf("rotate")||-1<a.indexOf("skew"))return"deg"}function I(a,c){return h.fnc(a)?a(c.target,c.id,c.total):a}function E(a,c){if(c in a.style)return getComputedStyle(a).getPropertyValue(c.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase())||"0"}function J(a,c){if(h.dom(a)&& +u(W,c))return"transform";if(h.dom(a)&&(a.getAttribute(c)||h.svg(a)&&a[c]))return"attribute";if(h.dom(a)&&"transform"!==c&&E(a,c))return"css";if(null!=a[c])return"object"}function X(a,c){var d=V(c),d=-1<c.indexOf("scale")?1:0+d;a=a.style.transform;if(!a)return d;for(var b=[],f=[],n=[],k=/(\w+)\((.+?)\)/g;b=k.exec(a);)f.push(b[1]),n.push(b[2]);a=r(n,function(a,b){return f[b]===c});return a.length?a[0]:d}function K(a,c){switch(J(a,c)){case "transform":return X(a,c);case "css":return E(a,c);case "attribute":return a.getAttribute(c)}return a[c]|| +0}function L(a,c){var d=/^(\*=|\+=|-=)/.exec(a);if(!d)return a;var b=y(a)||0;c=parseFloat(c);a=parseFloat(a.replace(d[0],""));switch(d[0][0]){case "+":return c+a+b;case "-":return c-a+b;case "*":return c*a+b}}function F(a,c){return Math.sqrt(Math.pow(c.x-a.x,2)+Math.pow(c.y-a.y,2))}function M(a){a=a.points;for(var c=0,d,b=0;b<a.numberOfItems;b++){var f=a.getItem(b);0<b&&(c+=F(d,f));d=f}return c}function N(a){if(a.getTotalLength)return a.getTotalLength();switch(a.tagName.toLowerCase()){case "circle":return 2* +Math.PI*a.getAttribute("r");case "rect":return 2*a.getAttribute("width")+2*a.getAttribute("height");case "line":return F({x:a.getAttribute("x1"),y:a.getAttribute("y1")},{x:a.getAttribute("x2"),y:a.getAttribute("y2")});case "polyline":return M(a);case "polygon":var c=a.points;return M(a)+F(c.getItem(c.numberOfItems-1),c.getItem(0))}}function Y(a,c){function d(b){b=void 0===b?0:b;return a.el.getPointAtLength(1<=c+b?c+b:0)}var b=d(),f=d(-1),n=d(1);switch(a.property){case "x":return b.x;case "y":return b.y; +case "angle":return 180*Math.atan2(n.y-f.y,n.x-f.x)/Math.PI}}function O(a,c){var d=/-?\d*\.?\d+/g,b;b=h.pth(a)?a.totalLength:a;if(h.col(b))if(h.rgb(b)){var f=/rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g.exec(b);b=f?"rgba("+f[1]+",1)":b}else b=h.hex(b)?T(b):h.hsl(b)?U(b):void 0;else f=(f=y(b))?b.substr(0,b.length-f.length):b,b=c&&!/\s/g.test(b)?f+c:f;b+="";return{original:b,numbers:b.match(d)?b.match(d).map(Number):[0],strings:h.str(a)||c?b.split(d):[]}}function P(a){a=a?p(h.arr(a)?a.map(m):m(a)):[];return r(a, +function(a,d,b){return b.indexOf(a)===d})}function Z(a){var c=P(a);return c.map(function(a,b){return{target:a,id:b,total:c.length}})}function aa(a,c){var d=C(c);if(h.arr(a)){var b=a.length;2!==b||h.obj(a[0])?h.fnc(c.duration)||(d.duration=c.duration/b):a={value:a}}return m(a).map(function(a,b){b=b?0:c.delay;a=h.obj(a)&&!h.pth(a)?a:{value:a};h.und(a.delay)&&(a.delay=b);return a}).map(function(a){return z(a,d)})}function ba(a,c){var d={},b;for(b in a){var f=I(a[b],c);h.arr(f)&&(f=f.map(function(a){return I(a, +c)}),1===f.length&&(f=f[0]));d[b]=f}d.duration=parseFloat(d.duration);d.delay=parseFloat(d.delay);return d}function ca(a){return h.arr(a)?A.apply(this,a):Q[a]}function da(a,c){var d;return a.tweens.map(function(b){b=ba(b,c);var f=b.value,e=K(c.target,a.name),k=d?d.to.original:e,k=h.arr(f)?f[0]:k,w=L(h.arr(f)?f[1]:f,k),e=y(w)||y(k)||y(e);b.from=O(k,e);b.to=O(w,e);b.start=d?d.end:a.offset;b.end=b.start+b.delay+b.duration;b.easing=ca(b.easing);b.elasticity=(1E3-Math.min(Math.max(b.elasticity,1),999))/ +1E3;b.isPath=h.pth(f);b.isColor=h.col(b.from.original);b.isColor&&(b.round=1);return d=b})}function ea(a,c){return r(p(a.map(function(a){return c.map(function(b){var c=J(a.target,b.name);if(c){var d=da(b,a);b={type:c,property:b.name,animatable:a,tweens:d,duration:d[d.length-1].end,delay:d[0].delay}}else b=void 0;return b})})),function(a){return!h.und(a)})}function R(a,c,d,b){var f="delay"===a;return c.length?(f?Math.min:Math.max).apply(Math,c.map(function(b){return b[a]})):f?b.delay:d.offset+b.delay+ +b.duration}function fa(a){var c=D(ga,a),d=D(S,a),b=Z(a.targets),f=[],e=z(c,d),k;for(k in a)e.hasOwnProperty(k)||"targets"===k||f.push({name:k,offset:e.offset,tweens:aa(a[k],d)});a=ea(b,f);return z(c,{children:[],animatables:b,animations:a,duration:R("duration",a,c,d),delay:R("delay",a,c,d)})}function q(a){function c(){return window.Promise&&new Promise(function(a){return p=a})}function d(a){return g.reversed?g.duration-a:a}function b(a){for(var b=0,c={},d=g.animations,f=d.length;b<f;){var e=d[b], +k=e.animatable,h=e.tweens,n=h.length-1,l=h[n];n&&(l=r(h,function(b){return a<b.end})[0]||l);for(var h=Math.min(Math.max(a-l.start-l.delay,0),l.duration)/l.duration,w=isNaN(h)?1:l.easing(h,l.elasticity),h=l.to.strings,p=l.round,n=[],m=void 0,m=l.to.numbers.length,t=0;t<m;t++){var x=void 0,x=l.to.numbers[t],q=l.from.numbers[t],x=l.isPath?Y(l.value,w*x):q+w*(x-q);p&&(l.isColor&&2<t||(x=Math.round(x*p)/p));n.push(x)}if(l=h.length)for(m=h[0],w=0;w<l;w++)p=h[w+1],t=n[w],isNaN(t)||(m=p?m+(t+p):m+(t+" ")); +else m=n[0];ha[e.type](k.target,e.property,m,c,k.id);e.currentValue=m;b++}if(b=Object.keys(c).length)for(d=0;d<b;d++)H||(H=E(document.body,"transform")?"transform":"-webkit-transform"),g.animatables[d].target.style[H]=c[d].join(" ");g.currentTime=a;g.progress=a/g.duration*100}function f(a){if(g[a])g[a](g)}function e(){g.remaining&&!0!==g.remaining&&g.remaining--}function k(a){var k=g.duration,n=g.offset,w=n+g.delay,r=g.currentTime,x=g.reversed,q=d(a);if(g.children.length){var u=g.children,v=u.length; +if(q>=g.currentTime)for(var G=0;G<v;G++)u[G].seek(q);else for(;v--;)u[v].seek(q)}if(q>=w||!k)g.began||(g.began=!0,f("begin")),f("run");if(q>n&&q<k)b(q);else if(q<=n&&0!==r&&(b(0),x&&e()),q>=k&&r!==k||!k)b(k),x||e();f("update");a>=k&&(g.remaining?(t=h,"alternate"===g.direction&&(g.reversed=!g.reversed)):(g.pause(),g.completed||(g.completed=!0,f("complete"),"Promise"in window&&(p(),m=c()))),l=0)}a=void 0===a?{}:a;var h,t,l=0,p=null,m=c(),g=fa(a);g.reset=function(){var a=g.direction,c=g.loop;g.currentTime= +0;g.progress=0;g.paused=!0;g.began=!1;g.completed=!1;g.reversed="reverse"===a;g.remaining="alternate"===a&&1===c?2:c;b(0);for(a=g.children.length;a--;)g.children[a].reset()};g.tick=function(a){h=a;t||(t=h);k((l+h-t)*q.speed)};g.seek=function(a){k(d(a))};g.pause=function(){var a=v.indexOf(g);-1<a&&v.splice(a,1);g.paused=!0};g.play=function(){g.paused&&(g.paused=!1,t=0,l=d(g.currentTime),v.push(g),B||ia())};g.reverse=function(){g.reversed=!g.reversed;t=0;l=d(g.currentTime)};g.restart=function(){g.pause(); +g.reset();g.play()};g.finished=m;g.reset();g.autoplay&&g.play();return g}var ga={update:void 0,begin:void 0,run:void 0,complete:void 0,loop:1,direction:"normal",autoplay:!0,offset:0},S={duration:1E3,delay:0,easing:"easeOutElastic",elasticity:500,round:0},W="translateX translateY translateZ rotate rotateX rotateY rotateZ scale scaleX scaleY scaleZ skewX skewY perspective".split(" "),H,h={arr:function(a){return Array.isArray(a)},obj:function(a){return-1<Object.prototype.toString.call(a).indexOf("Object")}, +pth:function(a){return h.obj(a)&&a.hasOwnProperty("totalLength")},svg:function(a){return a instanceof SVGElement},dom:function(a){return a.nodeType||h.svg(a)},str:function(a){return"string"===typeof a},fnc:function(a){return"function"===typeof a},und:function(a){return"undefined"===typeof a},hex:function(a){return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(a)},rgb:function(a){return/^rgb/.test(a)},hsl:function(a){return/^hsl/.test(a)},col:function(a){return h.hex(a)||h.rgb(a)||h.hsl(a)}},A=function(){function a(a, +d,b){return(((1-3*b+3*d)*a+(3*b-6*d))*a+3*d)*a}return function(c,d,b,f){if(0<=c&&1>=c&&0<=b&&1>=b){var e=new Float32Array(11);if(c!==d||b!==f)for(var k=0;11>k;++k)e[k]=a(.1*k,c,b);return function(k){if(c===d&&b===f)return k;if(0===k)return 0;if(1===k)return 1;for(var h=0,l=1;10!==l&&e[l]<=k;++l)h+=.1;--l;var l=h+(k-e[l])/(e[l+1]-e[l])*.1,n=3*(1-3*b+3*c)*l*l+2*(3*b-6*c)*l+3*c;if(.001<=n){for(h=0;4>h;++h){n=3*(1-3*b+3*c)*l*l+2*(3*b-6*c)*l+3*c;if(0===n)break;var m=a(l,c,b)-k,l=l-m/n}k=l}else if(0=== +n)k=l;else{var l=h,h=h+.1,g=0;do m=l+(h-l)/2,n=a(m,c,b)-k,0<n?h=m:l=m;while(1e-7<Math.abs(n)&&10>++g);k=m}return a(k,d,f)}}}}(),Q=function(){function a(a,b){return 0===a||1===a?a:-Math.pow(2,10*(a-1))*Math.sin(2*(a-1-b/(2*Math.PI)*Math.asin(1))*Math.PI/b)}var c="Quad Cubic Quart Quint Sine Expo Circ Back Elastic".split(" "),d={In:[[.55,.085,.68,.53],[.55,.055,.675,.19],[.895,.03,.685,.22],[.755,.05,.855,.06],[.47,0,.745,.715],[.95,.05,.795,.035],[.6,.04,.98,.335],[.6,-.28,.735,.045],a],Out:[[.25, +.46,.45,.94],[.215,.61,.355,1],[.165,.84,.44,1],[.23,1,.32,1],[.39,.575,.565,1],[.19,1,.22,1],[.075,.82,.165,1],[.175,.885,.32,1.275],function(b,c){return 1-a(1-b,c)}],InOut:[[.455,.03,.515,.955],[.645,.045,.355,1],[.77,0,.175,1],[.86,0,.07,1],[.445,.05,.55,.95],[1,0,0,1],[.785,.135,.15,.86],[.68,-.55,.265,1.55],function(b,c){return.5>b?a(2*b,c)/2:1-a(-2*b+2,c)/2}]},b={linear:A(.25,.25,.75,.75)},f={},e;for(e in d)f.type=e,d[f.type].forEach(function(a){return function(d,f){b["ease"+a.type+c[f]]=h.fnc(d)? +d:A.apply($jscomp$this,d)}}(f)),f={type:f.type};return b}(),ha={css:function(a,c,d){return a.style[c]=d},attribute:function(a,c,d){return a.setAttribute(c,d)},object:function(a,c,d){return a[c]=d},transform:function(a,c,d,b,f){b[f]||(b[f]=[]);b[f].push(c+"("+d+")")}},v=[],B=0,ia=function(){function a(){B=requestAnimationFrame(c)}function c(c){var b=v.length;if(b){for(var d=0;d<b;)v[d]&&v[d].tick(c),d++;a()}else cancelAnimationFrame(B),B=0}return a}();q.version="2.2.0";q.speed=1;q.running=v;q.remove= +function(a){a=P(a);for(var c=v.length;c--;)for(var d=v[c],b=d.animations,f=b.length;f--;)u(a,b[f].animatable.target)&&(b.splice(f,1),b.length||d.pause())};q.getValue=K;q.path=function(a,c){var d=h.str(a)?e(a)[0]:a,b=c||100;return function(a){return{el:d,property:a,totalLength:N(d)*(b/100)}}};q.setDashoffset=function(a){var c=N(a);a.setAttribute("stroke-dasharray",c);return c};q.bezier=A;q.easings=Q;q.timeline=function(a){var c=q(a);c.pause();c.duration=0;c.add=function(d){c.children.forEach(function(a){a.began= +!0;a.completed=!0});m(d).forEach(function(b){var d=z(b,D(S,a||{}));d.targets=d.targets||a.targets;b=c.duration;var e=d.offset;d.autoplay=!1;d.direction=c.direction;d.offset=h.und(e)?b:L(e,b);c.began=!0;c.completed=!0;c.seek(d.offset);d=q(d);d.began=!0;d.completed=!0;d.duration>b&&(c.duration=d.duration);c.children.push(d)});c.seek(0);c.reset();c.autoplay&&c.restart();return c};return c};q.random=function(a,c){return Math.floor(Math.random()*(c-a+1))+a};return q}); \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/jquery-3.3.1.min.js" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/jquery-3.3.1.min.js" new file mode 100644 index 0000000..4d9b3a2 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/jquery-3.3.1.min.js" @@ -0,0 +1,2 @@ +/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:n.sort,splice:n.splice},w.extend=w.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||g(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)n=a[t],a!==(r=e[t])&&(l&&r&&(w.isPlainObject(r)||(i=Array.isArray(r)))?(i?(i=!1,o=n&&Array.isArray(n)?n:[]):o=n&&w.isPlainObject(n)?n:{},a[t]=w.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},w.extend({expando:"jQuery"+("3.3.1"+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==c.call(e))&&(!(t=i(e))||"function"==typeof(n=f.call(t,"constructor")&&t.constructor)&&p.call(n)===d)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e){m(e)},each:function(e,t){var n,r=0;if(C(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(C(Object(e))?w.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:u.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)(r=!t(e[o],o))!==s&&i.push(e[o]);return i},map:function(e,t,n){var r,i,o=0,s=[];if(C(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&s.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&s.push(i);return a.apply([],s)},guid:1,support:h}),"function"==typeof Symbol&&(w.fn[Symbol.iterator]=n[Symbol.iterator]),w.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function C(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!g(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",I="\\["+M+"*("+R+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+R+"))|)"+M+"*\\]",W=":("+R+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+I+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),F=new RegExp("^"+M+"*,"+M+"*"),_=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="<a id='"+b+"'></a><select id='"+b+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:he(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:he(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=r.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=fe(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=pe(t);function ye(){}ye.prototype=r.filters=r.pseudos,r.setFilters=new ye,a=oe.tokenize=function(e,t){var n,i,o,a,s,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=r.preFilter;while(s){n&&!(i=F.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),n=!1,(i=_.exec(s))&&(n=i.shift(),o.push({value:n,type:i[0].replace(B," ")}),s=s.slice(n.length));for(a in r.filter)!(i=V[a].exec(s))||l[a]&&!(i=l[a](i))||(n=i.shift(),o.push({value:n,type:a,matches:i}),s=s.slice(n.length));if(!n)break}return t?s.length:s?oe.error(e):k(e,u).slice(0)};function ve(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function me(e,t,n){var r=t.dir,i=t.next,o=i||r,a=n&&"parentNode"===o,s=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||a)return e(t,n,i);return!1}:function(t,n,u){var l,c,f,p=[T,s];if(u){while(t=t[r])if((1===t.nodeType||a)&&e(t,n,u))return!0}else while(t=t[r])if(1===t.nodeType||a)if(f=t[b]||(t[b]={}),c=f[t.uniqueID]||(f[t.uniqueID]={}),i&&i===t.nodeName.toLowerCase())t=t[r]||t;else{if((l=c[o])&&l[0]===T&&l[1]===s)return p[2]=l[2];if(c[o]=p,p[2]=e(t,n,u))return!0}return!1}}function xe(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r<i;r++)oe(e,t[r],n);return n}function we(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Te(e,t,n,r,i,o){return r&&!r[b]&&(r=Te(r)),i&&!i[b]&&(i=Te(i,o)),se(function(o,a,s,u){var l,c,f,p=[],d=[],h=a.length,g=o||be(t||"*",s.nodeType?[s]:s,[]),y=!e||!o&&t?g:we(g,p,e,s,u),v=n?i||(o?e:h||r)?[]:a:y;if(n&&n(y,v,s,u),r){l=we(v,d),r(l,[],s,u),c=l.length;while(c--)(f=l[c])&&(v[d[c]]=!(y[d[c]]=f))}if(o){if(i||e){if(i){l=[],c=v.length;while(c--)(f=v[c])&&l.push(y[c]=f);i(null,v=[],l,u)}c=v.length;while(c--)(f=v[c])&&(l=i?O(o,f):p[c])>-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u<o;u++)if(n=r.relative[e[u].type])p=[me(xe(p),n)];else{if((n=r.filter[e[u].type].apply(null,e[u].matches))[b]){for(i=++u;i<o;i++)if(r.relative[e[i].type])break;return Te(u>1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u<i&&Ce(e.slice(u,i)),i<o&&Ce(e=e.slice(i)),i<o&&ve(e))}p.push(n)}return xe(p)}function Ee(e,t){var n=t.length>0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t<r;t++)if(w.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)w.find(e,i[t],n);return r>1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(w.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&w(e);if(!D.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s<o.length)!1===o[s].apply(n[0],n[1])&&e.stopOnFalse&&(s=o.length,n=!1)}e.memory||(n=!1),t=!1,i&&(o=n?[]:"")},l={add:function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){w.each(n,function(n,r){g(r)?e.unique&&l.has(r)||o.push(r):r&&r.length&&"string"!==x(r)&&t(r)})}(arguments),n&&!t&&u()),this},remove:function(){return w.each(arguments,function(e,t){var n;while((n=w.inArray(t,o,n))>-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t<o)){if((e=r.apply(s,u))===n.promise())throw new TypeError("Thenable self-resolution");l=e&&("object"==typeof e||"function"==typeof e)&&e.then,g(l)?i?l.call(e,a(o,n,I,i),a(o,n,W,i)):(o++,l.call(e,a(o,n,I,i),a(o,n,W,i),a(o,n,I,n.notifyWith))):(r!==I&&(s=void 0,u=[e]),(i||n.resolveWith)(s,u))}},c=i?l:function(){try{l()}catch(e){w.Deferred.exceptionHook&&w.Deferred.exceptionHook(e,c.stackTrace),t+1>=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},X=/^-ms-/,U=/-([a-z])/g;function V(e,t){return t.toUpperCase()}function G(e){return e.replace(X,"ms-").replace(U,V)}var Y=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Q(){this.expando=w.expando+Q.uid++}Q.uid=1,Q.prototype={cache:function(e){var t=e[this.expando];return t||(t={},Y(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[G(t)]=n;else for(r in t)i[G(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][G(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(G):(t=G(t))in r?[t]:t.match(M)||[]).length;while(n--)delete r[t[n]]}(void 0===t||w.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!w.isEmptyObject(t)}};var J=new Q,K=new Q,Z=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,ee=/[A-Z]/g;function te(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Z.test(e)?JSON.parse(e):e)}function ne(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(ee,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n=te(n)}catch(e){}K.set(e,t,n)}else n=void 0;return n}w.extend({hasData:function(e){return K.hasData(e)||J.hasData(e)},data:function(e,t,n){return K.access(e,t,n)},removeData:function(e,t){K.remove(e,t)},_data:function(e,t,n){return J.access(e,t,n)},_removeData:function(e,t){J.remove(e,t)}}),w.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=K.get(o),1===o.nodeType&&!J.get(o,"hasDataAttrs"))){n=a.length;while(n--)a[n]&&0===(r=a[n].name).indexOf("data-")&&(r=G(r.slice(5)),ne(o,r,i[r]));J.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof e?this.each(function(){K.set(this,e)}):z(this,function(t){var n;if(o&&void 0===t){if(void 0!==(n=K.get(o,e)))return n;if(void 0!==(n=ne(o,e)))return n}else this.each(function(){K.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?w.queue(this[0],e):void 0===t?this:this.each(function(){var n=w.queue(this,e,t);w._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&w.dequeue(this,e)})},dequeue:function(e){return this.each(function(){w.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=w.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=J.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var re=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ie=new RegExp("^(?:([+-])=|)("+re+")([a-z%]*)$","i"),oe=["Top","Right","Bottom","Left"],ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&w.contains(e.ownerDocument,e)&&"none"===w.css(e,"display")},se=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i};function ue(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return w.css(e,t,"")},u=s(),l=n&&n[3]||(w.cssNumber[t]?"":"px"),c=(w.cssNumber[t]||"px"!==l&&+u)&&ie.exec(w.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)w.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,w.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var le={};function ce(e){var t,n=e.ownerDocument,r=e.nodeName,i=le[r];return i||(t=n.body.appendChild(n.createElement(r)),i=w.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),le[r]=i,i)}function fe(e,t){for(var n,r,i=[],o=0,a=e.length;o<a;o++)(r=e[o]).style&&(n=r.style.display,t?("none"===n&&(i[o]=J.get(r,"display")||null,i[o]||(r.style.display="")),""===r.style.display&&ae(r)&&(i[o]=ce(r))):"none"!==n&&(i[o]="none",J.set(r,"display",n)));for(o=0;o<a;o++)null!=i[o]&&(e[o].style.display=i[o]);return e}w.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?w(this).show():w(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n<r;n++)J.set(e[n],"globalEval",!t||J.get(t[n],"globalEval"))}var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===x(o))w.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+w.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;w.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&w.inArray(o,r)>-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="<textarea>x</textarea>",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n<arguments.length;n++)u[n]=arguments[n];if(t.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,t)){s=w.event.handlers.call(this,t,l),n=0;while((o=s[n++])&&!t.isPropagationStopped()){t.currentTarget=o.elem,r=0;while((a=o.handlers[r++])&&!t.isImmediatePropagationStopped())t.rnamespace&&!t.rnamespace.test(a.namespace)||(t.handleObj=a,t.data=a.data,void 0!==(i=((w.event.special[a.origType]||{}).handle||a.handler).apply(o.elem,u))&&!1===(t.result=i)&&(t.preventDefault(),t.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,t),t.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&e.button>=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?w(i,this).index(l)>-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(e,t){Object.defineProperty(w.Event.prototype,e,{enumerable:!0,configurable:!0,get:g(t)?function(){if(this.originalEvent)return t(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[e]},set:function(t){Object.defineProperty(this,e,{enumerable:!0,configurable:!0,writable:!0,value:t})}})},fix:function(e){return e[w.expando]?e:new w.Event(e)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==Se()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===Se()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&N(this,"input"))return this.click(),!1},_default:function(e){return N(e.target,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},w.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},w.Event=function(e,t){if(!(this instanceof w.Event))return new w.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ee:ke,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&w.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[w.expando]=!0},w.Event.prototype={constructor:w.Event,isDefaultPrevented:ke,isPropagationStopped:ke,isImmediatePropagationStopped:ke,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ee,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ee,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ee,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},w.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&we.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Te.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},w.event.addProp),w.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){w.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||w.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),w.fn.extend({on:function(e,t,n,r){return De(this,e,t,n,r)},one:function(e,t,n,r){return De(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,w(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=ke),this.each(function(){w.event.remove(this,e,n,t)})}});var Ne=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/<script|<style|<link/i,je=/checked\s*(?:[^=]|=\s*.checked.)/i,qe=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n<r;n++)w.event.add(t,i,l[i][n])}K.hasData(e)&&(s=K.access(e),u=w.extend({},s),K.set(t,u))}}function Me(e,t){var n=t.nodeName.toLowerCase();"input"===n&&pe.test(e.type)?t.checked=e.checked:"input"!==n&&"textarea"!==n||(t.defaultValue=e.defaultValue)}function Re(e,t,n,r){t=a.apply([],t);var i,o,s,u,l,c,f=0,p=e.length,d=p-1,y=t[0],v=g(y);if(v||p>1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f<p;f++)l=i,f!==d&&(l=w.clone(l,!0,!0),u&&w.merge(s,ye(l,"script"))),n.call(e[f],l,f);if(u)for(c=s[s.length-1].ownerDocument,w.map(s,Oe),f=0;f<u;f++)l=s[f],he.test(l.type||"")&&!J.access(l,"globalEval")&&w.contains(c,l)&&(l.src&&"module"!==(l.type||"").toLowerCase()?w._evalUrl&&w._evalUrl(l.src):m(l.textContent.replace(qe,""),c,l))}return e}function Ie(e,t,n){for(var r,i=t?w.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||w.cleanData(ye(r)),r.parentNode&&(n&&w.contains(r.ownerDocument,r)&&ve(ye(r,"script")),r.parentNode.removeChild(r));return e}w.extend({htmlPrefilter:function(e){return e.replace(Ne,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r<i;r++)Me(o[r],a[r]);if(t)if(n)for(o=o||ye(e),a=a||ye(s),r=0,i=o.length;r<i;r++)Pe(o[r],a[r]);else Pe(e,s);return(a=ye(s,"script")).length>0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(w.cleanData(ye(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return Re(this,arguments,function(t){var n=this.parentNode;w.inArray(this,e)<0&&(w.cleanData(ye(this)),n&&n.replaceChild(t,this))},e)}}),w.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){w.fn[e]=function(e){for(var n,r=[],i=w(e),o=i.length-1,a=0;a<=o;a++)n=a===o?this:this.clone(!0),w(i[a])[t](n),s.apply(r,n.get());return this.pushStack(r)}});var We=new RegExp("^("+re+")(?!px)[a-z%]+$","i"),$e=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},Be=new RegExp(oe.join("|"),"i");!function(){function t(){if(c){l.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",c.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",be.appendChild(l).appendChild(c);var t=e.getComputedStyle(c);i="1%"!==t.top,u=12===n(t.marginLeft),c.style.right="60%",s=36===n(t.right),o=36===n(t.width),c.style.position="absolute",a=36===c.offsetWidth||"absolute",be.removeChild(l),c=null}}function n(e){return Math.round(parseFloat(e))}var i,o,a,s,u,l=r.createElement("div"),c=r.createElement("div");c.style&&(c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",h.clearCloneStyle="content-box"===c.style.backgroundClip,w.extend(h,{boxSizingReliable:function(){return t(),o},pixelBoxStyles:function(){return t(),s},pixelPosition:function(){return t(),i},reliableMarginLeft:function(){return t(),u},scrollboxSize:function(){return t(),a}}))}();function Fe(e,t,n){var r,i,o,a,s=e.style;return(n=n||$e(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||w.contains(e.ownerDocument,e)||(a=w.style(e,t)),!h.pixelBoxStyles()&&We.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function _e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}var ze=/^(none|table(?!-c[ea]).+)/,Xe=/^--/,Ue={position:"absolute",visibility:"hidden",display:"block"},Ve={letterSpacing:"0",fontWeight:"400"},Ge=["Webkit","Moz","ms"],Ye=r.createElement("div").style;function Qe(e){if(e in Ye)return e;var t=e[0].toUpperCase()+e.slice(1),n=Ge.length;while(n--)if((e=Ge[n]+t)in Ye)return e}function Je(e){var t=w.cssProps[e];return t||(t=w.cssProps[e]=Qe(e)||e),t}function Ke(e,t,n){var r=ie.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ze(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=w.css(e,n+oe[a],!0,i)),r?("content"===n&&(u-=w.css(e,"padding"+oe[a],!0,i)),"margin"!==n&&(u-=w.css(e,"border"+oe[a]+"Width",!0,i))):(u+=w.css(e,"padding"+oe[a],!0,i),"padding"!==n?u+=w.css(e,"border"+oe[a]+"Width",!0,i):s+=w.css(e,"border"+oe[a]+"Width",!0,i));return!r&&o>=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a<i;a++)o[t[a]]=w.css(e,t[a],!1,r);return o}return void 0!==n?w.style(e,t,n):w.css(e,t)},e,t,arguments.length>1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ct(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),y=J.get(e,"fxshow");n.queue||(null==(a=w._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,w.queue(e,"fx").length||a.empty.fire()})}));for(r in t)if(i=t[r],it.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!y||void 0===y[r])continue;g=!0}d[r]=y&&y[r]||w.style(e,r)}if((u=!w.isEmptyObject(t))||!w.isEmptyObject(d)){f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=y&&y.display)&&(l=J.get(e,"display")),"none"===(c=w.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=w.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===w.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1;for(r in d)u||(y?"hidden"in y&&(g=y.hidden):y=J.access(e,"fxshow",{display:l}),o&&(y.hidden=!g),g&&fe([e],!0),p.done(function(){g||fe([e]),J.remove(e,"fxshow");for(r in d)w.style(e,r,d[r])})),u=lt(g?y[r]:0,r,p),r in y||(y[r]=u.start,g&&(u.end=u.start,u.start=0))}}function ft(e,t){var n,r,i,o,a;for(n in e)if(r=G(n),i=t[r],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=w.cssHooks[r])&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function pt(e,t,n){var r,i,o=0,a=pt.prefilters.length,s=w.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=nt||st(),n=Math.max(0,l.startTime+l.duration-t),r=1-(n/l.duration||0),o=0,a=l.tweens.length;o<a;o++)l.tweens[o].run(r);return s.notifyWith(e,[l,r,n]),r<1&&a?n:(a||s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:w.extend({},t),opts:w.extend(!0,{specialEasing:{},easing:w.easing._default},n),originalProperties:t,originalOptions:n,startTime:nt||st(),duration:n.duration,tweens:[],createTween:function(t,n){var r=w.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(ft(c,l.opts.specialEasing);o<a;o++)if(r=pt.prefilters[o].call(l,e,c,l.opts))return g(r.stop)&&(w._queueHooks(l.elem,l.opts.queue).stop=r.stop.bind(r)),r;return w.map(c,lt,l),g(l.opts.start)&&l.opts.start.call(e,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),w.fx.timer(w.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l}w.Animation=w.extend(pt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return ue(n.elem,e,ie.exec(t),n),n}]},tweener:function(e,t){g(e)?(t=e,e=["*"]):e=e.match(M);for(var n,r=0,i=e.length;r<i;r++)n=e[r],pt.tweeners[n]=pt.tweeners[n]||[],pt.tweeners[n].unshift(t)},prefilters:[ct],prefilter:function(e,t){t?pt.prefilters.unshift(e):pt.prefilters.push(e)}}),w.speed=function(e,t,n){var r=e&&"object"==typeof e?w.extend({},e):{complete:n||!n&&t||g(e)&&e,duration:e,easing:n&&t||t&&!g(t)&&t};return w.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in w.fx.speeds?r.duration=w.fx.speeds[r.duration]:r.duration=w.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){g(r.old)&&r.old.call(this),r.queue&&w.dequeue(this,r.queue)},r},w.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=w.isEmptyObject(e),o=w.speed(t,n,r),a=function(){var t=pt(this,w.extend({},e),o);(i||J.get(this,"finish"))&&t.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&!1!==e&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=w.timers,a=J.get(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&ot.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||w.dequeue(this,e)})},finish:function(e){return!1!==e&&(e=e||"fx"),this.each(function(){var t,n=J.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=w.timers,a=r?r.length:0;for(n.finish=!0,w.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),w.each(["toggle","show","hide"],function(e,t){var n=w.fn[t];w.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ut(t,!0),e,r,i)}}),w.each({slideDown:ut("show"),slideUp:ut("hide"),slideToggle:ut("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){w.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),w.timers=[],w.fx.tick=function(){var e,t=0,n=w.timers;for(nt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||w.fx.stop(),nt=void 0},w.fx.timer=function(e){w.timers.push(e),w.fx.start()},w.fx.interval=13,w.fx.start=function(){rt||(rt=!0,at())},w.fx.stop=function(){rt=null},w.fx.speeds={slow:600,fast:200,_default:400},w.fn.delay=function(t,n){return t=w.fx?w.fx.speeds[t]||t:t,n=n||"fx",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e=r.createElement("input"),t=r.createElement("select").appendChild(r.createElement("option"));e.type="checkbox",h.checkOn=""!==e.value,h.optSelected=t.selected,(e=r.createElement("input")).value="t",e.type="radio",h.radioValue="t"===e.value}();var dt,ht=w.expr.attrHandle;w.fn.extend({attr:function(e,t){return z(this,w.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!N(n.parentNode,"optgroup"))){if(t=w(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=w.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=w.inArray(w.valHooks.option.get(r),o)>-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("<script>").prop({charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&o("error"===e.type?404:200,e.type)}),r.head.appendChild(t[0])},abort:function(){n&&n()}}}});var Yt=[],Qt=/(=)\?(?=&|$)|\?\?/;w.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Yt.pop()||w.expando+"_"+Et++;return this[e]=!0,e}}),w.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=!1!==t.jsonp&&(Qt.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&Qt.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=g(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(Qt,"$1"+i):!1!==t.jsonp&&(t.url+=(kt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||w.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?w(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,Yt.push(i)),a&&g(o)&&o(a[0]),a=o=void 0}),"script"}),h.createHTMLDocument=function(){var e=r.implementation.createHTMLDocument("").body;return e.innerHTML="<form></form><form></form>",2===e.childNodes.length}(),w.parseHTML=function(e,t,n){if("string"!=typeof e)return[];"boolean"==typeof t&&(n=t,t=!1);var i,o,a;return t||(h.createHTMLDocument?((i=(t=r.implementation.createHTMLDocument("")).createElement("base")).href=r.location.href,t.head.appendChild(i)):t=r),o=A.exec(e),a=!n&&[],o?[t.createElement(o[1])]:(o=xe([e],t,a),a&&a.length&&w(a).remove(),w.merge([],o.childNodes))},w.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=vt(e.slice(s)),e=e.slice(0,s)),g(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&w.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?w("<div>").append(w.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},w.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){w.fn[t]=function(e){return this.on(t,e)}}),w.expr.pseudos.animated=function(e){return w.grep(w.timers,function(t){return e===t.elem}).length},w.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=w.css(e,"position"),f=w(e),p={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=w.css(e,"top"),u=w.css(e,"left"),(l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1)?(a=(r=f.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),g(t)&&(t=t.call(e,n,w.extend({},s))),null!=t.top&&(p.top=t.top-s.top+a),null!=t.left&&(p.left=t.left-s.left+i),"using"in t?t.using.call(e,p):f.css(p)}},w.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){w.offset.setOffset(this,e,t)});var t,n,r=this[0];if(r)return r.getClientRects().length?(t=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:t.top+n.pageYOffset,left:t.left+n.pageXOffset}):{top:0,left:0}},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===w.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===w.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=w(e).offset()).top+=w.css(e,"borderTopWidth",!0),i.left+=w.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-w.css(r,"marginTop",!0),left:t.left-i.left-w.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===w.css(e,"position"))e=e.offsetParent;return e||be})}}),w.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n="pageYOffset"===t;w.fn[e]=function(r){return z(this,function(e,r,i){var o;if(y(e)?o=e:9===e.nodeType&&(o=e.defaultView),void 0===i)return o?o[t]:e[r];o?o.scrollTo(n?o.pageXOffset:i,n?i:o.pageYOffset):e[r]=i},e,r,arguments.length)}}),w.each(["top","left"],function(e,t){w.cssHooks[t]=_e(h.pixelPosition,function(e,n){if(n)return n=Fe(e,t),We.test(n)?w(e).position()[t]+"px":n})}),w.each({Height:"height",Width:"width"},function(e,t){w.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){w.fn[r]=function(i,o){var a=arguments.length&&(n||"boolean"!=typeof i),s=n||(!0===i||!0===o?"margin":"border");return z(this,function(t,n,i){var o;return y(t)?0===r.indexOf("outer")?t["inner"+e]:t.document.documentElement["client"+e]:9===t.nodeType?(o=t.documentElement,Math.max(t.body["scroll"+e],o["scroll"+e],t.body["offset"+e],o["offset"+e],o["client"+e])):void 0===i?w.css(t,n,s):w.style(t,n,i,s)},t,a?i:void 0,a)}})}),w.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){w.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),w.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),w.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),w.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),g(e))return r=o.call(arguments,2),i=function(){return e.apply(t||this,r.concat(o.call(arguments)))},i.guid=e.guid=e.guid||w.guid++,i},w.holdReady=function(e){e?w.readyWait++:w.ready(!0)},w.isArray=Array.isArray,w.parseJSON=JSON.parse,w.nodeName=N,w.isFunction=g,w.isWindow=y,w.camelCase=G,w.type=x,w.now=Date.now,w.isNumeric=function(e){var t=w.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return w});var Jt=e.jQuery,Kt=e.$;return w.noConflict=function(t){return e.$===w&&(e.$=Kt),t&&e.jQuery===w&&(e.jQuery=Jt),w},t||(e.jQuery=e.$=w),w}); diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/site.js" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/site.js" new file mode 100644 index 0000000..ac49c18 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/site.js" @@ -0,0 +1,4 @@ +锘�// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification +// for details on configuring this project to bundle and minify static web assets. + +// Write your JavaScript code. diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/swaggerdoc.js" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/swaggerdoc.js" new file mode 100644 index 0000000..c01192b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/js/swaggerdoc.js" @@ -0,0 +1,139 @@ +锘縱ar exten = "";//涓嬭浇鏂囦欢鍚庣紑鍚� +var timerLoadExportBtn = null; +$(document).delegate("#select", "change", function () { + debugger + setTimeout("LoadExportApiWordBtn()", 300);//鍔犺浇瀵煎嚭鎸夐挳 + console.log("dom export ok"); +}); + +$(document).ready(function () { + InitLoad();//鍒濆鍖栧鍑� + //loading璁剧疆 + $.busyLoadSetup({ + animation: "slide", + background: "rgba(255, 152, 0, 0.86)" + }); +}); + +//鍒濆鍖� +function InitLoad() { + setTimeout("LoadExportApiWordBtn()", 300);//鍔犺浇瀵煎嚭鎸夐挳 +} + +//鍔犺浇鑷畾涔夊鍑烘寜閽� +function LoadExportApiWordBtn() { + $(".information-container").height(240);//鏂囨。浠嬬粛鍖哄煙楂樺害 + $(".topbar").height(35); + var btnExport = "<div class='selectBox' style='position: absolute;margin: 0;padding: 0;margin-left: 1432px;top: 2.5px;'>" + + "<span><a href='javascript:void(0);'>瀵煎嚭绂荤嚎鏂囨。</a></span>" + + "<div class='drop'>" + + "<ul style='margin: 0;padding: 0;'>" + + //"<li>" + + //"<a href='javascript:void(0);' onclick='ExportApiWord(1)'>瀵煎嚭 Word</a>" + + //"</li>" + + //"<li>" + + //"<a href='javascript:void(0);' onclick='ExportApiWord(2)'>瀵煎嚭 PDF</a>" + + //"</li>" + + "<li>" + + "<a href='javascript:void(0);' onclick='ExportApiWord(3)'>瀵煎嚭 Html</a>" + + "</li >" + + //"<li>" + + //"<a href='javascript:void(0);' onclick='ExportApiWord(4)'>瀵煎嚭 Xml</a>" + + //"</li >" + + //"<li>" + + //"<a href='javascript:void(0);' onclick='ExportApiWord(5)'>瀵煎嚭 Svg</a>" + + //"</li >" + + "</ul >" + + "</div >" + + "</div >"; + //information-container杩欎釜鍏冪礌鏄痵wagger鍚庢湡鍔ㄦ�佹覆鏌撳嚭鏉ョ殑锛屾墍鏈夎繖閲岃鍔犱釜寰幆鍒ゆ柇銆� + //绗竴娆¤繘鏉ュ鏋滄湁杩欎釜class鐩存帴鍔犺浇鎸夐挳閫�鍑� + if ($("*").hasClass("information-container")) { + $(".information-container").append(btnExport); + return; + } + //娌℃湁鍏冪礌绛夊緟鍏冪礌鍑虹幇鍦ㄥ姞杞芥寜閽� + timerLoadExportBtn = setInterval(function () { + if ($("*").hasClass("information-container")) { + $(".information-container").append(btnExport); + console.log("load ok"); + window.clearInterval(timerLoadExportBtn); + return; + } + console.log("loading"); + }, 788); +} + + +/** + * 寤惰繜鍑芥暟 + * @param {any} delay + */ +function sleep(delay) { + var start = (new Date()).getTime(); + while ((new Date()).getTime() - start < delay) { + continue; + } +} + +/* + * 瀵煎嚭 + */ +function ExportApiWord(type) { + switch (type) { + case 1: + exten = ".docx"; + break; + case 2: + exten = ".pdf"; + break; + case 3: + exten = ".html"; + break; + case 4: + exten = ".xml"; + break; + case 5: + exten = ".svg"; + break; + } + var version = $("#select option:selected").val(); + version = version.split('/')[2]; + var url = '/api/Swagger/ExportWord?type=' + exten + "&version=" + version; + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); // 涔熷彲浠ヤ娇鐢≒OST鏂瑰紡锛屾牴鎹帴鍙� + xhr.responseType = "blob"; // 杩斿洖绫诲瀷blob + // 瀹氫箟璇锋眰瀹屾垚鐨勫鐞嗗嚱鏁帮紝璇锋眰鍓嶄篃鍙互澧炲姞鍔犺浇妗�/绂佺敤涓嬭浇鎸夐挳閫昏緫 + xhr.onload = function () { + // 璇锋眰瀹屾垚 + if (this.status === 200) { + // 杩斿洖200 + var blob = this.response; + var reader = new FileReader(); + reader.readAsDataURL(blob); // 杞崲涓篵ase64锛屽彲浠ョ洿鎺ユ斁鍏琛ㄦ儏href + reader.onload = function(e) { + // 杞崲瀹屾垚锛屽垱寤轰竴涓猘鏍囩鐢ㄤ簬涓嬭浇 + var a = document.createElement('a'); + a.download = 'WIDESEA API鏂囨。 ' + version + exten; + a.href = e.target.result; + $("body").append(a); // 淇firefox涓棤娉曡Е鍙慶lick + a.click(); + $(a).remove(); + } + } else { + alert(this.status+this.statusText); + } + //鍏抽棴load + $.busyLoadFull('hide', + { + animation: "fade" + }); + }; + // 鍙戦�乤jax璇锋眰 + xhr.send(); + //鎵撳紑loader閬僵 + $.busyLoadFull('show', { + text: "LOADING ...", + animation: "fade" + }); +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/logo.jpg.jpg" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/logo.jpg.jpg" new file mode 100644 index 0000000..d479f96 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/logo.jpg.jpg" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/logo/favicon-32x32.png" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/logo/favicon-32x32.png" new file mode 100644 index 0000000..68062fe --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/logo/favicon-32x32.png" Binary files differ diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/swg-login.html" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/swg-login.html" new file mode 100644 index 0000000..16b0b3c --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_ProductMgmtServer/wwwroot/swg-login.html" @@ -0,0 +1,140 @@ +锘�<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8" /> + <title>鐧诲綍 - 鎺ュ彛鏂囨。</title> + <script src="js/jquery-3.3.1.min.js"></script> + <link type="text/css" href="css/style.css" rel="stylesheet" /> + <script src="js/anime.min.js"></script> +</head> +<body> + <div class="page"> + <div class="container"> + <div class="left"> + <div></div> + + <div class="login">鎺ュ彛鏂囨。</div> + <div class="eula">娆㈣繋浣跨敤锛�</div> + </div> + <div class="right"> + <svg viewBox="0 0 320 300"> + <defs> + <linearGradient inkscape:collect="always" + id="linearGradient" + x1="13" + y1="193.49992" + x2="307" + y2="193.49992" + gradientUnits="userSpaceOnUse"> + <stop style="stop-color:#ff00ff;" + offset="0" + id="stop876" /> + <stop style="stop-color:#ff0000;" + offset="1" + id="stop878" /> + </linearGradient> + </defs> + <path d="m 40,120.00016 239.99984,-3.2e-4 c 0,0 24.99263,0.79932 25.00016,35.00016 0.008,34.20084 -25.00016,35 -25.00016,35 h -239.99984 c 0,-0.0205 -25,4.01348 -25,38.5 0,34.48652 25,38.5 25,38.5 h 215 c 0,0 20,-0.99604 20,-25 0,-24.00396 -20,-25 -20,-25 h -190 c 0,0 -20,1.71033 -20,25 0,24.00396 20,25 20,25 h 168.57143" /> + </svg> + <div class="form"> + <label for="email">鐢ㄦ埛鍚�</label> + <input type="email" id="email"> + <label for="password">瀵嗙爜</label> + <input type="password" id="password"> + <input type="submit" id="submit" onclick="submit()" value="鐧� 褰�"> + </div> + </div> + </div> + </div> + + <script> + var current = null; + document.querySelector('#email').addEventListener('focus', function (e) { + if (current) current.pause(); + current = anime({ + targets: 'path', + strokeDashoffset: { + value: 0, + duration: 700, + easing: 'easeOutQuart' + }, + strokeDasharray: { + value: '240 1386', + duration: 700, + easing: 'easeOutQuart' + } + }); + }); + document.querySelector('#password').addEventListener('focus', function (e) { + if (current) current.pause(); + current = anime({ + targets: 'path', + strokeDashoffset: { + value: -336, + duration: 700, + easing: 'easeOutQuart' + }, + strokeDasharray: { + value: '240 1386', + duration: 700, + easing: 'easeOutQuart' + } + }); + }); + document.querySelector('#submit').addEventListener('focus', function (e) { + if (current) current.pause(); + current = anime({ + targets: 'path', + strokeDashoffset: { + value: -730, + duration: 700, + easing: 'easeOutQuart' + }, + strokeDasharray: { + value: '530 1386', + duration: 700, + easing: 'easeOutQuart' + } + }); + }); + + function GetQueryString(name) { + var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); + var r = window.location.search.substr(1).match(reg); + if (r != null) return decodeURI(r[2]); + return null; + } + + function submit() { + let postdata = { + "name": $("#email").val(), + "pwd": $("#password").val(), + }; + if (!(postdata.name && postdata.pwd)) { + alert('鍙傛暟涓嶆纭�'); + return + } + $.ajax({ + url: "/api/User/swgLogin", + type: "POST", + contentType: "application/json; charset=utf-8", + data: JSON.stringify(postdata), + dataType: 'json', + success: function (data) { + if (data?.result) { + var returnUrl = GetQueryString("returnUrl"); + if (returnUrl != null && returnUrl.length > 0) { + window.location.href = returnUrl; + } else { + window.location.href = "/index.html"; + } + } else { + alert('鍙傛暟涓嶆纭�'); + } + } + }); + } + </script> + +</body> +</html> \ No newline at end of file diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_DictionaryListService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_DictionaryListService.cs" new file mode 100644 index 0000000..0275214 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_DictionaryListService.cs" @@ -0,0 +1,19 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_SystemServices +{ + public class Sys_DictionaryListService : ServiceBase<Sys_DictionaryList, IRepository<Sys_DictionaryList>>, ISys_DictionaryListService + { + public Sys_DictionaryListService(IRepository<Sys_DictionaryList> BaseDal) : base(BaseDal) + { + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_DictionaryService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_DictionaryService.cs" new file mode 100644 index 0000000..ebb2107 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_DictionaryService.cs" @@ -0,0 +1,126 @@ +锘縰sing Newtonsoft.Json; +using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_Core.Caches; +using WIDESEA_Core.DB; +using WIDESEA_Core.Enums; +using WIDESEA_Core.Helper; +using WIDESEA_DTO.System; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_SystemServices +{ + public class Sys_DictionaryService : ServiceBase<Sys_Dictionary, IRepository<Sys_Dictionary>>, ISys_DictionaryService + { + private readonly IUnitOfWorkManage _unitOfWorkManage; + private readonly ICacheService _cacheService; + + public Sys_DictionaryService(IRepository<Sys_Dictionary> BaseDal, IUnitOfWorkManage unitOfWorkManage, ICacheService cacheService) : base(BaseDal) + { + _unitOfWorkManage = unitOfWorkManage; + _cacheService = cacheService; + } + + public List<VueDictionaryDTO> GetVueDictionary(string[] dicNos) + { + if (dicNos == null || dicNos.Count() == 0) return new List<VueDictionaryDTO>(); + List<VueDictionaryDTO> vueDictionaryDTOs = new List<VueDictionaryDTO>(); + + List<string> cacheDicNos = new List<string>(); + foreach (string n in dicNos) + { + string? str = _cacheService.Get(n); + if (!string.IsNullOrEmpty(str)) + { + VueDictionaryDTO? vueDictionary = JsonConvert.DeserializeObject<VueDictionaryDTO>(str); + + if (vueDictionary != null) + { + vueDictionaryDTOs.Add(vueDictionary); + cacheDicNos.Add(n); + } + } + } + if (dicNos.Where(x => !cacheDicNos.Contains(x)).Count() > 0) + { + List<string> list = dicNos.Where(x => !cacheDicNos.Contains(x)).ToList(); + List<Sys_Dictionary> dictionaries = GetDictionaries(list).ToList(); + + List<VueDictionaryDTO> selectDics = dictionaries.Select(s => new VueDictionaryDTO + { + DicNo = s.DicNo, + Config = s.Config, + //dbSql = s.Sql, + Data = s.DicList.OrderByDescending(o => o.OrderNo).Select(list => new { key = list.DicValue, value = list.DicName }) + }).ToList(); + + foreach (var v in dictionaries) + { + if (!string.IsNullOrEmpty(v.DBSql)) + { + VueDictionaryDTO? temp = selectDics.FirstOrDefault(x => x.DicNo == v.DicNo); + if (temp != null) + selectDics.Remove(temp); + selectDics.Add(new VueDictionaryDTO + { + Config = v.Config, + DicNo = v.DicNo, + Data = BaseDal.QueryDynamicDataBySql(v.DBSql), + SaveCache = false, + }); + } + } + + foreach (var item in selectDics) + { + if (!_cacheService.Exists(item.DicNo) && item.SaveCache) + { + _cacheService.Add(item.DicNo, item.Serialize()); + } + } + vueDictionaryDTOs.AddRange(selectDics); + } + + return vueDictionaryDTOs; + } + + public IEnumerable<Sys_Dictionary> GetDictionaries(IEnumerable<string> dicNos, bool executeSql = false) + { + List<Sys_Dictionary> Dictionaries = GetAllDictionary(dicNos); + + return Dictionaries; + } + + List<Sys_DictionaryList> Query(string sql) + { + try + { + return BaseDal.QueryDynamicDataBySql(sql, null).Select(s => new Sys_DictionaryList() + { + DicName = s.Value, + DicValue = s.Key.ToString() + }).ToList(); + } + catch (Exception ex) + { + throw ex; + } + } + + private List<Sys_Dictionary> GetAllDictionary(IEnumerable<string> dicNos) + { + //base.QueryData().ToList(); + List<Sys_Dictionary> _dictionaries = Db.Queryable<Sys_Dictionary>().Includes(x => x.DicList).Where(x => x.Enable == 1 && dicNos.Contains(x.DicNo)).ToList(); + return _dictionaries; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_LogService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_LogService.cs" new file mode 100644 index 0000000..41e40fe --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_LogService.cs" @@ -0,0 +1,19 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_SystemServices +{ + public class Sys_LogService : ServiceBase<Sys_Log, IRepository<Sys_Log>>, ISys_LogService + { + public Sys_LogService(IRepository<Sys_Log> BaseDal) : base(BaseDal) + { + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_MenuService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_MenuService.cs" new file mode 100644 index 0000000..497a8df --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_MenuService.cs" @@ -0,0 +1,361 @@ +锘縰sing AutoMapper; +using SqlSugar; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_DTO.System; +using WIDESEA_Core; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_Core.Helper; +using WIDESEA_ISystemServices; +using WIDESEA_Model; +using WIDESEA_Model.Models; + +namespace WIDESEA_SystemServices +{ + public class Sys_MenuService : ServiceBase<Sys_Menu, IRepository<Sys_Menu>>, ISys_MenuService + { + private readonly IUnitOfWorkManage _unitOfWorkManage; + private readonly IMapper _mapper; + + public Sys_MenuService(IRepository<Sys_Menu> BaseDal, IUnitOfWorkManage unitOfWorkManage, IMapper mapper) : base(BaseDal) + { + _unitOfWorkManage = unitOfWorkManage; + _mapper = mapper; + } + + /// <summary> + /// 鑾峰彇褰撳墠鐢ㄦ埛鎵�鏈夎彍鍗曚笌鏉冮檺 + /// </summary> + /// <returns></returns> + public object GetCurrentMenuActionList() + { + object obj = GetMenuActionList(App.User.RoleId); + if (obj is IEnumerable<object> list) + { + if (list.Any()) + { + return obj; + } + else + { + return WebResponseContent.Instance.Error("鏈幏鍙栧埌鑿滃崟淇℃伅"); + } + } + return obj; + } + + public List<MenuDTO> GetAllMenu() + { + List<Sys_Menu> menus = BaseDal.QueryData(x => x.Enable == 1 || x.Enable == 2).OrderByDescending(a => a.OrderNo).ThenByDescending(q => q.ParentId).ToList(); + List<MenuDTO> _menus = _mapper.Map<List<MenuDTO>>(menus); + _menus.ForEach(x => + { + x.MenuType ??= 0; + if (!string.IsNullOrEmpty(x.Auth) && x.Auth.Length > 10) + { + try + { + x.Actions = x.Auth.DeserializeObject<List<ActionDTO>>(); + } + catch { } + } + x.Actions ??= new List<ActionDTO>(); + }); + string test = _menus.Serialize(); + return _menus; + } + + public object GetSuperAdminMenu() + { + return GetAllMenu().Select(x => + new + { + id = x.MenuId, + name = x.MenuName, + url = x.Url, + parentId = x.ParentId, + icon = x.Icon, + x.Enable, + x.TableName, // 2022.03.26澧炵Щ鍔ㄧ鍔犺彍鍗曠被鍨� + permission = x.Actions.Select(s => s.Value).ToArray() + }).ToList(); + } + + public object GetMenuByRoleId(int roleId) + { + var menu = from a in GetPermissions(roleId) + join b in GetAllMenu() + on a.MenuId equals b.MenuId + orderby b.OrderNo descending + select new + { + id = a.MenuId, + name = b.MenuName, + url = b.Url, + parentId = b.ParentId, + icon = b.Icon, + b.Enable, + b.TableName, + permission = a.UserAuthArr + }; + return menu.ToList(); + } + + /// <summary> + /// 鑾峰彇瑙掕壊鏉冮檺鏃堕�氳繃瀹夊叏瀛楀吀閿佸畾鐨勮鑹瞚d + /// </summary> + private static ConcurrentDictionary<string, object> objKeyValue = new ConcurrentDictionary<string, object>(); + + public List<Permissions> GetPermissions(int roleId) + { + if (App.User.IsRoleIdSuperAdmin(roleId)) + { + //2020.12.27澧炲姞鑿滃崟鐣岄潰涓婁笉鏄剧ず锛屼絾鍙互鍒嗛厤鏉冮檺 + var permissions = BaseDal.QueryData(x => x.Enable == 1 || x.Enable == 2) + .Select(a => new Permissions + { + MenuId = a.MenuId, + ParentId = a.ParentId, + TableName = (a.TableName ?? "").ToLower(), + UserAuth = a.Auth, + MenuType = a.MenuType ?? 0 + }).ToList(); + return MenuActionToArray(permissions); + } + + //閿佸畾姣忎釜瑙掕壊锛岄�氳繃瀹夊叏瀛楀吀鍑忓皯閿佺矑搴︼紝鍚﹀垯澶氫釜鍚屾椂瑙掕壊鑾峰彇缂撳瓨浼氬鑷撮樆濉� + object objId = objKeyValue.GetOrAdd(roleId.ToString(), new object()); + //閿佸畾姣忎釜瑙掕壊 + lock (objId) + { + //娌℃湁redis/memory缂撳瓨瑙掕壊鐨勭増鏈彿鎴栦笌褰撳墠鏈嶅姟鍣ㄧ殑瑙掕壊鐗堟湰鍙蜂笉鍚屾椂锛屽埛鏂扮紦瀛� + + List<Permissions> _permissions = BaseDal.QueryTabs<Sys_Menu, Sys_RoleAuth, Permissions>((a, b) => new object[] { JoinType.Inner, a.MenuId == b.MenuId }, (a, b) => new Permissions { MenuId = a.MenuId, ParentId = a.ParentId, TableName = (a.TableName ?? "").ToLower(), MenuAuth = a.Auth, UserAuth = b.AuthValue ?? "", MenuType = a.MenuType ?? 0 }, (a, b) => b.RoleId == roleId, x => true); + + ActionToArray(_permissions); + + return _permissions; + } + } + + private List<Permissions> MenuActionToArray(List<Permissions> permissions) + { + permissions.ForEach(x => + { + try + { + x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth) + ? new string[0] + : x.UserAuth.DeserializeObject<List<Sys_Actions>>().Select(s => s.Value).ToArray(); + } + catch { } + finally + { + if (x.UserAuthArr == null) + { + x.UserAuthArr = new string[0]; + } + } + }); + return permissions; + } + + private List<Permissions> ActionToArray(List<Permissions> permissions) + { + permissions.ForEach(x => + { + try + { + var menuAuthArr = x.MenuAuth.DeserializeObject<List<Sys_Actions>>(); + x.UserAuthArr = string.IsNullOrEmpty(x.UserAuth) + ? new string[0] + : x.UserAuth.Split(",").Where(c => menuAuthArr.Any(m => m.Value == c)).ToArray(); + + } + catch { } + finally + { + if (x.UserAuthArr == null) + { + x.UserAuthArr = new string[0]; + } + } + }); + return permissions; + } + + public object GetMenu(List<int> menuIds) + { + return BaseDal.QueryData(x => menuIds.Contains(x.MenuId)).Select(a => + new + { + id = a.MenuId, + parentId = a.ParentId, + name = a.MenuName, + a.MenuType, + a.OrderNo + }).OrderByDescending(a => a.OrderNo) + .ThenByDescending(q => q.parentId).ToList(); + } + + public object GetTreeItem(int menuId) + { + var sysMenu = BaseDal.QueryData(x => x.MenuId == menuId) + .Select( + p => new + { + p.MenuId, + p.ParentId, + p.MenuName, + p.Url, + p.Auth, + p.OrderNo, + p.Icon, + p.Enable, + // 2022.03.26澧炵Щ鍔ㄧ鍔犺彍鍗曠被鍨� + MenuType = p.MenuType ?? 0, + p.CreateDate, + p.Creater, + p.TableName, + p.ModifyDate + }).FirstOrDefault(); + return sysMenu; + } + + /// <summary> + /// 鏍规嵁瑙掕壊ID鑾峰彇鑿滃崟涓庢潈闄� + /// </summary> + /// <param name="roleId"></param> + /// <returns></returns> + public object GetMenuActionList(int roleId) + { + if (App.User.IsRoleIdSuperAdmin(roleId)) + { + return GetSuperAdminMenu(); + } + return GetMenuByRoleId(roleId); + } + + + public List<MenuDTO> GetUserMenuList(int roleId) + { + if (App.User.IsRoleIdSuperAdmin(roleId)) + { + return GetAllMenu(); + } + List<int> menuIds = GetPermissions(roleId).Select(x => x.MenuId).ToList(); + return GetAllMenu().Where(x => menuIds.Contains(x.MenuId)).ToList(); + } + + public List<ActionDTO> GetActions(int menuId, List<ActionDTO> menuActions, List<Permissions> permissions, int roleId) + { + if (App.User.IsRoleIdSuperAdmin(roleId)) + { + return menuActions; + } + + return menuActions.Where(p => permissions + .Exists(w => menuId == w.MenuId + && w.UserAuthArr.Contains(p.Value))) + .ToList(); + } + + /// <summary> + /// 缂栬緫淇敼鑿滃崟鏃�,鑾峰彇鎵�鏈夎彍鍗� + /// </summary> + /// <returns></returns> + public object GetMenu() + { + if (App.User.IsRoleIdSuperAdmin(App.User.RoleId)) + { + List<int> menuIds = BaseDal.QueryData().Select(x => x.MenuId).ToList(); + return GetMenu(menuIds); + } + else + { + List<int> menuIds = GetPermissions(App.User.RoleId).Select(x => x.MenuId).ToList(); + return GetMenu(menuIds); + } + } + + /// <summary> + /// 鏂板缓鎴栫紪杈戣彍鍗� + /// </summary> + /// <param name="menu"></param> + /// <returns></returns> + public WebResponseContent Save(Sys_Menu menu) + { + WebResponseContent webResponse = new WebResponseContent(); + if (menu == null) return webResponse.Error("娌℃湁鑾峰彇鍒版彁浜ょ殑鍙傛暟"); + if (menu.MenuId > 0 && menu.MenuId == menu.ParentId) return webResponse.Error("鐖剁骇ID涓嶈兘鏄綋鍓嶈彍鍗曠殑ID"); + try + { + //webResponse = menu.ValidationEntity(x => new { x.MenuName, x.TableName }); + //if (!webResponse.Status) return webResponse; + if (menu.TableName != "/" && menu.TableName != ".") + { + // 2022.03.26澧炵Щ鍔ㄧ鍔犺彍鍗曠被鍨嬪垽鏂� + Sys_Menu sysMenu = BaseDal.QueryFirst(x => x.TableName == menu.TableName); + if (sysMenu != null) + { + sysMenu.MenuType ??= 0; + if (sysMenu.MenuType == menu.MenuType) + { + if ((menu.MenuId > 0 && sysMenu.MenuId != menu.MenuId) + || menu.MenuId <= 0) + { + return webResponse.Error($"瑙嗗浘/琛ㄥ悕銆恵menu.TableName}銆戝凡琚叾浠栬彍鍗曚娇鐢�"); + } + } + } + } + bool _changed = false; + if (menu.MenuId <= 0) + { + int id = BaseDal.AddData(menu); + menu.MenuId = id; + } + else + { + //2020.05.07鏂板绂佹閫夋嫨涓婄骇瑙掕壊涓鸿嚜宸� + if (menu.MenuId == menu.ParentId) + { + return webResponse.Error($"鐖剁骇id涓嶈兘涓鸿嚜宸�"); + } + if (BaseDal.QueryFirst(x => x.ParentId == menu.MenuId && menu.ParentId == x.MenuId) != null) + { + return webResponse.Error($"涓嶈兘閫夋嫨姝ょ埗绾d锛岄�夋嫨鐨勭埗绾d涓庡綋鍓嶈彍鍗曞舰鎴愪緷璧栧叧绯�"); + } + + _changed = BaseDal.QueryData(c => c.MenuId == menu.MenuId).Select(s => s.Auth).FirstOrDefault() != menu.Auth; + + BaseDal.UpdateData(menu); + } + webResponse.OK("淇濆瓨鎴愬姛", menu); + } + catch (Exception ex) + { + webResponse.Error(ex.Message); + } + return webResponse; + + } + + public WebResponseContent DelMenu(int menuId) + { + WebResponseContent webResponse = new WebResponseContent(); + if(BaseDal.QueryFirst(x=>x.ParentId == menuId) != null) + { + return webResponse = WebResponseContent.Instance.Error("褰撳墠鑿滃崟瀛樺湪瀛愯彍鍗�,璇峰厛鍒犻櫎瀛愯彍鍗�!"); + } + BaseDal.DeleteDataById(menuId); + + return webResponse = WebResponseContent.Instance.OK("鍒犻櫎鎴愬姛"); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_RoleAuthService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_RoleAuthService.cs" new file mode 100644 index 0000000..46a0dcc --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_RoleAuthService.cs" @@ -0,0 +1,19 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_SystemServices +{ + public class Sys_RoleAuthService : ServiceBase<Sys_RoleAuth, IRepository<Sys_RoleAuth>>, ISys_RoleAuthService + { + public Sys_RoleAuthService(IRepository<Sys_RoleAuth> BaseDal) : base(BaseDal) + { + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_RoleService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_RoleService.cs" new file mode 100644 index 0000000..89b550c --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_RoleService.cs" @@ -0,0 +1,209 @@ +锘縰sing Microsoft.AspNetCore.DataProtection.KeyManagement; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_DTO.System; +using WIDESEA_Core; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_Core.HttpContextUser; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; +using WIDESEA_Model.Models.System; + +namespace WIDESEA_SystemServices.System +{ + public class Sys_RoleService : ServiceBase<Sys_Role, IRepository<Sys_Role>>, ISys_RoleService + { + private readonly IUnitOfWorkManage _unitOfWorkManage; + private readonly ISys_MenuService _MenuService; + private readonly IRepository<Sys_RoleAuth> _RoleAuthRepository; + public Sys_RoleService(IRepository<Sys_Role> BaseDal, ISys_MenuService MenuService, IRepository<Sys_RoleAuth> roleAuthRepository, IUnitOfWorkManage unitOfWorkManage) : base(BaseDal) + { + _unitOfWorkManage = unitOfWorkManage; + _MenuService = MenuService; + _RoleAuthRepository = roleAuthRepository; + } + + public List<RoleNodes> GetAllChildren(int roleId) + { + if (roleId <= 0) return new List<RoleNodes>() { }; + var roles = GetAllRoleId(); + if (App.User.IsRoleIdSuperAdmin(roleId)) return roles; + + var list = GetChildren(roles, roleId); + return list; + } + + public List<RoleNodes> GetAllRoleId() + { + List<RoleNodes> roles = BaseDal.QueryData().Select(s => new RoleNodes() { Id = s.RoleId, ParentId = s.ParentId, RoleName = s.RoleName }).ToList(); + + return roles; + } + + /// <summary> + /// 鑾峰彇鎵�鏈夊瓙鑺傜偣 + /// </summary> + /// <param name="roleId"></param> + private List<RoleNodes> GetChildren(List<RoleNodes> roles, int roleId) + { + List<RoleNodes> rolesChildren = roles.Where(x => x.Id == roleId).Distinct().ToList(); + + for (int i = 0; i < rolesChildren.Count; i++) + { + RoleNodes node = rolesChildren[i]; + var children = roles.Where(x => x.ParentId == node.Id && !rolesChildren.Any(c => c.Id == x.Id)).Distinct().ToList(); + rolesChildren.AddRange(children); + } + return rolesChildren; + } + + /// <summary> + /// 缂栬緫鏉冮檺鏃惰幏鍙栧綋鍓嶇敤鎴蜂笅鐨勬墍鏈夎鑹蹭笌褰撳墠鐢ㄦ埛鐨勮彍鍗曟潈闄� + /// </summary> + /// <returns></returns> + public WebResponseContent GetCurrentTreePermission() + { + WebResponseContent content = GetCurrentUserTreePermission(); + int roleId = App.User.RoleId; + return WebResponseContent.Instance.OK(null, new + { + tree = content.Data, + roles = GetAllChildren(roleId) + }); + } + + /// <summary> + /// 缂栬緫鏉冮檺鏃讹紝鑾峰彇褰撳墠鐢ㄦ埛鐨勬墍鏈夎彍鍗曟潈闄� + /// </summary> + /// <returns></returns> + public WebResponseContent GetCurrentUserTreePermission() + { + return GetUserTreePermission(App.User.RoleId); + } + + /// <summary> + /// 缂栬緫鏉冮檺鏃讹紝鑾峰彇鎸囧畾瑙掕壊鐨勬墍鏈夎彍鍗曟潈闄� + /// </summary> + /// <param name="roleId"></param> + /// <returns></returns> + public WebResponseContent GetUserTreePermission(int roleId) + { + if (!App.User.IsRoleIdSuperAdmin(roleId) && App.User.RoleId != roleId) + { + if (!(GetAllChildren(App.User.RoleId)).Exists(x => x.Id == roleId)) + { + return WebResponseContent.Instance.Error("娌℃湁鏉冮檺鑾峰彇姝よ鑹茬殑鏉冮檺淇℃伅"); + } + } + //鑾峰彇鐢ㄦ埛鏉冮檺 + List<Permissions> permissions = _MenuService.GetPermissions(roleId); + //鏉冮檺鐢ㄦ埛鏉冮檺鏌ヨ鎵�鏈夌殑鑿滃崟淇℃伅 + List<MenuDTO> menus = _MenuService.GetUserMenuList(roleId); + //鑾峰彇褰撳墠鐢ㄦ埛鏉冮檺濡�:(Add,Search)瀵瑰簲鐨勬樉绀烘枃鏈俊鎭:Add锛氭坊鍔狅紝Search:鏌ヨ + var data = menus.Select(x => new + { + Id = x.MenuId, + Pid = x.ParentId, + Text = x.MenuName, + IsApp = x.MenuType == 1, + Actions = _MenuService.GetActions(x.MenuId, x.Actions, permissions, roleId) + }); + return WebResponseContent.Instance.OK(null, data); + } + + /// <summary> + /// 淇濆瓨瑙掕壊鏉冮檺 + /// </summary> + /// <param name="userPermissions"></param> + /// <param name="roleId"></param> + /// <returns></returns> + public WebResponseContent SavePermission(List<UserPermissionDTO> userPermissions, int roleId) + { + WebResponseContent content = new WebResponseContent(); + string message = ""; + try + { + if (!GetAllChildren(App.User.RoleId).Exists(x => x.Id == roleId)) + return WebResponseContent.Instance.Error("娌℃湁鏉冮檺淇敼姝よ鑹茬殑鏉冮檺淇℃伅"); + //褰撳墠鐢ㄦ埛鐨勬潈闄� + List<Permissions> permissions = _MenuService.GetPermissions(App.User.RoleId); + + List<int> originalMeunIds = new List<int>(); + //琚垎閰嶈鑹茬殑鏉冮檺 + List<Sys_RoleAuth> roleAuths = _RoleAuthRepository.QueryData(x => x.RoleId == roleId); + List<Sys_RoleAuth> updateAuths = new List<Sys_RoleAuth>(); + foreach (UserPermissionDTO x in userPermissions) + { + Permissions per = permissions.FirstOrDefault(p => p.MenuId == x.Id); + //涓嶈兘鍒嗛厤瓒呰繃褰撳墠鐢ㄦ埛鐨勬潈闄� + if (per == null) continue; + //per.UserAuthArr.Contains(a.Value)鏍¢獙鏉冮檺鑼冨洿 + string[] arr = x.Actions == null || x.Actions.Count == 0 + ? new string[0] + : x.Actions.Where(a => per.UserAuthArr.Contains(a.Value)) + .Select(s => s.Value).ToArray(); + + //濡傛灉褰撳墠鏉冮檺娌℃湁鍒嗛厤杩囷紝璁剧疆Auth_Id榛樿涓�0锛岃〃绀烘柊澧炵殑鏉冮檺 + var auth = roleAuths.Where(r => r.MenuId == x.Id).Select(s => new { s.AuthId, s.AuthValue, s.MenuId }).FirstOrDefault(); + string newAuthValue = string.Join(",", arr); + //鏉冮檺娌℃湁鍙戠敓鍙樺寲鍒欎笉澶勭悊 + if (auth == null || auth.AuthValue != newAuthValue) + { + updateAuths.Add(new Sys_RoleAuth() + { + RoleId = roleId, + MenuId = x.Id, + AuthValue = string.Join(",", arr), + AuthId = auth == null ? 0 : auth.AuthId, + ModifyDate = DateTime.Now, + Modifier = App.User.UserName, + CreateDate = DateTime.Now, + Creater = App.User.UserName + }); + } + else + { + originalMeunIds.Add(auth.MenuId); + } + + } + //鏇存柊鏉冮檺 + _RoleAuthRepository.UpdateData(updateAuths); + //鏂板鐨勬潈闄� + _RoleAuthRepository.AddData(updateAuths); + + //鑾峰彇鏉冮檺鍙栨秷鐨勬潈闄� + int[] authIds = roleAuths.Where(x => userPermissions.Select(u => u.Id) + .ToList().Contains(x.MenuId) || originalMeunIds.Contains(x.MenuId)) + .Select(s => s.AuthId) + .ToArray(); + List<Sys_RoleAuth> delAuths = roleAuths.Where(x => x.AuthValue != "" && !authIds.Contains(x.AuthId)).ToList(); + delAuths.ForEach(x => + { + x.AuthValue = ""; + }); + //灏嗗彇娑堢殑鏉冮檺璁剧疆涓�"" + _RoleAuthRepository.DeleteData(delAuths); + + int addCount = updateAuths.Where(x => x.AuthId <= 0).Count(); + int updateCount = updateAuths.Where(x => x.AuthId > 0).Count(); + + string _version = DateTime.Now.ToString("yyyyMMddHHMMssfff"); + + + content.OK($"淇濆瓨鎴愬姛锛氭柊澧炲姞閰嶈彍鍗曟潈闄恵addCount}鏉�,鏇存柊鑿滃崟{updateCount}鏉�,鍒犻櫎鏉冮檺{delAuths.Count}鏉�"); + } + catch (Exception ex) + { + message = "寮傚父淇℃伅锛�" + ex.Message + ex.StackTrace + ","; + } + + return content; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_TenantService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_TenantService.cs" new file mode 100644 index 0000000..e90129c --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_TenantService.cs" @@ -0,0 +1,79 @@ +锘縰sing SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WIDESEA_Core; +using WIDESEA_Core.AOP; +using WIDESEA_Core.BaseRepository; +using WIDESEA_Core.BaseServices; +using WIDESEA_Core.Const; +using WIDESEA_Core.Helper; +using WIDESEA_Core.Seed; +using WIDESEA_ISystemServices; +using WIDESEA_Model.Models; + +namespace WIDESEA_SystemServices +{ + public class Sys_TenantService : ServiceBase<Sys_Tenant, IRepository<Sys_Tenant>>, ISys_TenantService + { + private IUnitOfWorkManage _unitOfWorkManage; + public Sys_TenantService(IRepository<Sys_Tenant> BaseDal, IUnitOfWorkManage unitOfWorkManage) : base(BaseDal) + { + _unitOfWorkManage = unitOfWorkManage; + } + + public WebResponseContent InitTenantInfo(string tenantName, int tenantType) + { + WebResponseContent content = new WebResponseContent(); + try + { + Sys_Tenant tenant = new Sys_Tenant() + { + ConnectionString = TenantConst.DBConStr, + DbType = 1, + Status = 1, + TenantName = tenantName, + TenantType = tenantType, + CreateDate = DateTime.Now, + Creater = "1111" + }; + + int tenantId = BaseDal.Db.Insertable(tenant).ExecuteReturnIdentity(); + + tenant = BaseDal.QueryFirst(x => x.TenantId == tenantId); + + tenant.ConnectionString = string.Format(TenantConst.DBConStr, ".", "Tenant_WMSDB_" + tenantId, "sa", "P@ssw0rd").EncryptDES(AppSecret.DB); + + BaseDal.UpdateData(tenant); + + InitTenantDb(tenant); + content = WebResponseContent.Instance.OK(); + } + catch (Exception ex) + { + content = WebResponseContent.Instance.Error(ex.Message); + } + return content; + } + + public void InitTenantDb(Sys_Tenant tenant) + { + string conStr = tenant.ConnectionString.DecryptDES(AppSecret.DB); + + ConnectionConfig connectionConfig = new ConnectionConfig() + { + ConfigId = tenant.TenantId, + ConnectionString = conStr, + DbType = (DbType)tenant.DbType, + IsAutoCloseConnection = true, + AopEvents = new AopEvents() + { + DataExecuting = SqlSugarAop.DataExecuting + } + }; + DBSeed.InitTenantSeedAsync(Db.AsTenant(), connectionConfig); + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_UserService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_UserService.cs" new file mode 100644 index 0000000..73f4b3b --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/Sys_UserService.cs" @@ -0,0 +1,186 @@ +锘縰sing WIDESEA_Core.Authorization; +using WIDESEA_Core; +using WIDESEA_Core.BaseServices; +using WIDESEA_Core.Const; +using WIDESEA_Core.Helper; +using WIDESEA_Core.HttpContextUser; +using WIDESEA_ISystemServices; +using WIDESEA_Model; +using WIDESEA_Model.Models; +using WIDESEA_Core.BaseRepository; +using System.Net; +using WIDESEA_Core.Caches; + +namespace WIDESEA_SystemServices +{ + public class Sys_UserService : ServiceBase<Sys_User, IRepository<Sys_User>>, ISys_UserService + { + private readonly IUnitOfWorkManage _unitOfWorkManage; + private readonly ICacheService _cacheService; + private readonly ISys_MenuService _menuService; + public Sys_UserService(IRepository<Sys_User> repository, IUnitOfWorkManage unitOfWorkManage, ICacheService cacheService, ISys_MenuService menuService) : base(repository) + { + _unitOfWorkManage = unitOfWorkManage; + _cacheService = cacheService; + _menuService = menuService; + } + + public WebResponseContent Login(LoginInfo loginInfo) + { + WebResponseContent content = new WebResponseContent(); + try + { + //BaseDal.QueryFirst(x => x.UserName == loginInfo.UserName); + + string msg = string.Empty; + + #region 涓存椂浣跨敤 + try + { + loginInfo.Password = loginInfo.Password.EncryptDES(AppSecret.User); + } + catch + { + + } + #endregion + + UserInfo user = BaseDal.QueryFirst(x => x.UserName == loginInfo.UserName && x.UserPwd == loginInfo.Password, x => new UserInfo { HeadImageUrl = x.HeadImageUrl, RoleId = x.Role_Id, TenantId = x.TenantId, UserId = x.User_Id, UserName = x.UserName, UserTrueName = x.UserTrueName }); + if (user != null) + { + object obj = _menuService.GetMenuActionList(user.RoleId); + if (obj is not IEnumerable<object> list) + { + return WebResponseContent.Instance.Error("鏃犵櫥褰曟潈闄�"); + } + if (!list.Any()) + { + return WebResponseContent.Instance.Error("鏃犵櫥褰曟潈闄�"); + } + + string token = JwtHelper.IssueJwt(new TokenModelJwt() + { + UserId = user.UserId, + RoleId = user.RoleId, + UserName = user.UserName, + TenantId = user.TenantId, + }); + + _cacheService.AddOrUpdate(user.UserId.ToString(), token); + + content = WebResponseContent.Instance.OK(data: new { token, userName = user.UserTrueName, img = user.HeadImageUrl }); + } + else + { + content = WebResponseContent.Instance.Error("璐﹀彿鎴栧瘑鐮侀敊璇�"); + } + } + catch (Exception ex) + { + content = WebResponseContent.Instance.Error(ex.Message); + } + + return content; + } + + public override WebResponseContent UpdateData(SaveModel saveModel) + { + UpdateIgnoreColOnExecute = x => + { + return new List<string> + { + nameof(Sys_User.UserPwd), + nameof(Sys_User.TenantId) + }; + }; + return base.UpdateData(saveModel); + } + + public override WebResponseContent AddData(SaveModel saveModel) + { + string pwd = "123456"; + string uesrName = saveModel.MainData[nameof(Sys_User.UserName).FirstLetterToLower()].ToString(); + saveModel.MainData[nameof(Sys_User.UserPwd).FirstLetterToLower()] = pwd.EncryptDES(AppSecret.User); + + WebResponseContent content = base.AddData(saveModel); + if (content.Status) + { + return WebResponseContent.Instance.OK($"鐢ㄦ埛鏂板缓鎴愬姛.甯愬彿{uesrName}瀵嗙爜{pwd}"); + } + else + { + return content; + } + } + + /// <summary> + /// 涓汉涓績鑾峰彇褰撳墠鐢ㄦ埛淇℃伅 + /// </summary> + /// <returns></returns> + public WebResponseContent GetCurrentUserInfo() + { + var data = BaseDal.QueryFirst(x => x.User_Id == App.User.UserId, s => new + { + s.UserName, + s.UserTrueName, + //s.Address, + //s.PhoneNo, + //s.Email, + s.Remark, + //s.Gender, + s.RoleName, + s.HeadImageUrl, + s.CreateDate + }); + return WebResponseContent.Instance.OK(null, data); + } + + /// <summary> + /// 淇敼瀵嗙爜 + /// </summary> + /// <param name="parameters"></param> + /// <returns></returns> + public WebResponseContent ModifyPwd(string oldPwd, string newPwd) + { + WebResponseContent content = WebResponseContent.Instance; + oldPwd = oldPwd?.Trim(); + newPwd = newPwd?.Trim(); + string message = ""; + try + { + if (string.IsNullOrEmpty(oldPwd)) return WebResponseContent.Instance.Error("鏃у瘑鐮佷笉鑳戒负绌�"); + if (string.IsNullOrEmpty(newPwd)) return WebResponseContent.Instance.Error("鏂板瘑鐮佷笉鑳戒负绌�"); + if (newPwd.Length < 6) return WebResponseContent.Instance.Error("瀵嗙爜涓嶈兘灏戜簬6浣�"); + + int userId = App.User.UserId; + string userCurrentPwd = BaseDal.QueryFirst(x => x.User_Id == userId, s => s.UserPwd); + + string _oldPwd = oldPwd.EncryptDES(AppSecret.User); + if (_oldPwd != userCurrentPwd) return WebResponseContent.Instance.Error("鏃у瘑鐮佷笉姝g‘"); + + string _newPwd = newPwd.EncryptDES(AppSecret.User); + if (userCurrentPwd == _newPwd) return WebResponseContent.Instance.Error("鏂板瘑鐮佷笉鑳戒笌鏃у瘑鐮佺浉鍚�"); + + + BaseDal.UpdateData(new Sys_User + { + User_Id = userId, + UserPwd = _newPwd, + LastModifyPwdDate = DateTime.Now + }, new List<string> + { + nameof(Sys_User.LastModifyPwdDate), + nameof(Sys_User.UserPwd) + }); + + content = WebResponseContent.Instance.OK("瀵嗙爜淇敼鎴愬姛"); + } + catch (Exception ex) + { + message = ex.Message; + content = WebResponseContent.Instance.Error("鏈嶅姟鍣ㄤ簡鐐归棶棰�,璇风◢鍚庡啀璇�"); + } + return content; + } + } +} diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/WIDESEA_SystemServices.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/WIDESEA_SystemServices.csproj" new file mode 100644 index 0000000..483a1c7 --- /dev/null +++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WIDESEA_ProductMgmtServer/WIDESEA_SystemServices/WIDESEA_SystemServices.csproj" @@ -0,0 +1,13 @@ +锘�<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\WIDESEA_ISystemServices\WIDESEA_ISystemServices.csproj" /> + </ItemGroup> + +</Project> -- Gitblit v1.9.3