From 2eb2f19d2723273c2cd15e5f2f662067f95496ee Mon Sep 17 00:00:00 2001 From: Liujian <824010343@qq.com> Date: Mon, 12 Aug 2024 12:07:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=AB=AF=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package.json | 3 +- frontend/packages/businessEntry/.env | 7 +- frontend/packages/businessEntry/index.html | 6 - frontend/packages/businessEntry/src/App.tsx | 33 +- .../components/aoplatform/RenderRoutes.tsx | 192 ++---- frontend/packages/businessEntry/src/main.tsx | 6 - frontend/packages/businessEntry/tsconfig.json | 6 - .../packages/businessEntry/vite.config.ts | 6 - ....timestamp-1722480612803-56fa594878983.mjs | 85 +++ .../common/src/assets/layout-logo.png | Bin 0 -> 2221 bytes .../src/components/aoplatform/BasicLayout.tsx | 300 ++++++-- .../src/components/aoplatform/Breadcrumb.tsx | 6 - .../components/aoplatform/CopyAddrList.tsx | 12 +- .../src/components/aoplatform/DatePicker.tsx | 7 +- .../aoplatform/DrawerWithFooter.tsx | 7 +- .../aoplatform/DynamicKeyValueInput.tsx | 11 +- .../components/aoplatform/EditableTable.tsx | 17 - .../aoplatform/EditableTableWithModal.tsx | 2 +- .../src/components/aoplatform/GroupTree.tsx | 7 +- .../src/components/aoplatform/InsidePage.tsx | 10 +- .../aoplatform/InsidePageForHub.tsx | 30 - .../components/aoplatform/MemberTransfer.tsx | 7 +- .../src/components/aoplatform/Navigation.tsx | 145 ++-- .../src/components/aoplatform/PageList.tsx | 27 +- .../PublishApprovalModalContent.tsx | 37 +- .../aoplatform/ScrollableSection.tsx | 7 +- .../SubscribeApprovalModalContent.tsx | 25 +- .../aoplatform/TableBtnWithPermission.tsx | 7 +- .../aoplatform/TagWithPermission.tsx | 7 +- .../components/aoplatform/ThemeSwitcher.tsx | 34 + .../src/components/aoplatform/TimePicker.tsx | 7 +- .../aoplatform/TimeRangeSelector.tsx | 7 +- .../components/aoplatform/TransferTable.tsx | 10 +- .../components/aoplatform/TreeWithMore.tsx | 7 +- .../src/components/aoplatform/UserProfile.tsx | 5 +- .../components/aoplatform/WithPermission.tsx | 7 +- .../ArrayItemBlankComponent.tsx | 7 +- .../CustomCodeboxComponent.tsx | 7 +- .../CustomDialogComponent.tsx | 7 +- .../IntelligentPluginConfig.tsx | 641 ++---------------- .../IntelligentPluginList.tsx | 249 +++---- .../apispace/code-snippet/generate-code.ts | 3 - .../apispace/code-snippet/index.tsx | 32 - .../common/src/components/postcat/ApiEdit.tsx | 11 +- .../components/ApiMessageBody/constants.ts | 7 +- .../components/ApiRequestEditor/index.tsx | 1 - .../components/ApiResponseEditor/index.tsx | 1 - .../components/EditableDataGrid/index.tsx | 7 +- .../components/MessageDataGrid/constants.ts | 7 +- .../components/MessageDataGrid/index.tsx | 4 - .../components/ApiBasicInfoDisplay/index.tsx | 7 +- .../ApiPreview/components/ApiMatch/index.tsx | 7 +- .../ApiPreview/components/ApiProxy/index.tsx | 1 - .../components/QueryFields/index.tsx | 7 +- .../components/TestMessageDataGrid/index.tsx | 7 +- .../postcat/api/Clipboard/index.tsx | 7 +- .../components/postcat/api/Codebox/index.tsx | 1 - .../components/postcat/api/Collapse/index.tsx | 7 +- .../postcat/api/Dialog/base-dialog.tsx | 7 +- .../api/MoreSetting/components/ParamLimit.tsx | 7 +- .../api/MoreSetting/components/ValueEnum.tsx | 7 +- .../postcat/api/PreviewTable/index.tsx | 7 +- .../postcat/api/RequestMethod/index.tsx | 7 +- .../common/src/const/api-detail/index.ts | 2 +- .../common/src/const/approval/const.tsx | 13 +- .../common/src/const/approval/type.tsx | 16 +- frontend/packages/common/src/const/const.ts | 9 +- .../packages/common/src/const/permissions.ts | 463 +++++-------- .../common/src/const/permissions.yaml | 388 +++++------ frontend/packages/common/src/const/type.ts | 24 +- .../src/contexts/GlobalStateContext.tsx | 25 +- frontend/packages/common/src/hooks/excel.ts | 7 +- frontend/packages/common/src/hooks/http.ts | 1 - .../common/src/hooks/useInitializeMonaco.ts | 7 +- frontend/packages/common/src/monacoConfig.ts | 7 - .../packages/common/src/utils/dataTransfer.ts | 7 +- .../packages/common/src/utils/navigation.tsx | 26 +- .../packages/common/src/utils/permission.ts | 11 +- .../packages/common/src/utils/uploadPic.ts | 55 ++ frontend/packages/common/src/utils/ux.ts | 7 +- .../packages/common/src/utils/validate.ts | 6 - frontend/packages/common/tailwind.config.js | 19 +- frontend/packages/common/vite.config.ts | 6 - .../core/__tests__/hooks/copy.test.ts | 7 +- .../core/__tests__/hooks/crypto.test.ts | 7 +- .../core/__tests__/hooks/http.test.ts | 7 +- frontend/packages/core/index.html | 7 +- frontend/packages/core/src/App.css | 177 +++++ frontend/packages/core/src/App.tsx | 7 +- .../components/aoplatform/RenderRoutes.tsx | 200 ++---- .../packages/core/src/const/member/const.tsx | 13 +- .../packages/core/src/const/member/type.ts | 8 +- .../core/src/const/partitions/const.tsx | 14 - .../core/src/const/partitions/types.ts | 11 +- .../packages/core/src/const/role/const.tsx | 8 +- .../packages/core/src/const/system/const.tsx | 79 +-- .../packages/core/src/const/system/type.ts | 68 +- .../packages/core/src/const/team/const.tsx | 37 +- frontend/packages/core/src/const/team/type.ts | 19 +- .../packages/core/src/const/user/const.tsx | 7 +- .../core/src/contexts/DashboardContext.tsx | 14 +- .../core/src/contexts/PartitionContext.tsx | 7 +- .../core/src/contexts/SystemContext.tsx | 15 +- .../src/contexts/SystemMyServiceContext.tsx | 7 +- .../core/src/contexts/TeamContext.tsx | 16 +- frontend/packages/core/src/index.css | 13 +- frontend/packages/core/src/main.tsx | 7 +- frontend/packages/core/src/pages/Login.tsx | 1 - .../core/src/pages/approval/ApprovalPage.tsx | 7 +- .../src/pages/logRetrieval/LogRetrieval.tsx | 8 +- .../src/pages/logsettings/LogSettings.tsx | 67 +- .../logsettings/LogSettingsInstruction.tsx | 21 +- .../core/src/pages/member/MemberList.tsx | 91 ++- .../core/src/pages/member/MemberPage.tsx | 27 +- .../src/pages/member/Modal/EditMember.tsx | 7 +- .../src/pages/member/Modal/RenameDepModal.tsx | 7 +- .../pages/partitions/PartitionInsideCert.tsx | 30 +- .../partitions/PartitionInsideCluster.tsx | 13 +- .../partitions/PartitionInsideClusterNode.tsx | 40 +- .../resourcesettings/ResourceSettings.tsx | 66 +- .../ResourceSettingsInstruction.tsx | 16 +- .../core/src/pages/role/RoleConfig.tsx | 244 +++++++ .../packages/core/src/pages/role/RoleList.tsx | 159 ++--- .../pages/serviceCategory/ServiceCategory.tsx | 15 +- .../ServiceHubCategoryConfig.tsx | 2 +- .../core/src/pages/system/SystemConfig.tsx | 288 +++++--- .../src/pages/system/SystemInsideDocument.tsx | 146 ++++ .../src/pages/system/SystemInsidePage.tsx | 48 +- .../pages/system/SystemInsideSubscriber.tsx | 110 +-- .../core/src/pages/system/SystemList.tsx | 28 +- .../core/src/pages/system/SystemOutlet.tsx | 17 +- .../core/src/pages/system/SystemTopology.tsx | 32 +- .../system/api/SystemInsideApiCreate.tsx | 13 +- .../system/api/SystemInsideApiDetail.tsx | 15 +- .../system/api/SystemInsideApiDocument.tsx | 15 +- .../pages/system/api/SystemInsideApiList.tsx | 36 +- .../system/api/SystemInsideApiPlugin.tsx | 15 - .../pages/system/api/SystemInsideApiProxy.tsx | 7 +- .../system/approval/SystemInsideApproval.tsx | 7 +- .../approval/SystemInsideApprovalList.tsx | 30 +- .../system/publish/SystemInsidePublish.tsx | 11 +- .../publish/SystemInsidePublishList.tsx | 86 +-- .../publish/SystemInsidePublishOnline.tsx | 15 +- .../upstream/SystemInsideUpstreamContent.tsx | 206 ++---- .../core/src/pages/team/TeamConfig.tsx | 44 +- .../core/src/pages/team/TeamInsideMember.tsx | 99 ++- .../core/src/pages/team/TeamInsidePage.tsx | 16 +- .../packages/core/src/pages/team/TeamList.tsx | 23 +- frontend/packages/core/tailwind.config.js | 2 +- frontend/packages/core/tsconfig.json | 7 +- frontend/packages/core/vite.config.ts | 7 +- .../src/component/MonitorApiPage.tsx | 10 +- .../src/component/MonitorAppPage.tsx | 9 +- .../src/component/MonitorLineGraph.tsx | 7 +- .../src/component/MonitorSubPage.tsx | 11 +- .../dashboard/src/component/MonitorTable.tsx | 7 +- .../src/component/MonitorTotalPage.tsx | 13 +- frontend/packages/dashboard/src/const/type.ts | 4 - .../dashboard/src/pages/Dashboard.tsx | 62 +- .../dashboard/src/pages/DashboardApiList.tsx | 12 +- .../src/pages/DashboardApplicationList.tsx | 12 +- .../dashboard/src/pages/DashboardDetail.tsx | 17 +- .../src/pages/DashboardInstruction.tsx | 22 +- .../dashboard/src/pages/DashboardList.tsx | 7 +- .../src/pages/DashboardProjectList.tsx | 12 +- .../dashboard/src/pages/DashboardTabPage.tsx | 11 +- .../dashboard/src/pages/DashboardTotal.tsx | 16 +- .../packages/dashboard/src/utils/dashboard.ts | 6 - frontend/packages/market/index.html | 7 +- frontend/packages/market/src/App.tsx | 7 +- .../components/aoplatform/RenderRoutes.tsx | 11 +- .../market/src/const/serviceHub/const.tsx | 26 +- .../market/src/const/serviceHub/type.ts | 23 +- .../src/contexts/TenantManagementContext.tsx | 7 +- frontend/packages/market/src/index.css | 4 +- frontend/packages/market/src/main.tsx | 7 +- .../src/pages/serviceHub/ApiTestGroup.tsx | 7 +- .../pages/serviceHub/ApplyServiceModal.tsx | 47 +- .../serviceHub/ServiceHubApiDocument.tsx | 146 ++++ .../src/pages/serviceHub/ServiceHubDetail.tsx | 256 +++---- .../src/pages/serviceHub/ServiceHubGroup.tsx | 56 +- .../src/pages/serviceHub/ServiceHubList.tsx | 12 +- .../management/ApprovalModalContent.tsx | 93 +++ .../management/ManagementAppSetting.tsx | 8 +- .../management/ManagementAuthorityConfig.tsx | 261 +++++++ .../management/ManagementAuthorityView.tsx | 26 + .../management/ManagementConfig.tsx | 31 +- .../management/ManagementInsideAuth.tsx | 43 +- .../management/ManagementInsidePage.tsx | 80 +-- .../management/ManagementInsideService.tsx | 36 +- .../management/ServiceHubManagement.tsx | 36 +- frontend/packages/market/vite.config.ts | 7 +- .../openApi/src/pages/OpenApiConfig.tsx | 7 +- .../systemRunning/src/pages/SystemRunning.tsx | 14 +- .../src/pages/SystemRunningInstruction.tsx | 8 +- 195 files changed, 3438 insertions(+), 4219 deletions(-) create mode 100644 frontend/packages/businessEntry/vite.config.ts.timestamp-1722480612803-56fa594878983.mjs create mode 100644 frontend/packages/common/src/assets/layout-logo.png create mode 100644 frontend/packages/common/src/components/aoplatform/ThemeSwitcher.tsx create mode 100644 frontend/packages/common/src/utils/uploadPic.ts create mode 100644 frontend/packages/core/src/pages/role/RoleConfig.tsx create mode 100644 frontend/packages/core/src/pages/system/SystemInsideDocument.tsx create mode 100644 frontend/packages/market/src/pages/serviceHub/ServiceHubApiDocument.tsx create mode 100644 frontend/packages/market/src/pages/serviceHub/management/ApprovalModalContent.tsx create mode 100644 frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityConfig.tsx create mode 100644 frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityView.tsx diff --git a/frontend/package.json b/frontend/package.json index d2c6462..515a8d1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -49,6 +49,7 @@ "devDependencies": { "@ant-design/cssinjs": "^1.18.2", "@antv/g6": "^4.8.24", + "@iconify/react": "^5.0.2", "@testing-library/jest-dom": "^6.4.5", "@testing-library/react": "^15.0.7", "@testing-library/react-hooks": "^8.0.1", @@ -60,7 +61,7 @@ "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", "@vitejs/plugin-react": "^4.2.0", - "antd": "^5.17.0", + "antd": "^5.19.4", "babel-jest": "^29.7.0", "eslint": "^8.53.0", "eslint-plugin-react-hooks": "^4.6.0", diff --git a/frontend/packages/businessEntry/.env b/frontend/packages/businessEntry/.env index 35f2ce9..ef72921 100644 --- a/frontend/packages/businessEntry/.env +++ b/frontend/packages/businessEntry/.env @@ -1,9 +1,4 @@ -### - # @Date: 2024-07-12 13:53:03 - # @LastEditors: maggieyyy - # @LastEditTime: 2024-07-12 18:26:34 - # @FilePath: \frontend\packages\core\.env.business -### + // .env.pro VITE_APP_MODE=pro VITE_APP_TITLE=My Production App diff --git a/frontend/packages/businessEntry/index.html b/frontend/packages/businessEntry/index.html index 71bb310..3a72b49 100644 --- a/frontend/packages/businessEntry/index.html +++ b/frontend/packages/businessEntry/index.html @@ -1,9 +1,3 @@ - diff --git a/frontend/packages/businessEntry/src/App.tsx b/frontend/packages/businessEntry/src/App.tsx index 225862b..6296da9 100644 --- a/frontend/packages/businessEntry/src/App.tsx +++ b/frontend/packages/businessEntry/src/App.tsx @@ -1,9 +1,3 @@ -/* - * @Date: 2023-11-27 17:18:27 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-07-12 19:54:26 - * @FilePath: \frontend\packages\businessEntry\src\App.tsx - */ import '@core/App.css' import { ConfigProvider } from 'antd'; import RenderRoutes from '@businessEntry/components/aoplatform/RenderRoutes'; @@ -11,6 +5,7 @@ import {BreadcrumbProvider} from "@common/contexts/BreadcrumbContext.tsx"; import { StyleProvider } from '@ant-design/cssinjs'; import zhCN from 'antd/locale/zh_CN'; import useInitializeMonaco from "@common/hooks/useInitializeMonaco"; +import ThemeSwitcher from '@common/components/aoplatform/ThemeSwitcher' const antdComponentThemeToken = { token: { @@ -43,13 +38,12 @@ const antdComponentThemeToken = { optionHoverBg:'#EBEEF2' }, Layout: { - bodyBg: '#fff', - headerBg: '#fff', + bodyBg: 'linear-gradient(107.97deg, rgba(32,41,117,1) 4.41%,rgba(16,13,27,1) 86.11%);', + headerBg: 'transparent', headerColor: '#333', - headerHeight: 50, headerPadding: '10 20px', - lightSiderBg: '#fff', - siderBg: '#fff', + lightSiderBg: 'transparent', + siderBg: 'transparent', }, Breadcrumb:{ itemColor:'#666', @@ -116,6 +110,16 @@ const antdComponentThemeToken = { // itemSelectedColor:'#333', // itemSelectedBg:'#EBEEF2', // itemHoverBg:'#EBEEF2' + // itemHeight:'72px', + // darkItemBg:'transparent', + // itemBg:'transparent', + // itemSelectedBg:'transparent', + // darkItemSelectedBg:'transparent', + // subMenuItemBg:'transparent', + // itemActiveBg:'transparent', + // darkSubMenuItemBg:'transparent', + // activeBarHeight:'2px', + // activeBarBorderWidth:2 }, List:{ itemPadding:'8px 0' @@ -142,9 +146,10 @@ function App() { locale={zhCN} wave={{disabled:true}} theme={antdComponentThemeToken}> - - - + + + + ); diff --git a/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx b/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx index 01c1d6b..69f50f4 100644 --- a/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx +++ b/frontend/packages/businessEntry/src/components/aoplatform/RenderRoutes.tsx @@ -1,9 +1,3 @@ -/* - * @Date: 2024-06-04 08:54:24 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-07-12 19:55:47 - * @FilePath: \frontend\packages\businessEntry\src\components\aoplatform\RenderRoutes.tsx - */ import { BrowserRouter as Router, Routes, Route, Navigate, Outlet } from 'react-router-dom'; import Login from "@core/pages/Login.tsx" import BasicLayout from '@common/components/aoplatform/BasicLayout'; @@ -30,24 +24,23 @@ type RouteConfig = { } const APP_MODE = import.meta.env.VITE_APP_MODE; export type RouterParams = { - orgId:string teamId:string - systemId:string apiId:string serviceId:string - partitionId:string clusterId:string; memberGroupId:string userGroupId:string pluginName:string moduleId:string - accessType:'project'|'team'|'system' + accessType:'project'|'team'|'service' categoryId:string tagId:string dashboardType:string dashboardDetailId:string topologyId:string appId:string + roleType:string + roleId:string } const PUBLIC_ROUTES:RouteConfig[] = [ @@ -71,31 +64,24 @@ const PUBLIC_ROUTES:RouteConfig[] = [ component:, key:uuidv4() }, - { - path:'organization/*', - component:, - key: uuidv4(), - children:[ - { - path:'list', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/organization/OrganizationList.tsx')) - } - ] - }, { - path:'team/*', + path:'team', component:, key: uuidv4(), provider: TeamProvider, children:[ + { + path:'', + key: uuidv4(), + component: + }, { path:'list', key: uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamList.tsx')) }, { - path:'inside/:orgId/:teamId', + path:'inside/:teamId', lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamInsidePage.tsx')), key: uuidv4(), children:[ @@ -104,11 +90,6 @@ const PUBLIC_ROUTES:RouteConfig[] = [ key: uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamInsideMember.tsx')), }, - { - path:'access', - key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/team/TeamInsideAccess.tsx')), - }, { path:'setting', key: uuidv4(), @@ -119,28 +100,33 @@ const PUBLIC_ROUTES:RouteConfig[] = [ ] }, { - path:'system/*', + path:'service', component:, key: uuidv4(), provider: SystemProvider, children:[ + { + path:'', + key:uuidv4(), + component: + }, { path:'list', key: uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemList.tsx')), }, { - path:'list/:orgId/:teamId', + path:'list/:teamId', key: uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemList.tsx')), }, { - path:':orgId/:teamId', + path:':teamId', component:, key: uuidv4(), children:[ { - path:'inside/:systemId', + path:'inside/:serviceId', key: uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsidePage.tsx')), children:[ @@ -155,17 +141,9 @@ const PUBLIC_ROUTES:RouteConfig[] = [ lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/upstream/SystemInsideUpstreamContent.tsx')), }, { - path:'myService', + path:'document', key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/myService/SystemInsideMyService.tsx')), - }, - { - path:'subService', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/subSubscribe/SystemInsideSubService.tsx')), - children:[ - - ] + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsideDocument.tsx')), }, { path:'subscriber', @@ -180,6 +158,11 @@ const PUBLIC_ROUTES:RouteConfig[] = [ key: uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/approval/SystemInsideApproval.tsx')), children:[ + { + path:'', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/approval/SystemInsideApprovalList.tsx')), + }, { path:'*', key: uuidv4(), @@ -194,14 +177,6 @@ const PUBLIC_ROUTES:RouteConfig[] = [ children:[ ] }, - { - path:'authority', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/authority/SystemInsideAuthority.tsx')), - children:[ - - ] - }, { path:'publish', key: uuidv4(), @@ -214,16 +189,6 @@ const PUBLIC_ROUTES:RouteConfig[] = [ } ] }, - { - path:'access', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsideAccess.tsx')), - }, - { - path:'member', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/SystemInsideMember.tsx')), - }, { path:'setting', key: uuidv4(), @@ -239,55 +204,25 @@ const PUBLIC_ROUTES:RouteConfig[] = [ ] }, { - path:'partition/*', - component:, + path:'cluster', key: uuidv4(), - children:[ - { - path:'list', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionList.tsx')), - }, - { - path:'inside/:partitionId', - key: uuidv4(), - provider:PartitionProvider, - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsidePage.tsx')), - children:[ - { - path:'cluster', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideCluster.tsx')), - }, - { - path:'cert', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideCert.tsx')), - }, - APP_MODE === 'pro' &&{ - path:'dashboard_setting', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideDashboardSetting.tsx')), - }, - { - path:'setting', - key: uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionConfig.tsx')), - }, - { - path:'template/:moduleId', - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '../../../../common/src/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')), - key:uuidv4() - } - ] - } - ] + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideCluster.tsx')), + }, + { + path:'cert', + key: uuidv4(), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideCert.tsx')), }, { path:'serviceHub', component:, key:uuidv4(), children:[ + { + path:'', + key: uuidv4(), + component: + }, { path:'list', key:uuidv4(), @@ -310,13 +245,18 @@ const PUBLIC_ROUTES:RouteConfig[] = [ provider:TenantManagementProvider, key:uuidv4(), children:[ + { + path:'', + key:uuidv4(), + component: + }, { path:':teamId/inside/:appId', key:uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementInsidePage.tsx')), children:[ { - path:'service/:partitionId', + path:'service', key:uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@market/pages/serviceHub/management/ManagementInsideService.tsx')), }, @@ -345,10 +285,15 @@ const PUBLIC_ROUTES:RouteConfig[] = [ ] }, { - path:'member/*', + path:'member', key:uuidv4(), lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/member/MemberPage.tsx')), children:[ + { + path:'', + key:uuidv4(), + component: + }, { path:'list', key:uuidv4(), @@ -362,37 +307,30 @@ const PUBLIC_ROUTES:RouteConfig[] = [ ] }, { - path:'user/*', + path:'role', key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/user/UserPage.tsx')), + component:, children:[ + { + path: '', + key: uuidv4(), + component: + }, { path:'list', key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/user/UserList.tsx')), + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleList.tsx')), }, { - path:'list/:userGroupId', + path:':roleType/config', key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/user/UserList.tsx')), - } - ] - }, - { - path:'role/*', - key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleList.tsx')), - }, - { - path:'access', - key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/access/AccessPage.tsx')), - children:[ + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleConfig.tsx')), + }, { - path:':accessType', + path:':roleType/config/:roleId', key:uuidv4(), - lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/access/AccessList.tsx')), - }, + lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/role/RoleConfig.tsx')), + } ] }, APP_MODE === 'pro' &&{ @@ -421,7 +359,7 @@ const PUBLIC_ROUTES:RouteConfig[] = [ key:uuidv4(), children:[ { - path:':partitionId/:dashboardType', + path:':dashboardType', component:, key:uuidv4(), provider:DashboardProvider, diff --git a/frontend/packages/businessEntry/src/main.tsx b/frontend/packages/businessEntry/src/main.tsx index dd6dede..cfb7d8e 100644 --- a/frontend/packages/businessEntry/src/main.tsx +++ b/frontend/packages/businessEntry/src/main.tsx @@ -1,9 +1,3 @@ -/* - * @Date: 2023-11-27 17:18:27 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-05-29 18:26:15 - * @FilePath: \frontend\packages\core\src\main.tsx - */ import {StrictMode} from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' diff --git a/frontend/packages/businessEntry/tsconfig.json b/frontend/packages/businessEntry/tsconfig.json index 6784501..4bc7c38 100644 --- a/frontend/packages/businessEntry/tsconfig.json +++ b/frontend/packages/businessEntry/tsconfig.json @@ -1,9 +1,3 @@ -/* - * @Date: 2024-06-04 08:54:17 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-07-12 13:54:42 - * @FilePath: \frontend\packages\core\tsconfig.json - */ { "compilerOptions": { "target": "ES2020", diff --git a/frontend/packages/businessEntry/vite.config.ts b/frontend/packages/businessEntry/vite.config.ts index 665400c..895d519 100644 --- a/frontend/packages/businessEntry/vite.config.ts +++ b/frontend/packages/businessEntry/vite.config.ts @@ -1,9 +1,3 @@ -/* - * @Date: 2024-01-31 15:00:39 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-07-12 19:53:09 - * @FilePath: \frontend\packages\businessEntry\vite.config.ts - */ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import path from 'path' diff --git a/frontend/packages/businessEntry/vite.config.ts.timestamp-1722480612803-56fa594878983.mjs b/frontend/packages/businessEntry/vite.config.ts.timestamp-1722480612803-56fa594878983.mjs new file mode 100644 index 0000000..b2f5561 --- /dev/null +++ b/frontend/packages/businessEntry/vite.config.ts.timestamp-1722480612803-56fa594878983.mjs @@ -0,0 +1,85 @@ +// vite.config.ts +import { defineConfig } from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/vite@5.2.12_@types+node@20.14.2_less@4.2.0/node_modules/vite/dist/node/index.js"; +import react from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/@vitejs+plugin-react@4.3.0_vite@5.2.12_@types+node@20.14.2_less@4.2.0_/node_modules/@vitejs/plugin-react/dist/index.mjs"; +import path from "path"; +import dynamicImportVars from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/@rollup+plugin-dynamic-import-vars@2.1.2_rollup@4.18.0/node_modules/@rollup/plugin-dynamic-import-vars/dist/es/index.js"; +import tailwindcss from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/tailwindcss@3.4.4/node_modules/tailwindcss/lib/index.js"; +import autoprefixer from "file:///D:/eolink/applatform/frontend/node_modules/.pnpm/autoprefixer@10.4.19_postcss@8.4.38/node_modules/autoprefixer/lib/autoprefixer.js"; +var __vite_injected_original_dirname = "D:\\eolink\\applatform\\frontend\\packages\\businessEntry"; +var vite_config_default = defineConfig({ + cacheDir: "./node_modules/.vite", + build: { + outDir: "../../dist", + sourcemap: false, + chunkSizeWarningLimit: 5e4, + cacheDir: "./node_modules/.vite", + output: { + manualChunks(id) { + if (id.includes("node_modules")) { + return id.toString().split("node_modules/")[1].split("/")[0].toString(); + } + if (id.includes(".pnpm")) { + const segments = id.split(path.sep); + const packageName = segments[segments.indexOf(".pnpm") + 1].split("@")[0]; + return packageName; + } + } + } + }, + css: { + postcss: { + plugins: [ + tailwindcss(path.resolve(__vite_injected_original_dirname, "../common/tailwind.config.js")), + autoprefixer + ] + }, + preprocessorOptions: { + less: { + javascriptEnabled: true + } + }, + modules: { + localsConvention: "camelCase", + generateScopedName: "[local]_[hash:base64:2]" + } + }, + plugins: [ + react(), + dynamicImportVars({ + include: ["src"], + exclude: [], + warnOnError: false + }) + ], + resolve: { + alias: [ + { find: /^~/, replacement: "" }, + { find: "@common", replacement: path.resolve(__vite_injected_original_dirname, "../common/src") }, + { find: "@market", replacement: path.resolve(__vite_injected_original_dirname, "../market/src") }, + { find: "@core", replacement: path.resolve(__vite_injected_original_dirname, "../core/src") }, + { find: "@dashboard", replacement: path.resolve(__vite_injected_original_dirname, "../dashboard/src") }, + { find: "@openApi", replacement: path.resolve(__vite_injected_original_dirname, "../openApi/src") }, + { find: "@systemRunning", replacement: path.resolve(__vite_injected_original_dirname, "../systemRunning/src") }, + { find: "@businessEntry", replacement: path.resolve(__vite_injected_original_dirname, "./src") } + ] + }, + server: { + proxy: { + "/api/v1": { + // target: 'http://uat.apikit.com:11204/mockApi/aoplatform/', + target: "http://172.18.166.219:8288/", + changeOrigin: true + }, + "/api2/v1": { + // target: 'http://uat.apikit.com:11204/mockApi/aoplatform/', + target: "http://172.18.166.219:8288/", + changeOrigin: true + } + } + }, + logLevel: "info" +}); +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJEOlxcXFxlb2xpbmtcXFxcYXBwbGF0Zm9ybVxcXFxmcm9udGVuZFxcXFxwYWNrYWdlc1xcXFxidXNpbmVzc0VudHJ5XCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJEOlxcXFxlb2xpbmtcXFxcYXBwbGF0Zm9ybVxcXFxmcm9udGVuZFxcXFxwYWNrYWdlc1xcXFxidXNpbmVzc0VudHJ5XFxcXHZpdGUuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9EOi9lb2xpbmsvYXBwbGF0Zm9ybS9mcm9udGVuZC9wYWNrYWdlcy9idXNpbmVzc0VudHJ5L3ZpdGUuY29uZmlnLnRzXCI7LypcclxuICogQERhdGU6IDIwMjQtMDEtMzEgMTU6MDA6MzlcclxuICogQExhc3RFZGl0b3JzOiBtYWdnaWV5eXlcclxuICogQExhc3RFZGl0VGltZTogMjAyNC0wOC0wMSAxMDo1MDoxMlxyXG4gKiBARmlsZVBhdGg6IFxcZnJvbnRlbmRcXHBhY2thZ2VzXFxidXNpbmVzc0VudHJ5XFx2aXRlLmNvbmZpZy50c1xyXG4gKi9cclxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHJlYWN0IGZyb20gJ0B2aXRlanMvcGx1Z2luLXJlYWN0J1xyXG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJ1xyXG5pbXBvcnQgZHluYW1pY0ltcG9ydFZhcnMgZnJvbSAnQHJvbGx1cC9wbHVnaW4tZHluYW1pYy1pbXBvcnQtdmFycyc7XHJcbmltcG9ydCB0YWlsd2luZGNzcyBmcm9tICd0YWlsd2luZGNzcyc7XHJcbmltcG9ydCBhdXRvcHJlZml4ZXIgZnJvbSAnYXV0b3ByZWZpeGVyJztcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XHJcbiAgY2FjaGVEaXI6ICcuL25vZGVfbW9kdWxlcy8udml0ZScsXHJcbiAgYnVpbGQ6e1xyXG4gICAgb3V0RGlyOicuLi8uLi9kaXN0JyxcclxuICAgIHNvdXJjZW1hcDogZmFsc2UsXHJcbiAgICBjaHVua1NpemVXYXJuaW5nTGltaXQ6IDUwMDAwLFxyXG4gICAgY2FjaGVEaXI6ICcuL25vZGVfbW9kdWxlcy8udml0ZScsIFxyXG4gICAgICBvdXRwdXQ6IHtcclxuICAgICAgICBtYW51YWxDaHVua3MoaWQpIHtcclxuICAgICAgICAgIGlmIChpZC5pbmNsdWRlcygnbm9kZV9tb2R1bGVzJykpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGlkLnRvU3RyaW5nKCkuc3BsaXQoJ25vZGVfbW9kdWxlcy8nKVsxXS5zcGxpdCgnLycpWzBdLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICAvLyBcdTk0ODhcdTVCRjkgcG5wbSBcdTU0OEMgTW9ub3JlcG8gXHU3Mjc5XHU2QjhBXHU1OTA0XHU3NDA2XHJcbiAgICAgICAgICBpZiAoaWQuaW5jbHVkZXMoJy5wbnBtJykpIHtcclxuICAgICAgICAgICAgY29uc3Qgc2VnbWVudHMgPSBpZC5zcGxpdChwYXRoLnNlcCk7XHJcbiAgICAgICAgICAgIGNvbnN0IHBhY2thZ2VOYW1lID0gc2VnbWVudHNbc2VnbWVudHMuaW5kZXhPZignLnBucG0nKSArIDFdLnNwbGl0KCdAJylbMF07XHJcbiAgICAgICAgICAgIHJldHVybiBwYWNrYWdlTmFtZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0sXHJcbiAgICB9LFxyXG4gIGNzczoge1xyXG4gICAgcG9zdGNzczoge1xyXG4gICAgICBwbHVnaW5zOiBbXHJcbiAgICAgICAgdGFpbHdpbmRjc3MocGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4uL2NvbW1vbi90YWlsd2luZC5jb25maWcuanMnKSksIFxyXG4gICAgICAgIGF1dG9wcmVmaXhlclxyXG4gICAgICBdLFxyXG4gICAgfSxcclxuICAgIHByZXByb2Nlc3Nvck9wdGlvbnM6IHtcclxuICAgICAgbGVzczoge1xyXG4gICAgICAgIGphdmFzY3JpcHRFbmFibGVkOiB0cnVlLFxyXG4gICAgICB9LFxyXG4gICAgfSxcclxuICAgIG1vZHVsZXM6e1xyXG4gICAgICBsb2NhbHNDb252ZW50aW9uOlwiY2FtZWxDYXNlXCIsXHJcbiAgICAgIGdlbmVyYXRlU2NvcGVkTmFtZTpcIltsb2NhbF1fW2hhc2g6YmFzZTY0OjJdXCJcclxuICAgIH1cclxuICB9LFxyXG4gIHBsdWdpbnM6IFtyZWFjdCgpLFxyXG4gICAgICBkeW5hbWljSW1wb3J0VmFycyh7XHJcbiAgICAgICAgaW5jbHVkZTpbXCJzcmNcIl0sXHJcbiAgICAgICAgZXhjbHVkZTpbXSxcclxuICAgICAgICB3YXJuT25FcnJvcjpmYWxzZVxyXG4gICAgICAgfSksXHJcbiAgICBdLFxyXG4gIHJlc29sdmU6IHtcclxuICAgIGFsaWFzOiBbXHJcbiAgICAgIHsgZmluZDogL15+LywgcmVwbGFjZW1lbnQ6ICcnIH0sXHJcbiAgICAgIHsgZmluZDogJ0Bjb21tb24nLCByZXBsYWNlbWVudDogcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4uL2NvbW1vbi9zcmMnKSB9LFxyXG4gICAgICB7IGZpbmQ6ICdAbWFya2V0JywgcmVwbGFjZW1lbnQ6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLi9tYXJrZXQvc3JjJykgfSxcclxuICAgICAgeyBmaW5kOiAnQGNvcmUnLCByZXBsYWNlbWVudDogcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4uL2NvcmUvc3JjJykgfSxcclxuICAgICAgeyBmaW5kOiAnQGRhc2hib2FyZCcsIHJlcGxhY2VtZW50OiBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi4vZGFzaGJvYXJkL3NyYycpIH0sXHJcbiAgICAgIHsgZmluZDogJ0BvcGVuQXBpJywgcmVwbGFjZW1lbnQ6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLi9vcGVuQXBpL3NyYycpIH0sXHJcbiAgICAgIHsgZmluZDogJ0BzeXN0ZW1SdW5uaW5nJywgcmVwbGFjZW1lbnQ6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLi9zeXN0ZW1SdW5uaW5nL3NyYycpIH0sXHJcbiAgICAgIHsgZmluZDogJ0BidXNpbmVzc0VudHJ5JywgcmVwbGFjZW1lbnQ6IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuL3NyYycpIH0sXHJcbiAgICBdXHJcbiAgfSxcclxuICBzZXJ2ZXI6IHtcclxuICAgIHByb3h5OiB7XHJcbiAgICAgICcvYXBpL3YxJzoge1xyXG4gICAgICAgIC8vIHRhcmdldDogJ2h0dHA6Ly91YXQuYXBpa2l0LmNvbToxMTIwNC9tb2NrQXBpL2FvcGxhdGZvcm0vJyxcclxuICAgICAgICB0YXJnZXQ6ICdodHRwOi8vMTcyLjE4LjE2Ni4yMTk6ODI4OC8nLFxyXG4gICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcclxuICAgICAgfSxcclxuICAgICAgJy9hcGkyL3YxJzoge1xyXG4gICAgICAgIC8vIHRhcmdldDogJ2h0dHA6Ly91YXQuYXBpa2l0LmNvbToxMTIwNC9tb2NrQXBpL2FvcGxhdGZvcm0vJyxcclxuICAgICAgICB0YXJnZXQ6ICdodHRwOi8vMTcyLjE4LjE2Ni4yMTk6ODI4OC8nLFxyXG4gICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH0sXHJcbiAgbG9nTGV2ZWw6J2luZm8nXHJcbn0pXHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFNQSxTQUFTLG9CQUFvQjtBQUM3QixPQUFPLFdBQVc7QUFDbEIsT0FBTyxVQUFVO0FBQ2pCLE9BQU8sdUJBQXVCO0FBQzlCLE9BQU8saUJBQWlCO0FBQ3hCLE9BQU8sa0JBQWtCO0FBWHpCLElBQU0sbUNBQW1DO0FBYXpDLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzFCLFVBQVU7QUFBQSxFQUNWLE9BQU07QUFBQSxJQUNKLFFBQU87QUFBQSxJQUNQLFdBQVc7QUFBQSxJQUNYLHVCQUF1QjtBQUFBLElBQ3ZCLFVBQVU7QUFBQSxJQUNSLFFBQVE7QUFBQSxNQUNOLGFBQWEsSUFBSTtBQUNmLFlBQUksR0FBRyxTQUFTLGNBQWMsR0FBRztBQUMvQixpQkFBTyxHQUFHLFNBQVMsRUFBRSxNQUFNLGVBQWUsRUFBRSxDQUFDLEVBQUUsTUFBTSxHQUFHLEVBQUUsQ0FBQyxFQUFFLFNBQVM7QUFBQSxRQUN4RTtBQUVBLFlBQUksR0FBRyxTQUFTLE9BQU8sR0FBRztBQUN4QixnQkFBTSxXQUFXLEdBQUcsTUFBTSxLQUFLLEdBQUc7QUFDbEMsZ0JBQU0sY0FBYyxTQUFTLFNBQVMsUUFBUSxPQUFPLElBQUksQ0FBQyxFQUFFLE1BQU0sR0FBRyxFQUFFLENBQUM7QUFDeEUsaUJBQU87QUFBQSxRQUNUO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFDRixLQUFLO0FBQUEsSUFDSCxTQUFTO0FBQUEsTUFDUCxTQUFTO0FBQUEsUUFDUCxZQUFZLEtBQUssUUFBUSxrQ0FBVyw4QkFBOEIsQ0FBQztBQUFBLFFBQ25FO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxJQUNBLHFCQUFxQjtBQUFBLE1BQ25CLE1BQU07QUFBQSxRQUNKLG1CQUFtQjtBQUFBLE1BQ3JCO0FBQUEsSUFDRjtBQUFBLElBQ0EsU0FBUTtBQUFBLE1BQ04sa0JBQWlCO0FBQUEsTUFDakIsb0JBQW1CO0FBQUEsSUFDckI7QUFBQSxFQUNGO0FBQUEsRUFDQSxTQUFTO0FBQUEsSUFBQyxNQUFNO0FBQUEsSUFDWixrQkFBa0I7QUFBQSxNQUNoQixTQUFRLENBQUMsS0FBSztBQUFBLE1BQ2QsU0FBUSxDQUFDO0FBQUEsTUFDVCxhQUFZO0FBQUEsSUFDYixDQUFDO0FBQUEsRUFDSjtBQUFBLEVBQ0YsU0FBUztBQUFBLElBQ1AsT0FBTztBQUFBLE1BQ0wsRUFBRSxNQUFNLE1BQU0sYUFBYSxHQUFHO0FBQUEsTUFDOUIsRUFBRSxNQUFNLFdBQVcsYUFBYSxLQUFLLFFBQVEsa0NBQVcsZUFBZSxFQUFFO0FBQUEsTUFDekUsRUFBRSxNQUFNLFdBQVcsYUFBYSxLQUFLLFFBQVEsa0NBQVcsZUFBZSxFQUFFO0FBQUEsTUFDekUsRUFBRSxNQUFNLFNBQVMsYUFBYSxLQUFLLFFBQVEsa0NBQVcsYUFBYSxFQUFFO0FBQUEsTUFDckUsRUFBRSxNQUFNLGNBQWMsYUFBYSxLQUFLLFFBQVEsa0NBQVcsa0JBQWtCLEVBQUU7QUFBQSxNQUMvRSxFQUFFLE1BQU0sWUFBWSxhQUFhLEtBQUssUUFBUSxrQ0FBVyxnQkFBZ0IsRUFBRTtBQUFBLE1BQzNFLEVBQUUsTUFBTSxrQkFBa0IsYUFBYSxLQUFLLFFBQVEsa0NBQVcsc0JBQXNCLEVBQUU7QUFBQSxNQUN2RixFQUFFLE1BQU0sa0JBQWtCLGFBQWEsS0FBSyxRQUFRLGtDQUFXLE9BQU8sRUFBRTtBQUFBLElBQzFFO0FBQUEsRUFDRjtBQUFBLEVBQ0EsUUFBUTtBQUFBLElBQ04sT0FBTztBQUFBLE1BQ0wsV0FBVztBQUFBO0FBQUEsUUFFVCxRQUFRO0FBQUEsUUFDUixjQUFjO0FBQUEsTUFDaEI7QUFBQSxNQUNBLFlBQVk7QUFBQTtBQUFBLFFBRVYsUUFBUTtBQUFBLFFBQ1IsY0FBYztBQUFBLE1BQ2hCO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFBQSxFQUNBLFVBQVM7QUFDWCxDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo= diff --git a/frontend/packages/common/src/assets/layout-logo.png b/frontend/packages/common/src/assets/layout-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f60191cca52bc80a0ad7c3d975fb933e7b00a865 GIT binary patch literal 2221 zcmV;e2vYZnP)B zkVKE=bl@0%osxiUJkqucr);P;BnyBzyrYN zfc+RsIy&0Su|Q|q06q_SD(Y z(P}n4>%B5S=N-U3z#jr+baaHWr<}jRSD>#mJ=Iqs@H8X>_^tpM9UY+zVhi*g<~EXx~AuXAEo+_T4<`@pY!}2kJeB zL;|k}l;g{-ma@&ptdPbzKpN^8X}sS6(gtm?ks$VEh{Nv#7lGkX8PsNco#_X_&jWR* zz-@steDw}2q>0)aESho~LBA`^2;H0HpUOU^$Xu`jjMJxjdr z>9Qu&nSOx;5^fK);T-VBKwIiy3p}i{NxVjK0eh5f3u%;P3~9!hwk_oYWS*3il=Ts3 zn^ovYk$ZVXK~4fJ^5X*Xea|c8EbSSToS){$k_Fb*NKhjP#-|I&GxLT3e!&kI4UaF`NnDOTdoehm|%qi5me;sp&`%&zYV;wq%5E+x-yY zRI$;*;S0o(w1{FtJHpfbqc)&|{>tYmuoFRM=2#~Q)LA6O?npbVj3#0^6UajDJ%KW= zM234Y>7)NqCWu4LIXrPK(o{x7YAKsGWJ49Ha=t85d78sPiCKQ`IwS*TdEAIT%s%CA z;vp7X8kDF*f(#cErF=rk?uVGp1k$toHBiP)1Z3`(kXg#^R(>zir5)>Ue1Z~PjqOZ-1U?Z#&N;%v_Di&$ zWtYQqfYr}+WW*w^&@o-J{wfmm&^_q(&5%88T6tA{9~Ox7_{#KhB#75wi<|}C1H3Rm z#|uIsk=RWkIaX<1KnH|33Hfb>vvPdk>2v#TV?P$sj~-SyPzLW154EbU8_@&)x8 z?f_||nw(gi!T;|Bx+Be~TJKwlr}vC8r;IW88DkzX#yo0_c{u<4){5AF@p!K#CSR9F zjWH)2be0_#71{gB^@-8f6UH_4?YZA(B?CuYKI=>&*!1;{d~XK<@?GzvYK^LDok=6B zl3DDTt_HrwrQ^#Jz)OIek*ycEP`yhw#!FL903SnoC?5vsPnkLTivNQ0r)P#tIv1Yy z_%Pwykt`2Z*?uK;5Oj% zRHv$xVM`qv;5WJ5!k%^$lL_ljBMM=LJa`u+Wka5P8RZFbPwK1fdWb`PooYu~@@(Kd z_Kkh7uPLjFEAX2)^;ysQkV|f#FLT6++UiIPWL}~<64-+k3;q|bE*>!`3(?19h$ZT} z0lWivt)tNEkrzsSyrk?nGCYgLN#uQd4>;7xBI+;F&t*>{%bn%NH)&@E_MF4^EiBij z=!?v!(T9am-qRhC1?9v2G0Jdq1OFGBoIw^@?*jgkpSu=$w|HoV?kXePoN1k*>|1en zrU~U+9A-2-2h*5Q{tC7^?vb&?qGQKV)=@D+Uk*r6hI<>pt2`CwtP&4vPGSb_Ws`tlz$cr7T;sZWoIAcBd$xTMsGO@7BZbWs*gXBWp?z zAsG9jN1==5+(~@w%2Sq_IGszhtyyTSOa~ zVQ+vJ^Pgj6tA$T?cvH-=CqW;ISoVM)dMf%iGJhBWzqMTVFcLrr*&FoJn%CK~!zUhk zZSSYp@{srcg6+YTA`hdC_GiO`%=4y7*^okXuLpe5Q_1br&k{GlNAXV&I$z_OK6=>F zwO3j)NB<(52$Nr~Y~#K*=z4vV*xrx--{D>l33pB%g?|q}$M_)f0u~p327I-~b+&oT z#8GDvt#|6vu8DKoa7i{DA?>iO%&0NkTV{>l3_Ma(@GpUP;UX`9&H{0$5qhsP&99j>VNf93==U)Mvf}?|dIplZ^EQjX`;io% zx&Z-=7X$Yp{|i^+L1aNW^v$sy?I7WBuH>Ashg|C@`)6mbL3*m|5eIt=$;Z1F_(??F v8^GI=247jQFe00000NkvXXu0mjf>(false) const [,setIsRentMng] = useState(false) const [isMng,setIsMng] = useState(false) + const { accessData,checkPermission} = useGlobalContext() + const [pathname, setPathname] = useState(currentUrl); + const mainPage = project === 'core' ?'/service/list':'/serviceHub/list' + useEffect(() => { setIsServiceHub(currentUrl.includes('/serviceHub')) setIsRentMng(currentUrl.includes('/tenantManagement')) setIsMng(project === 'core' && !currentUrl.includes('/serviceHub') && !currentUrl.includes('/tenantManagement')) if(currentUrl === '/'){ - navigator( project === 'core' ?'/system/list':'/serviceHub/list') + navigator(mainPage) } }, [currentUrl]); + const headerMenuData = useMemo(() => { + // 判断权限 + const hasAccess = (access: unknown) => checkPermission(access as keyof typeof PERMISSION_DEFINITION[0]); + + // 过滤菜单项 + const filterMenu = (menu: Array<{ [k: string]: unknown }>) => { + return [...menu] + .filter(x => x) // 过滤掉空数据 + .map((item: any) => { + if (item.routes && item.routes.length > 0) { + // 递归处理子菜单 + const filteredRoutes: Array<{ [k: string]: unknown }> = filterMenu(item.routes); + + if(filteredRoutes.length === 0){ + return false + } + return {...item, routes: filteredRoutes}; + } + // 处理没有 routes 的菜单项 + if (item.access) { + return hasAccess(item.access) ? item : null; + } + + // 如果没有 access 和 routes,则保留 + return item; + }) + .filter(x => x); // 过滤掉处理后为 null 的项 + }; + + // 初始过滤操作 + const res = [...TOTAL_MENU_ITEMS]!.filter(x => x).map((x: any) => (x.routes ? { ...x, routes: filterMenu(x.routes) } : x)); + // 返回处理后的数据 + return { path: '/', routes: res.map(x=> ({...x, routes: x.routes?.filter(x=> (x.access || x.routes?.length > 0))})).filter(x=> (x.access || x.routes?.length > 0)) }; + }, [accessData]); + + + const openServiceHub =()=>{ isMng ? window.open(`/serviceHub/list`,'_blank') : navigator('/serviceHub/list') } @@ -43,40 +100,193 @@ const { Header, Sider, Content } = Layout; isServiceHub?window.open(`/tenantManagement/list`,'_blank') : navigator('/serviceHub/list') } + + const { modal,message } = App.useApp() + const { dispatch,resetAccess,getGlobalAccessData} = useGlobalContext() + const [userInfo,setUserInfo] = useState() + const resetPswRef = useRef(null) + const userProfileRef = useRef(null) + const {fetchData} = useFetch() + const navigate = useNavigate(); + + const getUserInfo = ()=>{ + fetchData>('account/profile',{method:'GET'}) + .then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + setUserInfo(data.profile) + dispatch({type:'UPDATE_USERDATA',userData:data.profile}) + }else{ + message.error(msg || '操作失败') + } + }) + } + + useEffect(() => { + getUserInfo() + getGlobalAccessData() + }, []); + + const logOut = ()=>{ + fetchData>('account/logout',{method:'GET'}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + dispatch({type:'LOGOUT'}) + resetAccess() + message.success(msg || '退出成功,将跳转至登录页') + navigate('/login') + }else{ + message.error(msg ||'操作失败') + } + }) + } + + const items: MenuProps['items'] = [ + { + key: '3', + label: ( + + 退出登录 + + ), + }, + ]; + + const openModal = (type:'userSetting'|'resetPsw')=>{ + let title:string = '' + let content:string|React.ReactNode = '' + switch (type){ + case 'userSetting': + title='用户设置' + content= + break; + case 'resetPsw': + title='重置密码' + content= + break; + } + modal.confirm({ + title, + content, + onOk:()=>{ + switch (type){ + case 'userSetting': + return userProfileRef.current?.save().then((res)=>{if(res === true) getUserInfo()}) + case 'resetPsw': + return resetPswRef.current?.save().then((res)=>{if(res === true) logOut()}) + } + }, + width:600, + okText:'确认', + cancelText:'取消', + closable:true, + icon:<>, + }) + } + + return( - -
-
+
+ + { + return document.getElementById('test-pro-layout') || document.body; + }} + > + { + return ( + +
{dom} +
+
+ ); + }, + }} + // actionsRender={(props) => { + // if (props.isMobile) return []; + // if (typeof window === 'undefined') return []; + // return [ + // + // ]; + // }} + headerTitleRender={() => ( +
navigator(mainPage)} />
-
- -
- - {/* */} - + )} + logo={Logo} + pageTitleRender={()=>'APIPark - 企业API数据开放平台'} + menuFooterRender={(props) => { + if (props?.collapsed) return undefined; + }} + menuItemRender={(item, dom) => ( +
{ + // 同级目录点击无效 + if(item.key && routerKeyMap.get(item.key) && routerKeyMap.get(item.key).length > 0 && routerKeyMap.get(item.key)?.indexOf(pathname.split('/')[1]) !== -1){ + return + } + if(item.key === pathname.split('/')[1]){ + return + } + + if(item.path){ + navigator(item.path) + } + setPathname(item.path || ''); + }} + > + {dom}
-
-
- - {!isMng? undefined : - - } - - - - - - -
+ )} + fixSiderbar={true} + layout='mix' + splitMenus={true} + collapsed={false} + collapsedButtonRender={false} + > +
+ +
+ + + + ) } export default BasicLayout \ No newline at end of file diff --git a/frontend/packages/common/src/components/aoplatform/Breadcrumb.tsx b/frontend/packages/common/src/components/aoplatform/Breadcrumb.tsx index 433ab90..a375cd4 100644 --- a/frontend/packages/common/src/components/aoplatform/Breadcrumb.tsx +++ b/frontend/packages/common/src/components/aoplatform/Breadcrumb.tsx @@ -1,9 +1,3 @@ -/* - * @Date: 2023-11-28 11:41:17 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-05-29 18:30:51 - * @FilePath: \frontend\packages\common\src\components\aoplatform\Breadcrumb.tsx - */ import { Breadcrumb } from "antd" import { useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx"; import {FC,useEffect} from "react"; diff --git a/frontend/packages/common/src/components/aoplatform/CopyAddrList.tsx b/frontend/packages/common/src/components/aoplatform/CopyAddrList.tsx index ff8ebbf..910b653 100644 --- a/frontend/packages/common/src/components/aoplatform/CopyAddrList.tsx +++ b/frontend/packages/common/src/components/aoplatform/CopyAddrList.tsx @@ -1,12 +1,8 @@ -/* - * @Date: 2024-02-04 14:06:22 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-05 15:48:54 - * @FilePath: \frontend\packages\common\src\components\aoplatform\CopyAddrList.tsx - */ + import { useState,FC } from 'react'; import { Tooltip, Button } from 'antd'; import useCopyToClipboard from '@common/hooks/copy'; +import { Icon } from '@iconify/react/dist/iconify.js'; type AddressItem = { expand?: boolean; @@ -54,7 +50,7 @@ const CopyAddrList: FC = ({ addrItem, onAddrItemChange, keyNa {(localAddrItem[keyName] as string[]).join(',')} {(localAddrItem[keyName] as string[]).length === 1 && ( - diff --git a/frontend/packages/common/src/components/aoplatform/GroupTree.tsx b/frontend/packages/common/src/components/aoplatform/GroupTree.tsx index e1efccf..efcd2c5 100644 --- a/frontend/packages/common/src/components/aoplatform/GroupTree.tsx +++ b/frontend/packages/common/src/components/aoplatform/GroupTree.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-06-04 08:54:16 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-04 11:36:01 - * @FilePath: \frontend\packages\common\src\components\aoplatform\GroupTree.tsx - */ + import DirectoryTree from "antd/es/tree/DirectoryTree"; import { DataNode, DirectoryTreeProps } from "antd/lib/tree"; import { forwardRef, useEffect, useImperativeHandle, useState } from "react"; diff --git a/frontend/packages/common/src/components/aoplatform/InsidePage.tsx b/frontend/packages/common/src/components/aoplatform/InsidePage.tsx index ae6082d..c2c82a4 100644 --- a/frontend/packages/common/src/components/aoplatform/InsidePage.tsx +++ b/frontend/packages/common/src/components/aoplatform/InsidePage.tsx @@ -1,15 +1,9 @@ -/* - * @Date: 2023-11-28 11:54:17 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-05-15 15:03:46 - * @FilePath: \frontend\packages\core\src\components\InsidePage.tsx - * @Description:内页(带顶部导航与描述、tag、右侧按钮-可选) - */ import { Button, Tag } from "antd" import {useNavigate} from "react-router-dom"; import WithPermission from "@common/components/aoplatform/WithPermission"; import { FC, ReactNode } from "react"; +import { LeftOutlined } from "@ant-design/icons"; class InsidePageProps { @@ -35,7 +29,7 @@ const InsidePage:FC = ({showBanner=true,pageTitle,tagList,showB //
{ showBanner &&
- {backUrl &&

{"< 返回"}

} + {backUrl &&

返回

}
{pageTitle} diff --git a/frontend/packages/common/src/components/aoplatform/InsidePageForHub.tsx b/frontend/packages/common/src/components/aoplatform/InsidePageForHub.tsx index a322d99..83a5559 100644 --- a/frontend/packages/common/src/components/aoplatform/InsidePageForHub.tsx +++ b/frontend/packages/common/src/components/aoplatform/InsidePageForHub.tsx @@ -1,10 +1,3 @@ -/* - * @Date: 2023-11-28 11:54:17 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-02 09:38:42 - * @FilePath: \frontend\packages\core\src\components\InsidePageForHub.tsx - * @Description:内页(带顶部导航与描述、tag、右侧按钮-可选) - */ import { Button, Tag } from "antd" import {useNavigate} from "react-router-dom"; @@ -29,29 +22,6 @@ const InsidePageForHub:FC = ({showBanner=true,pageTitle,tagList const navigate = useNavigate(); const goBack = () => { - // document.referrer 有误,隐藏此段逻辑 - // const currentPath = window.location.pathname; // 获取当前路径 - // // 注意:在使用 React Router 时,直接操作 window.location 可能不是最佳实践,但用于获取当前路径是可接受的 - // const referrerPath = document.referrer ? new URL(document.referrer).pathname : ''; // 获取上一步的路径 - - // // 定义一个函数来提取路由的开始部分 - // const getRouteStart = (path:string) => { - // const parts = path.split('/').filter(Boolean); // 分割路径,并移除空字符串 - // return parts.length > 0 ? parts[0] : null; // 返回路由的开始部分 - // }; - - // const currentRouteStart = getRouteStart(currentPath); - // const referrerRouteStart = getRouteStart(referrerPath); - // // 比较当前路径和上一步路径的路由开始部分是否相同 - // // console.log(currentPath,document,document.referrer, referrerPath, currentRouteStart, referrerRouteStart) - // if (currentRouteStart && referrerRouteStart && currentRouteStart === referrerRouteStart) { - // // 如果相同,跳转到`${currentRouteStart}/list` - // navigate(backUrl ?? `/${currentRouteStart}/list`); - // } else { - // // 如果不同,使用navigate实现返回上一步 - // navigate(-1); - // } - navigate(backUrl); }; return ( diff --git a/frontend/packages/common/src/components/aoplatform/MemberTransfer.tsx b/frontend/packages/common/src/components/aoplatform/MemberTransfer.tsx index 1dc00bd..ee7e81e 100644 --- a/frontend/packages/common/src/components/aoplatform/MemberTransfer.tsx +++ b/frontend/packages/common/src/components/aoplatform/MemberTransfer.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-05-16 15:38:43 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-05 18:55:12 - * @FilePath: \frontend\packages\common\src\components\aoplatform\MemberTransfer.tsx - */ + import { GetProp, TransferProps, TreeDataNode, theme, Transfer, Tree, Spin } from "antd"; import { DataNode, TreeProps } from "antd/es/tree"; import { Ref, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react"; diff --git a/frontend/packages/common/src/components/aoplatform/Navigation.tsx b/frontend/packages/common/src/components/aoplatform/Navigation.tsx index e7c952f..87d2ba6 100644 --- a/frontend/packages/common/src/components/aoplatform/Navigation.tsx +++ b/frontend/packages/common/src/components/aoplatform/Navigation.tsx @@ -1,85 +1,70 @@ + import {FC, useEffect, useMemo, useState} from 'react'; import type { MenuProps } from 'antd'; import { Menu } from 'antd'; import { useLocation, useNavigate} from "react-router-dom"; -import { getItem } from '@common/utils/navigation'; +import { getNavItem } from '@common/utils/navigation'; import { PERMISSION_DEFINITION } from '@common/const/permissions'; import { useGlobalContext } from '@common/contexts/GlobalStateContext'; -import { DashboardOutlined, DeploymentUnitOutlined, HddOutlined, TeamOutlined } from '@ant-design/icons'; - +import { ProjectFilled } from '@ant-design/icons'; +import { Icon } from '@iconify/react'; export type MenuItem = Required['items'][number]; -// type NavigationItemType = { -// title: string, -// iconType: string, -// icon: string, -// router: string, -// access:string [], -// children: NavigationItemType[] -// } const APP_MODE = import.meta.env.VITE_APP_MODE; -const routerKeyMap = new Map([ - ['assets','/assets'], - ['dashboard','/dashboard'], - ['systemrunning','/systemrunning'], - ['system','/system/list'], - ['servicecategories','/servicecategories'], - ['organization','/organization/list'], - ['team','/team/list'], - ['member','/member/list'], - ['user','/user/list'], - ['role','/role'], - ['access','/access'], - ['partition','/partition/list'], - ['openapi','/openapi'], - ['logsettings','/logsettings'], - ['resourcesettings','/resourcesettings']]) +// avoid changing route within ths same category +export const routerKeyMap = new Map([ + ['workspace',['tenantManagement','service','team','serviceHub']], + ['my',['tenantManagement','service','team']], + ['mainPage',['dashboard','systemrunning']], + ['operationCenter',['member','user','role','servicecategories']], + ['organization',['member','user','role']], + ['serviceHubSetting',['servicecategories']], + ['maintenanceCenter',['partition','logsettings','resourcesettings','openapi'] +]]) -const TOTAL_MENU_ITEMS: MenuProps['items'] = [ - APP_MODE === 'pro' ? getItem('仪表盘', 'mainPage', ,[ - // getItem(资产视图, 'assets',null,undefined,undefined,''), - getItem(运行视图, 'dashboard',null,undefined,undefined,''), - getItem(系统拓扑图, 'systemrunning',null,undefined,undefined,''), - // getItem((审批), 'approval', null), - ]):null, - - getItem('数据服务资产', 'dataAssets',, [ - getItem(内部数据服务, 'system',null,undefined,undefined,''), - getItem(服务分类管理, 'servicecategories',null,undefined,undefined,''), +export const TOTAL_MENU_ITEMS: MenuProps['items'] = [ + + getNavItem('工作空间', 'workspace','/tenantManagement',, [ + getNavItem('我的', 'my','/tenantManagement',,[ + getNavItem(应用, 'tenantManagement','/tenantManagement',null,undefined,undefined,''), + getNavItem(服务, 'service','/service',null,undefined,undefined,''), + getNavItem(团队, 'team','/team',null,undefined,undefined,''), + ],undefined,''), + getNavItem(API 市场, 'serviceHub','/serviceHub',,undefined,undefined,'system.workspace.api_market.view'), ]), - getItem('组织架构', 'operationCenter',, [ - getItem(成员与部门, 'member',null,undefined,undefined,'system.member.self.view'), - getItem(组织, 'organization',null,undefined,undefined,'system.organization.self.view'), - getItem(团队, 'team',null,undefined,undefined,''), - getItem(用户组, 'user',null,undefined,undefined,'system.user.self.view'), - getItem(自定义角色, 'role',null,undefined,undefined,'system.role.self.view'), - getItem(权限配置, 'access',null,undefined,undefined,'system.access.self.view'), - ]), - getItem('运维与集成', 'maintenanceCenter', , [ - getItem(部署管理, 'partition',null,undefined,undefined,'system.partition.self.view'), - getItem(日志配置, 'logsettings',null,undefined,undefined,'system.partition.self.view'), - APP_MODE === 'pro' ? getItem(资源配置, 'resourcesettings',null,undefined,undefined,'system.partition.self.view'):null, - // getItem(邮箱设置, 'email'), - APP_MODE === 'pro' ? getItem(Open API, 'openapi',null,undefined,undefined,'system.openapi.self.view'):null, - // getItem(Webhook, 'webhook'), - // getItem(HTTP 日志配置, 'httplog'), - // getItem(日志检索, 'logretrieval',null,undefined,undefined,'system.logRetrieval.self.view'), - // getItem(审计日志, 'auditlog'), + APP_MODE === 'pro' ? getNavItem('仪表盘', 'mainPage', '/dashboard',,[ + getNavItem(运行视图, 'dashboard','/dashboard',,undefined,undefined,''), + getNavItem(系统拓扑图, 'systemrunning','/systemrunning',,undefined,undefined,''), + ]):null, + + getNavItem('系统设置', 'operationCenter','/member',, [ + getNavItem('组织', 'organization','/member',,[ + getNavItem(成员, 'member','/member',null,undefined,undefined,'system.organization.member.view'), + getNavItem(角色, 'role','/role',null,undefined,undefined,'system.organization.role.view'), + ],undefined,''), + getNavItem('API 市场', 'serviceHubSetting','/servicecategories',,[ + getNavItem(服务分类管理, 'servicecategories','/servicecategories',null,undefined,undefined,'system.api_market.service_classification.view'), + ],undefined,'system.api_market.service_classification.view'), + + getNavItem('运维与集成', 'maintenanceCenter','/cluster', , [ + getNavItem(集群, 'cluster','/cluster',null,undefined,undefined,'system.devops.cluster.view'), + getNavItem(证书, 'cert','/cert',null,undefined,undefined,'system.devops.ssl_certificate.view'), + getNavItem(日志, 'logsettings','/logsettings',null,undefined,undefined,'system.devops.log_configuration.view'), + APP_MODE === 'pro' ? getNavItem(资源, 'resourcesettings','/resourcesettings',null,undefined,undefined,'system.partition.self.view'):null, + APP_MODE === 'pro' ? getNavItem(Open API, 'openapi','/openapi',null,undefined,undefined,'system.openapi.self.view'):null, + ]), ]), ]; const Navigation: FC = () => { - // const { message } = App.useApp() const location = useLocation() const [selectedKeys, setSelectedKeys] = useState('') const currentUrl = location.pathname const navigateTo = useNavigate() - // const {fetchData} = useFetch() - // const [navigationItemList, setNavigationItemList] = useState([]) const { accessData,checkPermission} = useGlobalContext() const onClick: MenuProps['onClick'] = (e) => { @@ -88,59 +73,21 @@ const Navigation: FC = () => { newUrl && navigateTo(newUrl) }; - // useEffect(()=>{ - // const newUrl = routerKeyMap.get(selectedKeys) - // console.log(newUrl) - // newUrl && navigateTo(newUrl) - // },[selectedKeys]) - - // 插件相关,暂时隐藏 - // const getNavigationData = ()=>{ - // fetchData>('navigation',{method:'GET',eoApiPrefix:'_system/'},).then(response=>{ - // const {code,data,msg} = response - // if(code === STATUS_CODE.SUCCESS){ - // setNavigationItemList(data.navigation) - // }else{ - // message.error(msg || '操作失败') - // } - // }) - // } - - // const navigations = useMemo(()=>{ - // const getNavTitle = (data:NavigationItemType,root?:boolean)=>{ - // if(root){ - // return data.title - // } - // return {data.title} - // } - - // const handleNavigationData:(data:NavigationItemType[],root?:boolean)=>MenuItem[] = (data:NavigationItemType[],root?:boolean)=>{ - // return data?.map(x=>getItem( - // getNavTitle(x,root), - // x.router.split('/')[0] === 'template' ? x.router.split('/')[1] : x.router.split('/')[0], - // x.icon, - // x.children && handleNavigationData(x.children))) - // } - - // return handleNavigationData(navigationItemList,true) - // },[navigationItemList]) - - const menuData = useMemo(()=>{ const filterMenu = (menu:Array<{[k:string]:unknown}>)=>{ return menu.filter(x=> x && (x.access ? checkPermission(x.access as keyof typeof PERMISSION_DEFINITION[0]): true)) } - return TOTAL_MENU_ITEMS!.filter(x=>x).map((x)=> ( x.children ? {...x, children:filterMenu(x.children)} : x))?.filter(x=> x.key === 'system' || (x.children && x.children?.length > 0)) + return TOTAL_MENU_ITEMS!.filter(x=>x).map((x)=> ( x.children ? {...x, children:filterMenu(x.children)} : x))?.filter(x=> x.key === 'service' || (x.children && x.children?.length > 0)) },[accessData]) useEffect(() => { setSelectedKeys(currentUrl.split('/')[1] === 'template' ? currentUrl.split('/')[2] : currentUrl.split('/')[1]) - // getNavigationData() }, [currentUrl]); return ( extends ProTableProps, RefAttributesvoid } const PageList = >(props: React.PropsWithChildren>,ref: React.Ref) => { - const {id,columns,request,dropMenu,searchPlaceholder,showPagination=true,primaryKey='id',addNewBtnTitle,addNewBtnAccess,tableClickAccess,onAddNewBtnClick,beforeSearchNode,onSearchWordChange,afterNewBtn,dragSortKey,onDragSortEnd,tableTitle,rowSelection,onChange,dataSource,onRowClick,showColSetting=false,minVirtualHeight,noTop,addNewBtnWrapperClass,tableTitleClass,delayLoading = true,besidesTableHeight} = props + const {id,columns,request,dropMenu,searchPlaceholder,showPagination=true,primaryKey='id',addNewBtnTitle,addNewBtnAccess,tableClickAccess,tableClass,onAddNewBtnClick,beforeSearchNode,onSearchWordChange,manualReloadTable,afterNewBtn,dragSortKey,onDragSortEnd,tableTitle,rowSelection,onChange,dataSource,onRowClick,showColSetting=false,minVirtualHeight,noTop,addNewBtnWrapperClass,tableTitleClass,delayLoading = true,besidesTableHeight, noScroll} = props const parentRef = useRef(null); const [tableHeight, setTableHeight] = useState(minVirtualHeight || window.innerHeight); const [tableWidth, setTableWidth] = useState(undefined); @@ -87,7 +85,7 @@ const PageList = >(props: React.PropsWithChild const debouncedHandleResize = debounce(handleResize, 200); - if (!resizeObserverRef.current) { + if (!resizeObserverRef.current || noScroll) { // 创建一个 ResizeObserver 来监听高度变化,只创建一次 resizeObserverRef.current = new ResizeObserver(debouncedHandleResize); // 开始监听 @@ -115,8 +113,7 @@ const PageList = >(props: React.PropsWithChild let width:number = 0 const res = columns?.map( (x)=>{ - // x.width = x.width ?? 100; - width += Number(x.width ?? (x.filters || x.sorter ? 120 : 100)) + width += Number(x.width ?? ((x.filters || x.sorter) ? 120 : 100)) x.copyable = x.copyable === false? false: true const sorter = localStorage.getItem(`${id}_sorter`) const filters = localStorage.getItem(`${id}_filters`) @@ -154,7 +151,7 @@ const PageList = >(props: React.PropsWithChild }; return ( -
+
{dragSortKey? actionRef={actionRef} columns={newColumns} @@ -164,7 +161,7 @@ const PageList = >(props: React.PropsWithChild request={request} dragSortKey={dragSortKey} onDragSortEnd={onDragSortEnd} - scroll={{ y: tableHeight }} + scroll={noScroll ? undefined :{ y: tableHeight }} options={{ reload: false, density: false, @@ -177,7 +174,7 @@ const PageList = >(props: React.PropsWithChild actionRef={actionRef} columns={newColumns} virtual - scroll={{x:tableWidth,y: tableHeight }} + scroll={noScroll ? undefined : {x:tableWidth,y: tableHeight }} size="middle" rowSelection={rowSelection} tableAlertRender={false} @@ -194,7 +191,7 @@ const PageList = >(props: React.PropsWithChild ):null, ]} toolbar={{ - actions:[...[beforeSearchNode],...[searchPlaceholder? debounce(onSearchWordChange, 100)(e) : undefined } onPressEnter={()=>actionRef.current?.reload?.()} allowClear placeholder={searchPlaceholder} prefix={{actionRef.current?.reload?.()}}/>}/>:null]], + actions:[...[beforeSearchNode],...[searchPlaceholder? debounce(onSearchWordChange, 100)(e) : undefined } onPressEnter={()=>manualReloadTable ? manualReloadTable():actionRef.current?.reload?.()} allowClear placeholder={searchPlaceholder} prefix={{actionRef.current?.reload?.()}}/>}/>:null]], }} options={{ reload: false, diff --git a/frontend/packages/common/src/components/aoplatform/PublishApprovalModalContent.tsx b/frontend/packages/common/src/components/aoplatform/PublishApprovalModalContent.tsx index 99d65ad..c8e6a8c 100644 --- a/frontend/packages/common/src/components/aoplatform/PublishApprovalModalContent.tsx +++ b/frontend/packages/common/src/components/aoplatform/PublishApprovalModalContent.tsx @@ -56,12 +56,6 @@ const apiColumns = [ ] const upstreamColumns = [ - { - title:'环境', - dataIndex:['partition','name'], - copyable: true, - ellipsis:true - }, { title:'上游类型', dataIndex:'type', @@ -101,19 +95,20 @@ type PublishApprovalModalProps = { type:'approval'|'view'|'add'|'publish'|'online' data:PublishApprovalInfoType | PublishApprovalInfoType &{id?:string} | PublishVersionTableListItem insideSystem?:boolean - systemId:string + serviceId:string + teamId:string clusterPublishStatus?:SystemInsidePublishOnlineItems[] } export type PublishApprovalModalHandle = { save:(operate:'pass'|'refuse') =>Promise - publish:(notSave?:boolean)=>Promise + publish:(notSave?:boolean)=>Promise> online:()=>Promise } export const PublishApprovalModalContent = forwardRef((props, ref) => { const { message } = App.useApp() - const { type,data,insideSystem = false,systemId} = props + const { type,data,insideSystem = false,serviceId, teamId} = props const [form] = Form.useForm(); const {fetchData} = useFetch() @@ -129,7 +124,7 @@ export const PublishApprovalModalContent = forwardRef>(`project/publish/${operate === 'pass' ? 'accept' : 'refuse'}`,{method: 'PUT',eoBody:({comments:value.opinion}), eoParams:{id:data!.id, project:systemId},eoTransformKeys:['versionRemark']}).then(response=>{ + return fetchData>(`service/publish/${operate === 'pass' ? 'accept' : 'refuse'}`,{method: 'PUT',eoBody:({comments:value.opinion}), eoParams:{id:data!.id, project:serviceId},eoTransformKeys:['versionRemark']}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -142,20 +137,20 @@ export const PublishApprovalModalContent = forwardRef {form.scrollToField(err.errorFields[0].name[0]); return Promise.reject(err)}) } - const publish:(notSave?:boolean)=>Promise = (notSave)=>{ + const publish:(notSave?:boolean)=>Promise> = (notSave)=>{ return new Promise((resolve, reject)=>{ form.validateFields().then((value)=>{ const body = {...value, ...(type === 'publish'&&{release:data.id})} fetchData>( - notSave ? 'project/publish/apply' : 'project/publish/release',{method: 'POST',eoBody:body, eoParams:{project:systemId},eoTransformKeys:['versionRemark']}).then(response=>{ - const {code,msg} = response - if(code === STATUS_CODE.SUCCESS){ - message.success(msg || '操作成功!') - resolve(true) - }else{ - message.error(msg || '操作失败') - reject(msg || '操作失败') - } + notSave ? 'service/publish/apply' : 'service/publish/release/do',{method: 'POST',eoBody:body, eoParams:{service:serviceId, team:teamId},eoTransformKeys:['versionRemark']}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || '操作成功!') + resolve(response) + }else{ + message.error(msg || '操作失败') + reject(msg || '操作失败') + } }).catch((errorInfo)=> reject(errorInfo)) }).catch((errorInfo)=> reject(errorInfo)) }) @@ -164,7 +159,7 @@ export const PublishApprovalModalContent = forwardRefPromise = ()=>{ return new Promise((resolve, reject)=>{ form.validateFields().then(()=>{ - fetchData>('project/publish/execute',{method: 'PUT', eoParams:{project:systemId,id:(data as PublishVersionTableListItem).flowId},eoTransformKeys:['versionRemark']}).then(response=>{ + fetchData>('service/publish/execute',{method: 'PUT', eoParams:{project:serviceId,id:(data as PublishVersionTableListItem).flowId},eoTransformKeys:['versionRemark']}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') diff --git a/frontend/packages/common/src/components/aoplatform/ScrollableSection.tsx b/frontend/packages/common/src/components/aoplatform/ScrollableSection.tsx index 43013b3..32b3c94 100644 --- a/frontend/packages/common/src/components/aoplatform/ScrollableSection.tsx +++ b/frontend/packages/common/src/components/aoplatform/ScrollableSection.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-03-13 17:27:29 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-04-01 16:41:51 - * @FilePath: \frontend\packages\core\src\components\ScrollableSection.tsx - */ + import {FC, useRef, useEffect, Children, cloneElement, isValidElement } from 'react'; interface ScrollableSectionProps { diff --git a/frontend/packages/common/src/components/aoplatform/SubscribeApprovalModalContent.tsx b/frontend/packages/common/src/components/aoplatform/SubscribeApprovalModalContent.tsx index 68cca34..efa25e8 100644 --- a/frontend/packages/common/src/components/aoplatform/SubscribeApprovalModalContent.tsx +++ b/frontend/packages/common/src/components/aoplatform/SubscribeApprovalModalContent.tsx @@ -9,7 +9,8 @@ type SubscribeApprovalModalProps = { type:'approval'|'view' data?:SubscribeApprovalInfoType inSystem?:boolean - systemId?:string + serviceId:string + teamId:string } export type SubscribeApprovalModalHandle = { @@ -17,14 +18,13 @@ export type SubscribeApprovalModalHandle = { } type FieldType = { - partition?:Array<{id:string,name:string,checked:boolean}> reason?:string; opinion?:string; }; const list = [ { - title:'申请方系统',key:'applyProject' + title:'申请方应用',key:'application' }, { title:'申请方所属团队',key:'applyTeam' @@ -38,16 +38,13 @@ const list = [ { title:'申请服务',key:'service' }, - { - title:'服务所属系统',key:'project' - }, { title:'服务所属团队',key:'team' } ] export const SubscribeApprovalModalContent = forwardRef((props, ref) => { const { message } = App.useApp() - const {data, type,inSystem=false,systemId} = props + const {data, type,inSystem=false, teamId, serviceId} = props const [form] = Form.useForm(); const {fetchData} = useFetch() @@ -66,7 +63,7 @@ export const SubscribeApprovalModalContent = forwardRef>(`${inSystem?'project/':''}approval/subscribe`,{method: 'POST',eoBody:({partition:value.partitions,opinion:value.opinion,operate}), eoParams:(inSystem ? {application:data!.id, project:systemId} : {id:data!.id})}).then(response=>{ + fetchData>(`${inSystem?'service/':''}approval/subscribe`,{method: 'POST',eoBody:({opinion:value.opinion,operate}), eoParams:(inSystem ? {apply:data!.id, team:teamId} : {id:data!.id,team:teamId})}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -86,7 +83,7 @@ export const SubscribeApprovalModalContent = forwardRef{ - form.setFieldsValue({opinion:'',...data,...(data?.areasList && data?.areasList?.length === 1 ? {partition:[data.areasList[0].id]} : {})}) + form.setFieldsValue({opinion:'',...data}) },[]) return ( @@ -111,16 +108,6 @@ export const SubscribeApprovalModalContent = forwardRef - - label="申请的环境" - name="partition" - rules={[{ required: true, message: '必填项' }]} - > - ({label:x.name,value:x.id}))} - /> - - label="申请原因" name="reason" diff --git a/frontend/packages/common/src/components/aoplatform/TableBtnWithPermission.tsx b/frontend/packages/common/src/components/aoplatform/TableBtnWithPermission.tsx index 235c1e5..4d0223d 100644 --- a/frontend/packages/common/src/components/aoplatform/TableBtnWithPermission.tsx +++ b/frontend/packages/common/src/components/aoplatform/TableBtnWithPermission.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-03-08 10:28:15 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-05-29 18:26:28 - * @FilePath: \frontend\packages\core\src\components\TableBtnWithPermission.tsx - */ + import { Button, Tooltip } from "antd" import { useState, useMemo, useEffect } from "react" import { useGlobalContext } from "@common/contexts/GlobalStateContext" diff --git a/frontend/packages/common/src/components/aoplatform/TagWithPermission.tsx b/frontend/packages/common/src/components/aoplatform/TagWithPermission.tsx index d5c8d55..cbc4e2f 100644 --- a/frontend/packages/common/src/components/aoplatform/TagWithPermission.tsx +++ b/frontend/packages/common/src/components/aoplatform/TagWithPermission.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-04-19 10:21:03 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-05-29 18:48:57 - * @FilePath: \frontend\packages\common\src\components\aoplatform\TagWithPermission.tsx - */ + import { Tag, TagProps } from "antd"; import { useState, useMemo, useEffect } from "react"; import { PERMISSION_DEFINITION } from "@common/const/permissions"; diff --git a/frontend/packages/common/src/components/aoplatform/ThemeSwitcher.tsx b/frontend/packages/common/src/components/aoplatform/ThemeSwitcher.tsx new file mode 100644 index 0000000..367bea9 --- /dev/null +++ b/frontend/packages/common/src/components/aoplatform/ThemeSwitcher.tsx @@ -0,0 +1,34 @@ + +import React, { useEffect, useState } from 'react'; + +const ThemeSwitcher = () => { + const [darkMode, setDarkMode] = useState(true); + + useEffect(() => { + let isDarkMode = localStorage.getItem('dark-mode'); + if(isDarkMode !== undefined && isDarkMode !== null){ + setDarkMode(isDarkMode === 'true') + }else{ + localStorage.setItem('dark-mode', (darkMode).toString()); + } + }, []); + + useEffect(()=>{ + document.documentElement.classList.toggle('dark', darkMode); + },[darkMode]) + + const toggleDarkMode = () => { + setDarkMode(!darkMode); + localStorage.setItem('dark-mode', (!darkMode).toString()); + document.documentElement.classList.toggle('dark', !darkMode); + }; + + return ( + // + <> + ); +}; + +export default ThemeSwitcher; \ No newline at end of file diff --git a/frontend/packages/common/src/components/aoplatform/TimePicker.tsx b/frontend/packages/common/src/components/aoplatform/TimePicker.tsx index 6ff6926..ef440fa 100644 --- a/frontend/packages/common/src/components/aoplatform/TimePicker.tsx +++ b/frontend/packages/common/src/components/aoplatform/TimePicker.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-02-19 18:11:53 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-05-29 18:13:58 - * @FilePath: \frontend\packages\common\src\components\aoplatform\TimePicker.tsx - */ + import {forwardRef} from 'react'; import type { PickerProps } from 'antd/es/date-picker/generatePicker'; import type { Moment } from 'moment'; diff --git a/frontend/packages/common/src/components/aoplatform/TimeRangeSelector.tsx b/frontend/packages/common/src/components/aoplatform/TimeRangeSelector.tsx index 60755b1..e66dd9c 100644 --- a/frontend/packages/common/src/components/aoplatform/TimeRangeSelector.tsx +++ b/frontend/packages/common/src/components/aoplatform/TimeRangeSelector.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-03-18 10:52:38 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-07 09:16:13 - * @FilePath: \frontend\packages\common\src\components\aoplatform\TimeRangeSelector.tsx - */ + import { useState } from 'react'; import { Radio, DatePicker, GetProps, RadioChangeEvent } from 'antd'; import dayjs, { Dayjs } from 'dayjs'; diff --git a/frontend/packages/common/src/components/aoplatform/TransferTable.tsx b/frontend/packages/common/src/components/aoplatform/TransferTable.tsx index 37b44ad..69bbc14 100644 --- a/frontend/packages/common/src/components/aoplatform/TransferTable.tsx +++ b/frontend/packages/common/src/components/aoplatform/TransferTable.tsx @@ -1,16 +1,10 @@ -/* - * @Date: 2024-01-31 15:00:10 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-05-17 16:42:12 - * @FilePath: \frontend\packages\core\src\components\TransferTable.tsx - */ + import { Input,Table} from "antd"; import {forwardRef, KeyboardEventHandler, Ref, useCallback, useEffect, useImperativeHandle, useRef, useState} from "react"; import styles from './TransferTable.module.css' import {CloseOutlined, SearchOutlined} from "@ant-design/icons"; import {debounce} from "lodash-es"; import {ColumnsType} from "antd/es/table"; -// import Table from '../../../../../../../github/ant-design/components/table/index'; export type TransferTableProps = { request?:(k?:string)=>Promise<{data:T[],success:boolean}> @@ -38,10 +32,8 @@ const TransferTable = forwardRef, Tran const [loading, setLoading] = useState(false) const parentRef = useRef(null); const [tableHeight, setTableHeight] = useState(window.innerHeight * 80 / 100 ); - // const [tableWidth, setTableWidth] = useState(216); const [tableShow, setTableShow] = useState(false); - // console.log(tableWidth) useImperativeHandle(ref, () =>({ selectedData: () => selectedData, selectedRowKeys: () => selectedRowKeys,})) diff --git a/frontend/packages/common/src/components/aoplatform/TreeWithMore.tsx b/frontend/packages/common/src/components/aoplatform/TreeWithMore.tsx index 971c8a5..e2f4199 100644 --- a/frontend/packages/common/src/components/aoplatform/TreeWithMore.tsx +++ b/frontend/packages/common/src/components/aoplatform/TreeWithMore.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-01-31 15:00:10 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-04-17 16:46:52 - * @FilePath: \frontend\packages\core\src\components\TreeWithMore.tsx - */ + import {CheckOutlined, LoadingOutlined, MoreOutlined} from "@ant-design/icons"; import {Dropdown, Input, InputRef, MenuProps} from "antd"; import { ReactNode, useEffect, useRef, useState} from "react"; diff --git a/frontend/packages/common/src/components/aoplatform/UserProfile.tsx b/frontend/packages/common/src/components/aoplatform/UserProfile.tsx index 6c51363..c6b98f7 100644 --- a/frontend/packages/common/src/components/aoplatform/UserProfile.tsx +++ b/frontend/packages/common/src/components/aoplatform/UserProfile.tsx @@ -2,10 +2,11 @@ import {App, Form, Input, Upload, UploadFile, UploadProps} from "antd"; import {forwardRef, useEffect, useImperativeHandle, useState} from "react"; import {useFetch} from "@common/hooks/http.ts"; import {RcFile, UploadChangeParam} from "antd/es/upload"; -import {LoadingOutlined, PlusOutlined} from "@ant-design/icons"; +import {LoadingOutlined} from "@ant-design/icons"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import { UserInfoType, UserProfileHandle, UserProfileProps } from "@common/const/type"; import { getImgBase64 } from "@common/utils/dataTransfer"; +import { Icon } from "@iconify/react/dist/iconify.js"; export const UserProfile = forwardRef((props,ref)=>{ const { message } = App.useApp() @@ -60,7 +61,7 @@ export const UserProfile = forwardRef((props const uploadButton = (
- {loading ? : }
+ {loading ? : }
); diff --git a/frontend/packages/common/src/components/aoplatform/WithPermission.tsx b/frontend/packages/common/src/components/aoplatform/WithPermission.tsx index 815a1dc..c094cd5 100644 --- a/frontend/packages/common/src/components/aoplatform/WithPermission.tsx +++ b/frontend/packages/common/src/components/aoplatform/WithPermission.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-02-26 15:18:46 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-05 15:49:03 - * @FilePath: \frontend\packages\common\src\components\aoplatform\WithPermission.tsx - */ + import { Tooltip } from "antd"; import { ReactElement, cloneElement, useEffect, useMemo, useState } from "react"; import { useGlobalContext } from "../../contexts/GlobalStateContext"; diff --git a/frontend/packages/common/src/components/aoplatform/formily2-customize/ArrayItemBlankComponent.tsx b/frontend/packages/common/src/components/aoplatform/formily2-customize/ArrayItemBlankComponent.tsx index 7c79a0a..2e573d3 100644 --- a/frontend/packages/common/src/components/aoplatform/formily2-customize/ArrayItemBlankComponent.tsx +++ b/frontend/packages/common/src/components/aoplatform/formily2-customize/ArrayItemBlankComponent.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-01-31 15:00:11 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-04-01 16:29:06 - * @FilePath: \frontend\packages\core\src\components\formily2-customize\ArrayItemBlankComponent.tsx - */ + import {forwardRef, useImperativeHandle, useState} from 'react' import { Input } from 'antd' diff --git a/frontend/packages/common/src/components/aoplatform/formily2-customize/CustomCodeboxComponent.tsx b/frontend/packages/common/src/components/aoplatform/formily2-customize/CustomCodeboxComponent.tsx index cce47df..43853bb 100644 --- a/frontend/packages/common/src/components/aoplatform/formily2-customize/CustomCodeboxComponent.tsx +++ b/frontend/packages/common/src/components/aoplatform/formily2-customize/CustomCodeboxComponent.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-01-31 15:00:11 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-04 18:15:06 - * @FilePath: \frontend\packages\common\src\components\aoplatform\formily2-customize\CustomCodeboxComponent.tsx - */ + import {forwardRef, useImperativeHandle, useState} from 'react' import { Codebox } from '@common/components/postcat/api/Codebox' diff --git a/frontend/packages/common/src/components/aoplatform/formily2-customize/CustomDialogComponent.tsx b/frontend/packages/common/src/components/aoplatform/formily2-customize/CustomDialogComponent.tsx index 79fdc72..938fac7 100644 --- a/frontend/packages/common/src/components/aoplatform/formily2-customize/CustomDialogComponent.tsx +++ b/frontend/packages/common/src/components/aoplatform/formily2-customize/CustomDialogComponent.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-01-31 15:00:11 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-05 15:15:58 - * @FilePath: \frontend\packages\common\src\components\aoplatform\formily2-customize\CustomDialogComponent.tsx - */ + import {forwardRef,useImperativeHandle} from 'react' import { createSchemaField } from '@formily/react' import { diff --git a/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginConfig.tsx b/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginConfig.tsx index c09181f..9f9c5a7 100644 --- a/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginConfig.tsx +++ b/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginConfig.tsx @@ -42,11 +42,39 @@ import {SimpleMapComponent} from "@common/components/aoplatform/formily2-customi import {CustomDialogComponent} from "@common/components/aoplatform/formily2-customize/CustomDialogComponent.tsx"; import {ArrayItemBlankComponent} from "@common/components/aoplatform/formily2-customize/ArrayItemBlankComponent.tsx"; import {DefaultOptionType} from "antd/es/cascader"; -import {createSchemaField, FormProvider} from "@formily/react"; +import {createSchemaField, FormProvider, RecursionField, useField, useForm} from "@formily/react"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import {useFetch} from "@common/hooks/http.ts"; import {App} from "antd"; -import { cloneDeep } from "lodash-es"; + + + +export const DynamicRender = (props) => { + const {schema} = props + const field = useField() + const form = useForm() + const [renderSchema, setRenderSchema] = useState({}) + + useEffect(() => { + form.clearFormGraph(`${field.address}.*`) + try{ + const parsedSchema = JSON.parse(schema) + setRenderSchema(parsedSchema[form?.values?.driver]) + }catch(e){ + console.error('渲染出错',e?.message) + } + }, [form.values.driver]) + + return ( + + ) +} + + export type IntelligentPluginConfigProps = { type:'add'|'edit' @@ -62,511 +90,6 @@ export type IntelligentPluginConfigHandle = { save:()=>Promise } -const finalSchema = { - "type": "object", - "properties": { - "layout": { - "type": "void", - "x-component": "FormLayout", - "x-component-props": { - "labelCol": 6, - "wrapperCol": 10, - "layout": "vertical" - }, - "properties": { - "id": { - "type": "string", - "title": "ID", - "required": true, - "pattern": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 4, - "wrapperCol": 20, - "labelAlign": "left" - }, - "x-component": "Input", - "x-component-props": { - "placeholder": "支持字母开头、英文数字中横线下划线组合" - }, - "x-disabled": false - }, - "title": { - "type": "string", - "title": "名称", - "required": true, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 4, - "wrapperCol": 20, - "labelAlign": "left" - }, - "x-component": "Input", - "x-component-props": { - "placeholder": "请输入名称" - } - }, - "driver": { - "type": "string", - "title": "Driver", - "required": true, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 4, - "wrapperCol": 20, - "labelAlign": "left" - }, - "x-component": "Select", - "x-component-props": { - "disabled": false - }, - "x-display": "hidden", - "enum": [ - { - "label": "文件", - "value": "file" - } - ] - }, - "description": { - "type": "string", - "title": "描述", - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 4, - "wrapperCol": 20, - "labelAlign": "left" - }, - "x-component": "Input.TextArea", - "x-component-props": { - "placeholder": "请输入描述" - } - }, - "config": { - "type": "object", - "x-component": "void", - "properties": { - "tabForm": { - "type": "void", - "x-component": "FormTab", - "x-component-props": { - "formTab": "{{formTab}}", - "centered": false - }, - "properties": { - "0a3d7fcc-a59f-435f-8be0-9ff2cd0809c6": { - "type": "object", - "x-component": "FormTab.TabPane", - "x-component-props": { - "tab": "华南", - "forceRender": true - }, - "properties": { - "_apinto_show": { - "type": "boolean", - "title": "启用", - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 4, - "wrapperCol": 20, - "labelAlign": "left" - }, - "x-component": "Switch", - "x-index": 0 - }, - "_apinto_backend": { - "type": "void", - "x-component": "void", - "x-reactions": { - "dependencies": [ - "._apinto_show" - ], - "fulfill": { - "state": { - "visible": "{{!!$deps[0]}}" - } - } - }, - "properties": { - "dir": { - "name": "dir", - "required": true, - "title": "存放目录", - "type": "string", - "x-component": "Input", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 2, - "x-validator": [] - }, - "expore": { - "default": "3", - "description": "单位:天", - "name": "expore", - "required": true, - "title": "过期时间", - "type": "number", - "x-component": "NumberPicker", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 4, - "x-validator": "integer" - }, - "file": { - "name": "file", - "required": true, - "title": "文件名称", - "type": "string", - "x-component": "Input", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 1, - "x-validator": [] - }, - "formatter": { - "title": "格式化配置", - "type": "object", - "x-component": "CustomCodeboxComponent", - "x-component-props": { - "mode": "json" - }, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - } - }, - "period": { - "default": "hour", - "enum": [ - { - "children": [], - "label": "小时", - "value": "hour" - }, - { - "children": [], - "label": "天", - "value": "day" - } - ], - "name": "period", - "required": true, - "title": "日志分割周期", - "x-component": "Select", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 3, - "x-validator": [] - }, - "scopes": { - "items": { - "properties": { - "remove": { - "type": "void", - "x-component": "ArrayItems.Remove", - "x-decorator": "FormItem" - }, - "select": { - "enum": [ - { - "label": "Access日志", - "value": "access_log" - } - ], - "type": "string", - "x-component": "Select", - "x-decorator": "FormItem" - }, - "sort": { - "type": "void", - "x-component": "ArrayItems.SortHandle", - "x-decorator": "FormItem" - } - }, - "type": "void", - "x-component": "Space" - }, - "name": "scopes", - "properties": { - "add": { - "title": "添加条目", - "type": "void", - "x-component": "ArrayItems.Addition", - "x-component-props": { - "defaultValue": "access_log" - } - } - }, - "required": true, - "title": "作用范围", - "type": "array", - "x-component": "ArrayItems", - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 0 - }, - "type": { - "default": "line", - "enum": [ - { - "children": [], - "label": "单行", - "value": "line" - }, - { - "children": [], - "label": "Json", - "value": "json" - } - ], - "name": "type", - "required": true, - "title": "输出格式", - "x-component": "Select", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 5, - "x-validator": [] - } - } - } - } - }, - "8bfbba9e-5931-40ac-8ac4-084d1ff36409": { - "type": "object", - "x-component": "FormTab.TabPane", - "x-component-props": { - "tab": "华北", - "forceRender": true - }, - "properties": { - "_apinto_show": { - "type": "boolean", - "title": "启用", - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 4, - "wrapperCol": 20, - "labelAlign": "left" - }, - "x-component": "Switch", - "x-index": 0 - }, - "_apinto_backend": { - "type": "void", - "x-component": "void", - "x-reactions": { - "dependencies": [ - "._apinto_show" - ], - "fulfill": { - "state": { - "visible": "{{!!$deps[0]}}" - } - } - }, - "properties": { - "dir": { - "name": "dir", - "required": true, - "title": "存放目录", - "type": "string", - "x-component": "Input", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 2, - "x-validator": [] - }, - "expore": { - "default": "3", - "description": "单位:天", - "name": "expore", - "required": true, - "title": "过期时间", - "type": "number", - "x-component": "NumberPicker", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 4, - "x-validator": "integer" - }, - "file": { - "name": "file", - "required": true, - "title": "文件名称", - "type": "string", - "x-component": "Input", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 1, - "x-validator": [] - }, - "formatter": { - "title": "格式化配置", - "type": "object", - "x-component": "CustomCodeboxComponent", - "x-component-props": { - "mode": "json" - }, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - } - }, - "period": { - "default": "hour", - "enum": [ - { - "children": [], - "label": "小时", - "value": "hour" - }, - { - "children": [], - "label": "天", - "value": "day" - } - ], - "name": "period", - "required": true, - "title": "日志分割周期", - "x-component": "Select", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 3, - "x-validator": [] - }, - "scopes": { - "items": { - "properties": { - "remove": { - "type": "void", - "x-component": "ArrayItems.Remove", - "x-decorator": "FormItem" - }, - "select": { - "enum": [ - { - "label": "Access日志", - "value": "access_log" - } - ], - "type": "string", - "x-component": "Select", - "x-decorator": "FormItem" - }, - "sort": { - "type": "void", - "x-component": "ArrayItems.SortHandle", - "x-decorator": "FormItem" - } - }, - "type": "void", - "x-component": "Space" - }, - "name": "scopes", - "properties": { - "add": { - "title": "添加条目", - "type": "void", - "x-component": "ArrayItems.Addition", - "x-component-props": { - "defaultValue": "access_log" - } - } - }, - "required": true, - "title": "作用范围", - "type": "array", - "x-component": "ArrayItems", - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 0 - }, - "type": { - "default": "line", - "enum": [ - { - "children": [], - "label": "单行", - "value": "line" - }, - { - "children": [], - "label": "Json", - "value": "json" - } - ], - "name": "type", - "required": true, - "title": "输出格式", - "x-component": "Select", - "x-component-props": {}, - "x-decorator": "FormItem", - "x-decorator-props": { - "labelCol": 6, - "wrapperCol": 10 - }, - "x-index": 5, - "x-validator": [] - } - } - } - } - } - } - } - } - } - } - } - } -} - const SchemaField = createSchemaField({ components: { ArrayCards, @@ -608,14 +131,14 @@ const SchemaField = createSchemaField({ CustomCodeboxComponent, SimpleMapComponent, CustomDialogComponent, - ArrayItemBlankComponent + ArrayItemBlankComponent, + DynamicRender } }) export const IntelligentPluginConfig = forwardRef((props,ref)=>{ - const { type,renderSchema,tabData,moduleId,driverSelectionOptions,initFormValue} = props + const { type,renderSchema,moduleId,driverSelectionOptions,initFormValue} = props const { message } = App.useApp() - const [schema, setSchema] = useState({}) const {fetchData} = useFetch() const form = createForm({ validateFirst: type === 'edit' }) form.setInitialValues(initFormValue || {}) @@ -694,104 +217,24 @@ export const IntelligentPluginConfig = forwardRef{ - const newSchema:{[k:string]:unknown} = {} - if(!tabData || tabData.length === 0) return - for(const tab of tabData){ - newSchema[tab.value!] = { - type: 'object', - 'x-component': 'FormTab.TabPane', - 'x-component-props': { - tab: tab.label, - forceRender:true - }, - properties:{ - _apinto_show:{ - type: 'boolean', - title: '启用', - 'x-decorator': 'FormItem', - 'x-decorator-props': { - labelCol:4, - wrapperCol: 20, - labelAlign:'left' - }, - 'x-component': 'Switch', - 'x-index':0, }, - _apinto_backend: { + container: { type: 'void', - 'x-component': 'void', - 'x-reactions': { - dependencies: ['._apinto_show'], - fulfill: { - state: { - visible: '{{!!$deps[0]}}', - }, - }, - }, - properties: renderSchema[form.values.driver]?.properties, - } - } - } - } - - const newSchema2 = {...pluginEditSchema, - properties:{ - ...pluginEditSchema.properties, - layout:{...pluginEditSchema.properties.layout, - properties:{ - ...pluginEditSchema.properties.layout.properties, - config: { - type: 'object', - 'x-component': 'void', - properties: { - tabForm:{ - type: 'void', - 'x-component': 'FormTab', - 'x-component-props': { - formTab: '{{formTab}}', - centered:false, - }, - properties: newSchema - } - } - } + 'x-component': 'DynamicRender', + 'x-component-props': { + schema: JSON.stringify(renderSchema), } } } } - - setSchema(newSchema2) } +} + - useEffect(() => { - getNewSchema() - }, [tabData,renderSchema,form.values.driver]); - const save :()=>Promise = ()=>{ return new Promise((resolve, reject)=>{ form.validate().then(()=>{ - const res = form.values - const newData = JSON.parse(JSON.stringify(res)); // 深拷贝对象,避免直接修改 Proxy - const config = newData.config; - - for (const tab in config) { - if (config[tab]._apinto_show) { - delete config[tab]._apinto_show; // 删除 _apinto_show 属性 - } else { - delete config[tab]; // 删除整个 tab - } - } - - fetchData>(type === 'add'?`dynamic/${moduleId}`:`dynamic/${moduleId}/config`,{method:type === 'add'? 'POST' : 'PUT',eoBody:newData, eoParams:{...(type !== 'add' && {id:initFormValue.id})}}).then(response=>{ + fetchData>(type === 'add'?`dynamic/${moduleId}`:`dynamic/${moduleId}/config`,{method:type === 'add'? 'POST' : 'PUT',eoBody:form.values, eoParams:{...(type !== 'add' && {id:initFormValue.id})}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -840,8 +283,8 @@ export const IntelligentPluginConfig = forwardRef
) diff --git a/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx b/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx index be6f968..9efd309 100644 --- a/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx +++ b/frontend/packages/common/src/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx @@ -1,16 +1,15 @@ import PageList from "@common/components/aoplatform/PageList.tsx"; -import {App, Button, Divider, Select, Spin} from "antd"; +import {App, Divider, Spin} from "antd"; import {useEffect, useRef, useState} from "react"; -import {Link, useLocation, useParams} from "react-router-dom"; +import { useLocation, useOutletContext, useParams} from "react-router-dom"; import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx"; import {ActionType, ParamsType, ProColumns} from "@ant-design/pro-components"; import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; import {DefaultOptionType} from "antd/es/cascader"; import {IntelligentPluginConfig, IntelligentPluginConfigHandle} from "./IntelligentPluginConfig.tsx"; -import {IntelligentPluginPublish, IntelligentPluginPublishHandle} from "./IntelligentPluginPublish.tsx"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import {useFetch} from "@common/hooks/http.ts"; -import {EntityItem, PartitionItem} from "@common/const/type.ts"; +import {EntityItem} from "@common/const/type.ts"; import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission.tsx"; import { DrawerWithFooter } from "@common/components/aoplatform/DrawerWithFooter.tsx"; @@ -72,41 +71,47 @@ export const StatusColorClass = { "待发布":'text-[#46BE11]', "未发布":'text-[#03a9f4]' } + + +export type DynamicPublish = { + code:number, + msg:string, + data:{ + success:Array, + fail:Array + } +} + export default function IntelligentPluginList(){ const { modal,message } = App.useApp() const [searchWord, setSearchWord] = useState('') const { moduleId } = useParams(); const [pluginName,setPluginName] = useState('-') - const [partitionOptions, setPartitionOption] = useState([]) + const [partitionOptions] = useState([{label:'default', value:'default'}]) const { setBreadcrumb } = useBreadcrumb() - // const [confirmLoading, setConfirmLoading] = useState(false); const [renderSchema ,setRenderSchema] = useState<{[k:string]:unknown}>({}) - const [tableStatusLoading, setTableStatusLoading] = useState(true) - // const [currentModalContentRef, setCurrentModalContentRef] = useState() const drawerFormRef = useRef(null); - const publishRef = useRef(null); const [driverOptions, setDriverOptions] = useState([]) const [tableListDataSource, setTableListDataSource] = useState([]); - const [tableListStatus, setTableListStatus] = useState<{[k:string]:{[key:string]:string}}|null>(null); const [tableHttpReload, setTableHttpReload] = useState(true); const [columns,setColumns] = useState[] >([]) const {fetchData} = useFetch() - const [partition, setCluster] = useState([]) const pageListRef = useRef(null); const [publishBtnLoading, setPublishBtnLoading] = useState(false) const [curDetail,setCurDetail] = useState<{[k: string]: unknown;}|undefined>() const [drawerType, setDrawerType] = useState<'add'|'edit'>('add') const [drawerOpen, setDrawerOpen] = useState(false) const [drawerLoading, setDrawerLoading] = useState(false) - const [tableStatusError, setTableStatusError] = useState(false) const location = useLocation().pathname + const {accessPrefix} = useOutletContext<{accessPrefix:string}>() + const getIntelligentPluginTableList=(params:ParamsType & { pageSize?: number | undefined; current?: number | undefined; keyword?: string | undefined; - },): Promise<{ data: DynamicTableItem[], success: boolean }>=> { + }): Promise<{ data: DynamicTableItem[], success: boolean }>=> { if(!tableHttpReload){ setTableHttpReload(true) return Promise.resolve({ @@ -118,101 +123,54 @@ export default function IntelligentPluginList(){ page:params.current, pageSize:params.pageSize, keyword:searchWord, - partition:JSON.stringify(partition) } - setTableListStatus({}) - setTableStatusLoading(true) - return Promise.allSettled( - [ - fetchData>(`dynamic/${moduleId}/list`,{method:'GET',eoParams:query,eoTransformKeys:['pageSize']}).then((res)=>{ - if(res.code === STATUS_CODE.SUCCESS) getConfig(res.data) ;message.destroy(); return res}), - fetchData>(`dynamic/${moduleId}/status`,{method:'GET',eoParams:query,eoTransformKeys:['pageSize']}).then((res)=>{ - if(res.code === STATUS_CODE.SUCCESS) setTableListStatus(res.data) ; return res}) - ]) - .then(([resultA, - resultB - ])=>{ - // 检查两个请求是否都成功 - const isSuccessA = resultA.status === 'fulfilled' && resultA.value.code === STATUS_CODE.SUCCESS; - const isSuccessB = resultB.status === 'fulfilled' && resultB.value.code === STATUS_CODE.SUCCESS; - // 根据请求结果更新状态 - if(!isSuccessB){ - message.error(resultB?.value?.msg || '操作失败') - } - if (isSuccessA) { - setTableStatusLoading(false) - setTableStatusError(!isSuccessB) - const fullTableListData =isSuccessB ? resultA.value.data.list?.map((x:DynamicTableItem)=>{return {...x,...resultB.value.data.list[x.id]}}):resultA.value.data.list - setTableListDataSource(fullTableListData); - getTableConfig(resultA.value.data, false,!isSuccessB) - return { data: fullTableListData, success: true,total:resultA.value.data.total }; - } else { - setTableListDataSource([]); - return { data: [], success: false }; - } - }).catch((e)=>{console.warn(e)}) + return fetchData>( + `dynamic/${moduleId}/list`, + {method:'GET',eoParams:query,eoTransformKeys:['pageSize']}).then((res)=>{ + message.destroy(); + if(res.code === STATUS_CODE.SUCCESS){ + getConfig(res.data) + setColumns(res.data.basic.fields.map((field:DynamicTableField)=>({ + title:field.title, + dataIndex:field.name, + copyable: true, + fixed:field.name === 'title' ? 'left' : undefined, + ellipsis:true, + width:field.name === 'title' ? 150 : undefined, + ...(field.enum?.length > 0 ?{ + onFilter: (value: string, record: { [x: string]: string | string[]; }) => record[field.name].indexOf(value) === 0, + filters:field.enum?.map((x:string)=>{return {text:x, value:x}}), + render:(_: unknown, entity: { [x: string]: string; })=> { + return {(entity[field.name] as string)} + }, + }:{}), + }))) + setTableListDataSource(res.data.list); + return ({ data: res.data.list, success: true,total:res.data.total }); + }else{ + setTableListDataSource([]); + return ({ data: [], success: false }); + } + }).catch((e)=>{console.warn(e); + return ({ data: [], success: false });}) } const getConfig = (data:DynamicTableConfig)=>{ const {basic,list } = data const {title,drivers} = basic - + setBreadcrumb([ {title:location.includes('resourcesettings') ? '资源配置': '日志配置'}, { title } ]) - + setPluginName(title) - if(!tableListStatus || !Object.keys(tableListStatus).length){ - setTableListDataSource(list) - getTableConfig(data,true,false) // 获取列表配置 - } setDriverOptions(drivers?.map((driver:DynamicDriverData) => { return { label: driver.title, value: driver.name } }) || []) - } - - const getTableConfig = (data:DynamicTableConfig,tableStatusLoading:boolean, tableStatusError:boolean)=>{ - const {basic,list } = data - const {title,drivers,fields} = basic - let statusColFlag:boolean = true - const newColumn : ProColumns[] = fields?.filter( - (x:DynamicTableField)=>{ - if(x.attr === 'status' && (tableStatusLoading || tableStatusError) && statusColFlag){ - statusColFlag = false - return true - } - return !(x.attr === 'status' && (tableStatusLoading || tableStatusError) && !statusColFlag) - } - ).map( - (x,index)=>{ - // 当状态list还未返回时,页面显示一个状态为loading的table - if (x.attr === 'status' && (tableStatusLoading || tableStatusError)) { - return { - title:(tableStatusLoading || tableStatusError) ? "状态" : x.title, - dataIndex:x.name, - render: ()=>tableStatusLoading ? : '-', - rowSpan:list.length || 1} as ProColumns - } - - return { - title:x.title, - fixed:index === 0 ? 'left' : false, - width:index === 0 ? 150 : undefined, - ...(x.enum?.length > 0 ?{ - onFilter: (value: string, record) => record[x.name].indexOf(value) === 0, - filters:x.enum?.map((x:string)=>{return {text:x, value:x}}), - render:(dom, entity)=> { - return {(entity[x.name] as string)} - }, - }:{}), - dataIndex:x.name, - ellipsis:true - } as ProColumns - }) - setColumns(newColumn) + } const getRender = ()=>{ @@ -225,41 +183,23 @@ export default function IntelligentPluginList(){ }) } - - const getPartitionList = ()=>{ - setPartitionOption([]) - return fetchData>('simple/partitions',{method:'GET'}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setPartitionOption(data.partitions?.map((x:PartitionItem)=>{return { - label:x.name,value:x.id - }})) - return Promise.resolve(data.partitions) - }else{ - message.error(msg || '操作失败') - return Promise.reject(msg || '操作失败') - } - }) - } - const operation:ProColumns[] =[ { title: '操作', key: 'option', - width: 178, + width: 150, fixed:'right', valueType: 'option', render: (_: React.ReactNode, entity: DynamicTableItem) => [ - {openModal('publish',entity)}} btnTitle="发布管理"/>, + {openModal('publish',entity)}} btnTitle={entity.status === '已发布' ? '下线' : '上线'}/>, , - {openDrawer('edit',entity)}} btnTitle="查看"/>, + {openDrawer('edit',entity)}} btnTitle="查看"/>, , - {openModal('delete',entity)}} btnTitle="删除"/>, + {openModal('delete',entity)}} btnTitle="删除"/>, ], } ] const handleClusterChange = (e:string[])=>{ - setCluster(e) setTableHttpReload(true) pageListRef.current?.reload() } @@ -316,27 +256,31 @@ export default function IntelligentPluginList(){ const openModal = async (type:'publish'|'delete', entity?:DynamicTableItem)=>{ let title:string = '' let content:string|React.ReactNode = '' - //console.log(renderSchema,driverOptions,entity) switch (type){ case 'publish':{ - title=`${pluginName}发布管理` - message.loading('正在加载数据') - const {code,data,msg} = await fetchData>(`dynamic/${moduleId}`,{method:'GET',eoParams:{id:entity!.id},eoTransformKeys:['update_time']}) + message.loading('正在操作') + await fetchData>(`dynamic/${moduleId}/${entity!.status === '已发布' ? 'offline':'online'}`, { + method: 'PUT', + eoParams:{id:entity!.id}, + }).then(response => { + const {code, msg} = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || '操作成功!') + return Promise.resolve(true) + } else { + message.error(msg || '操作失败') + return Promise.reject(msg || '操作失败') + } + }).catch((errorInfo)=> Promise.reject(errorInfo)) message.destroy() - if(code === STATUS_CODE.SUCCESS){ - content= - }else{ - message.error(msg || '操作失败') - return - } - break;} + return;} case 'delete': title='删除' content=确定删除成员?此操作无法恢复,确认操作? break; } - const modalInst = modal.confirm({ + modal.confirm({ title, content, onOk:()=>{ @@ -354,52 +298,19 @@ export default function IntelligentPluginList(){ cancelText:'取消', closable:true, icon:<>, - footer:(_, { OkBtn, CancelBtn }) =>{//console.log(_,OkBtn,CancelBtn); + footer:(_, { OkBtn, CancelBtn }) =>{ return ( - <> - {type === 'publish' ? <> - - - - : - <> - - - - } - + <> + + + ); }, }) } - // 渲染配置页时需要用到环境数据,在此合并数据 - const getFinalRender = ()=>{ - Promise.all([getRender(),getPartitionList()]).then(([render, partitions])=>{ - if(!partitions || partitions.length === 0) return - if(partitions.length === 1){ - setRenderSchema({[partitions[0].id]:{ - properties:render, - type:'object' - }}) - }else{ - setRenderSchema(partitions.map((p:EntityItem)=>({ - [p.id]:{ - type: 'void', - 'x-component': 'FormTab.TabPane', - 'x-component-props': { - tab: p.name, - }, - properties:render, - } - }))) - } - }) - } - useEffect(() => { getRender() - getPartitionList() pageListRef.current?.reload() }, [moduleId]); @@ -410,19 +321,11 @@ export default function IntelligentPluginList(){ columns = {[...columns,...operation]} request={(params)=>getIntelligentPluginTableList(params)} addNewBtnTitle={`添加${pluginName}`} - beforeSearchNode={[ x.id)} + options={data.roles?.map((x:{id:string,name:string})=>({label:x.name, value:x.id}))} + onChange={(value)=>{ + changeMemberInfo(value,entity ).then((res)=>{ + if(res) manualReloadTable() + }) + }} + /> + + ) + col.filters = data.roles?.map((x:{id:string,name:string})=>({text:x.name, value:x.id})) + col.onFilter = (value: unknown, record:MemberTableListItem) =>{ + return record.roles ? record.roles?.map((x)=>x.id).indexOf(value as string) !== -1 : false;} + } + } + setColumns(newCol) + return + } else { + message.error(msg || '操作失败') + } + }) + } return ( getMemberList()} addNewBtnTitle={(!memberGroupId ||['unknown','disable'].indexOf(memberGroupId?.toString()) === -1)?"添加账号" : ""} searchPlaceholder="输入用户名、邮箱查找成员" onAddNewBtnClick={() => { openModal('addMember') }} - addNewBtnAccess="system.member.member.add" + addNewBtnAccess="system.organization.member.add" rowSelection={{ // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT], selectedRowKeys, @@ -359,13 +396,13 @@ const MemberList = ()=>{ }), }} onRowClick={handleRowClick} - tableClickAccess="system.member.member.edit" + tableClickAccess="system.organization.member.edit" afterNewBtn={[ - memberGroupId &&, - memberGroupId &&, - memberGroupId !== 'disable' &&, - , - , + memberGroupId &&, + memberGroupId &&, + memberGroupId !== 'disable' &&, + , + , ]} onSearchWordChange={(e) => { setSearchWord(e.target.value) diff --git a/frontend/packages/core/src/pages/member/MemberPage.tsx b/frontend/packages/core/src/pages/member/MemberPage.tsx index 1faa557..0080f47 100644 --- a/frontend/packages/core/src/pages/member/MemberPage.tsx +++ b/frontend/packages/core/src/pages/member/MemberPage.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-01-31 15:00:11 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-07-09 11:01:30 - * @FilePath: \frontend\packages\core\src\pages\member\MemberPage.tsx - */ + import Tree, {DataNode} from "antd/es/tree"; import {Outlet, useNavigate, useParams } from "react-router-dom"; import {Key, useEffect, useMemo, useRef, useState} from "react"; @@ -115,11 +110,11 @@ const MemberPage = ()=>{ const isActionAllowed = (type:'addDep'|'addChild'|'addMember'|'rename'|'delete') => { const actionToPermissionMap = { - 'addDep': 'system.member.department.add', - 'addChild': 'system.member.department.add', - 'addMember': 'system.member.member.add', - 'rename': 'system.member.department.edit', - 'delete': 'system.member.department.delete' + 'addDep': 'system.organization.member.department.add', + 'addChild': 'system.organization.member.department.add', + 'addMember': 'system.organization.member.add', + 'rename': 'system.organization.member.department.edit', + 'delete': 'system.organization.member.department.delete' }; const action = actionToPermissionMap[type] as keyof typeof PERMISSION_DEFINITION[0]; @@ -131,7 +126,7 @@ const MemberPage = ()=>{ entity.id !== '-1' && { key: 'addDep', label: ( - ), @@ -139,7 +134,7 @@ const MemberPage = ()=>{ { key: 'addChild', label: ( - ), @@ -147,7 +142,7 @@ const MemberPage = ()=>{ entity.id !== '-1' && { key: 'addMember', label: ( - ), @@ -155,7 +150,7 @@ const MemberPage = ()=>{ entity.id !== '-1' && { key: 'rename', label: ( - ), @@ -163,7 +158,7 @@ const MemberPage = ()=>{ { key: 'delete', label: ( - ), diff --git a/frontend/packages/core/src/pages/member/Modal/EditMember.tsx b/frontend/packages/core/src/pages/member/Modal/EditMember.tsx index 30c4bb1..7cbc80b 100644 --- a/frontend/packages/core/src/pages/member/Modal/EditMember.tsx +++ b/frontend/packages/core/src/pages/member/Modal/EditMember.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-06-04 08:54:24 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-04 11:55:27 - * @FilePath: \frontend\packages\core\src\pages\member\Modal\EditMember.tsx - */ + import { App, Form, Input, TreeSelect } from "antd"; import { forwardRef, useState, useImperativeHandle, useEffect } from "react"; import WithPermission from "@common/components/aoplatform/WithPermission"; diff --git a/frontend/packages/core/src/pages/member/Modal/RenameDepModal.tsx b/frontend/packages/core/src/pages/member/Modal/RenameDepModal.tsx index 0d6c4a3..91d3710 100644 --- a/frontend/packages/core/src/pages/member/Modal/RenameDepModal.tsx +++ b/frontend/packages/core/src/pages/member/Modal/RenameDepModal.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-05-27 15:41:03 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-05-31 17:53:43 - * @FilePath: \frontend\packages\core\src\pages\member\Modal\RenameDepModal.tsx - */ + import { App, Form, Input } from "antd"; import { forwardRef, useImperativeHandle, useEffect } from "react"; import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; diff --git a/frontend/packages/core/src/pages/partitions/PartitionInsideCert.tsx b/frontend/packages/core/src/pages/partitions/PartitionInsideCert.tsx index b4fb704..89611d7 100644 --- a/frontend/packages/core/src/pages/partitions/PartitionInsideCert.tsx +++ b/frontend/packages/core/src/pages/partitions/PartitionInsideCert.tsx @@ -19,7 +19,7 @@ import { PERMISSION_DEFINITION } from "@common/const/permissions.ts"; const CertConfigModal = forwardRef((props, ref) => { const { message } = App.useApp() - const {type,entity,partitionId} = props + const {type,entity} = props const [form] = Form.useForm(); const [, forceUpdate] = useState(null); const {fetchData} = useFetch() @@ -31,7 +31,7 @@ const CertConfigModal = forwardRef>('partition/certificate',{method:type === 'add'? 'POST' : 'PUT',eoBody:(body), eoParams:type === 'add' ? {partition:partitionId}:{id:entity!.id}}).then(response=>{ + fetchData>('certificate',{method:type === 'add'? 'POST' : 'PUT',eoBody:(body), eoParams:type === 'add' ? {}:{id:entity!.id}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -58,7 +58,7 @@ const CertConfigModal = forwardRef + return (
{ const { modal,message } = App.useApp() const [init, setInit] = useState(true) const {fetchData} = useFetch() - const { partitionId } = useParams() const addRef = useRef(null) const editRef = useRef(null) const pageListRef = useRef(null); @@ -158,7 +157,7 @@ const PartitionInsideCert:FC = ()=>{ const {accessData} = useGlobalContext() const getPartitionCertList =(): Promise<{ data: PartitionCertTableListItem[], success: boolean }>=> { - return fetchData>('partition/certificates',{method:'GET',eoParams:{partition:partitionId},eoTransformKeys:['partition_id','update_time','not_before','not_after']}).then(response=>{ + return fetchData>('certificates',{method:'GET',eoTransformKeys:['partition_id','update_time','not_before','not_after']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ setInit((prev)=>prev ? false : prev) @@ -174,7 +173,7 @@ const PartitionInsideCert:FC = ()=>{ const deleteCert = (entity:PartitionCertTableListItem)=>{ return new Promise((resolve, reject)=>{ - fetchData>('partition/certificate',{method:'DELETE',eoParams:{id:entity.id,partition:partitionId}}).then(response=>{ + fetchData>('certificate',{method:'DELETE',eoParams:{id:entity.id}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -193,15 +192,15 @@ const PartitionInsideCert:FC = ()=>{ switch (type){ case 'add': title='添加证书' - content= + content= break; case 'edit':{ title='修改证书' message.loading('正在加载数据') - const {code,data,msg} = await fetchData>('partition/certificate',{method:'GET',eoParams:{id:entity!.id}}) + const {code,data,msg} = await fetchData>('certificate',{method:'GET',eoParams:{id:entity!.id}}) message.destroy() if(code === STATUS_CODE.SUCCESS){ - content= + content= }else{ message.error(msg || '操作失败') return @@ -229,7 +228,7 @@ const PartitionInsideCert:FC = ()=>{ width:600, okText:'确认', okButtonProps:{ - disabled : !checkAccess( `system.partition.cert.${type}` as keyof typeof PERMISSION_DEFINITION[0], accessData) + disabled : !checkAccess( `system.devops.ssl_certificate.${type}` as keyof typeof PERMISSION_DEFINITION[0], accessData) }, cancelText:'取消', closable:true, @@ -250,20 +249,19 @@ const PartitionInsideCert:FC = ()=>{ fixed:'right', valueType: 'option', render: (_: React.ReactNode, entity: PartitionCertTableListItem) => [ - {openModal('edit',entity)}} btnTitle="编辑"/>, + {openModal('edit',entity)}} btnTitle="编辑"/>, , - {openModal('delete',entity)}} btnTitle="删除"/>] + {openModal('delete',entity)}} btnTitle="删除"/>] } ] useEffect(() => { setBreadcrumb([ - {title:部署管理}, {title:'证书管理'} ]) getMemberList() manualReloadTable() - }, [partitionId]); + }, []); const getMemberList = async ()=>{ setMemberValueEnum({}) @@ -291,10 +289,10 @@ const PartitionInsideCert:FC = ()=>{ request={()=>getPartitionCertList()} showPagination={false} addNewBtnTitle="添加证书" - addNewBtnAccess="system.partition.cert.add" + addNewBtnAccess="system.devops.ssl_certificate.add" onAddNewBtnClick={()=>{openModal('add')}} onRowClick={(row:PartitionCertTableListItem)=>openModal('edit',row)} - tableClickAccess="system.partition.cert.edit" + tableClickAccess="system.devops.ssl_certificate.edit" /> ) diff --git a/frontend/packages/core/src/pages/partitions/PartitionInsideCluster.tsx b/frontend/packages/core/src/pages/partitions/PartitionInsideCluster.tsx index 0f1b6bb..f4b481c 100644 --- a/frontend/packages/core/src/pages/partitions/PartitionInsideCluster.tsx +++ b/frontend/packages/core/src/pages/partitions/PartitionInsideCluster.tsx @@ -1,10 +1,8 @@ import { FC, useEffect, useRef, useState} from "react"; -import {Link, useParams} from "react-router-dom"; import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx"; import {App, Button, Col, Collapse, Empty, Row, Spin, Tag} from "antd"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import {useFetch} from "@common/hooks/http.ts"; -import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; import { NodeModalHandle, PartitionClusterNodeTableListItem } from "../../const/partitions/types.ts"; import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; @@ -16,7 +14,6 @@ const PartitionInsideCluster:FC = ()=> { const {setBreadcrumb} = useBreadcrumb() const {modal, message} = App.useApp() const {fetchData} = useFetch() - const {partitionId} = useParams(); const [nodesList, setNodesList] = useState() const [loading, setLoading] = useState(false) const {accessData} = useGlobalContext() @@ -26,7 +23,7 @@ const PartitionInsideCluster:FC = ()=> { const getPartitionClusterInfo = () => { setNodesList([]) setLoading(true) - return fetchData>('partition/cluster/nodes', {method: 'GET', eoParams: {partition: partitionId},eoTransformKeys:['manager_address','service_address','peer_address']}).then(response => { + return fetchData>('cluster/nodes', {method: 'GET',eoTransformKeys:['manager_address','service_address','peer_address']}).then(response => { const {code, data, msg} = response if (code === STATUS_CODE.SUCCESS) { setNodesList(data.nodes) @@ -42,14 +39,13 @@ const PartitionInsideCluster:FC = ()=> { } const openModal = async (type:'editNode')=>{ - let title:string = '' let content:string|React.ReactNode = '' switch(type){ case 'editNode': { title = '重置配置' - content = + content = } break; } @@ -66,7 +62,7 @@ const PartitionInsideCluster:FC = ()=> { width:type === 'editNode' ? 900 : 600, okText:'确认', okButtonProps:{ - disabled:!checkAccess('system.partition.cluster.edit', accessData) + disabled:!checkAccess('system.devops.cluster.edit', accessData) }, cancelText:'取消', closable:true, @@ -76,7 +72,6 @@ const PartitionInsideCluster:FC = ()=> { useEffect(() => { setBreadcrumb([ - {title: 部署管理}, {title: '集群'} ]) getPartitionClusterInfo() @@ -85,7 +80,7 @@ const PartitionInsideCluster:FC = ()=> { return ( <>
-
+
} spinning={loading}>
{nodesList && nodesList.length > 0 ? diff --git a/frontend/packages/core/src/pages/partitions/PartitionInsideClusterNode.tsx b/frontend/packages/core/src/pages/partitions/PartitionInsideClusterNode.tsx index f216c29..81eb676 100644 --- a/frontend/packages/core/src/pages/partitions/PartitionInsideClusterNode.tsx +++ b/frontend/packages/core/src/pages/partitions/PartitionInsideClusterNode.tsx @@ -1,19 +1,13 @@ -/* - * @Date: 2024-04-19 15:22:46 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-06 17:58:01 - * @FilePath: \frontend\packages\core\src\pages\partitions\PartitionInsideClusterNode.tsx - */ + import {forwardRef, useImperativeHandle, useState} from "react"; import {App, Button, Form, Input, Table} from "antd"; import {useFetch} from "@common/hooks/http.ts"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import { NODE_MODAL_COLUMNS } from "../../const/partitions/const.tsx"; -import { NodeModalHandle, NodeModalProps, PartitionClusterNodeModalTableListItem, PartitionClusterNodeTableListItem, NodeModalFieldType, ClusterConfigHandle, PartitionClusterFieldType } from "../../const/partitions/types.ts"; +import { NodeModalHandle, PartitionClusterNodeModalTableListItem, PartitionClusterNodeTableListItem, NodeModalFieldType } from "../../const/partitions/types.ts"; import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; -export const ClusterNodeModal = forwardRef((props,ref)=>{ - const {partitionId} = props +export const ClusterNodeModal = forwardRef((_,ref)=>{ const { message } = App.useApp() const [form] = Form.useForm(); const [dataSource,setDataSource] = useState([]) @@ -23,7 +17,7 @@ export const ClusterNodeModal = forwardRef((prop setDataSource([]) return new Promise((resolve, reject)=>{ form.validateFields().then((value)=> { - fetchData>('partition/cluster/check', {method: 'POST', eoBody: (value),eoTransformKeys:['manager_address','service_address','peer_address']}).then(response => { + fetchData>('cluster/check', {method: 'POST', eoBody: (value),eoTransformKeys:['manager_address','service_address','peer_address']}).then(response => { const {code,data, msg} = response if (code === STATUS_CODE.SUCCESS) { message.success(msg || '操作成功') @@ -38,7 +32,7 @@ export const ClusterNodeModal = forwardRef((prop const save:()=>Promise = ()=>{ return new Promise((resolve, reject)=>{ form.validateFields().then(()=> { - fetchData>('partition/cluster/reset',{method:'PUT' ,eoBody:({managerAddress:form.getFieldValue('address')}), eoTransformKeys:['managerAddress'],eoParams:{partition:partitionId}}).then(response=>{ + fetchData>('cluster/reset',{method:'PUT' ,eoBody:({managerAddress:form.getFieldValue('address')}), eoTransformKeys:['managerAddress']}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -58,7 +52,7 @@ export const ClusterNodeModal = forwardRef((prop ) return ( - + ((prop autoComplete="off" name="partitionInsideClusterNode" > -
- - label="集群地址" - name="address" - className="p-0 bg-transparent rounded-none border-none w-[calc(100%-72px)]" - rules={[{ required: true, message: '必填项' }]} - > - test()}/> - -
- +
+ + label="集群地址" + name="address" + className="p-0 bg-transparent rounded-none border-none flex-1" + rules={[{ required: true, message: '必填项' }]} + > + test()}/> + +
+
{ diff --git a/frontend/packages/core/src/pages/resourcesettings/ResourceSettings.tsx b/frontend/packages/core/src/pages/resourcesettings/ResourceSettings.tsx index 7d9429c..8a5706e 100644 --- a/frontend/packages/core/src/pages/resourcesettings/ResourceSettings.tsx +++ b/frontend/packages/core/src/pages/resourcesettings/ResourceSettings.tsx @@ -1,20 +1,13 @@ -/* - * @Date: 2024-05-15 14:59:07 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-07 15:57:31 - * @FilePath: \frontend\packages\core\src\pages\resourcesettings\ResourceSettings.tsx - */ + import { Menu, MenuProps, Skeleton, message } from "antd"; import { Link, Outlet, useNavigate, useParams } from "react-router-dom"; import InsidePage from "@common/components/aoplatform/InsidePage"; import { useEffect, useState } from "react"; import { BasicResponse, STATUS_CODE } from "@common/const/const"; -import { DynamicMenuItem, PartitionItem } from "@common/const/type"; +import { DynamicMenuItem } from "@common/const/type"; import { useFetch } from "@common/hooks/http"; import { getItem } from "@common/utils/navigation"; import { RouterParams } from "@core/components/aoplatform/RenderRoutes"; -import { DefaultOptionType } from "antd/es/select"; -import ResourceSettingsInstruction from "./ResourceSettingsInstruction"; const LogSettings = ()=>{ const {moduleId} = useParams(); @@ -23,24 +16,6 @@ const LogSettings = ()=>{ const {fetchData} = useFetch() const [loading, setLoading] = useState(true) const navigateTo = useNavigate() - const [partitionOptions, setPartitionOption] = useState([]) - - const getPartitionList = ()=>{ - setPartitionOption([]) - return fetchData>('simple/partitions',{method:'GET'}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setPartitionOption(data.partitions?.map((x:PartitionItem)=>{return { - label:x.name,value:x.id - }})) - return Promise.resolve(data.partitions) - }else{ - message.error(msg || '操作失败') - return Promise.reject(msg || '操作失败') - } - }) - } - const getDynamicMenuList = ()=>{ setLoading(true) @@ -76,33 +51,30 @@ const LogSettings = ()=>{ useEffect(()=>{ setLoading(true) - Promise.all([getPartitionList(),getDynamicMenuList()]).finally(()=>setLoading(false)) + getDynamicMenuList() },[]) return ( <> - {loading ? null : partitionOptions && partitionOptions.length > 0 ? - -
- -
- + +
+ +
+ +
-
- : - - } + ) diff --git a/frontend/packages/core/src/pages/resourcesettings/ResourceSettingsInstruction.tsx b/frontend/packages/core/src/pages/resourcesettings/ResourceSettingsInstruction.tsx index 897c064..b1cd0af 100644 --- a/frontend/packages/core/src/pages/resourcesettings/ResourceSettingsInstruction.tsx +++ b/frontend/packages/core/src/pages/resourcesettings/ResourceSettingsInstruction.tsx @@ -2,12 +2,6 @@ import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"; import { useEffect } from "react"; import { Link } from "react-router-dom"; -/* - * @Date: 2024-03-25 10:35:24 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-07 16:24:16 - * @FilePath: \frontend\packages\core\src\pages\resourcesettings\ResourceSettingsInstruction.tsx - */ export default function ResourceSettingsInstruction() { const { setBreadcrumb } = useBreadcrumb() @@ -21,16 +15,16 @@ export default function ResourceSettingsInstruction() { return (
-

环境配置并开启资源插件

-

资源插件用于增强网关的功能和性能。在启用资源类插件之前,请确保已经配置了环境。例如,Redis插件可以提高缓存和速率限制的性能,配置完成后,可以使用Redis作为缓存数据库。

+

集群配置并开启资源插件

+

资源插件用于增强网关的功能和性能。在启用资源类插件之前,请确保已经配置了集群。例如,Redis插件可以提高缓存和速率限制的性能,配置完成后,可以使用Redis作为缓存数据库。

{/*

更多配置及关联问题,请点击帮助中心 {/* 查看更多

*/}
-

环境配置

-

新增环境的名称、描述和其他相关属性,并设置该环境内的集群地址,以确保插件能够正确识别和连接到这些集群

-

添加环境/配置已有环境的集群地址

+

集群配置

+

新增集群地址、描述和其他相关属性,以确保插件能够正确识别和连接到集群

+

配置集群地址

diff --git a/frontend/packages/core/src/pages/role/RoleConfig.tsx b/frontend/packages/core/src/pages/role/RoleConfig.tsx new file mode 100644 index 0000000..8896dad --- /dev/null +++ b/frontend/packages/core/src/pages/role/RoleConfig.tsx @@ -0,0 +1,244 @@ +import { useEffect, useMemo, useState} from "react"; +import {App, Button, Checkbox, Collapse, Form, GetProp, Input} from "antd"; +import {useFetch} from "@common/hooks/http.ts"; +import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; +import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; +import { useNavigate, useParams } from "react-router-dom"; +import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx"; +import { LeftOutlined } from "@ant-design/icons"; + +type PermissionItem = { + name:string + cname:string + value:string +} + +type PermissionClassify = PermissionItem & {children : ( PermissionItem & {dependents:string[]})[]} + +type RolePermissionItem = PermissionItem & { + children:PermissionClassify[]} + + +type DependenciesMapType = Map + +type PermissionCollapseProps = { + id?: string; + value?: string[]; + onChange?: (value:string[]) => void; + permissionTemplate:RolePermissionItem[] + dependenciesMap?: DependenciesMapType +} + +type PermissionInfo = { + permit: string[] + description: string + update_time: string + create_time: string + name: string +} + +const PermissionContent = ({permits,onChange,value=[],id,dependenciesMap}:{permits:PermissionClassify[],dependenciesMap:DependenciesMapType,value:string[],id:string, onChange?: (value:string[]) => void;})=>{ + + const onSingleCheckboxChange: GetProp = (e) => { + if(e.target.checked){ + onChange?.(Array.from(new Set([...value, e.target.id, ...(dependenciesMap?.get(e.target.id!)?.dependents || [])] as string[]))) + }else{ + const cancelValue = [...dependenciesMap?.get(e.target.id!)?.control || [], e.target.id] + onChange?.(value.filter(x=>!cancelValue.includes(x))) + } + }; + + return ( +
+ { + permits.map((item:PermissionClassify)=>( + <> +
+ {item.cname !== '' &&

{item.cname}

} +
+ {item.children.map(x=> 0 && value.indexOf(x.value)>-1} onChange={onSingleCheckboxChange}>{x.cname})} +
+
+ + )) + }
+ ) +} + // 自定义表单控件 + const PermissionCollapse:React.FC = (props)=>{ + const { id, value = [], onChange,permissionTemplate ,dependenciesMap} = props; + const [openCollapses, setOpenCollapses] = useState([]) + + const items = useMemo(()=>{ + const generatePermissionItem = (permissionItem:RolePermissionItem[])=> permissionItem.map((item:RolePermissionItem)=>({ + key:item.name, + label:item.cname, + children:onChange?.(e)} id={id!} dependenciesMap={dependenciesMap!}/> + })) + return permissionTemplate && permissionTemplate.length > 0 ? generatePermissionItem(permissionTemplate) : [] + },[permissionTemplate,value]) + + useEffect(()=>{ + permissionTemplate && setOpenCollapses(permissionTemplate?.map(x=>x.name)) + },[permissionTemplate]) + + const onCollapseChange = (keys: string | string[]) => { + setOpenCollapses(keys as string[]) + }; + + return + } + + +const RoleConfig = ()=>{ + const { message } = App.useApp() + const [form] = Form.useForm(); + // const [formData, dispatch] = useReducer(formReducer, {}); + // const [dataSource,setDataSource] = useState([]) + const {fetchData} = useFetch() + const navigateTo = useNavigate() + const { roleType, roleId} = useParams() + const [permissionTemplate, setPermissionTemplate] = useState() + const [dependenciesMap, setDependenciesMap] = useState() + const APP_MODE = import.meta.env.VITE_APP_MODE; + + + const generateDependenciesMap = (data:RolePermissionItem[])=>{ + const map = new Map() + data.forEach((item:RolePermissionItem)=>{ + item.children.forEach((child:PermissionClassify)=>{ + child.children.forEach((permission:PermissionItem & {dependents:string[]})=>{ + + if (permission.dependents && permission.dependents.length > 0) { + // 获取当前权限的依赖 + const currentDependents = map.get(permission.value); + if (currentDependents) { + currentDependents.dependents.push(...permission.dependents); + } else { + map.set(permission.value, { dependents: [...permission.dependents], control: [] }); + } + + // 更新依赖项的控制项 + permission.dependents.forEach((dependent: string) => { + const dependentEntry = map.get(dependent); + if (dependentEntry) { + dependentEntry.control.push(permission.value); + } else { + map.set(dependent, { dependents: [], control: [permission.value] }); + } + }); + } + }) + }) + }) + setDependenciesMap(map) + } + + const generateNewPermit:(data:RolePermissionItem[])=>RolePermissionItem[] = (data:RolePermissionItem[]) =>{ + return data.map((item:RolePermissionItem)=>({ + ...item,children:item.children.map((child:PermissionClassify)=>({ + ...child, + children:child.children.map((permission:PermissionItem & {dependents:string[]})=>({ + ...permission, value:`${roleType}.${item.value}.${child.value}.${permission.value}` + })) + })) + })) + } + + const getPermissionTemplate = ()=>{ + return fetchData>(`${roleType}/role/template`,{method:'GET'}).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + const newPermits = generateNewPermit(data.permits) + generateDependenciesMap(newPermits) + setPermissionTemplate(newPermits) + console.log(newPermits) + }else{ + console.log(message) + message.error(msg || '获取权限模板失败') + } + }) + } + + const getPermissionInfo = ()=>{ + fetchData>(`${roleType}/role`,{method:'GET',eoParams:{role:roleId}}).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || '操作成功!') + form.setFieldsValue({name:data.role.name,permits:data.role.permit}) + return Promise.resolve(true) + }else{ + message.error(msg || '操作失败') + return Promise.reject(msg || '操作失败') + } + }).catch((errInfo)=>Promise.reject(errInfo)) + } + + useEffect(() => { + getPermissionTemplate() + form.setFieldsValue({name:'',permits:[]}) + if(roleId){ + getPermissionInfo() + } + }, []); + + const onFinish =async() => { + const body = await form.validateFields() + + return fetchData>(`${roleType}/role`,{method:roleId === undefined? 'POST' : 'PUT',eoBody:({...body}),...(roleId !== undefined?{eoParams:{role:roleId}}:{})}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || '操作成功!') + return Promise.resolve(true) + }else{ + message.error(msg || '操作失败') + return Promise.reject(msg || '操作失败') + } + }).catch((errInfo)=>Promise.reject(errInfo)) + }; + + return (
+ navigateTo(-1)}> 返回 + + +
+ + + + + + + + {APP_MODE === 'pro' &&
+ + + + +
} +
+ +
+
) +} +export default RoleConfig \ No newline at end of file diff --git a/frontend/packages/core/src/pages/role/RoleList.tsx b/frontend/packages/core/src/pages/role/RoleList.tsx index 940fa98..9d92b96 100644 --- a/frontend/packages/core/src/pages/role/RoleList.tsx +++ b/frontend/packages/core/src/pages/role/RoleList.tsx @@ -1,98 +1,29 @@ -import {Alert, App, Divider, Form, Input} from "antd"; +import { App, Divider} from "antd"; import PageList from "@common/components/aoplatform/PageList.tsx"; -import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from "react"; +import { useEffect, useRef,} from "react"; import {ActionType, ProColumns} from "@ant-design/pro-components"; import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import {useFetch} from "@common/hooks/http.ts"; import { ROLE_TABLE_COLUMNS } from "../../const/role/const.tsx"; -import { RoleModalContentHandle, RoleModalContentProps, RoleTableListItem } from "../../const/role/type.ts"; -import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission.tsx"; import { PERMISSION_DEFINITION } from "@common/const/permissions.ts"; import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; import { checkAccess } from "@common/utils/permission.ts"; +import { useNavigate } from "react-router-dom"; +import { RoleTableListItem } from "@core/const/role/type.ts"; -const RoleModalContent = forwardRef((props, ref)=>{ - const { message } = App.useApp() - const {type,entity} = props - const [form] = Form.useForm(); - const {fetchData} = useFetch() - const save:()=>Promise = ()=>{ - return new Promise((resolve, reject)=>{ - form.validateFields().then((value)=>{ - fetchData>(type === 'add'? 'manage/role':'manage/role',{method:type === 'add'? 'POST' : 'PUT',eoBody:({name:value.name}),eoParams:{id:value!.id}}).then(response=>{ - const {code,msg} = response - if(code === STATUS_CODE.SUCCESS){ - message.success(msg || '操作成功!') - resolve(true) - }else{ - message.error(msg || '操作失败') - reject(msg || '操作失败') - } - }).catch((errorInfo)=> reject(errorInfo)) - }).catch((errorInfo)=> reject(errorInfo)) - }) - } - - useImperativeHandle(ref, ()=>({ - save - }) - ) - - useEffect(() => { - if(type === 'edit'){ - form.setFieldsValue(entity) - } - }, []); - - return ( - -
- - {type === 'edit' && - label="ID" - name="id" - hidden - rules={[{ required: true, message: '必填项' ,whitespace:true }]} - > - - } - - - label="角色名称" - name="name" - rules={[{ required: true, message: '必填项' ,whitespace:true }]} - > - - -
) -}) - const RoleList = ()=>{ - // const [searchWord, setSearchWord] = useState('') const { modal,message } = App.useApp() const { setBreadcrumb } = useBreadcrumb() - // const [confirmLoading, setConfirmLoading] = useState(false); const {fetchData} = useFetch() - const [init, setInit] = useState(true) const pageListRef = useRef(null); - const addRef = useRef(null) - const editRef = useRef(null) const {accessData} = useGlobalContext() + const navigateTo = useNavigate() - const operation:ProColumns[] =[ + const operation:(type:string)=>ProColumns[] =(type:string)=>[ + // TODO 开源版隐藏操作 { title: '操作', key: 'option', @@ -100,18 +31,18 @@ const RoleList = ()=>{ fixed:'right', valueType: 'option', render: (_: React.ReactNode, entity: RoleTableListItem) => [ - {openModal('edit',entity)}} btnTitle="编辑"/>, - , - {openModal('delete',entity)}} btnTitle="删除"/>, + {navigateTo(`/role/${type}/config/${entity.id}`)}} btnTitle="查看"/>, + // {navigateTo(`/role/${type}/config/${entity.id}`)}} btnTitle="编辑"/>, + // , + // {openModal(type as 'system'|'team','delete',entity)}} btnTitle="删除"/>, ], } ] - const getRoleList = ()=>{ - return fetchData>('manage/roles',{method:'GET'}).then(response=>{ + const getRoleList = (group:'team'|'system')=>{ + return fetchData>(`${group}/roles`,{method:'GET'}).then(response=>{ const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setInit((prev)=>prev ? false : prev) + if(code === STATUS_CODE.SUCCESS){ return {data:data.roles, success: true} }else{ message.error(msg || '操作失败') @@ -141,25 +72,17 @@ const RoleList = ()=>{ pageListRef.current?.reload() }; - const isActionAllowed = (type:'add'|'edit'|'delete') => { + const isActionAllowed = (accessType:'system'|'team', type:'add'|'edit'|'delete') => { - const permission = `system.role.self.${type}` as keyof typeof PERMISSION_DEFINITION[0] ; + const permission = `system.organization.role.${accessType}.${type}` as keyof typeof PERMISSION_DEFINITION[0] ; return !checkAccess(permission, accessData); }; - const openModal = (type:'add'|'edit'|'delete',entity?:RoleTableListItem)=>{ + const openModal = (accessType:'system'|'team', type:'delete',entity?:RoleTableListItem)=>{ let title:string = '' let content:string|React.ReactNode = '' switch (type){ - case 'add': - title='添加角色' - content= - break; - case 'edit': - title='编辑角色' - content= - break; case 'delete': title='删除' content='该数据删除后将无法找回,请确认是否删除?' @@ -171,10 +94,6 @@ const RoleList = ()=>{ content, onOk:()=>{ switch (type){ - case 'add': - return addRef.current?.save().then((res)=>{if(res === true) manualReloadTable()}) - case 'edit': - return editRef.current?.save().then((res)=>{if(res === true) manualReloadTable()}) case 'delete': return deleteRole(entity!).then((res)=>{if(res === true) manualReloadTable()}) } @@ -182,7 +101,7 @@ const RoleList = ()=>{ width:600, okText:'确认', okButtonProps:{ - disabled:isActionAllowed(type) + disabled:isActionAllowed(accessType, type) }, cancelText:'取消', closable:true, @@ -193,28 +112,44 @@ const RoleList = ()=>{ useEffect(() => { setBreadcrumb([ { - title: '自定义角色'}]) + title: '角色'}]) }, []); return (<> - -
+
+

系统级别角色

+ [], ...operation('system')]} + request={()=>getRoleList('system')} + addNewBtnTitle="添加角色" + showPagination={false} + onAddNewBtnClick={() => { + navigateTo(`/role/system/config`) + }} + noScroll={true} + addNewBtnAccess="system.organization.role.system.add" + onRowClick={(row:RoleTableListItem)=> navigateTo(`/role/system/config/${row.id}`)} + tableClickAccess="system.organization.role.system.edit" + /> +

团队级别角色

getRoleList()} + tableClass="role_table pl-btnbase" + columns={[...ROLE_TABLE_COLUMNS as ProColumns[], ...operation('team')]} + request={()=>getRoleList('team')} + showPagination={false} addNewBtnTitle="添加角色" - // searchPlaceholder="输入角色名称进行搜索" onAddNewBtnClick={() => { - openModal('add') + navigateTo(`/role/team/config`) }} - addNewBtnAccess="system.role.self.add" - // onSearchWordChange={(e) => { - // setSearchWord(e.target.value) - // }} - onRowClick={(row:RoleTableListItem)=>openModal('edit',row)} - tableClickAccess="system.role.self.edit" + noScroll={true} + addNewBtnAccess="system.organization.role.team.add" + onRowClick={(row:RoleTableListItem)=> navigateTo(`/role/team/config/${row.id}`)} + tableClickAccess="system.organization.role.team.edit" />
) diff --git a/frontend/packages/core/src/pages/serviceCategory/ServiceCategory.tsx b/frontend/packages/core/src/pages/serviceCategory/ServiceCategory.tsx index eceb61c..627c4ec 100644 --- a/frontend/packages/core/src/pages/serviceCategory/ServiceCategory.tsx +++ b/frontend/packages/core/src/pages/serviceCategory/ServiceCategory.tsx @@ -11,8 +11,9 @@ import { Key, useEffect, useMemo, useRef, useState } from "react"; import { ServiceHubCategoryConfig } from "./ServiceHubCategoryConfig"; import { useGlobalContext } from "@common/contexts/GlobalStateContext"; import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"; -import { LoadingOutlined, PlusOutlined } from "@ant-design/icons"; +import { LoadingOutlined } from "@ant-design/icons"; import { cloneDeep } from "lodash-es"; +import { Icon } from "@iconify/react/dist/iconify.js"; export default function ServiceCategory(){ const [gData, setGData] = useState([]); @@ -88,7 +89,7 @@ export default function ServiceCategory(){ { key: 'addChildCate', label: ( - ), @@ -96,7 +97,7 @@ export default function ServiceCategory(){ { key: 'renameCate', label: ( - ), @@ -104,7 +105,7 @@ export default function ServiceCategory(){ { key: 'delete', label: ( - ), @@ -144,7 +145,7 @@ export default function ServiceCategory(){ }; const action = actionToPermissionMap[type]; - const permission :keyof typeof PERMISSION_DEFINITION[0]= `system.serviceHub.category.${action}`; + const permission :keyof typeof PERMISSION_DEFINITION[0]= `system.api_market.service_classification.${action}`; return !checkAccess(permission, accessData); }; @@ -260,7 +261,9 @@ export default function ServiceCategory(){ onDrop={onDrop} treeData={treeData} /> - + + +
diff --git a/frontend/packages/core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx b/frontend/packages/core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx index cc76fe4..b4e31ea 100644 --- a/frontend/packages/core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx +++ b/frontend/packages/core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx @@ -68,7 +68,7 @@ export const ServiceHubCategoryConfig = forwardRef +
((_,ref) => { const { message,modal } = App.useApp() - const { teamId, systemId } = useParams(); + const { teamId, serviceId } = useParams(); const [onEdit, setOnEdit] = useState(!!teamId) const [form] = Form.useForm(); const {fetchData} = useFetch() const [teamOptionList, setTeamOptionList] = useState() - const [memberOptionList, setMemberOptionList] = useState() const navigate = useNavigate(); - const [partitionOption,setPartitionOption] = useState([]) - const [currentTeamId, setCurrentTeamId] = useState(teamId || '') const {setBreadcrumb} = useBreadcrumb() - const { setSystemInfo,setPartitionList} = useSystemContext() + const { setSystemInfo} = useSystemContext() + const [showClassify, setShowClassify] = useState() + const [imageBase64, setImageBase64] = useState(null); + const [tagOptionList, setTagOptionList] = useState([]) + const [serviceClassifyOptionList, setServiceClassifyOptionList] = useState() + const [uploadLoading, setUploadLoading] = useState(false) useImperativeHandle(ref, () => ({ save:onFinish })); + const beforeUpload = async (file: RcFile) => { + if (!['image/png', 'image/jpeg', 'image/svg+xml'].includes(file.type)) { + alert('只允许上传PNG、JPG或SVG格式的图片'); + return false; + } + + if (file.size > MAX_SIZE) { + try { + const compressedBase64 = await compressImage(file, MAX_SIZE); + setImageBase64(`data:${file.type};base64,${compressedBase64}`); + form.setFieldValue('logo', `data:${file.type};base64,${compressedBase64}`); + } catch (error) { + console.error('压缩图片时出错', error); + } + } else { + const reader = new FileReader(); + reader.onload = (e: ProgressEvent) => { + setImageBase64(e.target?.result as string); + form.setFieldValue('logo', e.target?.result); + }; + reader.readAsDataURL(file); + } + return false; + }; + + + const handleChange: UploadProps['onChange'] = (info: UploadChangeParam) => { + if (info.file.status === 'uploading') { + setUploadLoading(true); + return; + } + if (info.file.status === 'done') { + getImgBase64(info.file.originFileObj as RcFile, () => { + setUploadLoading(false); + }); + } + if (info.fileList.length === 0) { + form.setFieldValue( "logo", null ); + } + }; + + const uploadButton = ( +
+ {uploadLoading ? : } +
+ ); + + const getTagAndServiceClassifyList = ()=>{ + setTagOptionList([]) + setServiceClassifyOptionList([]) + fetchData>('catalogues',{method:'GET'}).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + setTagOptionList(data.tags?.map((x:TagType)=>{return { + label:x.name, value:x.name + }})||[]) + setServiceClassifyOptionList(data.catalogues) + + }else{ + message.error(msg || '操作失败') + } + }) + } + // 获取表单默认值 const getSystemInfo = () => { - fetchData>('project/info',{method:'GET',eoParams:{project:systemId},eoTransformKeys:['team_id']}).then(response=>{ + fetchData>('service/info',{method:'GET',eoParams:{team:teamId, service:serviceId},eoTransformKeys:['team_id','service_type']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ - setTimeout(()=>{form.setFieldsValue({...data.project,organization:data.project.organization.id,team:data.project.team.id,master:data.project.master.id,partition:data.project.partition?.map((x:EntityItem)=>x.id)})},0) - setCurrentTeamId(data.project.team.id) + setTimeout(()=>{ + form.setFieldsValue({ + ...data.service, + team:data.service.team.id, + catalogue:data.service.catalogue?.id, + logoFile:[ + { + uid: '-1', // 文件唯一标识 + name: 'image.png', // 文件名 + status: 'done', // 状态有:uploading, done, error, removed + url: data.service?.logo || '', // 图片 Base64 数据 + } + ] + }) + console.log({ + ...data.service, + team:data.service.team.id, + catalogue:data.service.catalogue?.id, + logoFile:[ + { + uid: '-1', // 文件唯一标识 + name: 'image.png', // 文件名 + status: 'done', // 状态有:uploading, done, error, removed + url: data.service?.logo || '', // 图片 Base64 数据 + } + ] + }) + setImageBase64(data.service.logo) + setShowClassify(data.service.serviceType === 'public') + },0) }else{ message.error(msg || '操作失败') } }) }; - useEffect(()=>{ - const newPartitions = (teamOptionList as (Array<(DefaultOptionType & { id: string; availablePartitions: EntityItem[] })>) )?.find(x => x.id === currentTeamId)?.availablePartitions?.map((p: EntityItem) => ({ label: p.name, value: p.id })) || [] - setPartitionOption(newPartitions) - if(!newPartitions || newPartitions.length === 0){ - form.setFieldValue('partition',[]) - return - } - const selectedPartitions =form.getFieldValue('partition') - if(selectedPartitions && selectedPartitions?.length > 0 ){ - form.setFieldValue('partition',newPartitions.filter(x=> selectedPartitions.indexOf(x.value) !== -1).map(x=>x.value)) - } - },[currentTeamId,teamOptionList]) - const onFinish:()=>Promise = () => { return form.validateFields().then((value)=>{ - return fetchData>(systemId === undefined? 'team/project':'project/info',{method:systemId === undefined? 'POST' : 'PUT',eoParams: {...(systemId === undefined ? {team:value.team} :{project:systemId})},eoBody:({...value,prefix:value.prefix?.trim()})}).then(response=>{ + return fetchData>(serviceId === undefined? 'team/service':'service/info',{method:serviceId === undefined? 'POST' : 'PUT',eoParams: {...(serviceId === undefined ? {team:value.team} :{service:serviceId,team:teamId})},eoBody:({...value,prefix:value.prefix?.trim()}), eoTransformKeys:['serviceType']},).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') - setSystemInfo(data.project) - setPartitionList(data.project.partition) + setSystemInfo(data.service) return Promise.resolve(true) }else{ message.error(msg || '操作失败') @@ -76,23 +166,6 @@ const SystemConfig = forwardRef((_,ref) => { }) }; - useEffect(()=>{ - currentTeamId && getMemberOptionList() - },[currentTeamId]) - - const getMemberOptionList = ()=>{ - setMemberOptionList([]) - fetchData>('team/members/simple',{method:'GET',eoParams:{team:currentTeamId}}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setMemberOptionList(data.teams?.map((x:TeamSimpleMemberItem)=>{return { - label:x.user.name, value:x.user.id - }})) - }else{ - message.error(msg || '操作失败') - } - }) - } const getTeamOptionList = ()=>{ setTeamOptionList([]) @@ -109,11 +182,11 @@ const SystemConfig = forwardRef((_,ref) => { } const deleteSystem = ()=>{ - fetchData>('team/project',{method:'DELETE',eoParams:{team:teamId,project:systemId}}).then(response=>{ + fetchData>('team/service',{method:'DELETE',eoParams:{team:teamId,service:serviceId}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') - navigate(`/system/list`) + navigate(`/service/list`) }else{ message.error(msg || '操作失败') } @@ -121,18 +194,14 @@ const SystemConfig = forwardRef((_,ref) => { } useEffect(() => { - - // getMemberOptionList() getTeamOptionList() - // getPartitionList() - - if (systemId !== undefined) { + getTagAndServiceClassifyList() + if (serviceId !== undefined) { setOnEdit(true); getSystemInfo(); - setBreadcrumb([ { - title: 内部数据服务 + title: 内部数据服务 }, { title: '设置' @@ -140,29 +209,12 @@ const SystemConfig = forwardRef((_,ref) => { } else { setOnEdit(false); - form.setFieldValue('id',uuidv4()); // 清空 initialValues - form.setFieldValue('team',teamId); // 清空 initialValues + form.setFieldValue('id',uuidv4()); + form.setFieldValue('team',teamId); + form.setFieldValue('serviceType','inner'); } return (form.setFieldsValue({})) - }, [systemId]); - - - // const getPartitionList = ()=>{ - // setPartitionOption([]) - // fetchData>('simple/organization/partitions',{method:'GET',eoParams:{organization:orgId}}).then(response=>{ - // const {code,data,msg} = response - // if(code === STATUS_CODE.SUCCESS){ - // setPartitionOption(data.partitions?.map((x:PartitionItem)=>{return { - // label:x.name,value:x.id - // }})) - // if(systemId === undefined && data.partitions?.length === 1){ - // form.setFieldValue('partition',[data.partitions[0].id]) - // } - // }else{ - // message.error(msg || '操作失败') - // } - // }) - // } + }, [serviceId]); const deleteSystemModal = async ()=>{ @@ -183,11 +235,10 @@ const SystemConfig = forwardRef((_,ref) => { }) } - return ( <>
- {/* */} + ((_,ref) => { form={form} className="mx-auto flex flex-col justify-between h-full" name="systemConfig" - // labelCol={{ offset:1, span: 4 }} - // wrapperCol={{ span: 19}} onFinish={onFinish} autoComplete="off" > @@ -230,6 +279,27 @@ const SystemConfig = forwardRef((_,ref) => { + + label="图标" + name="logoFile" + extra="仅支持 .png .jpg .jpeg .svg 格式的图片文件, 大于 1KB 的文件将被压缩" + valuePropName="fileList" getValueFromEvent={normFile} + > + +
+ {imageBase64 ? Logo : uploadButton} +
+
+ + + label="描述" name="description" @@ -237,56 +307,86 @@ const SystemConfig = forwardRef((_,ref) => { + + label="Logo" + name="logo" + hidden + > + + {!onEdit && label="所属团队" name="team" rules={[{ required: true, message: '必填项' }]} > - } + - label="负责人" - name="master" - extra="负责人对服务内的服务、服务、成员有管理权限" - rules={[{required: true, message: '必填项'}]} + label="标签" + name="tags" > - - label="环境权限" - name="partition" - rules={[{ required: true, message: '必填项' }]} + label="服务类型" + name="serviceType" + rules={[{required: true, message: '必填项'}]} + > + {setShowClassify(e.target.value === 'public')}} /> + + + {showClassify && + + label="所属服务分类" + name="catalogue" + extra="设置服务展示在服务市场中的哪个分类下" + rules={[{required: true, message: '必填项'}]} > - {partitionOption.length === 0 && 暂无可选环境,请检查所属团队可用环境} + + } {onEdit && <> - {/* */} + - {/* */} + }
{onEdit && <>
-

删除服务前,需要先删除所有服务内的服务,删除服务之后将无法找回,请谨慎操作!

+

删除服务之后将无法找回,请谨慎操作!

- {/* */} + - {/* */} +
} - {/*
*/} +
) diff --git a/frontend/packages/core/src/pages/system/SystemInsideDocument.tsx b/frontend/packages/core/src/pages/system/SystemInsideDocument.tsx new file mode 100644 index 0000000..35b5a4f --- /dev/null +++ b/frontend/packages/core/src/pages/system/SystemInsideDocument.tsx @@ -0,0 +1,146 @@ +import { Editor } from '@tinymce/tinymce-react'; +import hljs from 'highlight.js'; +import 'highlight.js/styles/default.css'; +import {useEffect, useState} from "react"; +import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; +import {useFetch} from "@common/hooks/http.ts"; +import {App, Button} from "antd"; +import { EntityItem } from '@common/const/type.ts'; +import WithPermission from '@common/components/aoplatform/WithPermission.tsx'; +import { RouterParams } from '@core/components/aoplatform/RenderRoutes'; +import { useParams } from 'react-router-dom'; +const ServiceInsideDocument = ()=>{ + const { message } = App.useApp() + const [serviceName,setServiceName] = useState() + const [updater,setUpdater] = useState() + const [updateTime,setUpdateTime]=useState() + const [initDoc, setInitDoc] = useState() + const [doc, setDoc] = useState() + const {fetchData} = useFetch() + const { serviceId, teamId} = useParams(); + + const save = ()=>{ + fetchData>('service/doc',{method:'PUT',eoBody:({doc:doc}) ,eoParams:{service:serviceId,team:teamId},eoTransformKeys:['update_time']}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || '操作成功!') + getServiceDoc() + }else{ + message.error(msg || '操作失败') + } + }) + } + + const handleEditorChange = (content:string, editor:unknown) => { + setDoc(content) + }; + const setupEditor = (editor:unknown) => { + editor.on('init', () => { + editor.contentDocument.querySelectorAll('pre code').forEach((block:HTMLElement) => { + hljs.highlightBlock(block); + }); + }); + + editor.on('SetContent', () => { + editor.contentDocument.querySelectorAll('pre code').forEach((block:HTMLElement) => { + hljs.highlightBlock(block); + }); + }); + }; + + const getServiceDoc = ()=>{ + fetchData>('service/doc',{method:'GET',eoParams:{service:serviceId,team:teamId},eoTransformKeys:['update_time']}).then(response=>{ + const {code,data,msg} = response + if(code === STATUS_CODE.SUCCESS){ + setServiceName(data.doc.name) + setUpdater(data.doc.updater.id === '' ? '-' : data.doc.updater.name) + setUpdateTime(data.doc.updater.id === '' ? '-' : data.doc.updateTime) + setInitDoc(data.doc.doc) + }else{ + message.error(msg || '操作失败') + } + }) + } + + useEffect(() => { + getServiceDoc() + }, []); + + return ( +
+ + +
+
+

最近一次更新者:{updater || '-'}最近一次更新时间:{updateTime || '-'}

+ +
+
+
) +} +export default ServiceInsideDocument \ No newline at end of file diff --git a/frontend/packages/core/src/pages/system/SystemInsidePage.tsx b/frontend/packages/core/src/pages/system/SystemInsidePage.tsx index 7163d04..15788ee 100644 --- a/frontend/packages/core/src/pages/system/SystemInsidePage.tsx +++ b/frontend/packages/core/src/pages/system/SystemInsidePage.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-01-31 15:00:11 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-07-12 20:58:39 - * @FilePath: \frontend\packages\core\src\pages\system\SystemInsidePage.tsx - */ + import {FC, useEffect, useMemo, useState} from "react"; import {Outlet, useLocation, useNavigate, useParams} from "react-router-dom"; import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; @@ -22,21 +17,20 @@ import { cloneDeep } from "lodash-es"; const SystemInsidePage:FC = ()=> { const { message } = App.useApp() - const {orgId, teamId,systemId,partitionId,apiId} = useParams(); + const { teamId,serviceId,apiId} = useParams(); const location = useLocation() const currentUrl = location.pathname const {fetchData} = useFetch() - const { setPartitionList,setPrefixForce,setApiPrefix ,systemInfo,setSystemInfo} = useSystemContext() - const { accessData,checkPermission,projectDataFlushed} = useGlobalContext() + const { setPrefixForce,setApiPrefix ,systemInfo,setSystemInfo} = useSystemContext() + const { accessData,checkPermission} = useGlobalContext() const [activeMenu, setActiveMenu] = useState() const navigateTo = useNavigate() const getSystemInfo = ()=>{ - fetchData>('project/info',{method:'GET',eoParams:{project:systemId}}).then(response=>{ + fetchData>('service/info',{method:'GET',eoParams:{team:teamId, service:serviceId}}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ - setSystemInfo(data.project) - setPartitionList(data.project.partition) + setSystemInfo(data.service) }else{ message.error(msg || '操作失败') } @@ -46,7 +40,7 @@ const SystemInsidePage:FC = ()=> { const getApiDefine = ()=>{ setApiPrefix('') setPrefixForce(false) - fetchData>('project/api/define',{method:'GET',eoParams:{project:systemId}}).then(response=>{ + fetchData>('service/api/define',{method:'GET',eoParams:{service:serviceId,team:teamId}}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ setApiPrefix(data.prefix) @@ -72,52 +66,52 @@ const SystemInsidePage:FC = ()=> { } const filteredMenu = filterMenu(SYSTEM_PAGE_MENU_ITEMS as MenuItemGroupType[]) setActiveMenu((pre)=>{ - if(!pre && projectDataFlushed){ + if(!pre){ const activeMenu = filteredMenu?.[0]?.children?.[0]?.key as string return activeMenu } return pre }) return filteredMenu || [] - },[accessData,projectDataFlushed]) + },[accessData]) const onMenuClick: MenuProps['onClick'] = ({key}) => { setActiveMenu(key) }; useEffect(() => { - if(partitionId !== undefined){ - setActiveMenu('upstream') - }else if(apiId !== undefined){ + if(apiId !== undefined){ setActiveMenu('api') - }else if(systemId !== currentUrl.split('/')[currentUrl.split('/').length - 1]){ + }else if(serviceId !== currentUrl.split('/')[currentUrl.split('/').length - 1]){ setActiveMenu(currentUrl.split('/')[currentUrl.split('/').length - 1]) + }else{ + setActiveMenu('upstream') } }, [currentUrl]); useEffect(()=>{ - if(accessData && accessData.get('system') && accessData.get('system')?.indexOf('project.mySystem.api.view') !== -1){ + if(accessData && accessData.get('team') && accessData.get('team')?.indexOf('team.service.api.view') !== -1){ getApiDefine() } },[accessData]) useEffect(()=>{ - if( activeMenu && systemId === currentUrl.split('/')[currentUrl.split('/').length - 1]){ - navigateTo(`/system/${orgId}/${teamId}/inside/${systemId}/${activeMenu}`) + if( activeMenu && serviceId === currentUrl.split('/')[currentUrl.split('/').length - 1]){ + navigateTo(`/service/${teamId}/inside/${serviceId}/${activeMenu}`) } },[activeMenu]) useEffect(() => { - systemId && getSystemInfo() - }, [systemId]); + serviceId && getSystemInfo() + }, [serviceId]); return ( <> 服务 ID:{systemId || '-'} + 服务 ID:{serviceId || '-'} }]} - backUrl="/system/list"> + backUrl="/service/list">
{ mode="inline" items={menuData as unknown as ItemType[] } /> -
+
diff --git a/frontend/packages/core/src/pages/system/SystemInsideSubscriber.tsx b/frontend/packages/core/src/pages/system/SystemInsideSubscriber.tsx index ae10bb5..d04123d 100644 --- a/frontend/packages/core/src/pages/system/SystemInsideSubscriber.tsx +++ b/frontend/packages/core/src/pages/system/SystemInsideSubscriber.tsx @@ -1,17 +1,16 @@ import {ActionType, ProColumns} from "@ant-design/pro-components"; import {FC, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState} from "react"; import {Link, useParams} from "react-router-dom"; -import {App, Checkbox, Form, Select,TreeSelect} from "antd"; +import {App, Form, Select,TreeSelect} from "antd"; import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx"; import {useFetch} from "@common/hooks/http.ts"; import { RouterParams } from "@core/components/aoplatform/RenderRoutes.tsx"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import PageList from "@common/components/aoplatform/PageList.tsx"; -import {useSystemContext} from "../../contexts/SystemContext.tsx"; import {DefaultOptionType} from "antd/es/cascader"; import { SYSTEM_SUBSCRIBER_TABLE_COLUMNS } from "../../const/system/const.tsx"; import { SystemSubscriberTableListItem, SystemSubscriberConfigFieldType, SystemSubscriberConfigHandle, SystemSubscriberConfigProps, SimpleSystemItem } from "../../const/system/type.ts"; -import { EntityItem, SimpleMemberItem } from "@common/const/type.ts"; +import { NewSimpleMemberItem, SimpleMemberItem } from "@common/const/type.ts"; import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission.tsx"; import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; @@ -20,19 +19,15 @@ import { checkAccess } from "@common/utils/permission.ts"; const SystemInsideSubscriber:FC = ()=>{ const { setBreadcrumb } = useBreadcrumb() const { modal,message } = App.useApp() - // const [confirmLoading, setConfirmLoading] = useState(false); const {fetchData} = useFetch() const [init, setInit] = useState(true) - // const [tableListDataSource, setTableListDataSource] = useState([]); - // const [tableHttpReload, setTableHttpReload] = useState(true); - const {systemId} = useParams() + const {serviceId, teamId} = useParams() const addRef = useRef(null) const pageListRef = useRef(null); const [memberValueEnum, setMemberValueEnum] = useState<{[k:string]:{text:string}}>({}) - const {partitionList} = useSystemContext() const {accessData} = useGlobalContext() const getSystemSubscriber = ()=>{ - return fetchData>('project/subscribers',{method:'GET',eoParams:{project:systemId},eoTransformKeys:['apply_time']}).then(response=>{ + return fetchData>('service/subscribers',{method:'GET',eoParams:{service:serviceId,team:teamId},eoTransformKeys:['apply_time']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ setInit((prev)=>prev ? false : prev) @@ -61,13 +56,12 @@ const SystemInsideSubscriber:FC = ()=>{ } const manualReloadTable = () => { - // setTableHttpReload(true); // 表格数据需要从后端接口获取 pageListRef.current?.reload() }; const deleteSubscriber = (entity:SystemSubscriberTableListItem)=>{ return new Promise((resolve, reject)=>{ - fetchData>('project/subscriber',{method:'DELETE',eoParams:{application:entity!.id,service:entity!.service.id,project:systemId}}).then(response=>{ + fetchData>('service/subscriber',{method:'DELETE',eoParams:{application:entity!.id,service:entity!.service.id,team:teamId}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -86,7 +80,7 @@ const SystemInsideSubscriber:FC = ()=>{ switch (type){ case 'add': title='新增订阅方' - content= + content= break; case 'delete': title='删除' @@ -108,7 +102,7 @@ const SystemInsideSubscriber:FC = ()=>{ width:600, okText:'确认', okButtonProps:{ - disabled : !checkAccess( `project.mySystem.subscriber.${type}`, accessData) + disabled : !checkAccess( `team.service.subscription.${type}`, accessData) }, cancelText:'取消', closable:true, @@ -124,7 +118,7 @@ const SystemInsideSubscriber:FC = ()=>{ fixed:'right', valueType: 'option', render: (_: React.ReactNode, entity: SystemSubscriberTableListItem) => [ - {openModal('delete',entity)}} btnTitle="删除"/>, + {openModal('delete',entity)}} btnTitle="删除"/>, ], } ] @@ -132,7 +126,7 @@ const SystemInsideSubscriber:FC = ()=>{ useEffect(() => { setBreadcrumb([ { - title:内部数据服务 + title:内部数据服务 }, { title:'订阅方管理' @@ -140,7 +134,7 @@ const SystemInsideSubscriber:FC = ()=>{ ]) getMemberList() manualReloadTable() - }, [systemId]); + }, [serviceId]); const columns = useMemo(()=>{ return SYSTEM_SUBSCRIBER_TABLE_COLUMNS.map(x=>{if(x.filters &&((x.dataIndex as string[])?.indexOf('applier') !== -1 || (x.dataIndex as string[])?.indexOf('approver') !== -1) ){x.valueEnum = memberValueEnum} return x}) @@ -156,7 +150,7 @@ const SystemInsideSubscriber:FC = ()=>{ showPagination={false} addNewBtnTitle="新增订阅方" onAddNewBtnClick={()=>{openModal('add')}} - addNewBtnAccess="project.mySystem.subscriber.add" + addNewBtnAccess="team.service.subscription.add" /> ) } @@ -166,19 +160,16 @@ export default SystemInsideSubscriber export const SystemSubscriberConfig = forwardRef((props, ref) => { const { message } = App.useApp() - const { systemId,partitionList} = props + const { serviceId, teamId} = props const [form] = Form.useForm(); const {fetchData} = useFetch() - const [myServiceOptionList, setMyServiceOptionList] = useState() const [systemOptionList, setSystemOptionList] = useState() const [memberOptionList, setMemberOptionList] = useState() - // const [avaliablePartitions, setAvaPartitions] = useState>([]) - const [subscriberSystemId, setSubscriberSystemId] = useState() - // const [partitionsList, setPartitionsList] = useState([]) + const [subscriberTeamId, setSubscriberTeamId] = useState() const save:()=>Promise = ()=>{ return new Promise((resolve, reject)=>{ form.validateFields().then((value)=>{ - fetchData>('project/subscriber',{method:'POST',eoBody:({...value,project:systemId}), eoParams:{project:systemId}}).then(response=>{ + fetchData>('service/subscriber',{method:'POST',eoBody:({...value,service:serviceId}), eoParams:{service:serviceId,team:teamId}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -197,29 +188,16 @@ export const SystemSubscriberConfig = forwardRef{ - setMyServiceOptionList([]) - fetchData>('simple/project/services',{method:'GET',eoParams:{project:systemId}}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setMyServiceOptionList(data.services?.map((x:EntityItem)=>{return { - label:x.name, value:x.id - }})) - }else{ - message.error(msg || '操作失败') - } - }) - } const getSystemList = ()=>{ setSystemOptionList([]) - fetchData>('simple/apps/mine',{method:'GET'}).then(response=>{ + fetchData>('simple/apps/mine',{method:'GET'}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ const teamMap = new Map(); - data.projects - .filter((x:SimpleSystemItem)=>x.id !== systemId) + data.apps + .filter((x:SimpleSystemItem)=>x.id !== serviceId) .forEach((item:SimpleSystemItem) => { if (!teamMap.has(item.team.id)) { teamMap.set(item.team.id, { @@ -248,17 +226,17 @@ export const SystemSubscriberConfig = forwardRef{ - subscriberSystemId && getMemberList() + subscriberTeamId && getMemberList() form.setFieldValue('applier',null) - },[subscriberSystemId]) + },[subscriberTeamId]) const getMemberList = ()=>{ setMemberOptionList([]) - fetchData>('simple/project/members',{method:'GET',eoParams:{project:subscriberSystemId}}).then(response=>{ + fetchData>('team/members/simple',{method:'GET',eoParams:{team:subscriberTeamId}}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ - setMemberOptionList(data.members?.map((x:SimpleMemberItem)=>{return { - label:x.name, value:x.id + setMemberOptionList(data.members?.map((x:NewSimpleMemberItem)=>{return { + label:x.user.name, value:x.user.id }})) }else{ message.error(msg || '操作失败') @@ -266,33 +244,11 @@ export const SystemSubscriberConfig = forwardRef{ - // fetchData>('simple/application/partitions',{method:'GET',eoParams:{application:applicationId},eoTransformKeys:['service_num']}).then(response=>{ - // const {code,data,msg} = response - // if(code === STATUS_CODE.SUCCESS){ - // setPartitionsList(data.partitions?.map((x:SimpleTeamItem)=>({label:x.name, value:x.id}))) - // }else{ - // message.error(msg || '操作失败') - // } - // }) - // } - useEffect(() => { - getMyServiceList() getSystemList() - }, [systemId]); - - + }, [serviceId]); - // const partitionsList = useMemo(()=>{ - // const newList = partitionList?.filter((x:EntityItem)=> avaliablePartitions && avaliablePartitions?.indexOf(x.id) !== -1)?.map((x:EntityItem)=>({label:x.name, value:x.id})) || [] - // if(newList.length === 1){ - // form.setFieldValue('partition',[newList[0].value]) - // } - // return newList - // },[partitionList, avaliablePartitions]) - - return ( + return (
- - label="订阅服务" - name="service" - rules={[{ required: true, message: '必填项' }]} - > - setFormShowHost(prev => ({...prev, [partition.id]:val === 'rewrite'}))}> + - {formShowHost[partition.id] && + {formShowHost && label="重写域名" name="upstreamHost" rules={[{ required: true, message: '必填项',whitespace:true }]} @@ -329,17 +223,15 @@ const globalConfigNodesRule: FormItemProps['rules'] = [ /> + + +
- )} - - ))} - - - -
) diff --git a/frontend/packages/core/src/pages/team/TeamConfig.tsx b/frontend/packages/core/src/pages/team/TeamConfig.tsx index 3e46539..0f10da3 100644 --- a/frontend/packages/core/src/pages/team/TeamConfig.tsx +++ b/frontend/packages/core/src/pages/team/TeamConfig.tsx @@ -4,7 +4,7 @@ import {Link, useLocation, useParams} from "react-router-dom"; import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; import { v4 as uuidv4 } from 'uuid' import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; -import {MemberItem, OrganizationItem} from "@common/const/type.ts"; +import {MemberItem} from "@common/const/type.ts"; import {useFetch} from "@common/hooks/http.ts"; import {DefaultOptionType} from "antd/es/cascader"; import { TeamConfigFieldType } from "../../const/team/type.ts"; @@ -31,11 +31,10 @@ const TeamConfig= forwardRef((props,ref) => { const currentUrl = location.pathname const {fetchData} = useFetch() const [managerOption, setManagerOption] = useState([]) - const [orgOption, setOrgOption] = useState([]) const { setBreadcrumb} = useBreadcrumb() const { setTeamInfo } =useTeamContext() const {checkPermission} = useGlobalContext() - const pageType= checkPermission('system.team.self.view') ? 'manage' : 'myteam' + const pageType= checkPermission('system.organization.team.view') ? 'manage' : 'myteam' const [canDelete, setCanDelete] = useState(false) useImperativeHandle(ref, () => ({ save:onFinish @@ -49,7 +48,7 @@ const TeamConfig= forwardRef((props,ref) => { }else{ params = {team:teamId!} } - return fetchData>(pageType === 'manage'?'manager/team' : 'team',{method:onEdit ? 'PUT' : 'POST', eoParams:params,eoBody:(value),eoTransformKeys:['teamId','orgId']}).then(response=>{ + return fetchData>(pageType === 'manage'?'manager/team' : 'team',{method:onEdit ? 'PUT' : 'POST', eoParams:params,eoBody:(value),eoTransformKeys:['teamId']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -71,27 +70,13 @@ const TeamConfig= forwardRef((props,ref) => { const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ setCanDelete(data.team.canDelete) - setTimeout(()=>{form.setFieldsValue({...data.team,organization:data.team.organization.id, master:data.team.master.id})},0) + setTimeout(()=>{form.setFieldsValue({...data.team})},0) }else{ message.error(msg || '操作失败') } }) }; - const getOrgList = ()=>{ - setOrgOption([]) - fetchData>('simple/organizations',{method:'GET'}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setOrgOption(data.organizations?.map((x:MemberItem)=>{return { - label:x.name, value:x.id - }}) || []) - }else{ - message.error(msg || '操作失败') - } - }) - } - const getManagerList = ()=>{ setManagerOption([]) fetchData>('simple/member',{method:'GET'}).then(response=>{ @@ -123,7 +108,6 @@ const TeamConfig= forwardRef((props,ref) => { useEffect(() => { getManagerList() - getOrgList() if(entity){ setOnEdit(true); form.setFieldsValue(entity) @@ -145,7 +129,7 @@ const TeamConfig= forwardRef((props,ref) => { return ( <>
- +
((props,ref) => { - {/* {!onEdit && <> */} - - label="所属组织" - name="organization" - rules={[{ required: true, message: '必填项' }]} - > - - - + {!onEdit && label="团队负责人" name="master" @@ -193,8 +168,7 @@ const TeamConfig= forwardRef((props,ref) => { > - - {/* } */} + } @@ -208,7 +182,7 @@ const TeamConfig= forwardRef((props,ref) => { - @@ -218,7 +192,7 @@ const TeamConfig= forwardRef((props,ref) => {

删除团队:删除操作不可恢复,请谨慎操作!

- +
} diff --git a/frontend/packages/core/src/pages/team/TeamInsideMember.tsx b/frontend/packages/core/src/pages/team/TeamInsideMember.tsx index f53d048..c6d77dc 100644 --- a/frontend/packages/core/src/pages/team/TeamInsideMember.tsx +++ b/frontend/packages/core/src/pages/team/TeamInsideMember.tsx @@ -3,7 +3,7 @@ import {ActionType, ProColumns} from "@ant-design/pro-components"; import {FC, useEffect, useMemo, useRef, useState} from "react"; import {Link, useParams} from "react-router-dom"; import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx"; -import {App, Button, Modal} from "antd"; +import {App, Button, Modal, Select} from "antd"; import {TransferTableHandle} from "@common/components/aoplatform/TransferTable.tsx"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import {useFetch} from "@common/hooks/http.ts"; @@ -16,10 +16,27 @@ import { checkAccess } from "@common/utils/permission.ts"; import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx"; import MemberTransfer from "@common/components/aoplatform/MemberTransfer.tsx"; import { DepartmentListItem } from "../../const/member/type.ts"; -import { addMemberToDepartment, getDepartmentWithMember } from "../user/UserList.tsx"; import {v4 as uuidv4} from 'uuid' import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; +export const getDepartmentWithMember = (department:(DepartmentListItem & {type?:'department'|'member'})[],departmentMap:Map) : (DepartmentWithMemberItem | undefined)[] =>{ + return department.map((x:DepartmentListItem & {type?:'department'|'member'})=>{ + const res = ({ + ...x, + key:x.id, + title:x.name, + type: x.type || 'department', + children:((x.type === 'member' || (!x.children||x.children.length === 0 )&& (!departmentMap.get(x.id) || departmentMap.get(x.id)!.length === 0))? undefined : [...(x.children && x.children.length > 0 ? getDepartmentWithMember(x.children,departmentMap) : []),...departmentMap.get(x.id) || []]) + }); + return res}).filter(node=>node.type === 'member' ||( node.children && node.children.length > 0)) +} + +export const addMemberToDepartment = (departmentMap: Map, departmentId: string, member: MemberItem) => { + const members = departmentMap.get(departmentId) || []; + members.push({...member, type: 'member'}); + departmentMap.set(departmentId, members); + } + const TeamInsideMember:FC = ()=>{ const [searchWord, setSearchWord] = useState('') const { setBreadcrumb} = useBreadcrumb() @@ -35,6 +52,7 @@ const TeamInsideMember:FC = ()=>{ const [modalVisible, setModalVisible] = useState(false) const [addMemberBtnDisabled, setAddMemberBtnDisabled] = useState(true) const [allMemberSelectedDepartIds, setAllMemberSelectedDepartIds] = useState([]) + const [columns,setColumns] = useState[]>([]) const operation:ProColumns[] =[ { @@ -44,7 +62,7 @@ const TeamInsideMember:FC = ()=>{ fixed:'right', valueType: 'option', render: (_: React.ReactNode, entity: TeamMemberTableListItem) => [ - !entity.role?.includes('负责人') &&{openModal('remove',entity)}} btnTitle="移出团队"/>] + {openModal('remove',entity)}} btnTitle="移出团队"/>] } ] @@ -101,11 +119,11 @@ const TeamInsideMember:FC = ()=>{ } const getMemberList = ()=>{ - return fetchData>('team/members',{method:'GET',eoParams:{keyword:searchWord, team:teamId},eoTransformKeys:['user_group','attach_time','user_id','can_delete']}).then(response=>{ + return fetchData>('team/members',{method:'GET',eoParams:{keyword:searchWord, team:teamId},eoTransformKeys:['attach_time','is_delete']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ if(!searchWord){ - setAllMemberIds(data.members?.map((x:TeamMemberTableListItem)=>x.userId) || []) + setAllMemberIds(data.members?.map((x:TeamMemberTableListItem)=>x.user.id) || []) } return {data:data.members, success: true} }else{ @@ -140,7 +158,7 @@ const TeamInsideMember:FC = ()=>{ const removeMember = (entity:TeamMemberTableListItem) =>{ return new Promise((resolve, reject)=>{ - fetchData>(`team/member`,{method:'DELETE',eoParams:{team:teamId,user:entity.userId}}).then(response=>{ + fetchData>(`team/member`,{method:'DELETE',eoParams:{team:teamId,user:entity.user.id}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -181,7 +199,7 @@ const TeamInsideMember:FC = ()=>{ width:600, okText:'确认', okButtonProps:{ - disabled: !checkAccess(`team.myTeam.member.edit`,accessData) + disabled: !checkAccess(`team.team.member.edit`,accessData) }, cancelText:'取消', closable:true, @@ -194,7 +212,64 @@ const TeamInsideMember:FC = ()=>{ pageListRef.current?.reload() }; + + const changeMemberInfo = (value:string[],entity:TeamMemberTableListItem )=>{ + //console.log(value) + return new Promise((resolve, reject) => { + fetchData>(`team/member/role`, {method: 'PUT',eoBody:({roles:value, users:[entity.user.id]}), eoParams: {team:teamId}}).then(response => { + const {code, msg} = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || '操作成功!') + resolve(true) + } else { + message.error(msg || '操作失败') + reject(msg || '操作失败') + } + }).catch((errorInfo)=> reject(errorInfo)) + }) + } + + const getRoleList = ()=>{ + fetchData}>>('simple/roles', {method: 'GET', eoParams: {group:'team'}}).then(response => { + const {code, data,msg} = response + if (code === STATUS_CODE.SUCCESS) { + + const newCol = [...TEAM_MEMBER_TABLE_COLUMNS] + for(const col of newCol){ + //console.log(col) + if(col.dataIndex === 'roles'){ + col.render = (_,entity)=>( + + x.value !== entity.project.id)}/> + } + // onSearch={handleTest} + /> + + { + apiDetail?.match && apiDetail.match?.length > 0 && + + } + + { + apiDetail?.proxy && Object.keys(apiDetail?.proxy).length > 0 && + + } + + {apiDetail && } +
+ // testClick(apiDocs.id)} entity={doc} /> + }]} + activeKey={activeKey} + onChange={(val)=>{setActiveKey(val as string[])}} + /> +
+ ))} + +
+ {/*
+
+

状态码

+ +
*/} +
+ + + document.getElementById('layout-ref')!} + items={category} + /> + +
+
+ + 退出测试 + } + closeIcon={false} + > + + + + ) +} + +export default ServiceHubApiDocument \ No newline at end of file diff --git a/frontend/packages/market/src/pages/serviceHub/ServiceHubDetail.tsx b/frontend/packages/market/src/pages/serviceHub/ServiceHubDetail.tsx index 4694177..9857ed4 100644 --- a/frontend/packages/market/src/pages/serviceHub/ServiceHubDetail.tsx +++ b/frontend/packages/market/src/pages/serviceHub/ServiceHubDetail.tsx @@ -1,58 +1,48 @@ -/* - * @Date: 2024-01-31 15:00:11 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-05 18:00:51 - * @FilePath: \frontend\packages\market\src\pages\serviceHub\ServiceHubDetail.tsx - */ -import {Link, useLocation, useParams} from "react-router-dom"; +import {Link, useNavigate, useParams} from "react-router-dom"; import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; -import {Anchor, App, Button, Collapse, Descriptions, Drawer, FloatButton, Input, Space} from "antd"; -import { useEffect, useMemo, useRef, useState} from "react"; +import { App, Avatar, Button, Descriptions, Divider, Tabs} from "antd"; +import { useEffect, useRef, useState} from "react"; import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx"; -import ApiPreview from "@common/components/postcat/ApiPreview.tsx"; -import ApiTestGroup from "./ApiTestGroup.tsx"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import {useFetch} from "@common/hooks/http.ts"; import {DefaultOptionType} from "antd/es/cascader"; -import {ApiDetail} from "@common/const/api-detail"; import { ApplyServiceHandle, ServiceBasicInfoType, ServiceDetailType } from "../../const/serviceHub/type.ts"; -import { SimpleSystemItem } from "@core/const/system/type.ts"; import { EntityItem } from "@common/const/type.ts"; -import ApiMatch from "@common/components/postcat/api/ApiPreview/components/ApiMatch/index.tsx"; -import ApiProxy from "@common/components/postcat/api/ApiPreview/components/ApiProxy/index.tsx"; -import InsidePageForHub from "@common/components/aoplatform/InsidePageForHub.tsx"; import { ApplyServiceModal } from "./ApplyServiceModal.tsx"; +import ServiceHubApiDocument from "./ServiceHubApiDocument.tsx"; +import { ApiFilled, LeftOutlined } from "@ant-design/icons"; +import { Typography } from 'antd'; +import { SimpleSystemItem } from "@core/const/system/type.ts"; +import { Icon } from "@iconify/react/dist/iconify.js"; + +const { Title, Text } = Typography; const ServiceHubDetail = ()=>{ - const {tagId, categoryId, teamId,serviceId} = useParams(); - const cluster:string = (new URLSearchParams(useLocation().search)).get('name') || '-' + const {serviceId} = useParams(); const {setBreadcrumb} = useBreadcrumb() - const [apiTestDrawOpen, setApiTestDrawOpen] = useState(false); const [serviceBasicInfo, setServiceBasicInfo] = useState() const [serviceName, setServiceName] = useState() const [serviceDesc, setServiceDesc] = useState() - const [apiDocs,setApiDocs ] = useState() + const [serviceDoc, setServiceDoc] = useState() const {fetchData} = useFetch() const applyRef = useRef(null) const { modal,message } = App.useApp() - const [partitionsList, setPartitionsList ] = useState>() const [mySystemOptionList, setMySystemOptionList] = useState() const [applied,setApplied] = useState(false) - const [selectedTestApi,setSelectedTestApi] = useState() - // const callbackUrl = new URLSearchParams(window.location.search).get('callbackUrl'); const [activeKey, setActiveKey] = useState([]) + const [service, setService] = useState() + const navigate = useNavigate(); const getServiceBasicInfo = ()=>{ - fetchData>('catalogue/service',{method:'GET',eoParams:{service:serviceId}}).then(response=>{ + fetchData>('catalogue/service',{method:'GET',eoParams:{service:serviceId}, eoTransformKeys:['app_num','api_num','update_time']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ - //console.log(data) + setService(data.service) setServiceBasicInfo(data.service.basic) setServiceName(data.service.name) setServiceDesc(data.service.description) - setApiDocs(data.service.apis) setApplied(data.service.applied) - setPartitionsList(data.service.partition) + setServiceDoc(data.service.document) setActiveKey(data.service.apis.map((x)=>x.id)) }else{ message.error(msg || '操作失败') @@ -60,59 +50,6 @@ const ServiceHubDetail = ()=>{ }) } - const getBasicInfo = useMemo(() => [ - { - key: 'organzation', - label: '所属组织', - children: serviceBasicInfo?.organization.name, - style: {padding: 0}, - }, - { - key: 'project', - label: '所属系统', - children: serviceBasicInfo?.project.name, - style: {padding: 0}, - }, - { - key: 'team', - label: '所属团队', - children: serviceBasicInfo?.team.name, - style: {padding: 0}, - }, - // { - // key: 'master', - // label: '负责人', - // children: serviceBasicInfo?.master?.name, - // style: {paddingBottom: '10px'}, - // } - ], [serviceBasicInfo]); - - - const category = useMemo(() => [ - { - key: 'apiDocument-list', - href: '#apiDocument-list', - title: 'API 列表', - children:apiDocs?.map((x)=>({ - key:x.id, - href:`#apiDocument-${x.id}`, - title:x.name - })) || [] - }, - // { - // key: 'apiDocument-statusCode', - // href: '#apiDocument-statusCode', - // title: '状态码', - // }, - ], [apiDocs]); - - const floatButtonStyle = { top:'10px',position:'sticky', width:'180px',height:'200px'} - const onClick = async (e: unknown, link: {href: string}) => { - // const arr = [...(collapseDefaultKeyNew as string[]), link.href]; - // setCollapseDefaultKeyNew(Array.from(new Set(arr))) - - } - useEffect(() => { if(!serviceId){ console.warn('缺少serviceId') @@ -126,38 +63,20 @@ const ServiceHubDetail = ()=>{ setBreadcrumb( [ {title:服务市场}, - // {title:服务市场}, {title:'服务详情'} ] ) - // setTimeout(()=>{ - // const element = document.querySelectorAll('.MuiDataGrid-main'); - // if(element?.length > 0){ - // for(const x of element){ - // x.childNodes[x.childNodes.length - 1 ].textContent === 'MUI X Missing license key' ? x.childNodes[x.childNodes.length - 1 ].textContent = '' :null - // } - // } - - // },500) }, []); - const testClick = (id:string)=>{//console.log('test'); - setApiTestDrawOpen(true) - setSelectedTestApi(id)} - - const onClose = () => { - setApiTestDrawOpen(false); - }; - const getMySelectList = ()=>{ setMySystemOptionList([]) - fetchData>('simple/apps/mine',{method:'GET'}).then(response=>{ + fetchData>('simple/apps/mine',{method:'GET'}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ - setMySystemOptionList(data.projects?.map((x:SimpleSystemItem)=>{return { - label:x.name, value:x.id, partition:x.partition?.map((x:EntityItem)=>x.id) + setMySystemOptionList(data.apps?.map((x:SimpleSystemItem)=>{return { + label:x.name, value:x.id }})) }else{ message.error(msg || '操作失败') @@ -165,10 +84,11 @@ const ServiceHubDetail = ()=>{ }) } + const openModal = (type:'apply')=>{ modal.confirm({ title:'申请服务', - content:, + content:, onOk:()=>{ return applyRef.current?.apply().then((res)=>{ if(res === true) setApplied(true) @@ -182,86 +102,66 @@ const ServiceHubDetail = ()=>{ }) } - return ( - openModal('apply')} backUrl={tagId === undefined && categoryId === undefined ? `/serviceHub/list` :`/serviceHub/list/${tagId === undefined ? 'category' : 'tag' }/${tagId ?? categoryId}`}> -
-
- -
-
-
-

API 列表

-
- {apiDocs?.map((apiDetail)=>( -
- (isActive? : )} - items={[{ - key: apiDetail.id, - label: {apiDetail.method}{apiDetail.name}, - children:
- - } - // onSearch={handleTest} - /> - - { - apiDetail?.match && apiDetail.match?.length > 0 && - - } - - { - apiDetail?.proxy && Object.keys(apiDetail?.proxy).length > 0 && - - } - - {apiDetail && } -
- // testClick(apiDocs.id)} entity={doc} /> - }]} - activeKey={activeKey} - onChange={(val)=>{setActiveKey(val as string[])}} - /> -
- ))} + const items = [ + { + key: 'introduction', + label: '介绍', + children: <>
,
+            icon: ,
+        },
+        {
+            key: 'api-document',
+            label: 'API 文档',
+            children: 
, + icon: + } + ] -
- {/*
-
-

状态码

- -
*/} + return ( +
+
+
+ navigate('/serviceHub/list')}>返回 +
+ {/* {service?.name?.substring(0,1)} */} + : undefined} + icon={serviceBasicInfo.logo ? '' :}> + +
+

{serviceName}

+
+ {serviceDesc || '-'} +
+ +
- - - document.getElementById('layout-ref')!} - items={category} - /> -
- - 退出测试 - } - closeIcon={false} - > - - - +
+ + +
+
+ + {serviceBasicInfo?.appNum || '-'} + {serviceBasicInfo?.team?.name || '-'} + {serviceBasicInfo?.catalogue?.name || '-'} + {serviceBasicInfo?.tags?.map(x=>x.name)?.join(',') || '-'} + + + + { serviceBasicInfo?.version || '-'} + {serviceBasicInfo?.updateTime || '-'} + +
+
) } diff --git a/frontend/packages/market/src/pages/serviceHub/ServiceHubGroup.tsx b/frontend/packages/market/src/pages/serviceHub/ServiceHubGroup.tsx index 8d3f1b0..0470a13 100644 --- a/frontend/packages/market/src/pages/serviceHub/ServiceHubGroup.tsx +++ b/frontend/packages/market/src/pages/serviceHub/ServiceHubGroup.tsx @@ -1,18 +1,11 @@ -/* - * @Date: 2024-05-30 12:07:53 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-06 17:01:16 - * @FilePath: \frontend\packages\market\src\pages\serviceHub\ServiceHubGroup.tsx - */ import {debounce} from "lodash-es"; import {SearchOutlined} from "@ant-design/icons"; import {App, Divider, Input, TreeDataNode} from "antd"; import {useCallback, useEffect, useState} from "react"; -import Tree, {DataNode, TreeProps} from "antd/es/tree"; +import Tree, {DataNode} from "antd/es/tree"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import {useFetch} from "@common/hooks/http.ts"; import { CategorizesType, TagType } from "../../const/serviceHub/type.ts"; -import { PartitionItem } from "@common/const/type.ts"; import { filterServiceList, initialServiceHubListState, SERVICE_HUB_LIST_ACTIONS, ServiceHubListActionType } from "./ServiceHubList.tsx"; type ServiceHubGroup = { @@ -24,23 +17,9 @@ type ServiceHubGroup = { export const ServiceHubGroup = ({children,filterOption,dispatch}:ServiceHubGroup)=>{ const {message} = App.useApp() const {fetchData} = useFetch() - // const [treeHeight, setTreeHeight] = useState(Math.ceil((window.innerHeight - 50 - 20 * 2 - (32 + 4 + 20) - ( 12 * 2 + 1 ) * 2 - ( 25 + 15 ) * 3) /3) ) useEffect(() => { getTagAndServiceClassifyList() - getPartitionList() - // const handleResize = () => { - // setTreeHeight(Math.ceil((window.innerHeight - 50 - 20 * 2 - (32 + 4 + 20) - ( 12 * 2 + 1 ) * 2 - ( 25 + 15 ) * 3) /3)) - // }; - - // const debouncedHandleResize = debounce(handleResize, 200); - - // // 监听窗口大小变化 - // window.addEventListener('resize', debouncedHandleResize); - // handleResize(); - // return () => { - // window.removeEventListener('resize', debouncedHandleResize); - // }; }, []); const onSearchWordChange = (e:string)=>{ @@ -64,22 +43,8 @@ export const ServiceHubGroup = ({children,filterOption,dispatch}:ServiceHubGroup }) } - const getPartitionList = ()=>{ - return fetchData>('simple/partitions',{method:'GET'}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - dispatch({type:SERVICE_HUB_LIST_ACTIONS.GET_PARTITIONS,payload:data.partitions}) - dispatch({type:SERVICE_HUB_LIST_ACTIONS.SET_SELECTED_PARTITION,payload:data.partitions.map((x:PartitionItem)=>x.id)}) - return Promise.resolve(data.partitions) - }else{ - message.error(msg || '操作失败') - return Promise.reject(msg || '操作失败') - } - }) - } - - const transferToTreeData = useCallback((data:CategorizesType[] | TagType[] | PartitionItem[]):TreeDataNode[]=>{ - const loop = (data: CategorizesType[] | TagType[] | PartitionItem[]): DataNode[] => + const transferToTreeData = useCallback((data:CategorizesType[] | TagType[] ):TreeDataNode[]=>{ + const loop = (data: CategorizesType[] | TagType[] ): DataNode[] => data?.map((item) => { if ((item as CategorizesType).children) { return { @@ -140,21 +105,6 @@ export const ServiceHubGroup = ({children,filterOption,dispatch}:ServiceHubGroup selectable={false} />
- -
-

环境

- -
diff --git a/frontend/packages/market/src/pages/serviceHub/ServiceHubList.tsx b/frontend/packages/market/src/pages/serviceHub/ServiceHubList.tsx index 0d9a5fd..8fe47a5 100644 --- a/frontend/packages/market/src/pages/serviceHub/ServiceHubList.tsx +++ b/frontend/packages/market/src/pages/serviceHub/ServiceHubList.tsx @@ -7,15 +7,14 @@ import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; import {useFetch} from "@common/hooks/http.ts"; import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx"; import { CategorizesType, ServiceHubTableListItem, TagType } from "../../const/serviceHub/type.ts"; -import { PartitionItem } from "@common/const/type.ts"; import { VirtuosoGrid } from 'react-virtuoso'; -import { ApiOutlined,LoadingOutlined,ProjectOutlined } from "@ant-design/icons"; +import { ApiOutlined,LoadingOutlined } from "@ant-design/icons"; import ServiceHubGroup from "./ServiceHubGroup.tsx"; +import { unset } from "lodash-es"; export enum SERVICE_HUB_LIST_ACTIONS { GET_CATEGORIES = 'GET_CATEGORIES', GET_TAGS ='GET_TAGS', - GET_PARTITIONS = 'GET_PARTITIONS', GET_SERVICES = 'GET_SERVICES', SET_SERVICES='SET_SERVICES', SET_SELECTED_CATE = 'SET_SELECTED_CATE', @@ -28,7 +27,6 @@ export enum SERVICE_HUB_LIST_ACTIONS { export type ServiceHubListActionType = | { type: SERVICE_HUB_LIST_ACTIONS.GET_CATEGORIES, payload: CategorizesType[] } | { type: SERVICE_HUB_LIST_ACTIONS.GET_TAGS, payload: TagType[] } -| { type: SERVICE_HUB_LIST_ACTIONS.GET_PARTITIONS, payload: PartitionItem[] } | { type: SERVICE_HUB_LIST_ACTIONS.GET_SERVICES, payload: ServiceHubTableListItem[] } | { type: SERVICE_HUB_LIST_ACTIONS.SET_SERVICES, payload: ServiceHubTableListItem[] } | { type: SERVICE_HUB_LIST_ACTIONS.SET_SELECTED_CATE, payload: string[] } @@ -40,7 +38,6 @@ export type ServiceHubListActionType = export const initialServiceHubListState = { categoriesList: [] as CategorizesType[], tagsList: [] as TagType[], - partitionList: [] as PartitionItem[], servicesList: [] as ServiceHubTableListItem[], showServicesList: [] as ServiceHubTableListItem[], selectedCate: [] as string[], @@ -58,8 +55,6 @@ export const initialServiceHubListState = { return { ...state, categoriesList: action.payload , getCateAndTagData:true}; case SERVICE_HUB_LIST_ACTIONS.GET_TAGS: return { ...state, tagsList: action.payload , getCateAndTagData:true}; - case SERVICE_HUB_LIST_ACTIONS.GET_PARTITIONS: - return { ...state, partitionList: action.payload, getPartitionData:true }; case SERVICE_HUB_LIST_ACTIONS.GET_SERVICES: return { ...state, servicesList: action.payload }; case SERVICE_HUB_LIST_ACTIONS.SET_SERVICES: @@ -89,7 +84,6 @@ export const initialServiceHubListState = { if((!x.tags || !x.tags.length )&& dataSet.selectedTag.indexOf('empty') === -1) return false if(x.tags && x.tags.length && !x.tags.some(tag => dataSet.selectedTag.includes(tag.id))) return false; if(!dataSet.selectedPartition || dataSet.selectedPartition.length === 0) return false - if(x.partitions && x.partitions.length && !x.partitions.some(partition => dataSet.selectedPartition.includes(partition.id))) return false; if( dataSet.keyword && !x.name.includes(dataSet.keyword)) return false return true }) @@ -188,7 +182,7 @@ export default ServiceHubList const CardTitle = (service:ServiceHubTableListItem)=>{ return(
- : undefined}> {service.logo ? '' : service.name.substring(0,1)} + : undefined}> {service.logo ? '' : service.name.substring(0,1)}

{service.name}

diff --git a/frontend/packages/market/src/pages/serviceHub/management/ApprovalModalContent.tsx b/frontend/packages/market/src/pages/serviceHub/management/ApprovalModalContent.tsx new file mode 100644 index 0000000..e54d7c0 --- /dev/null +++ b/frontend/packages/market/src/pages/serviceHub/management/ApprovalModalContent.tsx @@ -0,0 +1,93 @@ + +import { App, Form, Row, Col, Input } from "antd" +import { forwardRef, useImperativeHandle, useEffect } from "react" +import WithPermission from "@common/components/aoplatform/WithPermission" +import { BasicResponse, STATUS_CODE } from "@common/const/const" +import { useFetch } from "@common/hooks/http" +import { SYSTEM_SUBSCRIBE_APPROVAL_DETAIL_LIST } from "@core/const/system/const" +import { SubSubscribeApprovalModalHandle, SubSubscribeApprovalModalProps } from "@core/const/system/type" + +type FieldType = { + reason: string + opinion?:string +} + +export const ApprovalModalContent = forwardRef((props, ref) => { + const { message } = App.useApp() + const {data, type, serviceId, teamId} = props + const [form] = Form.useForm(); + const {fetchData} = useFetch() + + const reApply:()=>Promise = ()=>{ + return new Promise((resolve, reject)=>{ + if(type === 'view'){ + resolve(true) + return + } + form.validateFields().then((value)=>{ + fetchData>('catalogue/service/subscribe',{method: 'POST',eoParams:{team:teamId}, eoBody:({service:data!.service.id, applications:[serviceId], reason:value.reason})}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || '操作成功!') + resolve(true) + }else{ + message.error(msg || '操作失败') + reject(msg || '操作失败') + } + }).catch((errorInfo)=> reject(errorInfo)) + }).catch((errorInfo)=> reject(errorInfo)) + }) + } + + useImperativeHandle(ref, ()=>({ + reApply + }) + ) + + useEffect(()=>{ + form.setFieldsValue({...data}) + },[]) + + + return ( +
+ + + + {SYSTEM_SUBSCRIBE_APPROVAL_DETAIL_LIST?.map((x)=>{ + return ( + + {x.title}: + {/* {showData(x)} */} + {x.nested ? data?.[x.key]?.[x.nested] : ( (data as {[k:string]:unknown})?.[x.key] || '-')} + ) + })} + + + label="申请原因" + name="reason" + > + + + + label="审核意见" + name="opinion" + > + + + + +
+ ) +}) \ No newline at end of file diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementAppSetting.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementAppSetting.tsx index 877c4ee..e995f4e 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ManagementAppSetting.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementAppSetting.tsx @@ -1,9 +1,3 @@ -/* - * @Date: 2024-06-06 11:47:47 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-06 14:13:32 - * @FilePath: \frontend\packages\market\src\pages\serviceHub\management\ManagementAppSetting.tsx - */ import { RouterParams } from "@core/components/aoplatform/RenderRoutes"; import { useParams } from "react-router-dom"; import ManagementConfig from "./ManagementConfig"; @@ -12,7 +6,7 @@ export default function ManagementAppSetting(){ const {teamId,appId} = useParams() return ( -
+
应用管理
diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityConfig.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityConfig.tsx new file mode 100644 index 0000000..142dabd --- /dev/null +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityConfig.tsx @@ -0,0 +1,261 @@ +import {forwardRef, useEffect, useImperativeHandle, useState} from "react"; +import {App, Checkbox, Form, Input, Select,Switch} from "antd"; +import moment from "moment"; +import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; +import {useFetch} from "@common/hooks/http.ts"; +import DatePicker from "@common/components/aoplatform/DatePicker.tsx"; +import WithPermission from "@common/components/aoplatform/WithPermission.tsx"; +import { v4 as uuidv4} from 'uuid'; +import { ALGORITHM_ITEM } from "@core/const/system/const.tsx"; +import { EditAuthFieldType } from "@core/const/system/type"; + +export type ManagementAuthorityConfigProps = { + type:'add'|'edit' + data?:EditAuthFieldType + appId:string + teamId:string +} + +export type ManagementAuthorityConfigHandle = { + save:()=>Promise +} + +export const ManagementAuthorityConfig = forwardRef((props,ref)=>{ + const { message } = App.useApp() + const {type, data,appId, teamId} = props + const [form] = Form.useForm(); + const [driver, setDriver]=useState('basic') + const [algorithm, setAlgorithm] = useState('HS256') + const [, forceUpdate] = useState(null); + const {fetchData} = useFetch() + + const save :()=>Promise = ()=>{ + return new Promise((resolve, reject)=>{ + form.validateFields().then((value)=>{ + fetchData>('app/authorization',{method:type === 'add'? 'POST' : 'PUT',eoBody:({...value,expireTime:value.expireTime ? value.expireTime.unix() : 0}), eoParams:type === 'add' ? {app:appId,team:teamId}:{authorization:data!.id,app:appId,team:teamId},eoTransformKeys:['hideCredential','expireTime','tokenName','userName']}).then(response=>{ + const {code,msg} = response + if(code === STATUS_CODE.SUCCESS){ + message.success(msg || '操作成功!') + resolve(true) + }else{ + message.error(msg || '操作失败') + reject(msg || '操作失败') + } + }).catch((errorInfo)=> reject(errorInfo)) + }).catch((errorInfo)=> reject(errorInfo)) + })} + + useImperativeHandle(ref, ()=>({ + save + }) + ) + + const prefixSelector = ( + + + + ); + + const onAlgorithmChange = (algorithm:string)=>{ + setAlgorithm(algorithm) + } + + const onDriverChange = (driver:string)=>{ + setDriver(driver) + if(driver === 'jwt' && !form.getFieldValue(['config','algorithm'])){ + form.setFieldValue(['config','algorithm'],'HS256') + forceUpdate({}) + } + } + + + const disabledDate = (current: moment.Moment | null): boolean => { + // 禁用今天以前的日期,包括今天 + // 使用current?.startOf('day')是为了获取日期的开始时间点,以确保整个今天都被禁用 + // 如果只需要禁用今天之前的日期(今天可选),则可以将`isBefore`的第二个参数设置为 'day' + return current ? current.startOf('day') < moment().startOf('day') : false; + }; + + + useEffect(() => { + //console.log(data) + if(type === 'edit' && data){ + form.setFieldsValue({...data,expireTime:data.expireTime === 0 ? '' : moment(data.expireTime *1000)}) + forceUpdate({}) + }else{ + form.setFieldsValue({driver, position:'Header',tokenName:'Authorization'}) + form.setFieldValue(['config','userName'],uuidv4()) + form.setFieldValue(['config','password'],uuidv4()) + form.setFieldValue(['config','apikey'],uuidv4()) + forceUpdate({}) + } + }, []); + + return ( + // +
+ + label="名称" + name="name" + rules={[{required: true, message: '必填项',whitespace:true }]} + > + + + + + label="鉴权类型" + name="driver" + rules={[{required: true, message: '必填项'}]} + > + + + + {(()=>{ + switch(form.getFieldValue('driver')){ + case 'basic': + return <> + + label="用户名" + name={['config','userName']} + rules={[{required: true, message: '必填项',whitespace:true }]} + > + + + + + label="密码" + name={['config','password']} + rules={[{required: true, message: '必填项',whitespace:true }]} + > + + + + case 'jwt': + return <> + + label="Iss" + name={['config','iss']} + rules={[{required: true, message: '必填项'}]} + > + + + + + label="签名算法" + name={['config','algorithm']} + rules={[{required: true, message: '必填项'}]} + > + + + + + label="用户名" + name={['config','user']} + > + + + + + label="用户名 JsonPath" + name={['config','userPath']} + > + + + + + label="校验字段" + name={['config','claimsToVerify']} + > + + + + + label="SK" + name={['config','sk']} + rules={[{required: true, message: '必填项'}]} + > + + + + case 'apikey': + return <> + + label="Apikey" + name={['config','apikey']} + rules={[{required: true, message: '必填项',whitespace:true }]} + > + + + + } + + })()} + + + label="过期时间" + name="expireTime" + > + + + + + label="隐藏鉴权信息" + name="hideCredential" valuePropName="checked" + > + + + + //
+ ); +}) \ No newline at end of file diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityView.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityView.tsx new file mode 100644 index 0000000..f5133a8 --- /dev/null +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementAuthorityView.tsx @@ -0,0 +1,26 @@ +import {Col, Row} from "antd"; +import {useEffect, useState} from "react"; + +export type ManagementAuthorityViewProps = { + entity:Array<{key:string, value:string}> +} + +export const ManagementAuthorityView = ({entity}:ManagementAuthorityViewProps)=>{ + const [detail,setDetail] = useState>(entity) + + useEffect(() => { + setDetail(entity) + }, [entity]); + + return ( +
{ + detail?.length > 0 && detail.map((k,i)=>( + + {k.key}: + { k.value || '-'} + + )) + } +
+ ) +} \ No newline at end of file diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementConfig.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementConfig.tsx index ecae914..b1ee7a8 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ManagementConfig.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementConfig.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-01-31 15:00:11 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-06 14:40:21 - * @FilePath: \frontend\packages\market\src\pages\serviceHub\management\ManagementConfig.tsx - */ + import {App, Button, Divider, Form, Input, Row} from "antd"; import {forwardRef, useEffect, useImperativeHandle, useState} from "react"; import {v4 as uuidv4} from 'uuid' @@ -43,12 +38,12 @@ const ManagementConfig = forwardRefPromise = ()=>{ return new Promise((resolve, reject)=>{ form.validateFields().then((value)=>{ - fetchData>(type === 'add'? 'team/app' : 'app/info',{method:type === 'add'? 'POST' : 'PUT',eoBody:(value), eoParams:type === 'add' ? {team:teamId}:{app:appId}}).then(response=>{ + fetchData>(type === 'add'? 'team/app' : 'app/info',{method:type === 'add'? 'POST' : 'PUT',eoBody:(value), eoParams:type === 'add' ? {team:teamId}:{app:appId,team:teamId}}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') - form.setFieldsValue(data.projects) - type === 'edit' && setAppName(data.projects.name) + form.setFieldsValue(data.apps) + type === 'edit' && setAppName(data.apps.name) resolve(true) }else{ message.error(msg || '操作失败') @@ -61,11 +56,11 @@ const ManagementConfig = forwardRef { - fetchData>('app/info',{method:'GET',eoParams:{app:appId},eoTransformKeys:['as_app']}).then(response=>{ + fetchData>('app/info',{method:'GET',eoParams:{app:appId,team:teamId},eoTransformKeys:['as_app']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ - setAppName(data.project.name) - setTimeout(()=>{form.setFieldsValue({...data.project})},0) + setAppName(data.app.name) + setTimeout(()=>{form.setFieldsValue({...data.app})},0) }else{ message.error(msg || '操作失败') } @@ -96,7 +91,7 @@ const ManagementConfig = forwardRef{ - fetchData>('app',{method:'DELETE',eoParams:{app:appId}}).then(response=>{ + fetchData>('app',{method:'DELETE',eoParams:{app:appId,team:teamId}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -121,7 +116,7 @@ const ManagementConfig = forwardRef
- {/* */} + - {/* */} + }
@@ -177,9 +172,9 @@ const ManagementConfig = forwardRef

删除应用之后将无法找回,请谨慎操作!

- {/* */} + - {/* */} +
} diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideAuth.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideAuth.tsx index ad15bd5..db87377 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideAuth.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideAuth.tsx @@ -1,9 +1,3 @@ -/* - * @Date: 2024-05-30 18:19:04 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-06 17:08:00 - * @FilePath: \frontend\packages\market\src\pages\serviceHub\management\ManagementInsideAuth.tsx - */ import { MoreOutlined } from "@ant-design/icons" import { message, Card, Button, Tag, Dropdown, App, Empty } from "antd" import { useState, useEffect, forwardRef, useRef } from "react" @@ -11,26 +5,29 @@ import { VirtuosoGrid } from "react-virtuoso" import { BasicResponse, STATUS_CODE } from "@common/const/const" import { useBreadcrumb } from "@common/contexts/BreadcrumbContext" import { useFetch } from "@common/hooks/http" -import { EditAuthFieldType, SystemAuthorityConfigHandle, SystemAuthorityTableListItem } from "@core/const/system/type" +import { EditAuthFieldType, SystemAuthorityTableListItem } from "@core/const/system/type" import { Link, useParams } from "react-router-dom" import { RouterParams } from "@core/components/aoplatform/RenderRoutes" import moment from "moment" -import { SystemAuthorityConfig } from "@core/pages/system/authority/SystemAuthorityConfig" -import { SystemAuthorityView } from "@core/pages/system/authority/SystemAuthorityView" import { useTenantManagementContext } from "../../../contexts/TenantManagementContext" +import { ManagementAuthorityConfig, ManagementAuthorityConfigHandle } from "./ManagementAuthorityConfig" +import { ManagementAuthorityView } from "./ManagementAuthorityView" +import { checkAccess } from "@common/utils/permission" +import { useGlobalContext } from "@common/contexts/GlobalStateContext" export default function ManagementInsideAuth(){ const {modal} = App.useApp() const {fetchData} = useFetch() const [authList, setAuthList] = useState([]) const {appId,teamId} = useParams() - const addRef = useRef(null) - const editRef = useRef(null) + const addRef = useRef(null) + const editRef = useRef(null) const {appName} = useTenantManagementContext() + const {accessData} = useGlobalContext() const getSystemAuthority = ()=>{ - return fetchData>('project/authorizations',{method:'GET',eoParams:{project:appId},eoTransformKeys:['hide_credential','create_time','update_time','expire_time']}).then(response=>{ + return fetchData>('app/authorizations',{method:'GET',eoParams:{app:appId, team:teamId},eoTransformKeys:['hide_credential','create_time','update_time','expire_time']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ setAuthList(data.authorizations) @@ -49,7 +46,7 @@ export default function ManagementInsideAuth(){ const deleteAuthority = (entity:SystemAuthorityTableListItem)=>{ return new Promise((resolve, reject)=>{ - fetchData>('project/authorization',{method:'DELETE',eoParams:{authorization:entity!.id,project:appId}}).then(response=>{ + fetchData>('app/authorization',{method:'DELETE',eoParams:{authorization:entity!.id,app:appId, team:teamId}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -70,10 +67,10 @@ export default function ManagementInsideAuth(){ case 'view':{ title='鉴权详情' message.loading('正在加载数据') - const {code,data,msg} = await fetchData>('project/authorization/details',{method:'GET',eoParams:{authorization:entity!.id,project:appId}}) + const {code,data,msg} = await fetchData>('app/authorization/details',{method:'GET',eoParams:{authorization:entity!.id,app:appId, team:teamId}}) message.destroy() if(code === STATUS_CODE.SUCCESS){ - content= + content= }else{ message.error(msg || '操作失败') return @@ -81,15 +78,15 @@ export default function ManagementInsideAuth(){ break; case 'add': title='添加鉴权' - content= + content= break; case 'edit':{ title='编辑鉴权' message.loading('正在加载数据') - const {code,data,msg} = await fetchData>('project/authorization',{method:'GET',eoParams:{authorization:entity!.id,project:appId},eoTransformKeys:['hide_credential','token_name','expire_time','user_name','public_key','user_path','claims_to_verify','signature_is_base64']}) + const {code,data,msg} = await fetchData>('app/authorization',{method:'GET',eoParams:{authorization:entity!.id,app:appId, team:teamId},eoTransformKeys:['hide_credential','token_name','expire_time','user_name','public_key','user_path','claims_to_verify','signature_is_base64']}) message.destroy() if(code === STATUS_CODE.SUCCESS){ - content= + content= }else{ message.error(msg || '操作失败') return @@ -119,7 +116,7 @@ export default function ManagementInsideAuth(){ width:600, okText: '确认', okButtonProps:{ - // disabled : !checkAccess( `project.mySystem.auth.${type}`, accessData) + disabled : !checkAccess( `team.application.authorization.${type}`, accessData) }, cancelText:type === 'view'? '关闭':'取消', closable:true, @@ -139,7 +136,7 @@ export default function ManagementInsideAuth(){ { key: 'edit', label: ( - // + // @@ -149,7 +146,7 @@ export default function ManagementInsideAuth(){ { key: 'delete', label: ( - // + // @@ -158,7 +155,7 @@ export default function ManagementInsideAuth(){ }, ] - return (
+ return (
访问授权
{authList && authList.length > 0 ? ) }} - /> :
} + /> :
}
) } \ No newline at end of file diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsidePage.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsidePage.tsx index f03a92f..51c868b 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsidePage.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsidePage.tsx @@ -1,10 +1,5 @@ -/* - * @Date: 2024-05-30 18:18:40 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-07 17:37:01 - * @FilePath: \frontend\packages\market\src\pages\serviceHub\management\ManagementInsidePage.tsx - */ -import { ApiOutlined, ArrowLeftOutlined, LoadingOutlined } from "@ant-design/icons"; + +import { ArrowLeftOutlined, LoadingOutlined } from "@ant-design/icons"; import { App, Button, Menu, MenuProps, Spin } from "antd"; import { useState, useEffect, useMemo } from "react"; import { Link, Outlet, useLocation, useNavigate, useParams } from "react-router-dom"; @@ -13,75 +8,44 @@ import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"; import { useFetch } from "@common/hooks/http"; import { ItemType } from "antd/es/breadcrumb/Breadcrumb"; import { TENANT_MANAGEMENT_APP_MENU } from "../../../const/serviceHub/const"; -import { EntityItem, SimpleTeamItem } from "@common/const/type"; import { RouterParams } from "@core/components/aoplatform/RenderRoutes"; -import { getItem } from "@common/utils/navigation"; import { useTenantManagementContext } from "@market/contexts/TenantManagementContext"; import { ManagementConfigFieldType } from "./ManagementConfig"; +import { useGlobalContext } from "@common/contexts/GlobalStateContext"; export default function ManagementInsidePage(){ const { message } = App.useApp() const {fetchData} = useFetch() const { setBreadcrumb} = useBreadcrumb() - const [activeMenu, setActiveMenu] = useState() - const [partitionList, setPartitionList] = useState([]) - const {partitionId,appId,teamId} = useParams() + const [activeMenu, setActiveMenu] = useState('service') + const {appId,teamId} = useParams() const navigateTo = useNavigate() const currentUrl = useLocation().pathname const [openKeys, setOpenKeys] = useState([]) const [loading, setLoading] = useState(false) const {appName,setAppName} = useTenantManagementContext() + const {getTeamAccessData,cleanTeamAccessData} = useGlobalContext() - const getPartitionList = ()=>{ - setLoading(true) - fetchData>('simple/application/partitions',{method:'GET',eoParams:{application:appId},eoTransformKeys:['service_num']}).then(response=>{ - const {code,data,msg} = response - if(code === STATUS_CODE.SUCCESS){ - setPartitionList(data.partitions?.map((x:SimpleTeamItem)=>({label:
{x.name}{x.serviceNum || 0}
, key:x.id}))) - if(!partitionId && !activeMenu){ - data.partitions&&data.partitions.length > 0 ? navigateTo(`service/${data.partitions[0].id}`) :navigateTo('authorization') - return - } - }else{ - message.error(msg || '操作失败') - } - }).finally(()=>{ - setLoading(false) - }) -} - const menuData = useMemo(()=>{ - if(!partitionList || partitionList.length === 0) return TENANT_MANAGEMENT_APP_MENU - setOpenKeys(['service']) - const serviceMenu = getItem('订阅的服务', 'service', , partitionList as unknown as ItemType[]) - return [serviceMenu,...TENANT_MANAGEMENT_APP_MENU as unknown[]] - },[partitionList]) + return TENANT_MANAGEMENT_APP_MENU + },[]) + + useEffect(()=>{ + setActiveMenu(currentUrl.split('/').pop() || 'service') + },[currentUrl]) const onMenuClick: MenuProps['onClick'] = (node) => { setActiveMenu(node.key) - if(['authorization','setting'].includes(node.key)){ navigateTo(`/tenantManagement/${teamId}/inside/${appId}/${node.key}`) - }else{ - navigateTo(`/tenantManagement/${teamId}/inside/${appId}/service/${node.key}`) - } }; - - useEffect(()=>{ - if(!partitionId && currentUrl.includes('authorization')){ - setActiveMenu('authorization') - }else if(partitionId){ - setActiveMenu(partitionId) - } - },[currentUrl]) - useEffect(()=>{ const fetchDataAsync = async () => { let _appName = appName if(appId && !appName && !currentUrl.includes('setting')){ - const {code,data} = await fetchData>('app/info',{method:'GET',eoParams:{app:appId},eoTransformKeys:['as_app']}) + const {code,data} = await fetchData>('app/info',{method:'GET',eoParams:{app:appId,team:teamId},eoTransformKeys:['as_app']}) if(code === STATUS_CODE.SUCCESS){ - _appName = data.project.name + _appName = data.app.name setAppName(_appName) } } @@ -96,9 +60,15 @@ export default function ManagementInsidePage(){ }, [appId,appName]) - useEffect(() => { - getPartitionList() - }, [appId]); + +useEffect(()=>{ + if(teamId ){ + getTeamAccessData(teamId) + } + return ()=>{ + cleanTeamAccessData() + } +},[teamId]) return (<> } spinning={loading}> @@ -116,8 +86,8 @@ export default function ManagementInsidePage(){ items={menuData as unknown as ItemType[] } />
-
- getPartitionList()}}> +
+ {}}}>
) diff --git a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideService.tsx b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideService.tsx index 5dc52bb..9a9305d 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideService.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ManagementInsideService.tsx @@ -1,9 +1,3 @@ -/* - * @Date: 2024-05-30 18:18:52 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-06 17:09:14 - * @FilePath: \frontend\packages\market\src\pages\serviceHub\management\ManagementInsideService.tsx - */ import { MoreOutlined, SearchOutlined } from "@ant-design/icons" import { Card, Input,Button ,Dropdown,App, Tag, Empty } from "antd" import { debounce } from "lodash-es" @@ -13,22 +7,25 @@ import { BasicResponse, STATUS_CODE } from "@common/const/const" import { useBreadcrumb } from "@common/contexts/BreadcrumbContext" import { useFetch } from "@common/hooks/http" import { SubscribeApprovalInfoType } from "@common/const/approval/type" -import { SubSubscribeApprovalModalContent } from "@core/pages/system/subSubscribe/SubSubscribeApprovalDetailModalContent" import { Link, useNavigate, useOutletContext, useParams } from "react-router-dom" import { RouterParams } from "@core/components/aoplatform/RenderRoutes" import { TenantManagementServiceListItem } from "../../../const/serviceHub/type" import { useTenantManagementContext } from "../../../contexts/TenantManagementContext" +import { ApprovalModalContent } from "./ApprovalModalContent" +import { checkAccess } from "@common/utils/permission" +import { useGlobalContext } from "@common/contexts/GlobalStateContext" export default function ManagementInsideService(){ const {message, modal} = App.useApp() const [serviceList, setServiceList] = useState([]) const {fetchData} = useFetch() const { setBreadcrumb} = useBreadcrumb() - const {teamId,appId,partitionId} = useParams() + const {teamId,appId} = useParams() const navigateTo = useNavigate() const [keyword, setKeyword] = useState('') const { refreshGroup} = useOutletContext<{refreshGroup:()=>void,appName:string}>() const {appName} = useTenantManagementContext() + const {accessData} = useGlobalContext() const onSearchWordChange = (e)=>{ setKeyword(e.target.value) @@ -37,7 +34,7 @@ export default function ManagementInsideService(){ const cancelSubscribeApply = (entity:TenantManagementServiceListItem) => { return new Promise((resolve, reject)=>{ - fetchData>('application/subscription/cancel_apply',{method:'POST',eoParams:{subscription:entity.id!,application:appId!}}).then(response=>{ + fetchData>('application/subscription/cancel_apply',{method:'POST',eoParams:{subscription:entity.id!,application:appId!,team:teamId}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -52,7 +49,7 @@ export default function ManagementInsideService(){ const cancelSubscribe = (entity:TenantManagementServiceListItem) => { return new Promise((resolve, reject)=>{ - fetchData>('application/subscription/cancel',{method:'POST',eoParams:{subscription:entity.id!,application:appId!}}).then(response=>{ + fetchData>('application/subscription/cancel',{method:'POST',eoParams:{subscription:entity.id!,application:appId!,team:teamId}}).then(response=>{ const {code,msg} = response if(code === STATUS_CODE.SUCCESS){ message.success(msg || '操作成功!') @@ -66,17 +63,16 @@ export default function ManagementInsideService(){ } const openModal =async (type:'view'|'cancelSub'|'cancelSubApply',entity?:TenantManagementServiceListItem)=>{ - //console.log(type,entity) let title:string = '' let content:string|React.ReactNode = '' switch (type){ case 'view':{ message.loading('正在加载数据') - const {code,data,msg} = await fetchData>('project/subscription/approval',{method:'GET',eoParams:{subscription:entity!.id, project:appId},eoTransformKeys:['apply_project','apply_team','apply_time','approval_time']}) + const {code,data,msg} = await fetchData>('app/subscription/approval',{method:'GET',eoParams:{subscription:entity!.id, app:appId,team:teamId},eoTransformKeys:['apply_project','apply_team','apply_time','approval_time']}) message.destroy() if(code === STATUS_CODE.SUCCESS){ title='审批详情' - content = ; + content = ; }else{ message.error(msg || '操作失败') return @@ -109,7 +105,7 @@ export default function ManagementInsideService(){ width:600, okText:'确认', okButtonProps:{ - // disabled : !checkAccess( `project.mySystem.auth.${type}`, accessData) + disabled : !checkAccess( `team.application.authorization.${type}`, accessData) }, cancelText:'取消', closable:true, @@ -122,7 +118,7 @@ export default function ManagementInsideService(){ // { // key: 'edit', // label: ( - // // + // // // @@ -132,7 +128,7 @@ export default function ManagementInsideService(){ entity.applyStatus === 1 ? { key: 'cancelSubApply', label: ( - // + // @@ -141,7 +137,7 @@ export default function ManagementInsideService(){ }:{ key: 'cancelSub', label: ( - // + // @@ -151,7 +147,7 @@ export default function ManagementInsideService(){ ] const getServiceList = ()=>{ - fetchData>('application/subscriptions',{method:'GET', eoParams:{application:appId,partition:partitionId},eoTransformKeys:['apply_status']}).then(response=>{ + fetchData>('application/subscriptions',{method:'GET', eoParams:{application:appId,team:teamId},eoTransformKeys:['apply_status']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ setServiceList(data.subscriptions && data.subscriptions.length > 0 ? [...data.subscriptions] : []) @@ -166,9 +162,9 @@ export default function ManagementInsideService(){ useEffect(() => { getServiceList() - }, [partitionId]); + }, []); - return (
+ return (
服务 debounce(onSearchWordChange, 100)(e) : undefined } onPressEnter={()=>getServiceList()} allowClear placeholder='搜索服务' prefix={{getServiceList()}}/>}/> diff --git a/frontend/packages/market/src/pages/serviceHub/management/ServiceHubManagement.tsx b/frontend/packages/market/src/pages/serviceHub/management/ServiceHubManagement.tsx index b6e65b7..818fbc0 100644 --- a/frontend/packages/market/src/pages/serviceHub/management/ServiceHubManagement.tsx +++ b/frontend/packages/market/src/pages/serviceHub/management/ServiceHubManagement.tsx @@ -1,5 +1,4 @@ -import { ApiOutlined, PlusOutlined } from "@ant-design/icons"; -import { MenuProps, Menu, App, Avatar, Card, Tooltip } from "antd"; +import { MenuProps, Menu, App, Avatar, Card, Tooltip, Empty } from "antd"; import { useState, forwardRef, useEffect, useRef } from "react"; import { VirtuosoGrid } from "react-virtuoso"; import { BasicResponse, STATUS_CODE } from "@common/const/const"; @@ -11,6 +10,8 @@ import { useNavigate, useParams } from "react-router-dom"; import { RouterParams } from "@core/components/aoplatform/RenderRoutes"; import { SimpleTeamItem } from "@common/const/type"; import { useTenantManagementContext } from "../../../contexts/TenantManagementContext"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import { useGlobalContext } from "@common/contexts/GlobalStateContext"; export default function ServiceHubManagement() { const { message ,modal} = App.useApp() @@ -24,16 +25,17 @@ export default function ServiceHubManagement() { const [teamList, setTeamList] = useState([]) const {setAppName} = useTenantManagementContext() const navigateTo = useNavigate() -type MenuItem = Required['items'][number]; + const {getTeamAccessData,cleanTeamAccessData} = useGlobalContext() + type MenuItem = Required['items'][number]; const getServiceList = ()=>{ //console.log(pagination,sorter,categoryId,tagId) setServiceLoading(true) - fetchData>('my_apps',{method:'GET', eoParams:{ team:teamId,keyword:''},eoTransformKeys:['api_num','subscribe_num','subscribe_verify_num']}).then(response=>{ + fetchData>('my_apps',{method:'GET', eoParams:{ team:teamId,keyword:''},eoTransformKeys:['api_num','subscribe_num','subscribe_verify_num']}).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ - setServiceList([...data.projects,{type:'addNewItem'}]) + setServiceList([...data.apps,{type:'addNewItem'}]) }else{ message.error(msg || '操作失败') } @@ -53,7 +55,7 @@ const getServiceList = ()=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ setTeamList(data.teams.map((x:SimpleTeamItem)=>({label:
{x.name}{x.appNum || 0}
, key:x.id}))) - if(!teamId){ + if(!teamId && data.teams?.[0]?.id){ navigateTo(data.teams[0].id) } }else{ @@ -114,7 +116,13 @@ const getServiceList = ()=>{ } useEffect(()=>{ - teamId && getServiceList() + if(teamId ){ + getTeamAccessData(teamId) + getServiceList() + } + return ()=>{ + cleanTeamAccessData() + } },[teamId]) useEffect(() => { @@ -125,10 +133,10 @@ useEffect(() => { ) getTeamsList() setAppName('') - // getServiceList() }, []); - return (<> + return (<>{ + teamList && teamList.length > 0 ?
团队
@@ -152,8 +160,8 @@ useEffect(() => { return (
{ item.type === 'addNewItem' ?{openModal('add')}}> -
添加应用
-
: {setAppName(item.name);navigateTo(`/tenantManagement/${teamId}/inside/${item.id}`)}}> +
添加应用
+
: {setAppName(item.name);navigateTo(`/tenantManagement/${teamId}/inside/${item.id}/service`)}}> {item.description || '暂无服务描述'} }
@@ -183,13 +191,15 @@ useEffect(() => { }} />
-
) +
: + + } + ) } const CardTitle = (service:ServiceHubAppListItem)=>{ return(
- {/* {service?.name?.substring(0,1)} */} } />

{service.name}

diff --git a/frontend/packages/market/vite.config.ts b/frontend/packages/market/vite.config.ts index 1b55653..a1c1546 100644 --- a/frontend/packages/market/vite.config.ts +++ b/frontend/packages/market/vite.config.ts @@ -1,9 +1,4 @@ -/* - * @Date: 2024-01-31 15:00:39 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-07 09:56:57 - * @FilePath: \frontend\packages\market\vite.config.ts - */ + import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import path from 'path' diff --git a/frontend/packages/openApi/src/pages/OpenApiConfig.tsx b/frontend/packages/openApi/src/pages/OpenApiConfig.tsx index 79102de..e8afd6f 100644 --- a/frontend/packages/openApi/src/pages/OpenApiConfig.tsx +++ b/frontend/packages/openApi/src/pages/OpenApiConfig.tsx @@ -1,9 +1,4 @@ -/* - * @Date: 2024-01-31 15:00:11 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-04 11:55:42 - * @FilePath: \frontend\packages\core\src\pages\openApi\OpenApiConfig.tsx - */ + import {App, Form, Input} from "antd"; import {forwardRef, useEffect, useImperativeHandle} from "react"; import {BasicResponse, STATUS_CODE} from "@common/const/const.ts"; diff --git a/frontend/packages/systemRunning/src/pages/SystemRunning.tsx b/frontend/packages/systemRunning/src/pages/SystemRunning.tsx index 3f9a793..ed0be46 100644 --- a/frontend/packages/systemRunning/src/pages/SystemRunning.tsx +++ b/frontend/packages/systemRunning/src/pages/SystemRunning.tsx @@ -1,9 +1,3 @@ -/* - * @Date: 2024-03-15 10:53:52 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-07-12 20:01:30 - * @FilePath: \frontend\packages\systemRunning\src\pages\SystemRunning.tsx - */ import { useRef, useState, useEffect, useCallback } from "react"; import { useFetch } from "@common/hooks/http.ts"; @@ -77,7 +71,7 @@ export default function SystemRunning(){ const {message} = App.useApp() const graphRef = useRef(null); const graphContainerRef = useRef(null); - const {partitionId,topologyId} = useParams() + const {topologyId} = useParams() const [graph, setGraph] = useState(null); const [graphData, setGraphData] = useState(); const [currentNode, setCurrentNode] = useState() @@ -237,7 +231,7 @@ export default function SystemRunning(){ const getNodeData = ()=>{ setLoading(true) - fetchData>('topology',{method:'GET',eoParams:{id:partitionId},eoTransformKeys:['invoke_services','is_app','is_server']},).then(response=>{ + fetchData>('topology',{method:'GET',eoTransformKeys:['invoke_services','is_app','is_server']},).then(response=>{ const {code,data,msg} = response if(code === STATUS_CODE.SUCCESS){ const newGraphData = relativeFormatter(data) @@ -558,7 +552,7 @@ export default function SystemRunning(){ { showGraph ?
-
+
@@ -573,7 +567,7 @@ export default function SystemRunning(){
- :} spinning={loading}>{!loading && } + :} spinning={loading}>{!loading && } }) } diff --git a/frontend/packages/systemRunning/src/pages/SystemRunningInstruction.tsx b/frontend/packages/systemRunning/src/pages/SystemRunningInstruction.tsx index decc03e..4eb9459 100644 --- a/frontend/packages/systemRunning/src/pages/SystemRunningInstruction.tsx +++ b/frontend/packages/systemRunning/src/pages/SystemRunningInstruction.tsx @@ -1,9 +1,3 @@ -/* - * @Date: 2024-04-02 18:18:12 - * @LastEditors: maggieyyy - * @LastEditTime: 2024-06-07 15:56:27 - * @FilePath: \frontend\packages\core\src\pages\systemRunning\SystemRunningInstruction.tsx - */ import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"; import { useEffect } from "react"; import { Link } from "react-router-dom"; @@ -27,7 +21,7 @@ export default function SystemRunningInstruction() {

内部数据服务设置

支持根据权限,拆分人员对 API 添加 、上游设置、鉴权设置等信息发布及管理;同时支持管理 API 调用服务(包含第三方调用)及订阅;

-

添加内部数据服务信息

+

添加内部数据服务信息