├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── LICENSE ├── README.md ├── src ├── .editorconfig ├── .idea │ ├── .idea.BlazorAdmin │ │ └── .idea │ │ │ ├── .gitignore │ │ │ ├── .name │ │ │ ├── encodings.xml │ │ │ ├── indexLayout.xml │ │ │ └── vcs.xml │ └── config │ │ └── applicationhost.config ├── .template.config │ ├── template.json │ └── templates │ │ ├── web │ │ ├── BlazorAdmin.sln │ │ └── BlazorAdmin │ │ │ ├── BlazorAdmin.csproj │ │ │ └── simple.db │ │ ├── winforms │ │ ├── BlazorAdmin.sln │ │ └── BlazorAdmin │ │ │ ├── BlazorAdmin.csproj │ │ │ └── simple.db │ │ └── wpf │ │ ├── BlazorAdmin.sln │ │ └── BlazorAdmin │ │ ├── BlazorAdmin.csproj │ │ └── simple.db ├── BlazorAdmin.Client │ ├── AutoInjectWasmctContext.cs │ ├── BlazorAdmin.Client.csproj │ ├── FreeRoutes.razor │ ├── HttpClientHandlers │ │ └── GeneratedApiHandler.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Routes.razor │ ├── TestPages │ │ ├── AdditionalTest.cs │ │ ├── Components │ │ │ ├── DialogTest.razor │ │ │ └── RouteParam.razor │ │ ├── LocatorTest.cs │ │ ├── Tasks │ │ │ ├── TaskInfo.cs │ │ │ ├── TestCronExpression.razor │ │ │ ├── TestCronExpression.razor.cs │ │ │ ├── TestTask.cs │ │ │ └── TestTaskList.cs │ │ ├── TestBodyEvent.razor │ │ ├── TestCamera.razor │ │ ├── TestException.razor │ │ ├── TestGrid.razor │ │ ├── TestGrid.razor.css │ │ ├── TestGrid.razor.js │ │ ├── TestIcon.razor │ │ ├── TestPageAction.razor │ │ ├── TestQuery.razor │ │ ├── TestQuery.razor.cs │ │ ├── TestRouteParam.razor │ │ ├── TestRouteParam.razor.css │ │ ├── TestSplitAndDataTable.razor │ │ ├── TestSplitAndDataTable.razor.cs │ │ ├── TestStackPanel.razor │ │ ├── TestStackPanel.razor.cs │ │ ├── TestStackPanel.razor.css │ │ └── TestTabs.razor │ ├── _Imports.razor │ ├── usings.cs │ └── wwwroot │ │ ├── appsettings.Development.json │ │ └── appsettings.json ├── BlazorAdmin.sln ├── BlazorAdmin │ ├── .config │ │ └── dotnet-tools.json │ ├── App.razor │ ├── AutoInjectContext.cs │ ├── BlazorAdmin.csproj │ ├── Langs │ │ └── zh-CN │ │ │ └── RouterStore.json │ ├── LightOrmTableContext.cs │ ├── Login.cs │ ├── LoginOld.razor │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── ServerFreeRoutes.razor │ ├── ServerRoutes.razor │ ├── _Imports.razor │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── simple.db │ ├── usings.cs │ └── wwwroot │ │ ├── app.css │ │ ├── favicon.ico │ │ └── js │ │ ├── blazor-admin-project.js │ │ └── blazor-admin-project.js.map ├── RunBuild │ └── RunBuild.csproj ├── Shared │ ├── Project.AppCore │ │ ├── Auth │ │ │ ├── JwtTokenHelper.cs │ │ │ └── PersistingRevalidatingAuthenticationStateProvider.cs │ │ ├── BackgroundServices │ │ │ └── TempFileCleanUpService.cs │ │ ├── HttpContextExtensions.cs │ │ ├── Middlewares │ │ │ ├── CheckBrowserEnabledMiddleware.cs │ │ │ ├── ClientHeartBeatMiddleware.cs │ │ │ ├── FileDownloaderMiddleware.cs │ │ │ ├── GetClientIpMiddleware.cs │ │ │ ├── MiddlewareHelpers.cs │ │ │ ├── RedirectToLauchUrl.cs │ │ │ └── SetUserInfoMiddleware.cs │ │ ├── Program.cs │ │ ├── Project.AppCore.csproj │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── Services │ │ │ ├── ClientService.cs │ │ │ ├── DefaultAuthenticationService.cs │ │ │ └── FileService.cs │ │ ├── WebService.cs │ │ └── usings.cs │ ├── Project.Constraints │ │ ├── Aop │ │ │ ├── AopLogger.cs │ │ │ ├── AopPermissionCheck.cs │ │ │ └── LogInfoAttribute.cs │ │ ├── AppConst.cs │ │ ├── Common │ │ │ ├── Attributes │ │ │ │ ├── AutoLoadJsModuleAttribute.cs │ │ │ │ ├── ColumnDefinitionAttribute.cs │ │ │ │ ├── ExcludeFromInteractiveRoutingAttribute.cs │ │ │ │ ├── LangNameAttribute.cs │ │ │ │ ├── PageInfoAttribute.cs │ │ │ │ └── RelatedPermissionAttribute.cs │ │ │ ├── ClassHelper.cs │ │ │ ├── ConstraintString.cs │ │ │ ├── ExpressionHelper.cs │ │ │ ├── ObjectExtensions.cs │ │ │ ├── SessionCache.cs │ │ │ ├── StaticCache.cs │ │ │ ├── StyleBuilder.cs │ │ │ └── UserAgentHelper.cs │ │ ├── IAppSession.cs │ │ ├── IAuthenticationStateProvider.cs │ │ ├── IDashboardContentProvider.cs │ │ ├── Models │ │ │ ├── ClientInfo.cs │ │ │ ├── JsActionResult.cs │ │ │ ├── KeyRelations.cs │ │ │ ├── LoginFormModel.cs │ │ │ ├── Permissions │ │ │ │ ├── IPower.cs │ │ │ │ ├── IRole.cs │ │ │ │ ├── IRolePower.cs │ │ │ │ ├── IRunLog.cs │ │ │ │ ├── IUser.cs │ │ │ │ └── IUserRole.cs │ │ │ ├── QueryResult.cs │ │ │ ├── Request │ │ │ │ ├── ConditionUnit.cs │ │ │ │ ├── GenericRequest.cs │ │ │ │ └── IRequest.cs │ │ │ ├── SaveActionType.cs │ │ │ ├── SelectItem.cs │ │ │ └── UserInfo.cs │ │ ├── Options │ │ │ ├── AppSetting.cs │ │ │ ├── CameraResolution.cs │ │ │ ├── ClientHubOptions.cs │ │ │ ├── CultureOptions.cs │ │ │ └── Token.cs │ │ ├── Page │ │ │ ├── BasicComponent.cs │ │ │ ├── JsComponentBase.cs │ │ │ └── PageIndex.cs │ │ ├── PageHelper │ │ │ └── IPageAction.cs │ │ ├── Project.Constraints.csproj │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── Services │ │ │ ├── CircuitTrackerGlobalInfo.cs │ │ │ ├── IAddtionalTnterceptor.cs │ │ │ ├── IAuthService.cs │ │ │ ├── IBasicService.cs │ │ │ ├── IClientService.cs │ │ │ ├── IDownloadService.cs │ │ │ ├── IDownloadServiceProvider.cs │ │ │ ├── ILanguageService.cs │ │ │ ├── ILoginPage.cs │ │ │ ├── ILoginService.cs │ │ │ ├── IPageLocatorService.cs │ │ │ ├── IPemissionService.cs │ │ │ ├── IProjectSettingService.cs │ │ │ ├── IRunLogService.cs │ │ │ ├── ISvgIconService.cs │ │ │ ├── IUserService.cs │ │ │ └── IWebSettingInitService.cs │ │ ├── Store │ │ │ ├── IAppStore.cs │ │ │ ├── IProtectedLocalStorage.cs │ │ │ ├── IRouterStore.cs │ │ │ ├── IUserStore.cs │ │ │ └── Models │ │ │ │ ├── LayoutMode.cs │ │ │ │ ├── RouteMenu.cs │ │ │ │ ├── RouterMeta.cs │ │ │ │ ├── StorageResult.cs │ │ │ │ └── TagRoute.cs │ │ ├── UI │ │ │ ├── Builders │ │ │ │ ├── BindableComponentBuilder.cs │ │ │ │ ├── ButtonComponentBuilder.cs │ │ │ │ ├── ComponentBuilder.cs │ │ │ │ ├── ComponentBuilderBasic.cs │ │ │ │ ├── ElementBuilder.cs │ │ │ │ ├── PropComponentBuilder.cs │ │ │ │ └── SelectComponentBuilder.cs │ │ │ ├── ConditionInfo.cs │ │ │ ├── Dropdown │ │ │ │ ├── DropdownOptions.cs │ │ │ │ └── ProfileInfo.cs │ │ │ ├── Extensions │ │ │ │ ├── AlertExtensions.cs │ │ │ │ ├── BuildFormExtension.cs │ │ │ │ ├── BuildTableExtensions.cs │ │ │ │ ├── ButtonBuilderExtensions.cs │ │ │ │ ├── DialogExtensions.cs │ │ │ │ ├── DrawerExtensions.cs │ │ │ │ ├── MessageExtensions.cs │ │ │ │ ├── RenderFragmentBuilderExtensions.cs │ │ │ │ ├── SelectBuilderExtensions.cs │ │ │ │ ├── TableButtonCollectHelperExtensions.cs │ │ │ │ ├── UIComponentExtensions.cs │ │ │ │ └── UIServiceExtensions.cs │ │ │ ├── Flyout │ │ │ │ ├── DialogTemplate.cs │ │ │ │ ├── DrawerTemplate.razor │ │ │ │ ├── FlyoutOptions.cs │ │ │ │ └── FormDialogTemplate.cs │ │ │ ├── Form │ │ │ │ ├── FormBuilder.cs │ │ │ │ └── FormOptions.cs │ │ │ ├── IAppDomEventHandler.cs │ │ │ ├── IJsComponent.cs │ │ │ ├── IUIService.cs │ │ │ ├── Props │ │ │ │ ├── ButtonProp.cs │ │ │ │ ├── CardProp.cs │ │ │ │ ├── DefaultProp.cs │ │ │ │ ├── GridProp.cs │ │ │ │ ├── HtmlProp.cs │ │ │ │ ├── ModalProp.cs │ │ │ │ ├── SelectProp.cs │ │ │ │ └── SwitchProp.cs │ │ │ ├── Table │ │ │ │ ├── ColumnInfo.cs │ │ │ │ ├── ColumnItemContext.cs │ │ │ │ ├── TableButton.cs │ │ │ │ ├── TableColumnContext.cs │ │ │ │ └── TableOptions.cs │ │ │ └── Tree │ │ │ │ └── TreeOptions.cs │ │ ├── Utils │ │ │ ├── AsyncEventInvoke.cs │ │ │ ├── BooleanStatusManager.cs │ │ │ ├── ClaimsHelper.cs │ │ │ ├── ConditionUnitHelper.cs │ │ │ ├── EnumHelper.cs │ │ │ └── HashHelper.cs │ │ └── usings.cs │ ├── Project.UI.AntBlazor │ │ ├── Components │ │ │ ├── AntCol.cs │ │ │ ├── AntDropdown.razor │ │ │ ├── AntDynamicTable.razor │ │ │ ├── AntForm.razor │ │ │ ├── AntLogin.razor │ │ │ ├── AntMenu.razor │ │ │ ├── AntMenu.razor.css │ │ │ ├── AntMenuItem.razor │ │ │ ├── AntMenuItem.razor.css │ │ │ ├── AntPopover.razor │ │ │ ├── AntProfile.razor │ │ │ ├── AntTable.razor │ │ │ ├── AntTable.razor.cs │ │ │ ├── AntTableColumns.cs │ │ │ └── AntTree.cs │ │ ├── Extensions.cs │ │ ├── Project.UI.AntBlazor.csproj │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── UIService.cs │ │ ├── Utils.cs │ │ └── _Imports.razor │ ├── Project.UI.FluentUI │ │ ├── Components │ │ │ ├── FluentEnumSelect.cs │ │ │ ├── FluentLogin.razor │ │ │ ├── FluentTable.razor │ │ │ ├── FluentUIMenu.razor │ │ │ ├── FluentUIMenuItem.razor │ │ │ └── IconHelper.cs │ │ ├── Extensions.cs │ │ ├── Project.UI.FluentUI.csproj │ │ ├── UIService.cs │ │ └── _Imports.razor │ └── Project.Web.Shared │ │ ├── Auth │ │ └── PersistentAuthenticationStateProvider.cs │ │ ├── Basic │ │ ├── AdvanceQuery.razor │ │ ├── DataTableView.cs │ │ ├── DefaultTableHeader.razor │ │ ├── DefaultTableHeader.razor.css │ │ ├── ModelPage.cs │ │ └── ModelPageExtension.cs │ │ ├── BasicSetting.cs │ │ ├── ComponentHelper │ │ ├── MCard.cs │ │ ├── MGrid.cs │ │ ├── MModal.cs │ │ ├── StackPanel.razor │ │ └── StackPanel.razor.css │ │ ├── Components │ │ ├── ActionWatcher │ │ │ ├── ActionWatcher.razor │ │ │ ├── ActionWatcher.razor.cs │ │ │ └── ActionWatcher.razor.ts │ │ ├── Camera │ │ │ ├── Camera.razor │ │ │ ├── Camera.razor.cs │ │ │ ├── Camera.razor.ts │ │ │ ├── CameraOptions.cs │ │ │ ├── CameraTest.razor │ │ │ ├── ICameraObject.cs │ │ │ ├── ICameraOptions.cs │ │ │ └── Resolution.cs │ │ ├── ClientHub │ │ │ ├── ClientHub.cs │ │ │ └── ClientHub.ts │ │ ├── ConditionBuilder │ │ │ ├── ConditionBuilder.razor │ │ │ ├── ConditionGroup.razor │ │ │ ├── Group.razor │ │ │ ├── Group.razor.css │ │ │ └── SingleConditionBuilder.razor │ │ ├── Conditions │ │ │ ├── Condition.razor │ │ │ ├── Condition.razor.cs │ │ │ ├── ConditionBase.cs │ │ │ ├── DateCondition.cs │ │ │ ├── EmptyCondition.razor │ │ │ ├── QueryConditions.razor │ │ │ ├── QueryConditions.razor.cs │ │ │ └── SimpleCondition.razor │ │ ├── Downloader │ │ │ ├── DownloadNotFound.razor │ │ │ ├── DownloadNotFound.razor.css │ │ │ ├── Downloader.razor │ │ │ └── Downloader.razor.ts │ │ ├── EdgeWidget │ │ │ ├── EdgeWidget.razor │ │ │ ├── EdgeWidget.razor.cs │ │ │ ├── EdgeWidget.razor.css │ │ │ └── EdgeWidget.razor.ts │ │ ├── ErrorCatcher │ │ │ ├── CrashPage.razor │ │ │ ├── CrashPage.razor.css │ │ │ ├── ErrorCatcher.cs │ │ │ ├── ErrorPage.razor │ │ │ ├── ErrorPage.razor.css │ │ │ └── IError.cs │ │ ├── Fetch │ │ │ ├── Fetch.razor │ │ │ ├── Fetch.razor.cs │ │ │ └── Fetch.razor.ts │ │ ├── ForbiddenPage.razor │ │ ├── ForbiddenPage.razor.css │ │ ├── FullScreen │ │ │ ├── FullScreen.razor │ │ │ ├── FullScreen.razor.cs │ │ │ └── FullScreen.razor.ts │ │ ├── Icon │ │ │ ├── FontIcon.cs │ │ │ ├── IconSelector.razor │ │ │ ├── IconSelector.razor.css │ │ │ ├── MIcon.cs │ │ │ ├── SvgIcon.cs │ │ │ ├── SvgIcon2.razor │ │ │ └── SvgIcon2.razor.ts │ │ ├── InputBuilder.cs │ │ ├── JsTimer │ │ │ ├── JsTimer.razor │ │ │ ├── JsTimer.razor.cs │ │ │ └── JsTimer.razor.ts │ │ ├── Link │ │ │ └── VLink.razor │ │ ├── MTree │ │ │ ├── CheckBoxState.razor │ │ │ ├── CheckBoxState.razor.css │ │ │ ├── MTree.razor │ │ │ ├── MTree.razor.cs │ │ │ ├── MTree.razor.css │ │ │ ├── MTreeNode.razor │ │ │ ├── MTreeNode.razor.cs │ │ │ └── MTreeNode.razor.css │ │ ├── Reconnector │ │ │ ├── IReconnector.cs │ │ │ ├── Reconnector.cs │ │ │ ├── ReconnectorContent.razor │ │ │ ├── ReconnectorContent.razor.css │ │ │ ├── ReconnectorOutlet.cs │ │ │ ├── WebAdminReconnector.razor │ │ │ └── WebAdminReconnector.razor.css │ │ ├── Script │ │ │ └── VScript.razor │ │ ├── ScrollBar │ │ │ ├── Bar.ts │ │ │ ├── HorizontalScroll.razor │ │ │ ├── HorizontalScroll.razor.css │ │ │ ├── HorizontalScroll.razor.ts │ │ │ ├── ScrollBar.razor │ │ │ ├── ScrollBar.razor.cs │ │ │ ├── ScrollBar.razor.css │ │ │ ├── ScrollBar.razor.ts │ │ │ └── Thumb.ts │ │ ├── SplitView │ │ │ ├── SplitView.razor │ │ │ ├── SplitView.razor.css │ │ │ └── SplitView.razor.ts │ │ └── WaterMark │ │ │ ├── IWatermarkService.cs │ │ │ ├── WaterMark.razor │ │ │ └── WaterMark.razor.ts │ │ ├── CustomSetting.cs │ │ ├── IndexLoading │ │ ├── IndexLoading.razor │ │ └── IndexLoading.razor.css │ │ ├── JsCore │ │ ├── Utils.ts │ │ ├── baseComponent.ts │ │ ├── componentStore.ts │ │ ├── customEventHandler.ts │ │ ├── dragHelper.ts │ │ ├── eventHandler.ts │ │ ├── eventHandlerSet.ts │ │ ├── handlerBase.ts │ │ ├── resizeHandler.ts │ │ └── utils.ts │ │ ├── Langs │ │ ├── en-US │ │ │ └── index.json │ │ ├── zh-CN │ │ │ └── index.json │ │ └── 语言文件查找说明.md │ │ ├── Layouts │ │ ├── AppRoot.razor │ │ ├── AppRoot.razor.cs │ │ ├── AuthorizedLayout.razor │ │ ├── FreeMainLayout.razor │ │ ├── LayoutComponents │ │ │ ├── AppMain.razor │ │ │ ├── Banner.razor │ │ │ ├── Banner.razor.css │ │ │ ├── LanguageSelect.razor │ │ │ ├── ModifyUserPassword.razor │ │ │ ├── NavBar.razor │ │ │ ├── NavBar.razor.css │ │ │ ├── NavMenu.razor │ │ │ ├── NavMenu.razor.css │ │ │ ├── NavMenuItem.razor │ │ │ ├── NavMenuItem.razor.css │ │ │ ├── NavTabs.razor │ │ │ ├── NavTabs.razor.cs │ │ │ ├── NavTabs.razor.css │ │ │ ├── NavTabs.razor.ts │ │ │ ├── Profile.razor │ │ │ ├── Profile.razor.css │ │ │ ├── RedirectToLogin.razor │ │ │ ├── SideBar.razor │ │ │ ├── SideBar.razor.css │ │ │ ├── WebSetting.razor │ │ │ └── WebSettingItems │ │ │ │ ├── LanguageSelector.razor │ │ │ │ ├── LayoutManager.razor │ │ │ │ ├── LayoutManager.razor.css │ │ │ │ └── ThemeManager.razor │ │ ├── Layouts │ │ │ ├── Aside.razor │ │ │ ├── Aside.razor.css │ │ │ ├── CardLayout.razor │ │ │ ├── CardLayout.razor.css │ │ │ ├── ClassicLayout.razor │ │ │ ├── ClassicLayout.razor.css │ │ │ ├── Header.razor │ │ │ ├── Header.razor.css │ │ │ ├── LayoutBase.cs │ │ │ ├── LineLayout.razor │ │ │ ├── Main.razor │ │ │ ├── Main.razor.css │ │ │ ├── Section.razor │ │ │ └── Section.razor.css │ │ ├── MainLayout.razor │ │ ├── MainLayout.razor.css │ │ ├── NotAuthorizedLayout.razor │ │ ├── RootLayout.razor │ │ └── RootLayout.razor.cs │ │ ├── Locales │ │ ├── EmbeddedJson │ │ │ ├── EmbeddedJsonLocalizer.cs │ │ │ └── EmbeddedJsonLocalizerFactory.cs │ │ ├── Extensions │ │ │ └── AddJsonLocales.cs │ │ └── Services │ │ │ ├── JsonInfo.cs │ │ │ ├── JsonLocalizationOptions.cs │ │ │ ├── JsonLocalizer.cs │ │ │ ├── JsonLocalizerFactory.cs │ │ │ └── LanguageService.cs │ │ ├── Pages │ │ ├── Component │ │ │ ├── AssignRolePowers.razor │ │ │ ├── AssignUserRoles.razor │ │ │ ├── JsonDisplay.razor │ │ │ ├── JsonDisplay.razor.css │ │ │ └── PowerIconSelector.razor │ │ ├── Dashboard.razor │ │ ├── Dashboard.razor.cs │ │ ├── DefaultLogin.razor │ │ ├── DefaultLogin.razor.css │ │ ├── OnlineUsers.cs │ │ ├── OperationLog.cs │ │ ├── PageIndex.cs │ │ ├── PermissionSetting.razor │ │ ├── PermissionSetting.razor.cs │ │ ├── RolePermission.cs │ │ ├── UnSupportPage.razor │ │ └── UserPage.cs │ │ ├── Project.Web.Shared.csproj │ │ ├── ProjectInit.cs │ │ ├── ProjectSetting.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── Routers │ │ ├── AllPages.cs │ │ └── RouterStore.cs │ │ ├── Services │ │ ├── DefaultPermissionService.cs │ │ ├── DefaultRunLogService.cs │ │ ├── DefaultUserService.cs │ │ └── SvgIconService.cs │ │ ├── Store │ │ ├── AppSession.cs │ │ ├── AppStore.cs │ │ ├── CacheItem.cs │ │ ├── MyProtectedLocalStorage.cs │ │ ├── StoreBase.cs │ │ └── UserStore.cs │ │ ├── Utils │ │ ├── DownloadExtensions.cs │ │ ├── FontAwesomeHelper.cs │ │ └── JsRuntimeExtension.cs │ │ ├── _Imports.razor │ │ ├── usings.cs │ │ └── wwwroot │ │ ├── assets │ │ ├── Cortana.png │ │ ├── avator.png │ │ ├── login_bg.png │ │ ├── logo.png │ │ ├── notsupport.jpg │ │ ├── p403_01.svg │ │ ├── p403_02.svg │ │ ├── p404.svg │ │ ├── p500_01.svg │ │ └── p500_02.svg │ │ ├── css │ │ └── font-awesome4.7.min.css │ │ ├── favicon.ico │ │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ │ ├── icons │ │ ├── svg-assign_permissions.svg │ │ ├── svg-camera.svg │ │ ├── svg-clear.svg │ │ ├── svg-collapse_menu.svg │ │ ├── svg-connecting.svg │ │ ├── svg-data1.svg │ │ ├── svg-expand_menu.svg │ │ ├── svg-fullscreen.svg │ │ ├── svg-home.svg │ │ ├── svg-language.svg │ │ ├── svg-left.svg │ │ ├── svg-loading.svg │ │ ├── svg-log.svg │ │ ├── svg-login.svg │ │ ├── svg-logout.svg │ │ ├── svg-maintain.svg │ │ ├── svg-pda.svg │ │ ├── svg-periodic.svg │ │ ├── svg-permission.svg │ │ ├── svg-region.svg │ │ ├── svg-right.svg │ │ ├── svg-rights.svg │ │ ├── svg-role.svg │ │ ├── svg-selective.svg │ │ ├── svg-setting.svg │ │ ├── svg-station.svg │ │ ├── svg-statistics.svg │ │ ├── svg-switch.svg │ │ └── svg-user.svg │ │ └── js │ │ └── jscomponentbase │ │ ├── CustomEventHandler.js │ │ ├── HandlerBase.js │ │ ├── ResizeHandler.js │ │ ├── base-component.js │ │ ├── component-store.js │ │ ├── drag-helper.js │ │ ├── event-handler.js │ │ └── utils.js ├── main.ts ├── package-lock.json ├── package.json ├── themeManager.ts ├── tsconfig.json ├── tsup.config.ts └── utilsAggregation.ts └── template.csproj /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (web)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | "program": "${workspaceFolder}/BlazorWebAdmin/bin/Debug/net6.0/BlazorWebAdmin.dll", 13 | "args": [], 14 | "cwd": "${workspaceFolder}/BlazorWebAdmin", 15 | "stopAtEntry": false, 16 | "serverReadyAction": { 17 | "action": "openExternally", 18 | "pattern": "\\bNow listening on:\\s+(https?://\\S+)" 19 | }, 20 | "env": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | }, 23 | "sourceFileMap": { 24 | "/Views": "${workspaceFolder}/Views" 25 | } 26 | }, 27 | { 28 | "name": ".NET Core Attach", 29 | "type": "coreclr", 30 | "request": "attach" 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 MarvelTiter_yaoqinglin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 使用方式 2 | ## 创建Template包 3 | - 项目根目录下运行`dotnet pack` 4 | - 安装`./bin/Release`下生成的nuget包 5 | - 运行`dotnet new mtblazor -n projectName` 6 | 7 | ## master分支 web host 8 | ## master.wpf分支 wpf host 9 | -------------------------------------------------------------------------------- /src/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 4 | # dotnet_diagnostic.CS8618.severity = none 5 | 6 | # CS8603: 可能返回 null 引用。 7 | # dotnet_diagnostic.CS8603.severity = none 8 | 9 | # IDE0008: 使用显式类型 10 | dotnet_diagnostic.IDE0008.severity = none 11 | -------------------------------------------------------------------------------- /src/.idea/.idea.BlazorAdmin/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # Rider 忽略的文件 5 | /modules.xml 6 | /projectSettingsUpdater.xml 7 | /contentModel.xml 8 | /.idea.BlazorAdmin.iml 9 | # 基于编辑器的 HTTP 客户端请求 10 | /httpRequests/ 11 | # Datasource local storage ignored files 12 | /dataSources/ 13 | /dataSources.local.xml 14 | -------------------------------------------------------------------------------- /src/.idea/.idea.BlazorAdmin/.idea/.name: -------------------------------------------------------------------------------- 1 | BlazorAdmin -------------------------------------------------------------------------------- /src/.idea/.idea.BlazorAdmin/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/.idea/.idea.BlazorAdmin/.idea/indexLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ../../BlazorWebAdmin 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/.idea/.idea.BlazorAdmin/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/.template.config/templates/web/BlazorAdmin/simple.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/.template.config/templates/web/BlazorAdmin/simple.db -------------------------------------------------------------------------------- /src/.template.config/templates/winforms/BlazorAdmin/BlazorAdmin.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net8.0-windows 6 | enable 7 | true 8 | enable 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Always 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/.template.config/templates/winforms/BlazorAdmin/simple.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/.template.config/templates/winforms/BlazorAdmin/simple.db -------------------------------------------------------------------------------- /src/.template.config/templates/wpf/BlazorAdmin/BlazorAdmin.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net8.0-windows 6 | BlazorWpfAdmin 7 | enable 8 | enable 9 | true 10 | false 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Always 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/.template.config/templates/wpf/BlazorAdmin/simple.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/.template.config/templates/wpf/BlazorAdmin/simple.db -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/AutoInjectWasmctContext.cs: -------------------------------------------------------------------------------- 1 | namespace BlazorAdmin.Client; 2 | 3 | 4 | [AutoInjectGenerator.AutoInjectContext] 5 | public static partial class AutoInjectWasmctContext 6 | { 7 | [AutoInjectGenerator.AutoInjectConfiguration(Include = "WASM")] 8 | public static partial void AutoInjectWasm(this IServiceCollection services); 9 | } 10 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/BlazorAdmin.Client.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | true 8 | Default 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/FreeRoutes.razor: -------------------------------------------------------------------------------- 1 | @using Project.Web.Shared.Layouts 2 | @using System.Reflection 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:5454", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 17 | "applicationUrl": "http://localhost:5227", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "IIS Express": { 23 | "commandName": "IISExpress", 24 | "launchBrowser": true, 25 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/Routes.razor: -------------------------------------------------------------------------------- 1 | @using Project.Web.Shared.Layouts 2 | @using System.Reflection 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/AdditionalTest.cs: -------------------------------------------------------------------------------- 1 | using AutoInjectGenerator; 2 | using Project.Constraints.Services; 3 | using Project.Constraints.Store.Models; 4 | 5 | namespace BlazorAdmin.Client.TestPages 6 | { 7 | [AutoInject(ServiceType = typeof(IAddtionalInterceptor))] 8 | public class AdditionalTest(IPageLocatorService pageLocator) : IAddtionalInterceptor 9 | { 10 | public Task RouterChangingAsync(TagRoute route) 11 | { 12 | Console.WriteLine($"AdditionalTest: RouterChangingAsync: {route.RouteUrl}"); 13 | return Task.FromResult(true); 14 | } 15 | 16 | public Task AfterWebApplicationAccessedAsync() 17 | { 18 | pageLocator.SetPage("LocatorTest"); 19 | return Task.CompletedTask; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/Components/DialogTest.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints.UI.Flyout 2 | @inherits DialogTemplate 3 | 4 |

Close Test

5 | Input: @(UI.BuildNumberInput(this).Bind(() => Value).Render()) 6 | @UI.BuildButton(this).Primary().Text("关闭").OnClick(CloseAsync).Render() 7 | @code { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/Components/RouteParam.razor: -------------------------------------------------------------------------------- 1 | @page "/param/{Id}" 2 | @using Project.Constraints.Common.Attributes 3 | @using Project.Constraints.PageHelper 4 | @implements IRoutePageTitle 5 | @* @attribute [TagTitle("路由参数")] *@ 6 | 接收的路由参数: @Id 7 | @code { 8 | [Parameter] public string? Id { get; set; } 9 | public RenderFragment GetTitle() 10 | { 11 | return $"详情-{Id}".AsContent(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/LocatorTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Project.Constraints.Common.Attributes; 3 | using Project.Constraints.Page; 4 | using Project.Constraints.Services; 5 | using Project.Constraints.UI; 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | namespace BlazorAdmin.Client.TestPages 9 | { 10 | #if DEBUG 11 | [Route("/testlocator")] 12 | [PageInfo(Title = "Locator测试", Icon = "fa fa-question-circle-o", ForceShowOnNavMenu = true, GroupId = "test")] 13 | #endif 14 | public class LocatorTest : PageIndex 15 | { 16 | protected override Type? GetPageType(IPageLocatorService pageLocator) 17 | { 18 | return pageLocator.GetPage("LocatorTest"); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/Tasks/TaskInfo.cs: -------------------------------------------------------------------------------- 1 | using MT.LightTask; 2 | using Project.Constraints.Common.Attributes; 3 | 4 | namespace BlazorAdmin.Client.TestPages.Tasks; 5 | 6 | public class TaskInfo 7 | { 8 | [ColumnDefinition("任务名称")] 9 | public string? Name { get; set; } 10 | [ColumnDefinition("调度状态")] 11 | public TaskScheduleStatus ScheduleStatus { get; internal set; } 12 | [ColumnDefinition("任务状态")] 13 | public TaskRunStatus TaskStatus { get; internal set; } 14 | [ColumnDefinition("最后运行时间", Format = "yyyy-MM-dd HH:mm:ss")] 15 | public DateTimeOffset? LastRuntime { get; internal set; } 16 | [ColumnDefinition("下次运行时间", Format = "yyyy-MM-dd HH:mm:ss")] 17 | public DateTimeOffset? NextRuntime { get; internal set; } 18 | [ColumnDefinition("最后运行耗时", Format = "dd\\-hh\\:mm\\:ss")] 19 | public TimeSpan? LastRunElapsedTime { get; internal set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/Tasks/TestCronExpression.razor: -------------------------------------------------------------------------------- 1 | 

TestCronExpression

2 | 3 | @UI.BuildInput(this).Bind(() => taskName).Render() 4 | @UI.BuildInput(this).Bind(() => cronExpressionString).Render() 5 | 6 |

7 | @UI.BuildButton(this).OnClick(Next).Text("下一次执行时间").Render() 8 | @UI.BuildButton(this).OnClick(NextTen).Text("连续10次").Render() 9 |

10 | @UI.BuildButton(this).Text("创建任务").OnClick(CreateTask).Render() 11 | 12 | @foreach(var i in values) 13 | { 14 |

@($"基准: {i.Item1:yyyy-MM-dd HH:mm:ss}") -> @($"下一次: {i.Item2:yyyy-MM-dd HH:mm:ss}")

15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/Tasks/TestTask.cs: -------------------------------------------------------------------------------- 1 | using AutoInjectGenerator; 2 | using MT.LightTask; 3 | 4 | namespace BlazorAdmin.Client.TestPages.Tasks 5 | { 6 | // [AutoInject(ServiceType = typeof(TestTask))] 7 | [AutoInjectSelf] 8 | public class TestTask : ITask 9 | { 10 | public Task ExecuteAsync(CancellationToken cancellationToken = default) 11 | { 12 | Console.WriteLine($"Task测试2: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"); 13 | return Task.CompletedTask; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestBodyEvent.razor: -------------------------------------------------------------------------------- 1 | @page "/testbodyevent" 2 | @using Project.Constraints.Common.Attributes 3 | @using System.Diagnostics.CodeAnalysis 4 | @using Project.Constraints.UI 5 | @attribute [PageInfo(Title = "BodyEvent测试", Icon = "fa fa-question-circle-o", ForceShowOnNavMenu = true, GroupId = "test")] 6 | @implements IAsyncDisposable 7 |
8 | @foreach (var item in keys) 9 | { 10 | @($"{item.Item1:yyyy-MM-dd HH:mm:ss}") => @item.Item2 11 | } 12 |
13 | @code { 14 | [CascadingParameter, NotNull] public IAppDomEventHandler? AppDom { get; set; } 15 | List<(DateTime, string)> keys = []; 16 | protected override void OnInitialized() 17 | { 18 | base.OnInitialized(); 19 | AppDom.OnKeyDown += HandleKeyDown; 20 | } 21 | 22 | Task HandleKeyDown(KeyboardEventArgs e) 23 | { 24 | keys.Add((DateTime.Now, e.Key)); 25 | return InvokeAsync(StateHasChanged); 26 | } 27 | 28 | public ValueTask DisposeAsync() 29 | { 30 | AppDom.OnKeyDown -= HandleKeyDown; 31 | return ValueTask.CompletedTask; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestCamera.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints.Common.Attributes 2 | @page "/testcamera" 3 | @attribute [PageInfo(Title = "Camera测试", Icon = "fa fa-question-circle-o", ForceShowOnNavMenu = true, GroupId = "test")] 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestGrid.razor.css: -------------------------------------------------------------------------------- 1 | .item { 2 | border: solid 1px black; 3 | height: 300px; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | } 8 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestGrid.razor.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestIcon.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints.Common.Attributes 2 | @using Project.Web.Shared.Components 3 | @page "/testicon" 4 | @attribute [PageInfo(Title = "Icon测试", Icon = "fa fa-question-circle-o", ForceShowOnNavMenu = true, GroupId = "test")] 5 | 6 | 7 | 8 | 9 | @code { 10 | string selectedIcon = string.Empty; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestPageAction.razor: -------------------------------------------------------------------------------- 1 | @page "/testpageaction" 2 | @using Project.Constraints.Common.Attributes 3 | @using System.Diagnostics.CodeAnalysis 4 | @using Project.Constraints.PageHelper 5 | @using Project.Constraints.UI 6 | @attribute [PageInfo(Title = "PageAction测试", Icon = "fa fa-question-circle-o", ForceShowOnNavMenu = true, GroupId = "test")] 7 | @implements IPageAction 8 |
9 | @foreach (var item in contents) 10 | { 11 | @($"{item.Item1:yyyy-MM-dd HH:mm:ss}") => @item.Item2 12 | } 13 |
14 | @code { 15 | List<(DateTime, string)> contents = []; 16 | 17 | public Task OnShowAsync() 18 | { 19 | contents.Add((DateTime.Now, "PageShow")); 20 | return InvokeAsync(StateHasChanged); 21 | } 22 | 23 | public Task OnHiddenAsync() 24 | { 25 | contents.Add((DateTime.Now, "PageHidden")); 26 | return Task.CompletedTask; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestQuery.razor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Project.Constraints.Common.Attributes; 3 | using Project.Web.Shared.Layouts; 4 | namespace BlazorAdmin.Client.TestPages 5 | { 6 | #if DEBUG 7 | [Route("/test4")] 8 | [PageInfo(Title = "Query测试", Icon = "fa fa-question-circle-o", GroupId = "test")] 9 | //[Layout(typeof(NotAuthorizedLayout))] 10 | #endif 11 | public partial class TestQuery 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestRouteParam.razor: -------------------------------------------------------------------------------- 1 | @page "/testrouteparam" 2 | @using Project.Constraints.Common.Attributes 3 | @attribute [PageInfo(Title = "路由参数测试", Icon = "fa fa-question-circle-o", ForceShowOnNavMenu = true, GroupId = "test")] 4 | @inject NavigationManager Navigation 5 | 路由参数123 6 | 路由参数456 7 | 路由参数789 8 |

9 | 路由参数123 10 |

11 |

12 | 路由参数456 13 |

14 |

15 | 路由参数789 16 |

17 | @code { 18 | public void NavigateTo(string id) 19 | { 20 | Navigation.NavigateTo($"/param/{id}", replace: true); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestRouteParam.razor.css: -------------------------------------------------------------------------------- 1 | .nav-p { 2 | border: 1px solid #ccc; 3 | border-radius: 4px; 4 | padding: 4px 12px; 5 | display: inline-flex; 6 | cursor: pointer; 7 | } 8 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestStackPanel.razor.css: -------------------------------------------------------------------------------- 1 | .stack-item { 2 | display: block; 3 | border: 1px solid black; 4 | } 5 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/TestPages/TestTabs.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints.Common.Attributes 2 | @using Project.Constraints.UI 3 | @page "/testtabs" 4 | @attribute [PageInfo(Title = "Tab测试", Icon = "fa fa-question-circle-o", ForceShowOnNavMenu = true, GroupId = "test")] 5 | @inject IUIService UI 6 | @(UI.BuildTabs() 7 | .AddTab("测试1") 8 | .AddTab("测试2") 9 | .AddTab("测试3", "测试3".AsContent()) 10 | .Render() 11 | ) 12 | @code { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazorAdmin.Client 10 | @using Project.Constraints.UI.Extensions 11 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/usings.cs: -------------------------------------------------------------------------------- 1 | [assembly: AutoWasmApiGenerator.ApiInvokerAssembly] -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/wwwroot/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft.AspNetCore": "Warning" 7 | } 8 | }, 9 | "AllowedHosts": "*", 10 | "AppSetting": { 11 | // 是否加载仅由PageGroup和PageInfo标注的页面 12 | "LoadUnregisteredPage": true, 13 | // 是否从数据库加载路由配置 14 | "LoadPageFromDatabase": true, 15 | // 是否启用切面代理 16 | "UseAspectProxy": true, 17 | // 异常页面是否允许显示详细信息 18 | "ShowExceptionDetial": true, 19 | "AppTitle": "管理网站", 20 | "AppShortName": "管理网站", 21 | // 页面默认布局 22 | "LayoutMode": "Card", 23 | // 默认语言 24 | "AppLanguage": "zh-CN", 25 | // 开启在线用户页面 26 | "ClientHubOptions": { 27 | "Enable": true 28 | }, 29 | // 自定义摄像头分辨率 30 | "CameraResolutions": [ 31 | { 32 | "Name": null, 33 | "Width": 2560, 34 | "Height": 1600 35 | } 36 | ] 37 | }, 38 | "CultureOptions": { 39 | "Enabled": true, 40 | "SupportedCulture": [ 41 | { 42 | "Name": "简体中文", 43 | "Culture": "zh-CN" 44 | }, 45 | { 46 | "Name": "English", 47 | "Culture": "en-US" 48 | } 49 | ] 50 | }, 51 | "ConnectionStrings": { 52 | "Sqlite": "DataSource=simple.db" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/BlazorAdmin.Client/wwwroot/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*", 9 | "AppSetting": { 10 | // 是否加载仅由PageGroup和PageInfo标注的页面 11 | "LoadUnregisteredPage": true, 12 | // 是否从数据库加载路由配置 13 | "LoadPageFromDatabase": true, 14 | // 是否启用切面代理 15 | "UseAspectProxy": true, 16 | // 异常页面是否允许显示详细信息 17 | "ShowExceptionDetial": true, 18 | "AppTitle": "管理网站", 19 | "AppShortName": "管理网站", 20 | // 页面默认布局 21 | "LayoutMode": "Card", 22 | // 默认语言 23 | "AppLanguage": "zh-CN", 24 | // 开启在线用户页面 25 | "ClientHubOptions": { 26 | "Enable": true 27 | }, 28 | // 自定义摄像头分辨率 29 | "CameraResolutions": [ 30 | { 31 | "Name": null, 32 | "Width": 2560, 33 | "Height": 1600 34 | } 35 | ] 36 | }, 37 | "CultureOptions": { 38 | "Enabled": true, 39 | "SupportedCulture": [ 40 | { 41 | "Name": "简体中文", 42 | "Culture": "zh-CN" 43 | }, 44 | { 45 | "Name": "English", 46 | "Culture": "en-US" 47 | } 48 | ] 49 | }, 50 | "ConnectionStrings": { 51 | "Sqlite": "DataSource=simple.db" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/BlazorAdmin/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-ef": { 6 | "version": "9.0.0", 7 | "commands": [ 8 | "dotnet-ef" 9 | ], 10 | "rollForward": false 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/BlazorAdmin/Langs/zh-CN/RouterStore.json: -------------------------------------------------------------------------------- 1 | { 2 | "TestPage": "测试页" 3 | } 4 | -------------------------------------------------------------------------------- /src/BlazorAdmin/LightOrmTableContext.cs: -------------------------------------------------------------------------------- 1 | using LightORM; 2 | 3 | namespace BlazorAdmin 4 | { 5 | [LightORMTableContext] 6 | public partial class LightOrmTableContext : ITableContext 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/BlazorAdmin/LoginOld.razor: -------------------------------------------------------------------------------- 1 | @* @page "/account/login" *@ 2 | @* @using Microsoft.AspNetCore.Components.Web *@ 3 | @* @using Microsoft.Extensions.Configuration *@ 4 | @* @using Microsoft.Extensions.Options *@ 5 | @* @using Project.Constraints.Common.Attributes *@ 6 | @* @using Project.Constraints.Options *@ 7 | @* @using Project.Constraints.Page *@ 8 | @* @using Project.Web.Shared.Layouts *@ 9 | @* @layout NotAuthorizedLayout *@ 10 | @* @inject IOptionsMonitor AppOptions *@ 11 | @* @inherits BasicComponent *@ 12 | @* @attribute [ExcludeFromInteractiveRouting] *@ 13 | @* 登录 *@ 14 | @* *@ 15 | @* *@ 16 | @* *@ 17 | @* *@ 28 | -------------------------------------------------------------------------------- /src/BlazorAdmin/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:28880", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "applicationUrl": "http://localhost:5085", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "IIS Express": { 22 | "commandName": "IISExpress", 23 | "launchBrowser": true, 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/BlazorAdmin/ServerFreeRoutes.razor: -------------------------------------------------------------------------------- 1 | @using Project.Web.Shared.Layouts 2 | 3 | -------------------------------------------------------------------------------- /src/BlazorAdmin/ServerRoutes.razor: -------------------------------------------------------------------------------- 1 | @using Project.Web.Shared.Layouts 2 | 3 | -------------------------------------------------------------------------------- /src/BlazorAdmin/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazorAdmin 10 | @using Project.Constraints.UI.Extensions 11 | -------------------------------------------------------------------------------- /src/BlazorAdmin/simple.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/BlazorAdmin/simple.db -------------------------------------------------------------------------------- /src/BlazorAdmin/usings.cs: -------------------------------------------------------------------------------- 1 | using AutoWasmApiGenerator; 2 | 3 | [assembly: WebControllerAssembly] 4 | 5 | // TODO Table AutoRowSpan 6 | // TODO 动态DataTable渲染 7 | // TODO 模板测试 8 | // TODO BuildSelect多选 9 | -------------------------------------------------------------------------------- /src/BlazorAdmin/wwwroot/app.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/BlazorAdmin/wwwroot/app.css -------------------------------------------------------------------------------- /src/BlazorAdmin/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/BlazorAdmin/wwwroot/favicon.ico -------------------------------------------------------------------------------- /src/Shared/Project.AppCore/Middlewares/GetClientIpMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using AutoInjectGenerator; 3 | using Microsoft.AspNetCore.Http; 4 | 5 | namespace Project.AppCore.Middlewares; 6 | 7 | // [AutoInject(ServiceType = typeof(GetClientIpMiddleware), LifeTime = InjectLifeTime.Singleton)] 8 | // public class GetClientIpMiddleware : IMiddleware 9 | // { 10 | // public async Task InvokeAsync(HttpContext context, RequestDelegate next) 11 | // { 12 | // string ip; 13 | // var headers = context.Request.Headers; 14 | // if (headers.TryGetValue("X-Forwarded-For", out var value)) 15 | // { 16 | // ip = value.ToString().Split(',') 17 | // .FirstOrDefault(s => !string.IsNullOrWhiteSpace(s))? 18 | // .Trim(); 19 | // } 20 | // else 21 | // { 22 | // ip = context.Connection.RemoteIpAddress.ToIpString(); 23 | // } 24 | // 25 | // await context.Response.WriteAsync(ip); 26 | // } 27 | // } -------------------------------------------------------------------------------- /src/Shared/Project.AppCore/Middlewares/MiddlewareHelpers.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | 3 | namespace Project.AppCore.Middlewares 4 | { 5 | internal static class MiddlewareHelpers 6 | { 7 | 8 | internal static bool RequestFile(HttpContext context) 9 | { 10 | var path = context.Request.Path; 11 | var ext = Path.GetExtension(path); 12 | return !string.IsNullOrEmpty(ext); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/Shared/Project.AppCore/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Project.AppCore 2 | { 3 | public class Program 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /src/Shared/Project.AppCore/Project.AppCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | Library 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Shared/Project.AppCore/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "iisExpress": { 4 | "applicationUrl": "http://localhost:10939", 5 | "sslPort": 0 6 | } 7 | }, 8 | "profiles": { 9 | "http": { 10 | "commandName": "Project", 11 | "dotnetRunMessages": true, 12 | "launchBrowser": true, 13 | "applicationUrl": "http://localhost:5277", 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "IIS Express": { 19 | "commandName": "IISExpress", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Shared/Project.AppCore/Services/FileService.cs: -------------------------------------------------------------------------------- 1 | using AutoInjectGenerator; 2 | using Microsoft.Extensions.Hosting; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Project.AppCore.Services 10 | { 11 | [AutoInject(Group = "SERVER", LifeTime = InjectLifeTime.Singleton)] 12 | public class FileService : IFileService 13 | { 14 | public string GetStaticFileWithVersion(string path) 15 | { 16 | //if (environment.IsDevelopment()) 17 | //{ 18 | // return path; 19 | //} 20 | var file = Path.Combine("wwwroot", path); 21 | var fi = new FileInfo(file); 22 | if (!fi.Exists) 23 | { 24 | return path; 25 | } 26 | return $"{path}?v={fi.LastWriteTimeUtc:yyMMddHHmmssfff}"; 27 | } 28 | 29 | public Task GetStaticFileWithVersionAsync(string path) 30 | { 31 | return Task.FromResult(GetStaticFileWithVersion(path)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Shared/Project.AppCore/usings.cs: -------------------------------------------------------------------------------- 1 | global using Microsoft.Extensions.Localization; 2 | global using Project.Constraints.Models; 3 | global using Project.Constraints.Models.Request; 4 | global using Project.Constraints.Services; 5 | global using Microsoft.Extensions.Configuration; 6 | global using Microsoft.Extensions.Logging; 7 | global using Microsoft.Extensions.DependencyInjection; 8 | global using LightORM; -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Aop/AopPermissionCheck.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.Store; 2 | using AutoAopProxyGenerator; 3 | using AutoInjectGenerator; 4 | using System.Reflection; 5 | 6 | namespace Project.Constraints.Aop; 7 | 8 | // [AutoInject(ServiceType = typeof(AopPermissionCheck))] 9 | [AutoInjectSelf] 10 | public class AopPermissionCheck(IUserStore userStore) : IAspectHandler 11 | { 12 | public Task Invoke(ProxyContext context, Func process) 13 | { 14 | var action = FormattedAction(context); 15 | if (userStore.UserInfo?.UserPowers == null) 16 | { 17 | return process.Invoke(); 18 | } 19 | if (userStore.UserInfo.UserPowers.Contains(action) == false) 20 | { 21 | context.SetReturnValue(new QueryResult() { IsSuccess = false, Message = "没有权限" }); 22 | return Task.CompletedTask; 23 | } 24 | else 25 | { 26 | return process.Invoke(); 27 | } 28 | } 29 | 30 | private static string FormattedAction(ProxyContext context) 31 | { 32 | var related = context.ServiceMethod.GetCustomAttribute(); 33 | string? p = !string.IsNullOrEmpty(related?.PermissionId) ? related.PermissionId : context.ServiceMethod.Name; 34 | return p.EndsWith("Async") ? p[..^5] : p; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Aop/LogInfoAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Project.Constraints.Aop 4 | { 5 | [AttributeUsage(AttributeTargets.Method)] 6 | public class LogInfoAttribute : Attribute 7 | { 8 | public string? Module { get; set; } 9 | public string? Action { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Common/Attributes/AutoLoadJsModuleAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Project.Constraints.Common.Attributes 8 | { 9 | [AttributeUsage(AttributeTargets.Class)] 10 | public class AutoLoadJsModuleAttribute : Attribute 11 | { 12 | /// 13 | /// 不包含js文件名称 14 | /// 15 | public string? Path { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Common/Attributes/ExcludeFromInteractiveRoutingAttribute.cs: -------------------------------------------------------------------------------- 1 | #if NET8_0 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Project.Constraints.Common.Attributes; 9 | 10 | [AttributeUsage(AttributeTargets.Class)] 11 | public class ExcludeFromInteractiveRoutingAttribute : Attribute 12 | { 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Common/Attributes/LangNameAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Common.Attributes; 2 | 3 | [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class)] 4 | public class LangNameAttribute : Attribute 5 | { 6 | public LangNameAttribute(string name) 7 | { 8 | Name = name; 9 | } 10 | 11 | public string Name { get; } 12 | } -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Common/Attributes/RelatedPermissionAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Common.Attributes; 2 | 3 | public class RelatedPermissionAttribute : Attribute 4 | { 5 | public string? PermissionId { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Common/ClassHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Project.Constraints.Common 4 | { 5 | public class ClassHelper 6 | { 7 | public static ClassHelper Default => new ClassHelper(); 8 | 9 | private Dictionary> cssClassMap = new Dictionary>(); 10 | 11 | public string Class 12 | { 13 | get 14 | { 15 | List classes = new List(); 16 | foreach (var item in cssClassMap) 17 | { 18 | if (item.Value()) 19 | { 20 | classes.Add(item.Key); 21 | } 22 | } 23 | return string.Join(" ", classes.ToArray()); 24 | } 25 | } 26 | 27 | 28 | public ClassHelper AddClass(string? cssClass, Func? condition = null) 29 | { 30 | if (cssClass == null) return this; 31 | condition ??= () => true; 32 | cssClassMap.Add(cssClass, condition); 33 | return this; 34 | } 35 | 36 | public ClassHelper RemoveClass(string cssClass) 37 | { 38 | cssClassMap.Remove(cssClass); 39 | return this; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Common/ConstraintString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Project.Constraints.Common 8 | { 9 | public class ConstraintString 10 | { 11 | public const string APP_STORE_KEY = "APP_SETTING"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Common/SessionCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | 3 | namespace Project.Constraints.Common 4 | { 5 | //[AutoInject] 6 | public class SessionCache 7 | { 8 | readonly ConcurrentDictionary caches = []; 9 | public T GetOrAdd(string key, Func func) 10 | { 11 | return caches.GetOrAdd(key, func.Invoke()); 12 | } 13 | 14 | public T? GetCache(string key) 15 | { 16 | if (caches.TryGetValue(key, out var cache)) { return cache; } 17 | return default; 18 | } 19 | 20 | public void AddCache(string key, T value) 21 | { 22 | _ = caches.GetOrAdd(key, value); 23 | } 24 | 25 | public static T GetOrAddStatic(string key, Func func) 26 | { 27 | return StaticCache.GetOrAdd(key, func); 28 | } 29 | 30 | public static T GetCacheStatic(string key) 31 | { 32 | return StaticCache.GetCache(key); 33 | } 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Common/StaticCache.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | 3 | namespace Project.Constraints.Common; 4 | 5 | public static class StaticCache 6 | { 7 | static readonly ConcurrentDictionary caches = new(); 8 | 9 | public static T GetCache(string key) 10 | { 11 | if (caches.TryGetValue(key, out var cache)) { return cache; } 12 | return default!; 13 | } 14 | 15 | public static void AddOrUpdate(string key, T value, Func? update = null) 16 | { 17 | update ??= (k, v) => value; 18 | caches.AddOrUpdate(key, value, update); 19 | } 20 | 21 | public static T GetOrAdd(string key, Func func) 22 | { 23 | return caches.GetOrAdd(key, func.Invoke()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/IAppSession.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Project.Constraints.Store; 3 | using Project.Constraints.UI; 4 | 5 | namespace Project.Constraints; 6 | 7 | //[AutoInject] 8 | public interface IAppSession 9 | { 10 | event Func? WebApplicationAccessedEvent; 11 | event Func? LoginSuccessEvent; 12 | event Func? OnLoadedAsync; 13 | NavigationManager Navigator { get; } 14 | public bool Loaded { get; set; } 15 | IAppStore AppStore { get; } 16 | //IAuthenticationStateProvider AuthenticationStateProvider { get; } 17 | IRouterStore RouterStore { get; } 18 | IUserStore UserStore { get; } 19 | IUIService UI { get; } 20 | Action? Update { get; set; } 21 | Task NotifyWebApplicationAccessedAsync(); 22 | Task NotifyLoginSuccessAsync(); 23 | } 24 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/IAuthenticationStateProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints; 2 | 3 | public interface IAuthenticationStateProvider 4 | { 5 | UserInfo? Current { get; } 6 | // Task IdentifyUser(UserInfo info); 7 | Task ClearState(); 8 | } 9 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/IDashboardContentProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints; 2 | 3 | public interface IDashboardContentProvider 4 | { 5 | Type? GetComponentType(); 6 | void SetComponentType(Type? type); 7 | } 8 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Models/ClientInfo.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.Store; 2 | 3 | namespace Project.Constraints.Models; 4 | 5 | public class ClientInfo 6 | { 7 | //[ColumnDefinition("Id", width: "50", Ellipsis = true)] 8 | [NotNull] public string? CircuitId { get; set; } 9 | 10 | [ColumnDefinition("用户ID", width: "100")] 11 | public string? UserId => UserInfo?.UserId ?? "vistor"; 12 | 13 | [ColumnDefinition("用户姓名", width: "100")] 14 | public string? UserName => UserInfo?.UserName ?? "游客"; 15 | 16 | [ColumnDefinition("IP", width: "150")] 17 | public string? IpAddress { get; set; } 18 | 19 | [ColumnDefinition("接入时间", width: "150")] 20 | public DateTime CreateTime { get; set; } = DateTime.Now; 21 | [ColumnDefinition("活跃时间", width: "150")] 22 | public DateTime BeatTime { get; set; } = DateTime.Now; 23 | public UserInfo? UserInfo { get; set; } 24 | 25 | [ColumnDefinition("UserAgent", Ellipsis = true)] 26 | public string? UserAgent { get; set; } 27 | } -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Models/JsActionResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Project.Constraints.Models 8 | { 9 | public class SvgInfo 10 | { 11 | public string? Content { get; set; } 12 | public int? Width { get; set; } 13 | public int? Height { get; set; } 14 | } 15 | public class JsActionResult : IQueryResult 16 | { 17 | public bool IsSuccess { get; set; } 18 | public string? Message { get; set; } 19 | public object? Payload { get; set; } 20 | public int Code { get; set; } 21 | } 22 | public class JsActionResult : JsActionResult 23 | { 24 | public new T? Payload { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Models/KeyRelations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Project.Constraints.Models 8 | { 9 | public class KeyRelations 10 | { 11 | public KeyRelations(TM? main, IEnumerable? values) 12 | { 13 | Main = main; 14 | Slaves = [.. values]; 15 | } 16 | public KeyRelations() 17 | { 18 | 19 | } 20 | public TM? Main { get; set; } 21 | public TS[]? Slaves { get; set; } 22 | 23 | public static implicit operator KeyRelations((TM?, IEnumerable?) v) => new(v.Item1, v.Item2); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Models/LoginFormModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Project.Constraints.Models 4 | { 5 | public class LoginFormModel 6 | { 7 | [Required] 8 | public string UserName { get; set; } = ""; 9 | [Required] 10 | public string Password { get; set; } = ""; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Models/Permissions/IRole.cs: -------------------------------------------------------------------------------- 1 |  2 | using AutoGenMapperGenerator; 3 | 4 | namespace Project.Constraints.Models.Permissions 5 | { 6 | [LangName("Role")] 7 | public interface IRole 8 | { 9 | [NotNull] string? RoleId { get; set; } 10 | [NotNull] string? RoleName { get; set; } 11 | IEnumerable? Powers { get; set; } 12 | } 13 | #if (ExcludeDefaultService) 14 | #else 15 | [LightTable(Name = "ROLE")] 16 | [GenMapper] 17 | public partial class Role : IRole, IAutoMap 18 | { 19 | [ColumnDefinition(Readonly = true)] 20 | [LightColumn(Name = "ROLE_ID", PrimaryKey = true)] 21 | [NotNull] 22 | public string? RoleId { get; set; } 23 | [ColumnDefinition] 24 | [LightColumn(Name = "ROLE_NAME")] 25 | [NotNull] 26 | public string? RoleName { get; set; } 27 | 28 | [ColumnDefinition(Visible = false)] 29 | [Ignore] 30 | public IEnumerable? Powers { get; set; } 31 | } 32 | #endif 33 | } 34 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Models/Permissions/IRolePower.cs: -------------------------------------------------------------------------------- 1 | using AutoGenMapperGenerator; 2 | 3 | namespace Project.Constraints.Models.Permissions 4 | { 5 | [LangName("RolePower")] 6 | public interface IRolePower 7 | { 8 | [NotNull] string? RoleId { get; set; } 9 | [NotNull] string? PowerId { get; set; } 10 | } 11 | #if (ExcludeDefaultService) 12 | #else 13 | [LightTable(Name = "ROLE_POWER")] 14 | [GenMapper] 15 | public partial class RolePower : IRolePower, IAutoMap 16 | { 17 | [LightColumn(Name = "ROLE_ID", PrimaryKey = true)] 18 | [NotNull] public string? RoleId { get; set; } 19 | [LightColumn(Name = "POWER_ID", PrimaryKey = true)] 20 | [NotNull] public string? PowerId { get; set; } 21 | } 22 | #endif 23 | } 24 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Models/Permissions/IUserRole.cs: -------------------------------------------------------------------------------- 1 |  2 | using AutoGenMapperGenerator; 3 | 4 | namespace Project.Constraints.Models.Permissions 5 | { 6 | [LangName("UserRole")] 7 | public interface IUserRole 8 | { 9 | [NotNull] string? UserId { get; set; } 10 | [NotNull] string? RoleId { get; set; } 11 | } 12 | 13 | #if (ExcludeDefaultService) 14 | #else 15 | [LightTable(Name = "USER_ROLE")] 16 | [GenMapper] 17 | public partial class UserRole : IUserRole, IAutoMap 18 | { 19 | [LightColumn(Name = "USER_ID", PrimaryKey = true)] 20 | [NotNull] 21 | public string? UserId { get; set; } 22 | [LightColumn(Name = "ROLE_ID", PrimaryKey = true)] 23 | [NotNull] 24 | public string? RoleId { get; set; } 25 | } 26 | #endif 27 | } 28 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Models/SaveActionType.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Models 2 | { 3 | public enum SaveActionType 4 | { 5 | Insert, 6 | Update, 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Models/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Models; 2 | 3 | public class UserInfo 4 | { 5 | public string UserId { get; set; } = string.Empty; 6 | public string? UserName { get; set; } 7 | public string PasswordHash { get; set; } = string.Empty; 8 | /// 9 | /// 框架内Api 10 | /// 11 | [NotNull] 12 | public string? Token { get; set; } 13 | 14 | public string[] Roles { get; set; } = []; 15 | public string[] UserPowers { get; set; } = []; 16 | public string[] UserPages { get; set; } = []; 17 | /// 18 | /// 存储用户额外信息 19 | /// 20 | public Dictionary AdditionalValue { get; set; } = []; 21 | 22 | public DateTime CreatedTime { get; set; } = DateTime.Now; 23 | // public DateTime ActiveTime { get; set; } = DateTime.Now; 24 | public static UserInfo Visitor => new UserInfo() { UserId = $"{Guid.NewGuid():N}", UserName = "游客" }; 25 | 26 | } -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Options/AppSetting.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.Store.Models; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace Project.Constraints.Options; 5 | public sealed class AppSetting 6 | { 7 | [NotNull] public string? AppTitle { get; set; } 8 | [NotNull] public string? AppShortName { get; set; } 9 | public LayoutMode? LayoutMode { get; set; } 10 | public AppRunMode RunMode { get; set; } = AppRunMode.Server; 11 | public string? AppLanguage { get; set; } 12 | public string? LauchUrl { get; set; } 13 | // public bool LoadUnregisteredPage { get; set; } 14 | public bool LoadPageFromDatabase { get; set; } = true; 15 | public bool UseAspectProxy { get; set; } 16 | public bool ShowExceptionDetial { get; set; } 17 | public int SupportedMajorVersion { get; set; } = 75; 18 | public List? CameraResolutions { get; set; } 19 | public ClientHubOptions ClientHubOptions { get; set; } = new(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Options/CameraResolution.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Options; 2 | 3 | public record CameraResolution 4 | { 5 | public string? Name { get; set; } 6 | public int Width { get; set; } 7 | public int Height { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Options/ClientHubOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Options; 2 | 3 | public class ClientHubOptions 4 | { 5 | /// 6 | /// 是否启用 7 | /// 8 | public bool Enable { get; set; } 9 | /// 10 | /// 服务器扫描过期客户端的频率,默认5分钟扫一次 11 | /// 12 | public TimeSpan ServerScanFrequency { get; set; } = TimeSpan.FromMinutes(5); 13 | /// 14 | /// 客户端发送心跳的频率,默认5秒一次 15 | /// 16 | public TimeSpan ClientSendFrequency { get; set; } = TimeSpan.FromSeconds(5); 17 | /// 18 | /// 心跳超时时间限制 19 | /// 20 | public TimeSpan ClearTimeoutLimit { get; set; } = TimeSpan.FromSeconds(15); 21 | public string[] AllowUsers { get; set; } = []; 22 | public string[] AllowRoles { get; set; } = []; 23 | } 24 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Options/CultureOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Options; 2 | 3 | public sealed class LangInfo 4 | { 5 | [NotNull] public string? Name { get; set; } 6 | [NotNull] public string? Culture { get; set; } 7 | } 8 | public sealed class CultureOptions 9 | { 10 | public bool Enabled { get; set; } 11 | public LangInfo[] SupportedCulture { get; set; } = []; 12 | } 13 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Options/Token.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Options; 2 | 3 | public sealed class Token 4 | { 5 | public int MaxFreeTime { get; set; } = 900; 6 | public bool NeedAuthentication { get; set; } = true; 7 | public TimeSpan Expire { get; set; } = TimeSpan.FromDays(15); 8 | public int LimitedFreeTime => MaxFreeTime < 300 ? 300 : MaxFreeTime; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/PageHelper/IPageAction.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Constraints.PageHelper; 4 | 5 | public interface IPageAction 6 | { 7 | //RenderFragment GetTitle(); 8 | Task OnShowAsync(); 9 | Task OnHiddenAsync(); 10 | } 11 | 12 | public interface IRoutePageTitle 13 | { 14 | RenderFragment GetTitle(); 15 | } 16 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Project.Constraints.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Project.Constraints": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "https://localhost:55315;http://localhost:55316" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/CircuitTrackerGlobalInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | using System.Net; 3 | 4 | namespace Project.Constraints.Services 5 | { 6 | public static class CircuitTrackerGlobalInfo 7 | { 8 | public static ConcurrentDictionary CircuitClients { get; set; } = new(); 9 | 10 | public static string ToIpString(this IPAddress? address) 11 | { 12 | address = address ?? IPAddress.IPv6Loopback; 13 | var ipstr = address.ToString(); 14 | return ipstr.StartsWith("::ffff:") ? address.MapToIPv4().ToString() : ipstr; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/IAddtionalTnterceptor.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.Store.Models; 2 | 3 | namespace Project.Constraints.Services 4 | { 5 | public interface IAddtionalInterceptor 6 | { 7 | public Task LoginSuccessAsync(UserInfo result) => Task.CompletedTask; 8 | public Task RouterChangingAsync(TagRoute route) => Task.FromResult(true); 9 | public Task RouteMetaFilterAsync(RouterMeta meta) => Task.FromResult(true); 10 | public Task AfterWebApplicationAccessedAsync() => Task.CompletedTask; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/IAuthService.cs: -------------------------------------------------------------------------------- 1 | using AutoAopProxyGenerator; 2 | using AutoInjectGenerator; 3 | using AutoWasmApiGenerator; 4 | using MT.Generators.Abstraction; 5 | using Project.Constraints.Aop; 6 | using Project.Constraints.Models.Permissions; 7 | 8 | namespace Project.Constraints.Services 9 | { 10 | [WebController(Route = "account")] 11 | [AddAspectHandler(AspectType = typeof(AopLogger))] 12 | public interface IAuthService 13 | { 14 | [WebMethod(Route = "login")] 15 | [LogInfo(Module = "登录模块", Action = "用户登录")] 16 | Task> SignInAsync(LoginFormModel loginForm); 17 | 18 | [WebMethod(Method = WebMethod.Get, Route = "logout")] 19 | [LogInfo(Module = "登录模块", Action = "用户登出")] 20 | Task SignOutAsync(); 21 | 22 | Task CheckUserPasswordAsync(UserPwd pwd); 23 | 24 | [LogInfo(Module = "登录模块", Action = "修改密码")] 25 | Task ModifyUserPasswordAsync(UserPwd pwd); 26 | 27 | Task CheckUserStatusAsync(UserInfo? userInfo); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/IBasicService.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.Aop; 2 | using Project.Constraints.Models; 3 | using Project.Constraints.Models.Request; 4 | using System.Linq.Expressions; 5 | 6 | namespace Project.Constraints.Services 7 | { 8 | // //[Aspectable(AspectHandleType = typeof(LogAop))] 9 | // [LogAop] 10 | //public partial interface IBasicService 11 | //{ 12 | // //[LogInfo(Action = "查询", Module = "BasicService")] 13 | // Task> GetListAsync(GenericRequest req); 14 | // Task> GetSingleAsync(Expression> whereExp); 15 | // [LogInfo(Action = "新增", Module = "BasicService")] 16 | // Task> AddItem(T item); 17 | // [LogInfo(Action = "更新", Module = "BasicService")] 18 | // Task> UpdateItem(T item, Expression> primaryKey); 19 | // [LogInfo(Action = "更新", Module = "BasicService")] 20 | // Task> UpdateItem(Expression> exp, Expression> primaryKey); 21 | // [LogInfo(Action = "删除", Module = "BasicService")] 22 | // Task> DeleteItem(Expression> whereLambda); 23 | //} 24 | } 25 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/IClientService.cs: -------------------------------------------------------------------------------- 1 | using AutoWasmApiGenerator; 2 | using Project.Constraints.Models.Request; 3 | 4 | namespace Project.Constraints.Services; 5 | 6 | [WebController(Route = "hub")] 7 | public interface IClientService 8 | { 9 | Task> GetCountAsync(); 10 | Task> GetClientsAsync(GenericRequest query); 11 | Task CheckPermissionAsync(UserInfo? user); 12 | Task AddOrUpdateAsync(ClientInfo client); 13 | // Task> GetClientAsync(string key); 14 | } -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/IDownloadService.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Services 2 | { 3 | public interface IDownloadService 4 | { 5 | Task DownloadFileAsync(string filename, params string[] paths); 6 | Task DownloadStreamAsync(string filename, Stream stream); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/IDownloadServiceProvider.cs: -------------------------------------------------------------------------------- 1 | using AutoInjectGenerator; 2 | 3 | namespace Project.Constraints.Services 4 | { 5 | public interface IDownloadServiceProvider 6 | { 7 | IDownloadService? GetService(); 8 | void Register(IDownloadService service); 9 | } 10 | 11 | [AutoInject] 12 | public class DownloadServiceProvider : IDownloadServiceProvider 13 | { 14 | private IDownloadService? service; 15 | public IDownloadService? GetService() => service; 16 | 17 | public void Register(IDownloadService service) 18 | { 19 | this.service = service; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/ILanguageService.cs: -------------------------------------------------------------------------------- 1 | using AutoInjectGenerator; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading.Tasks; 9 | 10 | namespace Project.Constraints.Services 11 | { 12 | public interface ILanguageService 13 | { 14 | event Action? LanguageChanged; 15 | CultureInfo CurrentCulture { get; } 16 | void SetLanguage(string name); 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/ILoginPage.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.UI; 2 | 3 | namespace Project.Constraints.Services; 4 | 5 | public interface ILoginPage 6 | { 7 | Task HandleLogin(LoginFormModel model); 8 | IUIService UI { get; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/ILoginService.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.Aop; 2 | using Project.Constraints.Models; 3 | 4 | namespace Project.Constraints.Services 5 | { 6 | //[Aspectable(AspectHandleType = typeof(LogAop))] 7 | //[LogAop] 8 | //[WebController(Route = "login")] 9 | //[ApiInvokerGenerate(typeof(AutoInjectAttribute))] 10 | //[AttachAttributeArgument(typeof(ApiInvokerGenerateAttribute), typeof(AutoInjectAttribute), "Group", "WASM")] 11 | public partial interface ILoginService 12 | { 13 | [LogInfo(Action = "用户登录", Module = "登录模块")] 14 | Task> LoginAsync(string username, string password); 15 | [LogInfo(Action = "用户登录[缓存]", Module = "登录模块")] 16 | Task> UpdateLastLoginTimeAsync(UserInfo info); 17 | Task CheckUser(UserInfo info); 18 | [LogInfo(Action = "用户登出", Module = "登录模块")] 19 | Task> LogoutAsync(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/IRunLogService.cs: -------------------------------------------------------------------------------- 1 | using AutoInjectGenerator; 2 | using AutoWasmApiGenerator; 3 | using MT.Generators.Abstraction; 4 | using Project.Constraints.Models; 5 | using Project.Constraints.Models.Permissions; 6 | using Project.Constraints.Models.Request; 7 | 8 | namespace Project.Constraints.Services 9 | { 10 | public interface IRunLogService : IRunLogService where TRunLog : IRunLog 11 | { 12 | Task> GetRunLogsAsync(GenericRequest runLog); 13 | Task WriteLog(TRunLog log); 14 | } 15 | 16 | //[WebController(Route = "writelog", Authorize = true)] 17 | //[ApiInvokerGenerate] 18 | public interface IRunLogService 19 | { 20 | [WebMethod(Route = "write")] 21 | Task WriteLog(MinimalLog log); 22 | } 23 | 24 | #if (ExcludeDefaultService) 25 | #else 26 | [WebController(Route = "runlog", Authorize = true)] 27 | public interface IStandardRunLogService : IRunLogService { } 28 | #endif 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/ISvgIconService.cs: -------------------------------------------------------------------------------- 1 | using AutoWasmApiGenerator; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Project.Constraints.Services 9 | { 10 | [WebController(Route = "svg")] 11 | public interface ISvgIconService 12 | { 13 | [WebMethod(Method = WebMethod.Get)] 14 | Task> GetIcon(string? name); 15 | Task> GetAllIcon(); 16 | } 17 | [WebController(Route = "file")] 18 | public interface IFileService 19 | { 20 | [ApiInvokeNotSupported] 21 | string GetStaticFileWithVersion(string path); 22 | Task GetStaticFileWithVersionAsync(string path); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Services/IWebSettingInitService.cs: -------------------------------------------------------------------------------- 1 | using AutoInjectGenerator; 2 | using Project.Constraints.Store; 3 | 4 | namespace Project.Constraints.Services 5 | { 6 | public interface IWebSettingInitService 7 | { 8 | void UpdateUserInfo(UserInfo info); 9 | void ApplyAppSetting(IAppStore app); 10 | } 11 | 12 | [AutoInject] 13 | public class WebSettingInitService : IWebSettingInitService 14 | { 15 | private readonly IAuthService authenticationService; 16 | 17 | public WebSettingInitService(IAuthService authenticationService) 18 | { 19 | this.authenticationService = authenticationService; 20 | } 21 | public void ApplyAppSetting(IAppStore app) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | 26 | public void UpdateUserInfo(UserInfo info) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Store/IAppStore.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.Store.Models; 2 | 3 | namespace Project.Constraints.Store 4 | { 5 | public enum ThemeMode 6 | { 7 | Light, 8 | Dark, 9 | OS 10 | } 11 | public interface IAppStore 12 | { 13 | bool Working { get; set; } 14 | LayoutMode? Mode { get; set; } 15 | string? AppLanguage { get; set; } 16 | ThemeMode Theme { get; set; } 17 | bool Collapsed { get; set; } 18 | int SideBarExpandWidth { get; set; } 19 | string MainThemeColor { get; set; } 20 | void ApplySetting(IAppStore? app); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Store/IProtectedLocalStorage.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.Store.Models; 2 | 3 | namespace Project.Constraints.Store 4 | { 5 | public interface IProtectedLocalStorage 6 | { 7 | ValueTask> GetAsync(string key); 8 | ValueTask Clear(); 9 | ValueTask SetAsync(string key, object value); 10 | ValueTask DeleteAsync(string key); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Store/IRouterStore.cs: -------------------------------------------------------------------------------- 1 | using Project.Constraints.Store.Models; 2 | 3 | namespace Project.Constraints.Store 4 | { 5 | public interface IStore 6 | { 7 | event Action DataChangedEvent; 8 | } 9 | 10 | public interface IRouterStore : IStore, IDisposable 11 | { 12 | event Func>? RouterChangingEvent; 13 | event Func>? RouteMetaFilterEvent; 14 | List TopLinks { get; } 15 | IEnumerable Menus { get; } 16 | TagRoute? Current { get; } 17 | string CurrentUrl { get; } 18 | void GoTo(string uri); 19 | Task RouteDataChangedHandleAsync(Microsoft.AspNetCore.Components.RouteData routeData); 20 | void Remove(string link); 21 | Task RemoveOther(string link); 22 | Task Reset(); 23 | //Task Reload(); 24 | /// 25 | /// 初始化菜单 26 | /// 27 | /// 28 | /// 29 | Task InitMenusAsync(UserInfo? userInfo); 30 | Type? GetRouteType(string routeUrl); 31 | string GetLocalizerString(RouterMeta meta); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Store/IUserStore.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Store; 2 | 3 | public interface IUserStore 4 | { 5 | // event Func LoginSuccessEvent; 6 | UserInfo? UserInfo { get; } 7 | string[] Roles { get; } 8 | string? UserId { get; } 9 | string UserDisplayName { get; } 10 | void SetUser(UserInfo? userInfo); 11 | void ClearUser(); 12 | } -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Store/Models/LayoutMode.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Project.Constraints.Store.Models 4 | { 5 | public enum LayoutMode 6 | { 7 | [Display(Name = "经典")] 8 | Classic, 9 | [Display(Name = "卡片式")] 10 | Card, 11 | [Display(Name = "流线型")] 12 | Line, 13 | } 14 | 15 | public enum AppRunMode 16 | { 17 | Server, 18 | WebAssembly, 19 | Auto 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Store/Models/RouteMenu.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Store.Models 2 | { 3 | public class RouteMenu : RouterMeta 4 | { 5 | public RouteMenu() 6 | { 7 | 8 | } 9 | public RouteMenu(RouterMeta meta) 10 | { 11 | RouteId = meta.RouteId; 12 | RouteUrl = meta.RouteUrl; 13 | Icon = meta.Icon; 14 | RouteTitle = meta.RouteTitle; 15 | Redirect = meta.Redirect; 16 | Pin = meta.Pin; 17 | Group = meta.Group; 18 | Cache = meta.Cache; 19 | Sort = meta.Sort; 20 | } 21 | public IEnumerable? Children { get; set; } 22 | public bool HasChildren => Children != null && Children.Any(); 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Store/Models/RouterMeta.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Project.Constraints.Store.Models 4 | { 5 | public class RouterMeta : IEqualityComparer 6 | { 7 | [NotNull] public string? RouteId { get; set; } 8 | [NotNull] public string? RouteUrl { get; set; } 9 | public string? Icon { get; set; } 10 | [NotNull] public string? RouteTitle { get; set; } 11 | public string Redirect { get; set; } = "NoRedirect"; 12 | public bool Pin { get; set; } 13 | public string? Group { get; set; } 14 | public int Sort { get; set; } 15 | public bool HasPageInfo { get; set; } 16 | public bool Cache { get; set; } = true; 17 | public bool ForceShowOnNavMenu { get; set; } 18 | [NotNull] public Type? RouteType { get; set; } 19 | public bool Equals(RouterMeta? x, RouterMeta? y) 20 | { 21 | return x?.RouteId == y?.RouteId; 22 | } 23 | 24 | public int GetHashCode([DisallowNull] RouterMeta obj) 25 | { 26 | return obj.RouteId.GetHashCode(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Store/Models/StorageResult.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.Store.Models 2 | { 3 | public readonly struct StorageResult 4 | { 5 | public StorageResult(bool success, TValue? value) 6 | { 7 | Success = success; 8 | Value = value; 9 | } 10 | public bool Success { get; } 11 | public TValue? Value { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Builders/SelectComponentBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Project.Constraints.UI.Props; 3 | 4 | namespace Project.Constraints.UI.Builders 5 | { 6 | public class SelectComponentBuilder : BindableComponentBuilder, IBindableInputComponent, ISelectInput 7 | where TComponent : IComponent 8 | where TPropModel : DefaultProp, new() 9 | { 10 | public SelectComponentBuilder() 11 | { 12 | 13 | } 14 | 15 | public SelectComponentBuilder(Func, RenderFragment> newRender) 16 | { 17 | this.newRender = newRender; 18 | } 19 | 20 | public SelectComponentBuilder(Action> tpropHandle) 21 | { 22 | this.tpropHandle = tpropHandle; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Dropdown/DropdownOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Constraints.UI.Dropdown 4 | { 5 | public class ActionInfo 6 | { 7 | public string? Label { get; set; } 8 | //public RenderFragment? Content { get; set; } 9 | //public Delegate? OnClick { get; set; } 10 | public EventCallback OnClick { get; set; } 11 | } 12 | 13 | public class DropdownOptions 14 | { 15 | public bool HiddenMode { get; set; } 16 | public RenderFragment? Content { get; set; } 17 | public List? Actions { get; set; } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Dropdown/ProfileInfo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Constraints.UI.Dropdown; 4 | 5 | public class ProfileInfo 6 | { 7 | public RenderFragment? Content { get; set; } 8 | public string? UserName { get; set; } 9 | public List? Actions { get; set; } 10 | } -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Extensions/AlertExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.UI.Extensions 2 | { 3 | public static class AlertExtensions 4 | { 5 | public static void AlertSuccess(this IUIService service, string title, string message) 6 | { 7 | service.Alert(MessageType.Success, title, message); 8 | } 9 | 10 | public static void AlertError(this IUIService service, string title, string message) 11 | { 12 | service.Alert(MessageType.Error, title, message); 13 | } 14 | 15 | public static void AlertWarning(this IUIService service, string title, string message) 16 | { 17 | service.Alert(MessageType.Warning, title, message); 18 | } 19 | 20 | public static void AlertInfo(this IUIService service, string title, string message) 21 | { 22 | service.Alert(MessageType.Information, title, message); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Extensions/BuildTableExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Project.Constraints.Common; 3 | using Project.Constraints.Models.Request; 4 | using Project.Constraints.UI.Table; 5 | using System.Data; 6 | 7 | namespace Project.Constraints.UI.Extensions 8 | { 9 | public static class BuildTableExtensions 10 | { 11 | public static RenderFragment BuildDynamicTable(this IUIService service, DataTable dataSource) 12 | { 13 | var options = new TableOptions(); 14 | options.LoadDataOnLoaded = true; 15 | options.OnQueryAsync = request => Task.FromResult(dataSource.ToEnumerable().CollectionResult()); 16 | return service.BuildDynamicTable(options); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Extensions/ButtonBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Project.Constraints.UI.Props; 3 | 4 | namespace Project.Constraints.UI.Extensions 5 | { 6 | public static class ButtonBuilderExtensions 7 | { 8 | public static IButtonInput Text(this IButtonInput btn, string text) 9 | { 10 | //btn.s 11 | btn.Set("ChildContent", text.AsContent()); 12 | return btn; 13 | } 14 | 15 | public static IButtonInput Primary(this IButtonInput btn) 16 | { 17 | return btn.SetButtonType(ButtonType.Primary); 18 | } 19 | 20 | public static IButtonInput SetButtonType(this IButtonInput btn, ButtonType type) 21 | { 22 | btn.Set(p => p.ButtonType, type); 23 | return btn; 24 | } 25 | } 26 | 27 | public static class CheckboxBuilderExtensions 28 | { 29 | public static IBindableInputComponent Text(this IBindableInputComponent component, string label) 30 | { 31 | component.Set(p => p.Label, label); 32 | return component; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Extensions/MessageExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.UI.Extensions 2 | { 3 | public static class MessageExtensions 4 | { 5 | public static void Success(this IUIService service, string message) 6 | { 7 | service.Message(MessageType.Success, message); 8 | } 9 | 10 | public static void Info(this IUIService service, string message) 11 | { 12 | service.Message(MessageType.Information, message); 13 | } 14 | 15 | public static void Error(this IUIService service, string message) 16 | { 17 | service.Message(MessageType.Error, message); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Extensions/UIServiceExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Project.Constraints.UI.Extensions; 8 | 9 | public static class UIServiceExtensions 10 | { 11 | public static bool ShowResult(this IUIService ui, IQueryResult result) 12 | { 13 | if (result.IsSuccess) 14 | { 15 | ui.Success(result.Message ?? "操作成功"); 16 | } 17 | else 18 | { 19 | ui.Error(result.Message ?? "出错"); 20 | } 21 | return result.IsSuccess; 22 | } 23 | 24 | public static bool ShowError(this IUIService ui, IQueryResult result) 25 | { 26 | if (!result.IsSuccess) 27 | { 28 | ui.Error(result.Message ?? "出错"); 29 | } 30 | return result.IsSuccess; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Flyout/DrawerTemplate.razor: -------------------------------------------------------------------------------- 1 | @typeparam TData 2 | @inherits DialogTemplate 3 | 4 |
5 |
6 | 7 | @ChildContent 8 | 9 |
10 |
11 | @UI.BuildButton(this).OnClick(HandleOk).Set(b => b.Text, "Ok").Set(b => b.ButtonType, ButtonType.Primary).Render() 12 | @UI.BuildButton(this).OnClick(HandleCancel).Set(b => b.Text, "Close").Render() 13 |
14 |
15 | 16 | @code { 17 | [Parameter] public EventCallback OnOk { get; set; } 18 | [Parameter] public EventCallback OnCancel { get; set; } 19 | 20 | Task HandleOk() 21 | { 22 | if (OnOk.HasDelegate) 23 | { 24 | return OnOk.InvokeAsync(); 25 | } 26 | return Task.CompletedTask; 27 | } 28 | 29 | Task HandleCancel() 30 | { 31 | if (OnCancel.HasDelegate) 32 | { 33 | return OnCancel.InvokeAsync(); 34 | } 35 | return Task.CompletedTask; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/IAppDomEventHandler.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Web; 2 | 3 | namespace Project.Constraints.UI; 4 | 5 | public interface IAppDomEventHandler 6 | { 7 | event Func BodyClickEvent; 8 | event Func OnKeyDown; 9 | event Func OnKeyUp; 10 | event Func OnThemeChanged; 11 | } 12 | 13 | public interface IThemeChangedBroadcast 14 | { 15 | Task NotifyThemeChangedAsync(); 16 | } 17 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/IJsComponent.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.UI 2 | { 3 | public interface IJsComponent 4 | { 5 | Lazy Id { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Props/ButtonProp.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.UI.Props 2 | { 3 | public class ButtonProp 4 | { 5 | public ButtonType ButtonType { get; set; } = ButtonType.Default; 6 | public string? Text { get; set; } 7 | public bool FakeButton { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Props/CardProp.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Constraints.UI.Props 4 | { 5 | public class CardProp 6 | { 7 | public string? Title { get; set; } 8 | public RenderFragment? TitleTemplate { get; set; } 9 | public RenderFragment? ChildContent { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Props/DefaultProp.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Constraints.UI.Props 4 | { 5 | public class DefaultProp 6 | { 7 | public string? Label { get; set; } 8 | public bool EnableValueExpression { get; set; } = true; 9 | public string BindValueName { get; set; } = "Value"; 10 | public bool StringValue { get; set; } = false; 11 | } 12 | 13 | public class DatePickerProp: DefaultProp 14 | { 15 | public bool WithTime { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Props/GridProp.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Constraints.UI.Props; 4 | 5 | public class GridProp 6 | { 7 | public RenderFragment? ChildContent { get; set; } 8 | public int RowSpan { get; set; } 9 | public int ColSpan { get; set; } 10 | } -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Props/HtmlProp.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.UI.Props 2 | { 3 | [AttributeUsage(AttributeTargets.Property)] 4 | public class PropNameAttribute : Attribute 5 | { 6 | public PropNameAttribute(string name) 7 | { 8 | Name = name; 9 | } 10 | 11 | public PropNameAttribute() 12 | { 13 | 14 | } 15 | 16 | public string? Name { get; } 17 | } 18 | public class HtmlProp 19 | { 20 | [PropName("class")] 21 | public string? Class { get; set; } 22 | [PropName("style")] 23 | public string? Style { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Props/ModalProp.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Constraints.UI.Props 4 | { 5 | public class ModalProp : DefaultProp 6 | { 7 | public string? Title { get; set; } 8 | public bool Visible { get; set; } 9 | public string? Width { get; set; } 10 | public EventCallback VisibleChanged { get; set; } 11 | public RenderFragment? ChildContent { get; set; } 12 | public bool HideDefaultFooter { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Props/SelectProp.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace Project.Constraints.UI.Props 4 | { 5 | public class SelectProp : DefaultProp 6 | { 7 | public bool AllowClear { get; set; } = true; 8 | public bool AllowSearch { get; set; } = true; 9 | public Expression? LabelExpression { get; set; } 10 | public Expression? ValueExpression { get; set; } 11 | public bool ButtonGroup { get; set; } 12 | public bool Mulitple { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Props/SwitchProp.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Constraints.UI.Props 4 | { 5 | public class SwitchProp : DefaultProp 6 | { 7 | public string? CheckedLabel { get; set; } 8 | public string? UnCheckedLabel { get; set; } 9 | } 10 | 11 | public class TabsProp 12 | { 13 | public class TabItem 14 | { 15 | public string? Title { get; set; } 16 | public RenderFragment? TitleTemplate { get; set; } 17 | public RenderFragment? Content { get; set; } 18 | } 19 | public string? ActiveKey { get; set; } 20 | public string? Type { get; set; } 21 | public EventCallback OnChange { get; set; } 22 | public List TabContents { get; set; } = []; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Table/ColumnItemContext.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Constraints.UI.Table; 2 | 3 | public class ColumnItemContext(object instance, ColumnInfo col) 4 | { 5 | public object Instance { get; set; } = instance; 6 | public ColumnInfo Column { get; set; } = col; 7 | 8 | public object? GetValue() => Column.GetValue(Instance); 9 | public T? GetValue() 10 | { 11 | if (Column.GetValue(Instance) is T t) 12 | { 13 | return t; 14 | } 15 | return default; 16 | } 17 | public void SetValue(object val) => Column.SetValue(Instance, val); 18 | } 19 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/UI/Tree/TreeOptions.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Project.Constraints.UI.Tree 3 | { 4 | public sealed class TreeData(TData data) 5 | { 6 | public TData Data { get; set; } = data; 7 | public List>? Children { get; set; } 8 | } 9 | public sealed class TreeOptions(IEnumerable> datas) 10 | { 11 | public bool Readonly { get; set; } 12 | public bool IncludeIndeterminate { get; set; } 13 | public List> Datas { get; set; } = datas.ToList(); 14 | public Func? KeyExpression { get; set; } 15 | public Func? TitleExpression { get; set; } 16 | public Func DisableExpression { get; set; } = d => false; 17 | public Func? IconExpression { get; set; } 18 | public Func? OnCheckedChanged { get; set; } 19 | public Func, IEnumerable>?> ChildrenExpression => node => node.Children; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Utils/AsyncEventInvoke.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Project.Constraints.Utils; 8 | 9 | public static class AsyncEventInvoke 10 | { 11 | public static async Task InvokeAsync(this Func>? @delegate, TP param) 12 | { 13 | if (@delegate is null) return true; 14 | foreach (var item in @delegate.GetInvocationList().Cast>>()) 15 | { 16 | var b = await item.Invoke(param); 17 | if (!b) return false; 18 | } 19 | return true; 20 | } 21 | 22 | public static async Task InvokeAsync(this Func? @delegate, TP param) 23 | { 24 | if (@delegate is null) return ; 25 | foreach (var item in @delegate.GetInvocationList().Cast>()) 26 | { 27 | await item.Invoke(param); 28 | } 29 | } 30 | 31 | public static async Task InvokeAsync(this Func? @delegate) 32 | { 33 | if (@delegate is null) return; 34 | foreach (var item in @delegate.GetInvocationList().Cast>()) 35 | { 36 | await item.Invoke(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/Utils/HashHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Project.Constraints.Utils; 9 | 10 | public static class HashHelper 11 | { 12 | public static string ToHash(this string? value, string algorithm = "SHA256") 13 | { 14 | if (string.IsNullOrEmpty(value)) return string.Empty; 15 | byte[] inputBytes = Encoding.UTF8.GetBytes(value); 16 | var bytes = algorithm switch 17 | { 18 | "MD5" => MD5.HashData(inputBytes), 19 | "SHA1" => SHA1.HashData(inputBytes), 20 | "SHA256" => SHA256.HashData(inputBytes), 21 | "SHA384" => SHA384.HashData(inputBytes), 22 | "SHA512" => SHA512.HashData(inputBytes), 23 | _ => throw new ArgumentException("Unsupported hash algorithm", nameof(algorithm)) 24 | }; 25 | return Convert.ToHexString(bytes); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Shared/Project.Constraints/usings.cs: -------------------------------------------------------------------------------- 1 | global using Project.Constraints.Models; 2 | global using Project.Constraints.Common.Attributes; 3 | global using System.Diagnostics.CodeAnalysis; 4 | global using LightORM; -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Components/AntCol.cs: -------------------------------------------------------------------------------- 1 | using AntDesign; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Project.UI.AntBlazor.Components 5 | { 6 | public class AntCol : GridCol 7 | { 8 | #pragma warning disable BL0007 // Component parameters should be auto properties 9 | [Parameter] public int ColSpan { get => base.Span.AsT1; set => base.Span = value; } 10 | #pragma warning restore BL0007 // Component parameters should be auto properties 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Components/AntDropdown.razor: -------------------------------------------------------------------------------- 1 | @using System.Diagnostics.CodeAnalysis 2 | 3 | 4 | 5 | @foreach (var item in Options.Actions ?? []) 6 | { 7 | 8 | 9 | 10 | } 11 | 12 | 13 | 14 | @Options.Content 15 | 16 | 17 | 18 | @code { 19 | [Parameter, NotNull] public DropdownOptions? Options { get; set; } 20 | } -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Components/AntMenu.razor: -------------------------------------------------------------------------------- 1 | @* 需要套一个元素才能让 ::deep 选择到 *@ 2 |
3 | 4 | @foreach (var item in Router.Menus.Where(m => m.Group == "ROOT")) 5 | { 6 | 7 | } 8 | 9 |
10 | 11 | @code { 12 | [Parameter, NotNull] public IRouterStore? Router { get; set; } 13 | [Parameter] public bool Horizontal { get; set; } 14 | [Parameter, NotNull] public IAppStore? App { get; set; } 15 | 16 | bool Collapsed => Horizontal ? false : App.Collapsed; 17 | } 18 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Components/AntMenu.razor.css: -------------------------------------------------------------------------------- 1 | ::deep .nav-icon { 2 | font-size: 18px; 3 | } 4 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Components/AntMenuItem.razor.css: -------------------------------------------------------------------------------- 1 | .subtitle_template { 2 | display: flex; 3 | justify-content: left; 4 | align-items: center; 5 | } 6 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Components/AntPopover.razor: -------------------------------------------------------------------------------- 1 |  2 | @Options.Trigger 3 | 4 | @code { 5 | [Parameter, NotNull] public PopoverOptions? Options { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Extensions.cs: -------------------------------------------------------------------------------- 1 | using AntDesign; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Project.Constraints.UI; 4 | 5 | namespace Project.UI.AntBlazor 6 | { 7 | public static class Extensions 8 | { 9 | public static void AddAntDesignUI(this IServiceCollection services) 10 | { 11 | services.AddAntDesign(); 12 | services.AddScoped(); 13 | } 14 | 15 | public static CheckboxOption[] ConvertToCheckBoxOptions(this IEnumerable items, Func label, Func value) 16 | { 17 | return items.Select(item => 18 | { 19 | return new CheckboxOption() { Label = label.Invoke(item), Value = value.Invoke(item) }; 20 | }).ToArray(); 21 | } 22 | 23 | public static RadioOption[] ConvertToRadioOptions(this IEnumerable items, Func label, Func value) 24 | { 25 | return items.Select(item => 26 | { 27 | return new RadioOption() { Label = label.Invoke(item), Value = value.Invoke(item) }; 28 | }).ToArray(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Project.UI.AntBlazor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | Library 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:51200", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "applicationUrl": "http://localhost:5192", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "IIS Express": { 22 | "commandName": "IISExpress", 23 | "launchBrowser": true, 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Project.UI.AntBlazor 8 | { 9 | internal class Utils 10 | { 11 | public static AntDesign.ButtonType GetButtonType(string? buttonType) => buttonType switch 12 | { 13 | "primary" => AntDesign.ButtonType.Primary, 14 | "text" => AntDesign.ButtonType.Text, 15 | _ => AntDesign.ButtonType.Default 16 | }; 17 | 18 | public static AntDesign.ColumnFixPlacement? GetColumnFix(string? fix) => fix switch 19 | { 20 | "left" => AntDesign.ColumnFixPlacement.Left, 21 | "right" => AntDesign.ColumnFixPlacement.Right, 22 | _ => null 23 | }; 24 | 25 | public static AntDesign.ColumnAlign GetColumnAlign(string? align) => align switch 26 | { 27 | "left" => AntDesign.ColumnAlign.Left, 28 | "center" => AntDesign.ColumnAlign.Center, 29 | "right" => AntDesign.ColumnAlign.Right, 30 | _ => AntDesign.ColumnAlign.Left 31 | }; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.AntBlazor/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using AntDesign 2 | @using Project.Constraints.UI 3 | @using Project.Constraints.UI.Dropdown 4 | @using Project.Constraints.UI.Flyout 5 | @using Project.Constraints.UI.Table 6 | @using Project.Constraints.Store 7 | @using System.Net.Http 8 | @using Microsoft.AspNetCore.Authorization 9 | @using Microsoft.AspNetCore.Components.Forms 10 | @using Microsoft.AspNetCore.Components.Routing 11 | @using Microsoft.AspNetCore.Components.Web 12 | @using Microsoft.AspNetCore.Components.Web.Virtualization 13 | @using Microsoft.JSInterop 14 | @using Project.Web.Shared.Components 15 | @using Microsoft.Extensions.Localization 16 | @using Microsoft.Extensions.Options 17 | @using Project.Constraints.Options 18 | @using Project.Constraints.Page 19 | @using Project.Web.Shared.Basic 20 | @using System.Web 21 | @using Project.Constraints 22 | @using System.Diagnostics.CodeAnalysis 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.FluentUI/Components/FluentUIMenu.razor: -------------------------------------------------------------------------------- 1 | @using System.Diagnostics.CodeAnalysis 2 | @using Microsoft.FluentUI.AspNetCore.Components 3 | @using Project.Constraints.Store 4 | 5 | @foreach (var item in Router.Menus.Where(m => m.Group == "ROOT")) 6 | { 7 | 8 | } 9 | 10 | 11 | @code { 12 | [Parameter, NotNull] public IRouterStore? Router { get; set; } 13 | [Parameter] public bool Horizontal { get; set; } 14 | [Parameter, NotNull] public IAppStore? App { get; set; } 15 | 16 | bool Collapsed => Horizontal ? false : App.Collapsed; 17 | } 18 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.FluentUI/Components/IconHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.FluentUI.AspNetCore.Components; 2 | using Microsoft.JSInterop; 3 | using Project.Constraints.Models; 4 | using Project.Constraints.Page; 5 | using Project.Constraints.Services; 6 | using System; 7 | using System.Collections.Concurrent; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace Project.UI.FluentUI.Components 14 | { 15 | public static class IconHelper 16 | { 17 | private static readonly ConcurrentDictionary fluentIcons = new(); 18 | public static async Task GetCustomIcon(this ISvgIconService service, string name, IconVariant variant = IconVariant.Regular, IconSize size = IconSize.Custom) 19 | { 20 | if (!fluentIcons.TryGetValue(name, out var icon)) 21 | { 22 | var svgPath = await service.GetIcon(name); 23 | icon = new Icon(name, variant, size, svgPath.Payload ?? string.Empty); 24 | fluentIcons[name] = icon; 25 | } 26 | return icon; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.FluentUI/Extensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.FluentUI.AspNetCore.Components; 3 | using Project.Constraints.UI; 4 | 5 | namespace Project.UI.FluentUI 6 | { 7 | public static class Extensions 8 | { 9 | public static void AddFluentUI(this IServiceCollection services) 10 | { 11 | services.AddHttpClient(); 12 | services.AddFluentUIComponents(); 13 | services.AddScoped(); 14 | } 15 | 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.FluentUI/Project.UI.FluentUI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | <_ContentIncludedByDefault Remove="wwwroot\background.png" /> 21 | <_ContentIncludedByDefault Remove="wwwroot\exampleJsInterop.js" /> 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Shared/Project.UI.FluentUI/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.FluentUI.AspNetCore.Components 2 | @using System.Diagnostics.CodeAnalysis 3 | @using Microsoft.Extensions.Localization 4 | @using Project.Constraints.Models.Request 5 | @using Project.Constraints.UI.Table -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Basic/DefaultTableHeader.razor.css: -------------------------------------------------------------------------------- 1 | .queryarea { 2 | display: flex; 3 | justify-content: space-between; 4 | align-items: center; 5 | width: 100%; 6 | margin-bottom: 10px; 7 | } 8 | 9 | .condition { 10 | flex: 1; 11 | } 12 | 13 | .enable-edit:hover { 14 | cursor: pointer; 15 | color: #1890ff; 16 | } 17 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Basic/ModelPageExtension.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/Basic/ModelPageExtension.cs -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/ComponentHelper/MModal.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Components.Rendering; 3 | using Project.Constraints.Page; 4 | using Project.Constraints.UI.Flyout; 5 | 6 | namespace Project.Web.Shared.ComponentHelper 7 | { 8 | public class MModal : BasicComponent 9 | { 10 | [Parameter] public bool Visible { get; set; } 11 | [Parameter] public EventCallback VisibleChanged { get; set; } 12 | [Parameter] public string? Title { get; set; } 13 | [Parameter] public RenderFragment? ChildContent { get; set; } 14 | [Parameter] public string? Width { get; set; } 15 | [Parameter] public bool HideDefaultFooter { get; set; } 16 | //FlyoutOptions 17 | protected override void BuildRenderTree(RenderTreeBuilder builder) 18 | { 19 | UI.BuildModal() 20 | .Set(p => p.Title, Title) 21 | .Set(p => p.ChildContent, ChildContent) 22 | .Set(p => p.Visible, Visible) 23 | .Set(p => p.VisibleChanged, VisibleChanged) 24 | .Set(p => p.HideDefaultFooter, HideDefaultFooter) 25 | .Set(p => p.Width, Width) 26 | .Render().Invoke(builder); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/ComponentHelper/StackPanel.razor: -------------------------------------------------------------------------------- 1 | 
2 | @ChildContent 3 |
4 | @code { 5 | [Parameter] public string? Class { get; set; } 6 | [Parameter] public string? Style { get; set; } 7 | [Parameter, NotNull] public RenderFragment? ChildContent { get; set; } 8 | [Parameter] public int Gap { get; set; } = 10; 9 | [Parameter] public bool Wrap { get; set; } 10 | /// 11 | /// row / column 12 | /// 13 | [Parameter] public string Direction { get; set; } = "row"; 14 | [Parameter] public bool IsVertial { get; set; } 15 | /// 16 | /// top / middle / bottom 17 | /// 18 | [Parameter] public string VertialAlign { get; set; } = "middle"; 19 | /// 20 | /// left / center / right 21 | /// 22 | [Parameter] public string HorizontalAlign { get; set; } = "left"; 23 | private string WrapStyle => Wrap ? "flex-wrap: wrap;" : ""; 24 | } 25 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/ActionWatcher/ActionWatcher.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @inherits JsComponentBase 3 |
4 | @ChildContent 5 |
-------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Camera/ICameraObject.cs: -------------------------------------------------------------------------------- 1 | using static Project.Web.Shared.Components.Camera; 2 | #pragma warning disable IDE0130 3 | namespace Project.Web.Shared.Components; 4 | 5 | public interface ICameraObject 6 | { 7 | IEnumerable Devices { get; } 8 | //SelectItem Resolutions { get; } 9 | Task SwitchCamera(string deviceId, Resolution? resolution = null); 10 | Task Start(Resolution? resolution); 11 | Task Start(); 12 | Task Stop(); 13 | Task ToggleClipBoxAsync(); 14 | Task Capture(); 15 | } 16 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Camera/ICameraOptions.cs: -------------------------------------------------------------------------------- 1 | using static Project.Web.Shared.Components.Camera; 2 | #pragma warning disable IDE0130 3 | namespace Project.Web.Shared.Components; 4 | 5 | public interface ICameraOptions 6 | { 7 | IEnumerable Resolutions { get; } 8 | SelectItem ResolutionOptions { get; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/ConditionBuilder/Group.razor.css: -------------------------------------------------------------------------------- 1 | .children-wrapper { 2 | position: relative; 3 | } 4 | 5 | .children-wrapper::before { 6 | content: ''; 7 | height: 95%; 8 | width: 5px; 9 | top: 50%; 10 | transform: translateY(-50%); 11 | background-color: #ccc; 12 | display: inline-block; 13 | position: absolute; 14 | border-radius: 5px; 15 | left: 5px; 16 | } 17 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Conditions/ConditionBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Project.Constraints.Page; 3 | 4 | namespace Project.Web.Shared.Components 5 | { 6 | public class ConditionBase : BasicComponent, ICondition 7 | { 8 | [CascadingParameter, NotNull] public IQueryCondition? Parent { get; set; } 9 | [Parameter] public string? Label { get; set; } 10 | [Parameter] public DateType? DateConfig { get; set; } 11 | [Parameter] public string? Style { get; set; } 12 | [Parameter] public RenderFragment? ChildContent { get; set; } 13 | [Parameter] public (int Start, int End) ColSpan { get; set; } 14 | [Parameter] public (int Start, int End) RowSpan { get; set; } 15 | [Parameter] public int? LabelWidth { get; set; } 16 | [Parameter] public int? ContentWidth { get; set; } 17 | private int? FinalContentWidth => ContentWidth ?? Parent.ContentWidth; 18 | protected string ContentWidthStyle => FinalContentWidth.HasValue ? $"{FinalContentWidth}px" : "unset"; 19 | protected string LabelWidthStyle => $"{LabelWidth ?? Parent.LabelWidth}px"; 20 | protected string ColumnWidthStyle => Parent.ColumnWidth.HasValue ? $"{Parent.ColumnWidth}px" : "unset"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Conditions/DateCondition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Project.Web.Shared.Components.Conditions 8 | { 9 | public class DateCondition : SimpleCondition 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Conditions/EmptyCondition.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @inherits ConditionBase 3 | 4 | 5 | 6 | @Label 7 | 8 | 9 | @ChildContent 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Conditions/QueryConditions.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @using System.Linq.Expressions 3 | @using Project.Constraints.Page 4 | @inherits BasicComponent 5 | 6 | @if (StackLayout || Header is not null) 7 | { 8 |
9 | @if (Header is not null) 10 | { 11 | 12 | @Header 13 | @UI.BuildButton(this).OnClick(() => expand = !expand).Text(expand ? "收起" : "展开").Render() 14 | 15 |
16 | 17 | @ChildContent 18 | 19 |
20 | } 21 | else 22 | { 23 | 24 | @ChildContent 25 | 26 | } 27 |
28 | } 29 | else 30 | { 31 |
32 | 33 | @ChildContent 34 | 35 |
36 | } 37 |
38 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Downloader/DownloadNotFound.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @page "/download/notfound" 3 | @inherits BasicComponent 4 |
5 |
6 |
7 | 8 |
9 |
10 | HTTP 404 - 请求下载的文件不存在! 11 |
12 |
13 |
14 |

15 | 您可以返回首页,或联系管理员 16 |

17 |
18 |
19 | 去首页 20 |
21 |
22 |
23 | 24 | @code { 25 | void NavigatorToIndex() 26 | { 27 | Navigator.NavigateTo("/"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/EdgeWidget/EdgeWidget.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @inherits JsComponentBase 3 |
4 |
5 |
6 |
7 | @if (ChildContent != null) 8 | { 9 | @ChildContent 10 | } 11 |
12 | 13 | @* *@ 14 | @* *@ 15 |
16 |
17 |
-------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/EdgeWidget/EdgeWidget.razor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Project.Web.Shared.Components 9 | { 10 | public partial class EdgeWidget : JsComponentBase 11 | { 12 | [Parameter] public RenderFragment? ChildContent { get; set; } 13 | /// 14 | /// left / top /right /bottom 15 | /// 16 | [Parameter] public string Position { get; set; } = "left"; 17 | 18 | ElementReference? maskDiv; 19 | ElementReference? containerDiv; 20 | ElementReference? triggerDiv; 21 | protected override async ValueTask Init() 22 | { 23 | await InvokeVoidAsync("init", new 24 | { 25 | mask = maskDiv, 26 | container = containerDiv, 27 | trigger = triggerDiv, 28 | }); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/EdgeWidget/EdgeWidget.razor.css: -------------------------------------------------------------------------------- 1 | .mark { 2 | position: fixed; 3 | width: 100%; 4 | height: 100%; 5 | display: none; 6 | top: 0; 7 | left: 0; 8 | } 9 | 10 | .mark.show { 11 | display: block; 12 | } 13 | 14 | .container { 15 | position: fixed; 16 | top: 200px; 17 | transition: all 0.3s; 18 | 19 | } 20 | 21 | .container.show { 22 | left: 0px !important; 23 | } 24 | 25 | .content { 26 | position: relative; 27 | box-shadow: var(--border-shadow); 28 | padding: 10px; 29 | } 30 | 31 | .trigger { 32 | position: absolute; 33 | right: -52px; 34 | top: 50%; 35 | transform: translateY(-50%); 36 | background: rgb(255 255 255 / 0.6); 37 | border-radius: 26px; 38 | box-shadow: var(--border-shadow); 39 | cursor: pointer; 40 | font-size: 48px; 41 | width: 52px; 42 | height: 52px; 43 | display: flex; 44 | } 45 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/ErrorCatcher/CrashPage.razor.css: -------------------------------------------------------------------------------- 1 | .exception-wrapper { 2 | width: fit-content; 3 | background-color: white; 4 | padding: 10px; 5 | text-align: left; 6 | font-size: 14px; 7 | position: absolute; 8 | left: 50%; 9 | right: 50%; 10 | width: 70vw; 11 | z-index: 999; 12 | border: 1px solid #ccc; 13 | box-shadow: 0 0 12px 0 rgb(0 0 0 / 20%); 14 | transform: translate(-50%, -50%); 15 | display: flex; 16 | flex-direction: column; 17 | max-height: 70vh; 18 | } 19 | 20 | .exception-message { 21 | font-size: 1.5em; 22 | } 23 | 24 | .exception-stacktrace { 25 | flex: 1; 26 | overflow-y: auto; 27 | padding: 0 1em; 28 | } 29 | 30 | .exception-stacktrace-item { 31 | white-space: pre-wrap; 32 | /* display: block; */ 33 | text-indent: -2em; 34 | padding-left: 2em; 35 | line-height: 2em; 36 | } 37 | 38 | .exception-footer { 39 | text-align: right; 40 | padding-right: 20px; 41 | } 42 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/ErrorCatcher/IError.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Web.Shared.Components 4 | { 5 | public interface IExceptionHandler 6 | { 7 | Task HandleExceptionAsync(Exception exception); 8 | } 9 | public interface IError 10 | { 11 | //event Func OnHandleExcetionAsync; 12 | //event Action OnHandleExcetion; 13 | void Register(TComponent component) where TComponent : IComponent, IExceptionHandler; 14 | void UnRegister(TComponent component) where TComponent : IComponent, IExceptionHandler; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Fetch/Fetch.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @inherits JsComponentBase 3 | @typeparam TData 4 |
-------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/ForbiddenPage.razor: -------------------------------------------------------------------------------- 1 | @page "/forbidden" 2 | @namespace Project.Web.Shared.Components 3 | @inherits BasicComponent 4 |
5 |
6 |
7 | 8 |
9 |
10 | HTTP 403 - 当前用户无法访问此页面! 11 |
12 | @*
13 |
14 |

15 | 您可以返回首页,或联系管理员 16 |

17 |
18 |
19 | 去首页 20 |
*@ 21 |
22 |
23 | 24 | @code { 25 | string svgName = "p403_01"; 26 | protected override void OnInitialized() 27 | { 28 | base.OnInitialized(); 29 | var i = Random.Shared.Next(0, 100); 30 | var index = i % 2 == 0 ? "01" : "02"; 31 | svgName = $"p403_{index}"; 32 | } 33 | 34 | void NavigatorToIndex() 35 | { 36 | Navigator.NavigateTo("/"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/FullScreen/FullScreen.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @inherits JsComponentBase 3 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/FullScreen/FullScreen.razor.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Web.Shared.Components 2 | { 3 | public partial class FullScreen : JsComponentBase 4 | { 5 | protected override async ValueTask Init() 6 | { 7 | await InvokeVoidAsync("init"); 8 | } 9 | 10 | public async ValueTask Toggle() 11 | { 12 | await InvokeVoidAsync("toggle"); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Icon/FontIcon.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Rendering; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | #pragma warning disable IDE0130 8 | namespace Project.Web.Shared.Components; 9 | 10 | public class FontIcon : ComponentBase 11 | { 12 | [Parameter] 13 | public string HtmlTag { get; set; } = "i"; 14 | [Parameter] 15 | public string? IconName { get; set; } 16 | [Parameter] 17 | public string? ClassName { get; set; } 18 | [Parameter(CaptureUnmatchedValues = true)] public Dictionary AdditionalParameters { get; set; } = []; 19 | string IconClass => $"{IconName} {ClassName}"; 20 | protected override void BuildRenderTree(RenderTreeBuilder builder) 21 | { 22 | builder.OpenElement(0, HtmlTag); 23 | builder.AddAttribute(1, "class", IconClass); 24 | builder.AddMultipleAttributes(2, AdditionalParameters); 25 | builder.CloseElement(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Icon/IconSelector.razor.css: -------------------------------------------------------------------------------- 1 | .icons-wrapper { 2 | display: grid; 3 | grid-template-columns: repeat(auto-fill, 2em); 4 | max-height: 50vh; 5 | overflow-y: scroll; 6 | font-size: 2em; 7 | align-items: center; 8 | justify-content: center; 9 | } 10 | 11 | .icons-wrapper span { 12 | display: flex; 13 | align-items: center; 14 | justify-content: center; 15 | padding: 5px; 16 | margin:1px; 17 | } 18 | 19 | .icons-wrapper span.selected { 20 | color: var(--major-color); 21 | box-shadow: var(--border-shadow); 22 | } 23 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/JsTimer/JsTimer.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @inherits JsComponentBase 3 |
4 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/JsTimer/JsTimer.razor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.JSInterop; 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | namespace Project.Web.Shared.Components 6 | { 7 | public partial class JsTimer 8 | { 9 | [Parameter, NotNull] public int? Interval { get; set; } 10 | [Parameter] public EventCallback Callback { get; set; } 11 | 12 | DotNetObjectReference? objRef; 13 | protected override async ValueTask Init() 14 | { 15 | objRef = DotNetObjectReference.Create(this); 16 | await InvokeVoidAsync("init", new 17 | { 18 | dotNetRef = objRef, 19 | interval = Interval, 20 | }); 21 | } 22 | 23 | [JSInvokable("Call")] 24 | public Task Invoke() 25 | { 26 | if (!Callback.HasDelegate) 27 | { 28 | return Task.CompletedTask; 29 | } 30 | return Callback.InvokeAsync(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/JsTimer/JsTimer.razor.ts: -------------------------------------------------------------------------------- 1 | import { BaseComponent } from "../../JsCore/baseComponent" 2 | import { getComponentById } from "../../JsCore/componentStore" 3 | 4 | export class JsTimer extends BaseComponent { 5 | instance: any 6 | interval: number 7 | timer?: number 8 | constructor(options: any) { 9 | super() 10 | this.instance = options.dotNetRef 11 | this.interval = options.interval 12 | } 13 | start() { 14 | this.timer = window.setInterval(() => { 15 | this.instance.invokeMethodAsync("Call") 16 | }, this.interval) 17 | } 18 | 19 | dispose() { 20 | if (this.timer) { 21 | window.clearInterval(this.timer) 22 | this.timer = undefined 23 | } 24 | } 25 | 26 | static init(id: string, options: any) { 27 | const timter: JsTimer = getComponentById(id, () => { 28 | return new JsTimer(options) 29 | }) 30 | timter.start() 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Link/VLink.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @using System.Diagnostics.CodeAnalysis 3 | 4 | @code { 5 | [Parameter, NotNull] public string? Href { get; set; } 6 | [Inject, NotNull] IFileService? FileService{ get; set; } 7 | [Parameter] public string Rel { get; set; } = "stylesheet"; 8 | string VersionHref => FileService.GetStaticFileWithVersion(Href); 9 | } 10 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/MTree/CheckBoxState.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | 3 | 4 | @code { 5 | [Parameter, NotNull] public string? State { get; set; } 6 | 7 | public const string Checked = "checked"; 8 | public const string Normal = "normal"; 9 | public const string Indeterminate = "indeterminate"; 10 | } 11 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/MTree/MTree.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @typeparam TNode 3 |
4 | @foreach (var item in DataSource) 5 | { 6 | 7 | 8 | 9 | } 10 |
-------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/MTree/MTree.razor.css: -------------------------------------------------------------------------------- 1 | body { 2 | } 3 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/MTree/MTreeNode.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @typeparam TNode 3 |
4 | 5 |
6 | 7 | @if (Root.TitleTemplate != null) 8 | { 9 | @Root.TitleTemplate(NodeValue) 10 | } 11 | else 12 | { 13 | @Root.TitleExpression?.Invoke(NodeValue) 14 | } 15 |
16 |
17 |
18 | @foreach (var child in Children) 19 | { 20 | 21 | 22 | 23 | } 24 |
25 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/MTree/MTreeNode.razor.css: -------------------------------------------------------------------------------- 1 | .power-tree-node { 2 | display: flex; 3 | align-items: center; 4 | cursor: pointer; 5 | padding: 1px; 6 | } 7 | 8 | .power-tree-node .node-narrow { 9 | width: 16px; 10 | height: 16px; 11 | position: relative; 12 | } 13 | 14 | 15 | .power-tree-node .node-narrow::after { 16 | content: ' '; 17 | border: 2px solid #d9d9d9; 18 | border-top: 0; 19 | border-left: 0; 20 | width: 8px; 21 | height: 8px; 22 | position: absolute; 23 | transition: all 0.3s; 24 | transform: rotate(45deg); 25 | top: 2px; 26 | } 27 | 28 | .power-tree-node .node-narrow.collapse::after { 29 | transform: rotate(-45deg); 30 | top: 4px; 31 | } 32 | 33 | .node-narrow.disable { 34 | opacity: 0; 35 | cursor: default; 36 | } 37 | 38 | .power-tree-node .node-title { 39 | margin-left: 10px; 40 | } 41 | 42 | .childrens { 43 | display: block; 44 | } 45 | 46 | .childrens.collapse { 47 | display: none; 48 | } 49 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Reconnector/IReconnector.cs: -------------------------------------------------------------------------------- 1 |  2 | using AutoInjectGenerator; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Project.Web.Shared.Components 6 | { 7 | public interface IReconnectorProvider 8 | { 9 | void UpdateTemplate(IReconnector reconnector); 10 | void RegisterView(Action action); 11 | } 12 | 13 | [AutoInject] 14 | public class ReconnectorProvider : IReconnectorProvider 15 | { 16 | Action? action; 17 | public void RegisterView(Action action) 18 | { 19 | this.action = action; 20 | } 21 | 22 | public void UpdateTemplate(IReconnector reconnector) 23 | { 24 | action?.Invoke(reconnector); 25 | } 26 | } 27 | 28 | public interface IReconnector 29 | { 30 | /// 31 | /// 正在重连的模板 32 | /// 33 | RenderFragment? ReconnectingTemplate { get; set; } 34 | 35 | /// 36 | /// 重连失败的模板 37 | /// 38 | RenderFragment? ReconnectFailedTemplate { get; set; } 39 | 40 | /// 41 | /// 服务器拒绝的模板 42 | /// 43 | RenderFragment? ReconnectRejectedTemplate { get; set; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Reconnector/Reconnector.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Web.Shared.Components 4 | { 5 | public class Reconnector : ComponentBase, IReconnector 6 | { 7 | /// 8 | /// 正在重连的模板 9 | /// 10 | [Parameter] 11 | public RenderFragment? ReconnectingTemplate { get; set; } 12 | 13 | /// 14 | /// 重连失败的模板 15 | /// 16 | [Parameter] 17 | public RenderFragment? ReconnectFailedTemplate { get; set; } 18 | 19 | /// 20 | /// 服务器拒绝的模板 21 | /// 22 | [Parameter] 23 | public RenderFragment? ReconnectRejectedTemplate { get; set; } 24 | [Inject, NotNull] public IReconnectorProvider? Provider { get; set; } 25 | protected override void OnAfterRender(bool firstRender) 26 | { 27 | base.OnAfterRender(firstRender); 28 | Provider.UpdateTemplate(this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Reconnector/ReconnectorContent.razor.css: -------------------------------------------------------------------------------- 1 | #components-reconnect-modal { 2 | position: fixed; 3 | z-index: 2000; 4 | top: 0; 5 | left: 0; 6 | right: 0; 7 | bottom: 0; 8 | } 9 | 10 | #components-reconnect-modal, 11 | #components-reconnect-modal.components-reconnect-hide, 12 | #components-reconnect-modal .reconnect-state { 13 | display: none; 14 | } 15 | 16 | #components-reconnect-modal.components-reconnect-show, 17 | #components-reconnect-modal.components-reconnect-failed, 18 | #components-reconnect-modal.components-reconnect-rejected, 19 | #components-reconnect-modal.components-reconnect-show .reconnect-state.show, 20 | #components-reconnect-modal.components-reconnect-failed .reconnect-state.failed, 21 | #components-reconnect-modal.components-reconnect-rejected .reconnect-state.rejected { 22 | display: block; 23 | } 24 | 25 | .reconnect-state .message { 26 | background-color: rgb(64, 158, 255); 27 | display: block; 28 | padding: 1rem; 29 | color: #fff; 30 | } 31 | 32 | .reconnect-state .message > a { 33 | text-decoration: underline; 34 | color: #fff; 35 | } 36 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Reconnector/ReconnectorOutlet.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.AspNetCore.Components.Rendering; 3 | 4 | namespace Project.Web.Shared.Components 5 | { 6 | /// 7 | /// 修改重新连接处理程序 (Blazor Server) 8 | /// https://learn.microsoft.com/zh-cn/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-7.0#modify-the-reconnection-handler-blazor-server 9 | /// 10 | public class ReconnectorOutlet : ComponentBase 11 | { 12 | /// 13 | /// 是否自动重连 (默认 true) 14 | /// 15 | [Parameter] 16 | public bool AutoReconnect { get; set; } = true; 17 | 18 | protected override void BuildRenderTree(RenderTreeBuilder builder) 19 | { 20 | builder.OpenComponent(0); 21 | builder.AddAttribute(1, nameof(ReconnectorContent.AutoReconnect), AutoReconnect); 22 | builder.CloseComponent(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Reconnector/WebAdminReconnector.razor.css: -------------------------------------------------------------------------------- 1 | .mask { 2 | background-color: black; 3 | opacity: 0.2; 4 | position: fixed; 5 | top: 0; 6 | left: 0; 7 | width: 100%; 8 | height: 100%; 9 | } 10 | 11 | .wrapper { 12 | position: fixed; 13 | width: 100%; 14 | height: 100vh; 15 | display: flex; 16 | justify-content: center; 17 | align-items: center; 18 | } 19 | 20 | .content { 21 | background-color: white; 22 | opacity: 1; 23 | padding: 20px; 24 | border-radius: 5px; 25 | box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%); 26 | } 27 | 28 | .connecting .content h1 { 29 | display: flex; 30 | } 31 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/Script/VScript.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @using System.Diagnostics.CodeAnalysis 3 | 4 | @code { 5 | [Parameter, NotNull] public string? Src { get; set; } 6 | [Inject, NotNull] IFileService? FileService { get; set; } 7 | string VersionSrc => FileService.GetStaticFileWithVersion(Src); 8 | } 9 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/ScrollBar/HorizontalScroll.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @inherits JsComponentBase 3 | @attribute [AutoLoadJsModule(Path = "Components/ScrollBar")] 4 |
5 | @ChildContent 6 |
7 | 8 | @code { 9 | private ElementReference? WrapElementRef; 10 | [Parameter, NotNull] public RenderFragment? ChildContent { get; set; } 11 | public ElementReference? GetWrapElementRef() => WrapElementRef; 12 | protected override ValueTask Init() 13 | { 14 | return InvokeVoidAsync("init", WrapElementRef); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/ScrollBar/HorizontalScroll.razor.css: -------------------------------------------------------------------------------- 1 | .wrap { 2 | overflow-x: auto; 3 | overflow-y: hidden; 4 | scrollbar-width: none; 5 | } 6 | 7 | .wrap::-webkit-scrollbar { 8 | height: 5px; 9 | } 10 | 11 | .wrap::-webkit-scrollbar-thumb { 12 | background: #eaeaea; 13 | border-radius: var(--el-border-radius-base); 14 | box-shadow: none; 15 | -webkit-box-shadow: none; 16 | } 17 | 18 | .wrap::-webkit-scrollbar-track { 19 | /* background: v-bind('config.layout.layoutMode == "Default" ? "none":config.getColorVal("headerBarBackground")');*/ 20 | } 21 | 22 | .wrap:hover::-webkit-scrollbar-thumb:hover { 23 | background: #c8c9cc; 24 | } 25 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/SplitView/SplitView.razor.css: -------------------------------------------------------------------------------- 1 | .split-view { 2 | display: flex; 3 | height: 100%; 4 | } 5 | 6 | .view-content { 7 | padding: 10px; 8 | } 9 | 10 | .split-view.row .view-content-first { 11 | width: 50%; 12 | height: 100%; 13 | } 14 | 15 | .split-view-separator { 16 | box-shadow: rgba(0,0,0,.1) 0px 0px 12px 0px; 17 | display: flex; 18 | align-items: center; 19 | border: 1px solid #ccc; 20 | } 21 | 22 | .split-view.column .split-view-separator:hover { 23 | cursor: row-resize; 24 | } 25 | 26 | .split-view.row .split-view-separator:hover { 27 | cursor: col-resize; 28 | } 29 | 30 | .view-content-second { 31 | flex: 1; 32 | height: 100%; 33 | } 34 | 35 | .split-view.column .view-content-first { 36 | width: 100%; 37 | height: 50%; 38 | } 39 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Components/WaterMark/WaterMark.razor.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/Components/WaterMark/WaterMark.razor.ts -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/IndexLoading/IndexLoading.razor: -------------------------------------------------------------------------------- 1 | @namespace Project.Web.Shared.Components 2 | @if (Loading) 3 | { 4 |
5 |
6 |
@Title
7 |
8 | } 9 | 10 | @code { 11 | [Parameter] public bool Loading { get; set; } 12 | [Parameter] public string Title { get; set; } = "正在加载,请耐心等待!"; 13 | } 14 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/JsCore/Utils.ts: -------------------------------------------------------------------------------- 1 | export interface IJsActionResult { 2 | isSuccess: boolean, 3 | message: string | undefined, 4 | payload: any 5 | } 6 | export function success(msg: string | undefined, payload?: any): IJsActionResult { 7 | return { 8 | isSuccess: true, 9 | message: msg, 10 | payload: payload 11 | } 12 | } 13 | 14 | export function failed(msg: string | undefined): IJsActionResult { 15 | return { 16 | isSuccess: false, 17 | message: msg, 18 | payload: null 19 | } 20 | } 21 | 22 | export const GAP = 4; 23 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/JsCore/baseComponent.ts: -------------------------------------------------------------------------------- 1 | import { getComponentById, removeComponent } from './componentStore' 2 | 3 | export class BaseComponent { 4 | dispose(): void { 5 | 6 | } 7 | 8 | static dispose(id: string): void { 9 | const com = getComponentById(id) 10 | if (com) { 11 | console.debug('dispose: ', id, com) 12 | com.dispose() 13 | removeComponent(id) 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/JsCore/componentStore.ts: -------------------------------------------------------------------------------- 1 | const allComponentMap = new Map() 2 | declare global { 3 | interface Window { 4 | allComponentMap: Map 5 | } 6 | } 7 | window.allComponentMap = allComponentMap 8 | 9 | export function getComponentById(id: string, init?: Function | Object) { 10 | if (!allComponentMap.has(id) && init !== undefined) { 11 | if (init instanceof Function) { 12 | allComponentMap.set(id, init()) 13 | } else if (init) { 14 | allComponentMap.set(id, init) 15 | } else { 16 | console.error('初始化异常', init) 17 | throw new Error('初始化异常') 18 | } 19 | } 20 | if (allComponentMap.has(id)) 21 | return allComponentMap.get(id) 22 | else 23 | return undefined 24 | } 25 | 26 | export function removeComponent(id: string): void { 27 | allComponentMap.delete(id) 28 | } 29 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/JsCore/customEventHandler.ts: -------------------------------------------------------------------------------- 1 | import {HandlerBase} from './handlerBase' 2 | 3 | export class CustomEventHandler extends HandlerBase { 4 | constructor(el: EventTarget 5 | , eventType: string 6 | , fn: Function 7 | , id: string 8 | , once: boolean 9 | , drop: Function | undefined = undefined) { 10 | super(el, eventType, fn, id, once, drop); 11 | } 12 | 13 | on(): void { 14 | this.element.addEventListener(this.type, this.action); 15 | } 16 | 17 | off(): void { 18 | this.element.removeEventListener(this.type, this.action); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/JsCore/dragHelper.ts: -------------------------------------------------------------------------------- 1 | import { EventHandler } from './eventHandler' 2 | const storeValue = {}; 3 | function storeOnSelectstart() { 4 | storeValue['onselectstart'] = document.onselectstart; 5 | document.onselectstart = () => false 6 | } 7 | 8 | function restoreOnSelectstart() { 9 | if (document.onselectstart !== storeValue['onselectstart']) 10 | document.onselectstart = storeValue['onselectstart'] 11 | } 12 | export function startDrag(e: Event, moveHandler: Function, upHandler?: Function) { 13 | e.stopImmediatePropagation() 14 | EventHandler.listen(document.documentElement, 'mousemove', moveHandler) 15 | EventHandler.once(document.documentElement, 'mouseup', e => { 16 | if (upHandler){ 17 | upHandler() 18 | } 19 | EventHandler.remove(document.documentElement, 'mousemove', moveHandler) 20 | restoreOnSelectstart() 21 | }) 22 | storeOnSelectstart() 23 | } 24 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/JsCore/eventHandler.ts: -------------------------------------------------------------------------------- 1 | import {addListener, getElementEvents} from './eventHandlerSet' 2 | 3 | export const EventHandler = { 4 | listen: function (el: EventTarget, eventType: string, action: Function) { 5 | if (!el) return 6 | addListener(el, eventType, action, false) 7 | }, 8 | once: function (el: EventTarget, eventType: string, action: Function) { 9 | if (!el) return 10 | addListener(el, eventType, action, true) 11 | }, 12 | remove: function (el: EventTarget, eventType: string, action?: Function) { 13 | if (!el) return 14 | const ets = getElementEvents(el); 15 | ets.removeHandler(eventType, action); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/JsCore/handlerBase.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | interface EventTarget { 3 | eventUid: any 4 | } 5 | } 6 | let eventUid = 1 7 | 8 | export function makeUid(el: EventTarget, uid: any = undefined): any { 9 | return ((uid && `${uid}::${eventUid++}`) || el.eventUid || eventUid++); 10 | } 11 | 12 | 13 | export class HandlerBase { 14 | element: EventTarget | Element 15 | id: string 16 | delegate: Function 17 | type: string 18 | once: boolean 19 | drop: Function | undefined 20 | 21 | constructor(el: EventTarget | Element 22 | , eventType: string 23 | , fn: Function 24 | , id: string 25 | , once: boolean 26 | , drop: Function | undefined = undefined) { 27 | this.element = el 28 | this.id = id 29 | this.delegate = fn 30 | this.type = eventType 31 | this.once = once 32 | this.drop = drop 33 | } 34 | 35 | action(event: any): void { 36 | if (this.once) { 37 | this.off() 38 | if (this.drop) this.drop() 39 | } 40 | this.delegate.apply(this.element, [event]); 41 | } 42 | 43 | bind(): void { 44 | } 45 | 46 | off(): void { 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/JsCore/resizeHandler.ts: -------------------------------------------------------------------------------- 1 | import {HandlerBase} from './handlerBase' 2 | 3 | export class ResizeHandler extends HandlerBase { 4 | resizeObserver: ResizeObserver 5 | 6 | constructor(el: Element | EventTarget 7 | , fn: Function 8 | , id: string 9 | , once: boolean 10 | , drop: Function | undefined = undefined) { 11 | super(el, 'resize', fn, id, once, drop); 12 | this.resizeObserver = new ResizeObserver(entries => { 13 | this.action(entries); 14 | }); 15 | } 16 | 17 | on(): void { 18 | if (this.element instanceof Element) 19 | this.resizeObserver.observe(this.element); 20 | } 21 | 22 | off(): void { 23 | this.resizeObserver.disconnect(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/JsCore/utils.ts: -------------------------------------------------------------------------------- 1 | export interface IJsActionResult { 2 | isSuccess: boolean, 3 | message: string | undefined, 4 | payload: any 5 | } 6 | export function success(msg: string | undefined, payload?: any): IJsActionResult { 7 | return { 8 | isSuccess: true, 9 | message: msg, 10 | payload: payload 11 | } 12 | } 13 | 14 | export function failed(msg: string | undefined): IJsActionResult { 15 | return { 16 | isSuccess: false, 17 | message: msg, 18 | payload: null 19 | } 20 | } 21 | 22 | export const GAP = 4; 23 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Langs/语言文件查找说明.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/Langs/语言文件查找说明.md -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/AppRoot.razor: -------------------------------------------------------------------------------- 1 | @* 使用services.AddCascadingAuthenticationState();代替 *@ 2 | @* *@ 3 | 4 | 5 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | @Context.UI.RenderContainer() 24 |
25 |
26 |
27 | @*
*@ -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/Banner.razor.css: -------------------------------------------------------------------------------- 1 | .layout-logo { 2 | width: 100%; 3 | height: 50px; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | box-sizing: border-box; 8 | padding: 10px; 9 | background: var(--background-color); 10 | } 11 | 12 | .layout-logo.line { 13 | width: unset; 14 | } 15 | 16 | .layout-logo .logo-img { 17 | width: 28px; 18 | } 19 | 20 | .layout-logo .website-name { 21 | display: block; 22 | text-align: center; 23 | width: 180px; 24 | padding-left: 4px; 25 | font-size: 20px; 26 | font-weight: 600; 27 | overflow: hidden; 28 | text-overflow: ellipsis; 29 | white-space: nowrap; 30 | } 31 | 32 | .layout-logo .menu-collapse-icon { 33 | font-size: 18px; 34 | display: inline-block; 35 | } 36 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/ModifyUserPassword.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints.UI.Flyout 2 | @using Project.Constraints.UI.Form 3 | @using MT.Toolkit.StringExtension; 4 | @inherits DialogTemplate 5 | 6 | @if (options != null) 7 | { 8 | @UI.BuildForm(options) 9 | } 10 | 11 | @code { 12 | FormOptions? options; 13 | protected override void OnInitialized() 14 | { 15 | base.OnInitialized(); 16 | if (Value != null) 17 | options = FormBuilder.Create().Build(UI, Value); 18 | } 19 | 20 | // public override Task OnPostAsync() 21 | // { 22 | // if (!(options?.Validate?.Invoke() ?? false)) 23 | // { 24 | // return Task.FromResult(false); 25 | // } 26 | // // if (User.UserInfo?.Password != Value?.OldPassword) 27 | // // { 28 | // // UI.Error(GetLocalizeString("OldPasswordError")); 29 | // // return Task.FromResult(false); 30 | // // } 31 | // if (Value?.Password != Value?.ConfirmPassword) 32 | // { 33 | // UI.Error(GetLocalizeString("PasswordDifference")); 34 | // return Task.FromResult(false); 35 | // } 36 | // return base.OnPostAsync(); 37 | // } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/NavBar.razor: -------------------------------------------------------------------------------- 1 |  5 | @code{ 6 | [Parameter] public string? Class{ get; set; } 7 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/NavBar.razor.css: -------------------------------------------------------------------------------- 1 | .nav-bar.card { 2 | display: flex; 3 | height: 50px; 4 | margin: 20px 16px 0 16px; 5 | } 6 | 7 | .nav-bar.classic { 8 | display: flex; 9 | height: 50px; 10 | background-color: #fff; 11 | } 12 | 13 | .nav-bar.line { 14 | flex: 1; 15 | } 16 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/NavMenu.razor.css: -------------------------------------------------------------------------------- 1 | .nav-menu { 2 | display: flex; 3 | align-items: center; 4 | height: 100%; 5 | margin-left: auto; 6 | overflow: hidden; 7 | background-color: var(--background-color); 8 | } 9 | 10 | 11 | .nav-menu.card { 12 | border-radius: 4px; 13 | box-shadow: var(--border-shadow); 14 | } 15 | 16 | .nav-menu.line { 17 | padding-left: 16px; 18 | } 19 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/NavMenuItem.razor: -------------------------------------------------------------------------------- 1 |  4 | 5 | @code { 6 | [Parameter] public EventCallback OnClick { get; set; } 7 | [Parameter] public string? Title { get; set; } 8 | [Parameter] public RenderFragment? ChildContent { get; set; } 9 | [Parameter] public bool FitContent { get; set; } 10 | private Task HandleClick() 11 | { 12 | if (OnClick.HasDelegate) 13 | { 14 | return OnClick.InvokeAsync(); 15 | } 16 | return Task.CompletedTask; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/NavMenuItem.razor.css: -------------------------------------------------------------------------------- 1 | .nav-menu-item { 2 | height: 100%; 3 | width: 40px; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | cursor: pointer; 8 | } 9 | 10 | .nav-menu-item.fit-width { 11 | width: unset; 12 | } 13 | 14 | .nav-menu-item:hover { 15 | background-color: var(--hover-bg-color); 16 | } 17 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/Profile.razor.css: -------------------------------------------------------------------------------- 1 | ::deep .out_wrapper { 2 | display: unset !important; 3 | } 4 | 5 | .wrapper { 6 | display: flex; 7 | height: 100%; 8 | padding: 0 10px; 9 | align-items: center; 10 | cursor: pointer; 11 | user-select: none; 12 | color: #000; 13 | } 14 | 15 | .wrapper .avatar { 16 | box-sizing: border-box; 17 | height: 25px; 18 | width: 25px; 19 | border-radius: 50%; 20 | } 21 | 22 | .wrapper .name { 23 | padding-left: 6px; 24 | white-space: nowrap; 25 | } 26 | 27 | .menu-item { 28 | border: 1px solid #ccc; 29 | padding: 2px 10px; 30 | text-align: center; 31 | border-radius: 5px; 32 | } 33 | 34 | .menu-item.green-tag { 35 | color: #389e0d; 36 | background: #f6ffed; 37 | border-color: #b7eb8f; 38 | } 39 | 40 | .menu-item.red-tag { 41 | color: #cf1322; 42 | background: #fff1f0; 43 | border-color: #ffa39e; 44 | } 45 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/RedirectToLogin.razor: -------------------------------------------------------------------------------- 1 | @code { 2 | 3 | [Inject, NotNull] NavigationManager? Nav { get; set; } 4 | [Inject, NotNull] IUIService? UI { get; set; } 5 | [Inject, NotNull] IAuthenticationStateProvider? StateProvider { get; set; } 6 | protected override async void OnInitialized() 7 | { 8 | base.OnInitialized(); 9 | try 10 | { 11 | @*_ = MsgSrv.Error("登录过期!请重新登录!");*@ 12 | // var redirect = Nav.ToBaseRelativePath(Nav.Uri); 13 | // Nav.NavigateTo($"/account/login?Redirect={HttpUtility.UrlEncode(redirect)}", true); 14 | await StateProvider.ClearState(); 15 | } 16 | catch 17 | { 18 | 19 | } 20 | } 21 | 22 | protected override void OnAfterRender(bool firstRender) 23 | { 24 | base.OnAfterRender(firstRender); 25 | 26 | // @*_ = MsgSrv.Error("登录过期!请重新登录!");*@ 27 | // var redirect = Navigator.ToBaseRelativePath(Navigator.Uri); 28 | // Navigator.NavigateTo($"/login?Redirect={HttpUtility.UrlEncode(redirect)}", true); 29 | // Navigator.NavigateTo("/login", true); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/SideBar.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints.Common 2 | @inherits Project.Constraints.Page.BasicComponent 3 | 9 | 10 | @code { 11 | [Parameter] public RenderFragment? TopBanner { get; set; } 12 | [Parameter] public string? Class { get; set; } 13 | [Parameter] public bool Horizontal { get; set; } 14 | protected override Task OnInitializedAsync() 15 | { 16 | Router.DataChangedEvent += StateHasChanged; 17 | return base.OnInitializedAsync(); 18 | } 19 | 20 | private string Width => UI.GetMenuWidth(App.Collapsed).ToPixel();// App.Collapsed ? 80.ToPixel() : App.SideBarExpandWidth.ToPixel(); 21 | 22 | public void ToggleCollapse() 23 | { 24 | // collapse = newState; 25 | StateHasChanged(); 26 | } 27 | 28 | protected override ValueTask OnDisposeAsync() 29 | { 30 | Router.DataChangedEvent -= StateHasChanged; 31 | return base.OnDisposeAsync(); 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/SideBar.razor.css: -------------------------------------------------------------------------------- 1 | .side_bar { 2 | transition: background .3s,width .3s cubic-bezier(.2,0,0,1) 0s; 3 | transition-property: background, width; 4 | transition-duration: 0.3s, 0.3s; 5 | transition-timing-function: ease, cubic-bezier(0.2, 0, 0, 1); 6 | transition-delay: 0s, 0s; 7 | } 8 | 9 | /*经典布局*/ 10 | .classic { 11 | background: var(--side-bar-bg); 12 | height: 100vh; 13 | box-shadow: var(--border-shadow); 14 | overflow: hidden; 15 | transition: width .3s ease; 16 | } 17 | 18 | /*卡片式布局*/ 19 | .card { 20 | background: var(--side-bar-bg); 21 | margin: 16px 1px 16px 16px; 22 | height: calc(100vh - 32px); 23 | box-shadow: var(--border-shadow); 24 | border-radius: 4px; 25 | overflow: hidden; 26 | transition: width .3s ease; 27 | } 28 | 29 | .line { 30 | flex: 1; 31 | } 32 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/WebSettingItems/LanguageSelector.razor: -------------------------------------------------------------------------------- 1 | @using System.Globalization 2 | @inherits BasicComponent 3 | 4 | @(UI.BuildSelect(this, Options.CurrentValue.SupportedCulture) 5 | .ValueExpression(l => l.Culture) 6 | .LabelExpression(l => l.Name) 7 | .Bind(() => current, ToggleLang) 8 | .Render() 9 | ) 10 | 11 | @code { 12 | [Inject, NotNull] IProtectedLocalStorage? Storage { get; set; } 13 | [Inject, NotNull] public IOptionsMonitor? Options { get; set; } 14 | [Inject, NotNull] public ILanguageService? Language { get; set; } 15 | 16 | string current = CultureInfo.DefaultThreadCurrentUICulture?.Name ?? ""; 17 | private Task ToggleLang() 18 | { 19 | if (current != CultureInfo.DefaultThreadCurrentUICulture?.Name) 20 | { 21 | var culture = CultureInfo.GetCultureInfo(current); 22 | App.AppLanguage = current; 23 | Storage.SetAsync(ConstraintString.APP_STORE_KEY, App); 24 | Language.SetLanguage(current); 25 | Navigator.NavigateTo(Navigator.Uri); 26 | } 27 | return Task.CompletedTask; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/WebSettingItems/LayoutManager.razor.css: -------------------------------------------------------------------------------- 1 | .layout-type { 2 | margin-right: 10px; 3 | width: 100px; 4 | height: 70px; 5 | display: flex; 6 | border: 1px solid #ccc; 7 | } 8 | .layout-type:hover{ 9 | cursor:pointer; 10 | } 11 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/LayoutComponents/WebSettingItems/ThemeManager.razor: -------------------------------------------------------------------------------- 1 | @using Project.Web.Shared.Utils 2 | @inherits JsComponentBase 3 |
4 | @(UI.BuildRadioGroup(this, modes) 5 | .LabelExpression(i => FormatLabel(i)) 6 | .ValueExpression(i => i) 7 | .Bind(() => Current, NotifyChanged) 8 | .Render()) 9 |
10 | 11 | @code { 12 | readonly ThemeMode[] modes = [ThemeMode.Light, ThemeMode.Dark, ThemeMode.OS]; 13 | [Parameter] public ThemeMode Current { get; set; } 14 | [Parameter] public EventCallback OnThemeChanged { get; set; } 15 | 16 | private async Task NotifyChanged() 17 | { 18 | if (OnThemeChanged.HasDelegate) 19 | { 20 | await OnThemeChanged.InvokeAsync(Current); 21 | } 22 | 23 | await Js.InvokeUtilsAsync("setTheme", $"{Current}".ToLower(), Context.UI.DarkStyle()); 24 | } 25 | 26 | 27 | static string FormatLabel(ThemeMode theme) 28 | { 29 | return theme switch 30 | { 31 | ThemeMode.Light => "亮色", 32 | ThemeMode.Dark => "暗色", 33 | ThemeMode.OS => "跟随系统", 34 | _ => "" 35 | }; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/Aside.razor: -------------------------------------------------------------------------------- 1 | @inherits ContainerBase 2 | 5 | @code { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/Aside.razor.css: -------------------------------------------------------------------------------- 1 | .aside { 2 | overflow: auto; 3 | box-sizing: border-box; 4 | flex-shrink: 0; 5 | } 6 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/CardLayout.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints 2 | @using Project.Web.Shared.Layouts.LayoutComponents 3 | @inherits LayoutBase 4 |
5 | 12 |
13 |
14 | 15 |
16 |
17 | 18 | 19 |
20 | @AppConst.Footer 21 |
22 |
23 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/CardLayout.razor.css: -------------------------------------------------------------------------------- 1 | .side-bar { 2 | width: 260px; 3 | } 4 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/ClassicLayout.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints 2 | @using Project.Web.Shared.Layouts.LayoutComponents 3 | @inherits LayoutBase 4 |
5 | 12 |
13 |
14 | 15 |
16 |
17 | 18 | 19 |
20 | @AppConst.Footer 21 |
22 |
23 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/ClassicLayout.razor.css: -------------------------------------------------------------------------------- 1 | .classic-sidebar{ 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/Header.razor: -------------------------------------------------------------------------------- 1 | @inherits ContainerBase 2 |
3 | @ChildContent 4 |
5 | @code { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/Header.razor.css: -------------------------------------------------------------------------------- 1 | .header { 2 | box-sizing: border-box; 3 | flex-shrink: 0; 4 | } 5 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/LineLayout.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints 2 | @using Project.Web.Shared.Layouts.LayoutComponents 3 | @inherits LayoutBase 4 |
5 |
6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 |
14 | @AppConst.Footer 15 |
16 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/Main.razor: -------------------------------------------------------------------------------- 1 | @inherits ContainerBase 2 |
3 | @ChildContent 4 |
5 | 6 | @code { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/Main.razor.css: -------------------------------------------------------------------------------- 1 | .main { 2 | --main-padding: 16px; 3 | display: block; 4 | flex: 1; 5 | flex-basis: auto; 6 | overflow: auto; 7 | box-sizing: border-box; 8 | padding: var(--main-padding); 9 | } 10 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/Section.razor: -------------------------------------------------------------------------------- 1 | @inherits ContainerBase 2 |
3 | @ChildContent 4 |
5 | 6 | @code { 7 | [Parameter] public bool Vertical { get; set; } 8 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/Layouts/Section.razor.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: row; 4 | flex: 1; 5 | flex-basis: auto; 6 | box-sizing: border-box; 7 | min-width: 0; 8 | } 9 | .container.is-vertical { 10 | flex-direction: column; 11 | } 12 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/MainLayout.razor.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/Layouts/MainLayout.razor.css -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/NotAuthorizedLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits RootLayout 2 | @*
元素需要加上 tabindex 才能触发键盘事件*@ 3 | @*https://github.com/dotnet/aspnetcore/issues/11137*@ 4 |
6 | 7 | @Body 8 | 9 | 10 |
11 | @code { 12 | [CascadingParameter][NotNull] IAppSession? AppSession { get; set; } 13 | protected override async Task OnInitializedAsync() 14 | { 15 | await base.OnInitializedAsync(); 16 | await AppSession.NotifyLoginSuccessAsync(); 17 | await AppSession.RouterStore.InitMenusAsync(null); 18 | var url = AppSession.Navigator.ToBaseRelativePath(AppSession.Navigator.Uri); 19 | AppSession.Navigator.NavigateTo(url); 20 | } 21 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Layouts/RootLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | @* @onclick="@HandleRootClick" *@ 3 | @* @onkeydown="@HandleKeyDownAction" *@ 4 | @* @onkeyup="@HandleKeyUpAction" *@ 5 |
7 | 8 | @Body 9 | 10 |
-------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Locales/Extensions/AddJsonLocales.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.DependencyInjection.Extensions; 3 | using Microsoft.Extensions.Localization; 4 | using Project.Web.Shared.Locales.EmbeddedJson; 5 | using Project.Web.Shared.Locales.Services; 6 | 7 | namespace Project.Web.Shared.Locales.Extensions 8 | { 9 | public static class AddJsonLocalesExtensions 10 | { 11 | public static IServiceCollection AddJsonLocales(this IServiceCollection services) 12 | { 13 | services.TryAddSingleton(); 14 | services.AddScoped(); 15 | services.TryAddTransient(typeof(IStringLocalizer<>), typeof(InteractiveLocalizer<>)); 16 | services.TryAddTransient(typeof(IStringLocalizer), typeof(InteractiveLocalizer)); 17 | return services; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Locales/Services/JsonLocalizationOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Web.Shared.Locales.Services 2 | { 3 | public class JsonLocalizationOptions 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Locales/Services/LanguageService.cs: -------------------------------------------------------------------------------- 1 | using AutoInjectGenerator; 2 | using System.Globalization; 3 | 4 | namespace Project.Web.Shared.Locales.Services 5 | { 6 | [AutoInject] 7 | public class LanguageService : ILanguageService 8 | { 9 | private CultureInfo? culture; 10 | public CultureInfo CurrentCulture => culture ?? CultureInfo.CurrentCulture; 11 | 12 | public event Action? LanguageChanged; 13 | 14 | public void SetLanguage(string name) 15 | { 16 | var c = CultureInfo.GetCultureInfo(name); 17 | if (c.Equals(CultureInfo.CurrentCulture)) 18 | { 19 | CultureInfo.CurrentCulture = c; 20 | } 21 | 22 | if (!(culture?.Equals(c) ?? false)) 23 | { 24 | culture = c; 25 | CultureInfo.CurrentCulture = culture; 26 | CultureInfo.DefaultThreadCurrentCulture = culture; 27 | CultureInfo.DefaultThreadCurrentUICulture = culture; 28 | LanguageChanged?.Invoke(culture); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Pages/Component/AssignRolePowers.razor: -------------------------------------------------------------------------------- 1 | @using System.Diagnostics.CodeAnalysis 2 | @using Project.Constraints.UI.Tree 3 | @typeparam TPower where TPower : class, IPower, new() 4 | 12 | 13 | @code { 14 | [Parameter, NotNull] public TreeOptions? Options { get; set; } 15 | [Parameter, NotNull] public ColumnItemContext? Context { get; set; } 16 | string[]? selectedKeys; 17 | protected override void OnInitialized() 18 | { 19 | base.OnInitialized(); 20 | var powers = Context.GetValue() as IEnumerable; 21 | selectedKeys = powers?.ToArray() ?? []; 22 | } 23 | 24 | Task UpdateSelected(string[] news) 25 | { 26 | selectedKeys = news; 27 | Context.SetValue(news); 28 | return Task.CompletedTask; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Pages/Component/JsonDisplay.razor: -------------------------------------------------------------------------------- 1 | @using Project.Constraints.UI.Flyout 2 | @using System.Text.Json 3 | @using System.Text.Unicode 4 | @inherits DialogTemplate 5 | 6 |
 7 |     @JsonValue
 8 | 
9 |
10 |     UserAgent: @Value?.UserAgent
11 | 
12 | 13 | @code { 14 | string JsonValue => JsonSerializer.Serialize(Value?.UserInfo, new JsonSerializerOptions() 15 | { 16 | WriteIndented = true, 17 | Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All) 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Pages/Component/JsonDisplay.razor.css: -------------------------------------------------------------------------------- 1 | pre { 2 | text-wrap: pretty; 3 | border: 1px solid #ccc; 4 | padding: 10px; 5 | } 6 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Pages/Component/PowerIconSelector.razor: -------------------------------------------------------------------------------- 1 | 
2 | 3 |   4 | 5 |
6 | 7 | @code { 8 | [Parameter, NotNull] public ColumnItemContext? Context { get; set; } 9 | string? iconName; 10 | protected override void OnInitialized() 11 | { 12 | base.OnInitialized(); 13 | iconName = Context.GetValue() as string; 14 | } 15 | 16 | Task Notify() 17 | { 18 | if (iconName != null) 19 | Context.SetValue(iconName); 20 | return Task.CompletedTask; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Pages/DefaultLogin.razor: -------------------------------------------------------------------------------- 1 | @inject IOptionsMonitor AppOptions 2 | 登录 3 | 14 | @code { 15 | [CascadingParameter(Name = "Login"), NotNull] public ILoginPage? LoginPage { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Pages/OperationLog.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Project.Constraints.PageHelper; 3 | using Project.Constraints.UI.Extensions; 4 | 5 | namespace Project.Web.Shared.Pages 6 | { 7 | public class OperationLog : ModelPage>, IPageAction 8 | where TRunLog : class, IRunLog, new() 9 | where TRunLogService : IRunLogService 10 | { 11 | [Inject, NotNull] TRunLogService? RunLogSrv { get; set; } 12 | protected override void OnInitialized() 13 | { 14 | base.OnInitialized(); 15 | Options.LoadDataOnLoaded = true; 16 | } 17 | 18 | public Task OnShowAsync() => Task.CompletedTask; 19 | 20 | public Task OnHiddenAsync() => Task.CompletedTask; 21 | 22 | protected override object SetRowKey(TRunLog model) => model.LogId; 23 | 24 | protected override Task> OnQueryAsync(GenericRequest query) => RunLogSrv.GetRunLogsAsync(query); 25 | 26 | protected override Task> OnExportAsync(GenericRequest query) => base.OnExportAsync(query); 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Pages/PermissionSetting.razor: -------------------------------------------------------------------------------- 1 | @typeparam TPower where TPower : class, IPower, new() 2 | @typeparam TRole where TRole : class, IRole, new() 3 | @typeparam TPermissionService where TPermissionService : IPermissionService 4 | @inherits ModelPage> 5 | 6 | @UI.BuildButton(this).Primary().Text(Localizer["PermissionSetting.AddRoot"]).OnClick(AddRootPowerAsync).Render() 7 | 8 | @TableFragment 9 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Pages/UnSupportPage.razor: -------------------------------------------------------------------------------- 1 | @layout Project.Web.Shared.Layouts.RootLayout 2 | @page "/unsupport" 3 | 4 |
5 | 6 |

不支持的浏览器,为了获取更好的使用体验,推荐使用Microsoft Edge

7 |
8 | 14 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Project.Web.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Never 17 | 18 | 19 | Never 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:10609", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "applicationUrl": "http://localhost:5025", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "IIS Express": { 22 | "commandName": "IISExpress", 23 | "launchBrowser": true, 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Store/CacheItem.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Project.Web.Shared.Store 4 | { 5 | public class CacheItem 6 | { 7 | public DateTime StartTime { get; set; } 8 | public DateTime ActiveTime { get; set; } 9 | public TimeSpan LifeTime { get; set; } 10 | public RenderFragment? Body { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Store/StoreBase.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Web.Shared.Store 2 | { 3 | public abstract class StoreBase : IDisposable 4 | { 5 | private bool disposedValue; 6 | 7 | public event Action? DataChangedEvent; 8 | protected void NotifyChanged() 9 | { 10 | DataChangedEvent?.Invoke(); 11 | } 12 | 13 | protected virtual void Release() 14 | { 15 | 16 | } 17 | 18 | protected virtual void SetNull() 19 | { 20 | 21 | } 22 | 23 | protected void Dispose(bool disposing) 24 | { 25 | if (!disposedValue) 26 | { 27 | if (disposing) 28 | { 29 | Release(); 30 | } 31 | SetNull(); 32 | disposedValue = true; 33 | } 34 | } 35 | 36 | public void Dispose() 37 | { 38 | Dispose(disposing: true); 39 | GC.SuppressFinalize(this); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Store/UserStore.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Web.Shared.Store; 2 | 3 | [AutoInject] 4 | public class UserStore : StoreBase, IUserStore 5 | { 6 | public UserInfo? UserInfo { get; private set; } 7 | public string[] Roles => UserInfo?.Roles ?? []; 8 | public string? UserId => UserInfo?.UserId; 9 | public string UserDisplayName => GetUserName(); 10 | 11 | public void SetUser(UserInfo? userInfo) 12 | { 13 | UserInfo = userInfo; 14 | } 15 | 16 | public void ClearUser() 17 | { 18 | UserInfo = null; 19 | } 20 | 21 | private string GetUserName() 22 | { 23 | return UserInfo?.UserName ?? "Unknow"; 24 | } 25 | // public event Func? LoginSuccessEvent; 26 | 27 | // private Task OnLoginSuccessAsync(UserInfo info) 28 | // { 29 | // if (LoginSuccessEvent != null) 30 | // return LoginSuccessEvent(info); 31 | // return Task.CompletedTask; 32 | // } 33 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Utils/DownloadExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Project.Web.Shared.Utils; 2 | 3 | public static class DownloadExtensions 4 | { 5 | public static Task DownloadAsync(this IDownloadService service, Func? serverSideDownload, 6 | Func? clientSideDownload) 7 | { 8 | if (OperatingSystem.IsBrowser()) 9 | { 10 | if (clientSideDownload == null) 11 | throw new NotSupportedException("Not Provide a client side download handler"); 12 | return clientSideDownload(); 13 | } 14 | 15 | if (serverSideDownload == null) 16 | throw new NotSupportedException("Not Provide a server side download handler"); 17 | return serverSideDownload(); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/Utils/FontAwesomeHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Text.RegularExpressions; 4 | 5 | namespace Project.Web.Shared.Utils; 6 | 7 | public static partial class FontAwesomeHelper 8 | { 9 | static readonly string[] icons = []; 10 | static FontAwesomeHelper() 11 | { 12 | var assembly = typeof(FontAwesomeHelper).Assembly; 13 | var resourceName = $"Project.Web.Shared.wwwroot.css.font-awesome4.7.min.css"; 14 | var resource = assembly.GetManifestResourceStream(resourceName); 15 | if (resource is null) return; 16 | using var reader = new StreamReader(resource); 17 | var content = reader.ReadToEnd(); 18 | var regex = Extrac47IconName(); 19 | icons = [.. regex.Matches(content).Select(m => $"fa fa-{m.Groups[1].Value}")]; 20 | } 21 | 22 | 23 | public static string[] AllIcons() => icons; 24 | 25 | //[GeneratedRegex("fa-(.+):before")] 26 | [GeneratedRegex("\\.fa-([a-zA-Z0-9-]+):before")] 27 | public static partial Regex Extrac47IconName(); 28 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Web 2 | @using System.Net.Http 3 | @using Microsoft.AspNetCore.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using Microsoft.Extensions.Localization 10 | @using Microsoft.Extensions.Options 11 | @using Project.Constraints 12 | @using Project.Constraints.UI 13 | @using Project.Constraints.UI.Extensions 14 | @using Project.Constraints.Options 15 | @using Project.Constraints.Page 16 | @using Project.Constraints.Store 17 | @using Project.Constraints.UI.Dropdown 18 | @using Project.Web.Shared.Basic 19 | @using Project.Web.Shared.Components 20 | @using Project.Web.Shared.ComponentHelper 21 | @using Project.Constraints.Common 22 | @using Project.Constraints.Common.Attributes 23 | @using Microsoft.AspNetCore.Components.Authorization -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/usings.cs: -------------------------------------------------------------------------------- 1 | global using Project.Constraints.Common; 2 | global using Project.Constraints.Page; 3 | global using Project.Constraints.Models.Permissions; 4 | global using Project.Constraints.Services; 5 | global using Project.Web.Shared.Basic; 6 | global using Project.Constraints.Models.Request; 7 | global using Project.Constraints.Models; 8 | global using Project.Constraints.UI.Table; 9 | global using Microsoft.Extensions.Localization; 10 | global using System.Diagnostics.CodeAnalysis; 11 | global using System.Security.Claims; 12 | global using System.Web; 13 | global using AutoInjectGenerator; 14 | global using Microsoft.AspNetCore.Components; 15 | global using Microsoft.AspNetCore.Components.Authorization; 16 | global using Microsoft.Extensions.Logging; 17 | global using Project.Constraints; 18 | global using Project.Constraints.Store; -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/assets/Cortana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/assets/Cortana.png -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/assets/avator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/assets/avator.png -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/assets/login_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/assets/login_bg.png -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/assets/logo.png -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/assets/notsupport.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/assets/notsupport.jpg -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/favicon.ico -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarvelTiter/BlazorWebAdmin/d71dec46c7540105e523b54d560775841f45323b/src/Shared/Project.Web.Shared/wwwroot/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-clear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-collapse_menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-connecting.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-expand_menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-fullscreen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-login.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-pda.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-statistics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/icons/svg-switch.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/js/jscomponentbase/CustomEventHandler.js: -------------------------------------------------------------------------------- 1 | import { HandlerBase } from "./HandlerBase.js"; 2 | import { EventHandler } from "./event-handler.js"; 3 | 4 | export class CustomEventHandler extends HandlerBase { 5 | constructor(el, eventType, fn, id, once) { 6 | super(el, eventType, fn, id, once); 7 | } 8 | action(event) { 9 | if (this.once) { 10 | EventHandler.remove(this.element, this.type, this.delegate); 11 | } 12 | this.delegate.apply(this.element, [event]); 13 | } 14 | on() { 15 | this.element.addEventListener(this.type, this.action); 16 | } 17 | 18 | off() { 19 | this.element.removeEventListener(this.type, this.action); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/js/jscomponentbase/HandlerBase.js: -------------------------------------------------------------------------------- 1 | export class HandlerBase { 2 | constructor(el, eventType, fn, id, once) { 3 | this.element = el; 4 | this.id = id; 5 | this.delegate = fn; 6 | this.type = eventType; 7 | this.once = once; 8 | } 9 | action(event) { 10 | } 11 | bind() { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/js/jscomponentbase/ResizeHandler.js: -------------------------------------------------------------------------------- 1 | import { HandlerBase } from "./HandlerBase.js"; 2 | 3 | export class ResizeHandler extends HandlerBase { 4 | constructor(el, fn, id, once) { 5 | super(el, 'resize', fn, id, once); 6 | this.resizeObserver = new ResizeObserver(entries => { 7 | this.action(entries); 8 | }); 9 | } 10 | action(event) { 11 | if (this.once) { 12 | this.off(); 13 | } 14 | this.delegate.apply(this.element, [event]); 15 | } 16 | on() { 17 | this.resizeObserver.observe(this.element); 18 | } 19 | off() { 20 | this.resizeObserver.disconnect(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/js/jscomponentbase/base-component.js: -------------------------------------------------------------------------------- 1 | import { getComponentById, removeComponent } from "./component-store.js" 2 | 3 | export class BaseComponent { 4 | 5 | dispose() { 6 | } 7 | 8 | static dispose(id) { 9 | const com = getComponentById(id); 10 | if (com) { 11 | console.debug("dispose: ", id, com); 12 | com.dispose(); 13 | removeComponent(id); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/js/jscomponentbase/component-store.js: -------------------------------------------------------------------------------- 1 | const alls = {} 2 | window.a = alls 3 | export function getComponentById(id, init) { 4 | if (!alls[id] && init) { 5 | if (typeof init == 'function') { 6 | alls[id] = init(); 7 | } else if (typeof init == 'object') { 8 | alls[id] = init; 9 | } else { 10 | console.error('初始化异常', init); 11 | throw new Error('初始化异常'); 12 | } 13 | } 14 | return alls[id]; 15 | } 16 | 17 | export function removeComponent(id) { 18 | delete alls[id]; 19 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/js/jscomponentbase/drag-helper.js: -------------------------------------------------------------------------------- 1 | import { EventHandler } from "./event-handler.js" 2 | const storeValue = {}; 3 | function storeOnSelectstart() { 4 | storeValue['onselectstart'] = document.onselectstart; 5 | document.onselectstart = () => false 6 | } 7 | 8 | function restoreOnSelectstart() { 9 | if (document.onselectstart !== storeValue['onselectstart']) 10 | document.onselectstart = storeValue['onselectstart'] 11 | } 12 | export function startDrag(e, moveHandler, upHandler) { 13 | e.stopImmediatePropagation() 14 | EventHandler.listen(document, 'mousemove', moveHandler) 15 | EventHandler.once(document, 'mouseup', e => { 16 | if (upHandler) 17 | upHandler() 18 | EventHandler.remove(document, 'mousemove', moveHandler) 19 | restoreOnSelectstart() 20 | }) 21 | storeOnSelectstart() 22 | } -------------------------------------------------------------------------------- /src/Shared/Project.Web.Shared/wwwroot/js/jscomponentbase/utils.js: -------------------------------------------------------------------------------- 1 | export function success(msg, payload) { 2 | return { 3 | isSuccess: true, 4 | message: msg, 5 | payload: payload 6 | } 7 | } 8 | 9 | export function failed(msg) { 10 | return { 11 | isSuccess: false, 12 | message: msg, 13 | } 14 | } 15 | 16 | export const GAP = 4; -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blazor-admin", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "build": "tsup", 7 | "build:pub": "tsup --minify terser" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/MarvelTiter/BlazorAdmin.git" 12 | }, 13 | "keywords": [ 14 | "blazor" 15 | ], 16 | "author": "marveltiter", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/MarvelTiter/BlazorAdmin/issues" 20 | }, 21 | "homepage": "https://github.com/MarvelTiter/BlazorAdmin#readme", 22 | "devDependencies": { 23 | "@swc/cli": "^0.3.14", 24 | "@swc/core": "^1.6.5", 25 | "terser": "^5.31.1", 26 | "tsup": "^8.1.0", 27 | "typescript": "^5.5.2" 28 | }, 29 | "dependencies": { 30 | "blazor-admin": "file:" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "forceConsistentCasingInFileNames": true, 5 | "allowImportingTsExtensions": true, 6 | "noEmit": true, 7 | "noImplicitAny": false, 8 | "noEmitOnError": true, 9 | "removeComments": false, 10 | "sourceMap": true, 11 | "moduleResolution": "node", 12 | "target": "ES2015" 13 | }, 14 | "exclude": [ 15 | "node_modules", 16 | "wwwroot" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | // const fs = require('fs'); 3 | // const path = require('path'); 4 | // /** 5 | // * 遍历指定目录下的所有文件 6 | // * @param {*} dir 7 | // */ 8 | // const getAllFile = function (dir) { 9 | // let res: any[] = [] 10 | // function traverse(dir) { 11 | // fs.readdirSync(dir).forEach((file) => { 12 | // const pathname = path.join(dir, file) 13 | // if (fs.statSync(pathname).isDirectory()) { 14 | // traverse(pathname) 15 | // } else { 16 | // if (pathname.endWith('.razor.ts')) 17 | // res.push({ 18 | // file, 19 | // pathname 20 | // }) 21 | // } 22 | // }) 23 | // } 24 | // traverse(dir) 25 | // return res; 26 | // } 27 | // var files = getAllFile('./') 28 | // console.log(files) 29 | export default defineConfig({ 30 | entry: ['./main.ts'], 31 | splitting: false, 32 | sourcemap: true, 33 | clean: true, 34 | // outDir: './BlazorAdmin/wwwroot/js', 35 | // target: ['es5'], 36 | // minify: "terser", 37 | esbuildOptions(options, context) { 38 | options.outdir = undefined 39 | options.outfile = './BlazorAdmin/wwwroot/js/blazor-admin-project.js' 40 | }, 41 | }) 42 | -------------------------------------------------------------------------------- /src/utilsAggregation.ts: -------------------------------------------------------------------------------- 1 | import { setTheme } from './themeManager.ts' 2 | function closeWin() { 3 | window.close() 4 | } 5 | 6 | function openWindow(url: string, width: number, height: number, target?: string) { 7 | const cW = window.outerWidth 8 | const cH = window.outerHeight 9 | let w = cW, h = cH 10 | if (width <= 1) { 11 | w = cW * width 12 | } 13 | if (height <= 1) { 14 | h = cH * height 15 | } 16 | const top = (cH - h) / 2 + window.screenTop 17 | const left = (cW - w) / 2 + window.screenLeft 18 | const features = `popup=yes, left=${left}, top=${top}, width=${w}, height=${h}` 19 | console.log(features) 20 | window.open(url, target, features) 21 | } 22 | 23 | // async function getClient() { 24 | // if (window.opener !== null) { 25 | // return [null, null] 26 | // } 27 | // const response = await fetch('/ip.client') 28 | // const ip = await response.text() 29 | // return [ip, navigator.userAgent] 30 | // } 31 | 32 | 33 | 34 | export default { 35 | closeWin, 36 | openWindow, 37 | setTheme 38 | } -------------------------------------------------------------------------------- /template.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Template 5 | 0.0.1 6 | MtBlazorAdminTemplate 7 | MtBlazorAdminTemplate 8 | MarvelTiter 9 | dotnet-new;templates;blazor-server;wpf;winforms 10 | BlazorAdmin Project Template 11 | net8.0 12 | true 13 | false 14 | content 15 | $(NoWarn);NU5128 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | --------------------------------------------------------------------------------