mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
Merge pull request #6 from maggieyyy/main
dashboard && tour && guest_login
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
## 代码同步
|
||||
packages目录下,部分子项目为企业版独有,不要同步到开源版:
|
||||
packages/businessEntry, packages/dashboard, packages/openApi, packages/systemRunning, README.pro.md
|
||||
packages/businessEntry, packages/openApi, packages/systemRunning, README.pro.md
|
||||
|
||||
## 安装依赖
|
||||
建议使用pnpm
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"dev": "lerna run dev --scope=core --stream",
|
||||
"dev:pro": "lerna run dev --scope=business-entry --stream",
|
||||
"stop": "kill-port --port 5000",
|
||||
"scan":"i18next-scanner --config i18next-scanner.config.js"
|
||||
"scan": "i18next-scanner --config i18next-scanner.config.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
@@ -42,6 +42,7 @@
|
||||
"react-ace": "^10.1.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^15.0.1",
|
||||
"react-joyride": "^2.8.2",
|
||||
"react-router-dom": "^6.20.0",
|
||||
"tailwindcss": "^3.3.5",
|
||||
"uuid": "^9.0.1",
|
||||
|
||||
@@ -11,7 +11,6 @@ import {FC,lazy} from 'react';
|
||||
import { TeamProvider } from '@core/contexts/TeamContext.tsx';
|
||||
import SystemOutlet from '@core/pages/system/SystemOutlet.tsx';
|
||||
import { DashboardProvider } from '@core/contexts/DashboardContext.tsx';
|
||||
import { PartitionProvider } from '@core/contexts/PartitionContext.tsx';
|
||||
import { TenantManagementProvider } from '@market/contexts/TenantManagementContext.tsx';
|
||||
|
||||
type RouteConfig = {
|
||||
@@ -182,6 +181,11 @@ const PUBLIC_ROUTES:RouteConfig[] = [
|
||||
key: uuidv4(),
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/publish/SystemInsidePublish.tsx')),
|
||||
children:[
|
||||
{
|
||||
path:'',
|
||||
key: uuidv4(),
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/system/publish/SystemInsidePublishList.tsx')),
|
||||
},
|
||||
{
|
||||
path:'*',
|
||||
key: uuidv4(),
|
||||
@@ -202,6 +206,10 @@ const PUBLIC_ROUTES:RouteConfig[] = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},{
|
||||
path:'dashboardsetting',
|
||||
key: uuidv4(),
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideDashboardSetting.tsx')),
|
||||
},
|
||||
{
|
||||
path:'cluster',
|
||||
@@ -338,16 +346,6 @@ const PUBLIC_ROUTES:RouteConfig[] = [
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@openApi/pages/OpenApiList.tsx')),
|
||||
key:uuidv4(),
|
||||
},
|
||||
{
|
||||
path:'logretrieval',
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/logRetrieval/LogRetrieval.tsx')),
|
||||
key:uuidv4(),
|
||||
},
|
||||
{
|
||||
path:'auditlog',
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/auditLog/AuditLog.tsx')),
|
||||
key:uuidv4(),
|
||||
},
|
||||
{
|
||||
path:'assets',
|
||||
component:<p>设计中</p>,
|
||||
@@ -394,7 +392,7 @@ const PUBLIC_ROUTES:RouteConfig[] = [
|
||||
key: uuidv4(),
|
||||
children:[{
|
||||
path:'template/:moduleId',
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '../../../../common/src/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')),
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@common/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')),
|
||||
key:uuidv4()
|
||||
}]
|
||||
|
||||
@@ -405,10 +403,20 @@ const PUBLIC_ROUTES:RouteConfig[] = [
|
||||
key: uuidv4(),
|
||||
children:[{
|
||||
path:'template/:moduleId',
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '../../../../common/src/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')),
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@common/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')),
|
||||
key:uuidv4()
|
||||
}]
|
||||
|
||||
},
|
||||
{
|
||||
path:'userProfile/*',
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/userProfile/UserProfile.tsx')),
|
||||
key:uuidv4(),
|
||||
children:[{
|
||||
path:'changepsw',
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/userProfile/ChangePsw.tsx')),
|
||||
key:uuidv4()
|
||||
}]
|
||||
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -433,7 +441,7 @@ const generateRoutes = (routerConfig: RouteConfig[]) => {
|
||||
const LazyComponent = route.lazy as React.ExoticComponent<unknown>;
|
||||
|
||||
routeElement = (
|
||||
<Suspense fallback={ <div className=''><Skeleton className='m-btnbase w-[calc(100%-20px)]' active /></div>}>
|
||||
<Suspense fallback={ <div className=''><Skeleton className='m-btnbase w-calc-100vw-minus-padding-r' active /></div>}>
|
||||
{route.provider ? (
|
||||
createElement(route.provider, {}, <LazyComponent />)
|
||||
) : (
|
||||
|
||||
@@ -28,6 +28,6 @@
|
||||
"@businessEntry/*": ["./src/*"],
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TransferTable.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/Navigation.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/GroupTree.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../common/src/components/aoplatform/ScrollableSection.tsx", "../common/src/utils/postcat.tsx", "../common/src/utils/curl.ts", "../common/src/components/aoplatform/ResetPsw.tsx", "../common/src/components/aoplatform/SubscribeApprovalModalContent.tsx", "src/components/aoplatform/RenderRoutes.tsx", "../common/src/components/aoplatform/PublishApprovalModalContent.tsx", "../common/src/components/aoplatform/InsidePage.tsx", "../common/src/const/type.ts", "../common/src/components/aoplatform/intelligent-plugin", "../common/src/const/domain"],
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/Navigation.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../common/src/components/aoplatform/ScrollableSection.tsx", "../common/src/utils/postcat.tsx", "../common/src/utils/curl.ts", "../common/src/components/aoplatform/ResetPsw.tsx", "../common/src/components/aoplatform/SubscribeApprovalModalContent.tsx", "src/components/aoplatform/RenderRoutes.tsx", "../common/src/components/aoplatform/PublishApprovalModalContent.tsx", "../common/src/components/aoplatform/InsidePage.tsx", "../common/src/const/type.ts", "../common/src/components/aoplatform/intelligent-plugin", "../common/src/const/domain"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
||||
@@ -55,10 +55,10 @@ const themeToken = {
|
||||
getNavItem(<a>{$t('API 市场')}</a>, 'serviceHub','/serviceHub',<Icon icon="ic:baseline-hub" width="18" height="18"/>,undefined,undefined,'system.workspace.api_market.view'),
|
||||
]),
|
||||
|
||||
APP_MODE === 'pro' ? getNavItem($t('仪表盘'), 'mainPage', '/dashboard',<Icon icon="ic:baseline-bar-chart" width="18" height="18"/>,[
|
||||
getNavItem(<a >{$t('运行视图')}</a>, 'dashboard','/dashboard',<ProjectFilled />,undefined,undefined,''),
|
||||
getNavItem(<a >{$t('系统拓扑图')}</a>, 'systemrunning','/systemrunning',<ProjectFilled />,undefined,undefined,''),
|
||||
]):null,
|
||||
getNavItem($t('仪表盘'), 'mainPage', APP_MODE === 'pro' ? '/dashboard' : '/dashboard/total',<Icon icon="ic:baseline-bar-chart" width="18" height="18"/>,[
|
||||
getNavItem(<a >{$t('运行视图')}</a>, 'dashboard',APP_MODE === 'pro' ? '/dashboard' : '/dashboard/total' ,<ProjectFilled />,undefined,undefined,'system.dashboard.dashboard.view'),
|
||||
APP_MODE === 'pro' ? getNavItem(<a >{$t('系统拓扑图')}</a>, 'systemrunning','/systemrunning',<ProjectFilled />,undefined,undefined,'system.dashboard.systemrunning.view') : null,
|
||||
]),
|
||||
|
||||
getNavItem($t('系统设置'), 'operationCenter','/member',<Icon icon="ic:baseline-settings" width="18" height="18"/>, [
|
||||
getNavItem($t('组织'), 'organization','/member',null,[
|
||||
@@ -70,6 +70,7 @@ const themeToken = {
|
||||
],undefined,'system.api_market.service_classification.view'),
|
||||
|
||||
getNavItem($t('运维与集成'), 'maintenanceCenter','/cluster', null, [
|
||||
getNavItem(<a>{$t('监控报表')}</a>, 'dashboardsetting','/dashboardsetting',<Icon icon="ic:baseline-monitor-heart" width="18" height="18"/>,undefined,undefined,'system.devops.dashboardsetting.view'),
|
||||
getNavItem(<a>{$t('集群')}</a>, 'cluster','/cluster',<Icon icon="ic:baseline-device-hub" width="18" height="18"/>,undefined,undefined,'system.devops.cluster.view'),
|
||||
getNavItem(<a>{$t('证书')}</a>, 'cert','/cert',<Icon icon="ic:baseline-security" width="18" height="18"/>,undefined,undefined,'system.devops.ssl_certificate.view'),
|
||||
getNavItem(<a>{$t('日志')}</a>, 'logsettings','/logsettings',<Icon icon="ic:baseline-sticky-note-2" width="18" height="18"/>,undefined,undefined,'system.devops.log_configuration.view'),
|
||||
@@ -79,7 +80,6 @@ const themeToken = {
|
||||
]),
|
||||
],[state.language])
|
||||
|
||||
useEffect(()=>{console.log(state.language, $t('工作空间'))},[state.language])
|
||||
|
||||
useEffect(() => {
|
||||
if(currentUrl === '/'){
|
||||
@@ -119,6 +119,7 @@ const themeToken = {
|
||||
|
||||
// 初始过滤操作
|
||||
const res = [...TOTAL_MENU_ITEMS]!.filter(x => x).map((x: any) => (x.routes ? { ...x, routes: filterMenu(x.routes) } : x));
|
||||
console.log(res)
|
||||
// 返回处理后的数据
|
||||
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, state.language]);
|
||||
@@ -196,6 +197,7 @@ const themeToken = {
|
||||
return document.getElementById('test-pro-layout') || document.body;
|
||||
}}
|
||||
>
|
||||
|
||||
<ProLayout
|
||||
prefixCls="apipark-layout"
|
||||
location={{
|
||||
|
||||
@@ -53,7 +53,7 @@ interface PageListProps<T> extends ProTableProps<T, unknown>, RefAttributes<Acti
|
||||
|
||||
|
||||
const PageList = <T extends Record<string, unknown>>(props: React.PropsWithChildren<PageListProps<T>>,ref: React.Ref<ActionType>) => {
|
||||
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 {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<HTMLDivElement>(null);
|
||||
const [tableHeight, setTableHeight] = useState(minVirtualHeight || window.innerHeight);
|
||||
const [tableWidth, setTableWidth] = useState<number|undefined>(undefined);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import JoyRide, { Props } from 'react-joyride'
|
||||
|
||||
const Tour = (props: Partial<Props>) => {
|
||||
return (
|
||||
<>
|
||||
<JoyRide
|
||||
continuous={true}
|
||||
showSkipButton={false}
|
||||
showProgress={true}
|
||||
scrollToFirstStep
|
||||
scrollOffset={400}
|
||||
{...props}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Tour
|
||||
@@ -27,7 +27,7 @@ export const routerKeyMap = new Map<string, string[]|string>([
|
||||
['operationCenter',['member','user','role','servicecategories']],
|
||||
['organization',['member','user','role']],
|
||||
['serviceHubSetting',['servicecategories']],
|
||||
['maintenanceCenter',['partition','logsettings','resourcesettings','openapi']
|
||||
['maintenanceCenter',['dashboardsetting','cluster','cert','logsettings','resourcesettings','openapi']
|
||||
]])
|
||||
|
||||
|
||||
|
||||
@@ -139,6 +139,11 @@ export const PERMISSION_DEFINITION = [
|
||||
"anyOf": [{ "backend": ["system.api_market.service_classification.manager"] }]
|
||||
}
|
||||
},
|
||||
"system.devops.dashboardsetting.view":{
|
||||
"grented":{
|
||||
"anyOf":[{"backend":[]}]
|
||||
}
|
||||
},
|
||||
"system.devops.cluster.view": {
|
||||
"granted": {
|
||||
"anyOf": [{ "backend": ["system.devops.cluster.view"] }]
|
||||
@@ -224,6 +229,16 @@ export const PERMISSION_DEFINITION = [
|
||||
"anyOf": [{ "backend": ["system.workspace.api_market.view"] }]
|
||||
}
|
||||
},
|
||||
"system.dashboard.dashboard.view": {
|
||||
"granted": {
|
||||
"anyOf": [{ "backend": [] }]
|
||||
}
|
||||
},
|
||||
"system.dashboard.systemrunning.view": {
|
||||
"granted": {
|
||||
"anyOf": [{ "backend": [] }]
|
||||
}
|
||||
},
|
||||
"team.service.api.view": {
|
||||
"granted": {
|
||||
"anyOf": [{ "backend": ["team.service.api.view"] }]
|
||||
|
||||
@@ -17,6 +17,8 @@ export const checkAccess:(access:AccessDataType, accessData:Map<string,string[]>
|
||||
}
|
||||
|
||||
const hasIntersection = (arr1:string[], arr2:string[])=> {
|
||||
// 当没有对应后端权限字段时,默认有权限
|
||||
if(arr1.length === 0) return true
|
||||
const set = new Set(arr1.length > arr2.length ? arr2:arr1)
|
||||
const arr = arr1.length > arr2.length ? arr1:arr2
|
||||
for (const item of arr) {
|
||||
|
||||
@@ -91,6 +91,9 @@ module.exports = {
|
||||
'.h-calc-100vh-minus-navbar': {
|
||||
height: 'calc(100vh - var(--layout-header-height))',
|
||||
},
|
||||
'.w-calc-100vw-minus-padding-r': {
|
||||
width: 'calc(100% - 40px)',
|
||||
},
|
||||
}, ['responsive', 'hover']);
|
||||
}
|
||||
],
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'dayjs/locale/zh-cn';
|
||||
import dayjs from 'dayjs';
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useGlobalContext } from '@common/contexts/GlobalStateContext';
|
||||
import Joyride from 'react-joyride';
|
||||
|
||||
type Locale = ConfigProviderProps['locale'];
|
||||
|
||||
@@ -139,6 +140,7 @@ const antdComponentThemeToken = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function App() {
|
||||
const [locale, setLocal] = useState<Locale>(enUS);
|
||||
useInitializeMonaco()
|
||||
|
||||
@@ -11,8 +11,6 @@ import {useGlobalContext} from "@common/contexts/GlobalStateContext.tsx";
|
||||
import {FC,lazy} from 'react';
|
||||
import { TeamProvider } from '@core/contexts/TeamContext.tsx';
|
||||
import SystemOutlet from '@core/pages/system/SystemOutlet.tsx';
|
||||
import { DashboardProvider } from '@core/contexts/DashboardContext.tsx';
|
||||
import { PartitionProvider } from '@core/contexts/PartitionContext.tsx';
|
||||
import { TenantManagementProvider } from '@market/contexts/TenantManagementContext.tsx';
|
||||
|
||||
type RouteConfig = {
|
||||
@@ -210,6 +208,11 @@ const PUBLIC_ROUTES:RouteConfig[] = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path:'dashboardsetting',
|
||||
key: uuidv4(),
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@core/pages/partitions/PartitionInsideDashboardSetting.tsx')),
|
||||
},
|
||||
{
|
||||
path:'cluster',
|
||||
key: uuidv4(),
|
||||
@@ -343,6 +346,18 @@ const PUBLIC_ROUTES:RouteConfig[] = [
|
||||
component:<p>设计中</p>,
|
||||
key:uuidv4()
|
||||
},
|
||||
{
|
||||
path:'dashboard',
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/Dashboard.tsx')),
|
||||
key:uuidv4(),
|
||||
children:[
|
||||
{
|
||||
path:'total',
|
||||
key:uuidv4(),
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@dashboard/pages/DashboardTotal.tsx')),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path:'template/:moduleId',
|
||||
lazy:lazy(() => import(/* webpackChunkName: "[request]" */ '@common/components/aoplatform/intelligent-plugin/IntelligentPluginList.tsx')),
|
||||
@@ -403,7 +418,7 @@ const generateRoutes = (routerConfig: RouteConfig[]) => {
|
||||
const LazyComponent = route.lazy as React.ExoticComponent<unknown>;
|
||||
|
||||
routeElement = (
|
||||
<Suspense fallback={ <div className=''><Skeleton className='m-btnbase w-[calc(100%-20px)]' active /></div>}>
|
||||
<Suspense fallback={ <div className=''><Skeleton className='m-btnbase w-calc-100vw-minus-padding-r' active /></div>}>
|
||||
{route.provider ? (
|
||||
createElement(route.provider, {}, <LazyComponent />)
|
||||
) : (
|
||||
|
||||
@@ -662,7 +662,7 @@ p{
|
||||
|
||||
.ant-pro-table-list-toolbar-setting-items{
|
||||
position:absolute;
|
||||
top:13px;
|
||||
top:14px;
|
||||
right:16px;
|
||||
z-index:9;
|
||||
.ant-pro-table-list-toolbar-setting-item{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {FC, useCallback, useEffect, useRef, useState} from "react";
|
||||
import {App, Button, Form, FormInstance, Input} from "antd";
|
||||
import {App, Button, Divider, Form, FormInstance, Input, Tooltip} from "antd";
|
||||
import {useGlobalContext} from "@common/contexts/GlobalStateContext.tsx";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
@@ -7,6 +7,7 @@ import {useNavigate} from "react-router-dom";
|
||||
// import {useCrypto} from "../hooks/crypto.ts";
|
||||
import Logo from '@common/assets/logo.png'
|
||||
import { $t } from "@common/locales";
|
||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||
|
||||
const Login:FC = ()=> {
|
||||
const {state, dispatch} = useGlobalContext()
|
||||
@@ -16,16 +17,19 @@ const Login:FC = ()=> {
|
||||
const formRef = useRef<FormInstance>(null);
|
||||
const [loading,setLoading] = useState<boolean>()
|
||||
// const { encryptByEnAES } = useCrypto();
|
||||
const [allowGuest, setAllowGuest] = useState<boolean>(false)
|
||||
|
||||
|
||||
const check = useCallback(()=>{
|
||||
fetchData<BasicResponse<{channel:Array<{name:string}>, status:string}>>('account/login',{method:'GET'}).then(response=>{
|
||||
const {code,data} = response
|
||||
|
||||
if(code === STATUS_CODE.SUCCESS && data.status !== 'anonymous'){
|
||||
dispatch({type:'LOGIN'})
|
||||
navigate(state.mainPage)
|
||||
}else{
|
||||
dispatch({type:'LOGOUT'})
|
||||
setAllowGuest(data.channel.filter(x=>x.name === 'guest_access').length > 0)
|
||||
}
|
||||
})
|
||||
},[])
|
||||
@@ -41,47 +45,54 @@ const Login:FC = ()=> {
|
||||
})
|
||||
},[])
|
||||
|
||||
|
||||
const fetchLogin = async (values:any)=>{
|
||||
try {
|
||||
setLoading(true);
|
||||
const { username, password } = values;
|
||||
// const encryptedPassword = encryptByEnAES(username, password);
|
||||
|
||||
const body = {
|
||||
name:username,
|
||||
password: password
|
||||
// client: 1,
|
||||
// type: 1,
|
||||
// app_type: 4,
|
||||
};
|
||||
|
||||
const {code,msg } = await fetchData<BasicResponse<null>>('account/login/username',{method:'POST',eoBody:(body)})
|
||||
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
dispatch({type:'LOGIN'})
|
||||
message.success(RESPONSE_TIPS.loginSuccess);
|
||||
const callbackUrl = new URLSearchParams(window.location.search).get('callbackUrl');
|
||||
if (callbackUrl && callbackUrl !== 'null') {
|
||||
navigate(callbackUrl);
|
||||
} else {
|
||||
navigate(state.mainPage);
|
||||
}
|
||||
}else{
|
||||
dispatch({type:'LOGOUT'})
|
||||
message.error(msg)
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
const login = async () => {
|
||||
if (formRef.current) {
|
||||
try {
|
||||
const values = await formRef.current.validateFields();
|
||||
setLoading(true);
|
||||
|
||||
const { username, password } = values;
|
||||
// const encryptedPassword = encryptByEnAES(username, password);
|
||||
|
||||
const body = {
|
||||
name:username,
|
||||
password: password
|
||||
// client: 1,
|
||||
// type: 1,
|
||||
// app_type: 4,
|
||||
};
|
||||
|
||||
const {code,msg } = await fetchData<BasicResponse<null>>('account/login/username',{method:'POST',eoBody:(body)})
|
||||
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
dispatch({type:'LOGIN'})
|
||||
message.success(RESPONSE_TIPS.loginSuccess);
|
||||
const callbackUrl = new URLSearchParams(window.location.search).get('callbackUrl');
|
||||
if (callbackUrl && callbackUrl !== 'null') {
|
||||
navigate(callbackUrl);
|
||||
} else {
|
||||
navigate(state.mainPage);
|
||||
}
|
||||
}else{
|
||||
dispatch({type:'LOGOUT'})
|
||||
message.error(msg)
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
const values = await formRef.current.validateFields();
|
||||
fetchLogin(values);
|
||||
}
|
||||
};
|
||||
|
||||
const loginAsGuest = ()=>{
|
||||
fetchLogin({username:'guest',password:'12345678'})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
check()
|
||||
getSystemInfo()
|
||||
@@ -133,15 +144,26 @@ const Login:FC = ()=> {
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<div className=" justify-center">
|
||||
<Form.Item
|
||||
className="p-0 bg-transparent rounded border-none mb-0"
|
||||
>
|
||||
<Button loading={loading} className="h-[40px] mt-mbase w-full inline-flex justify-center items-center" type="primary" htmlType="submit">
|
||||
{$t('登录')}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item
|
||||
className="p-0 bg-transparent rounded border-none "
|
||||
>
|
||||
<Button loading={loading} className="h-[40px] mt-mbase w-full inline-flex justify-center items-center" type="primary" htmlType="submit">
|
||||
{$t('登录')}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
{
|
||||
allowGuest && <>
|
||||
<Divider />
|
||||
|
||||
<Form.Item
|
||||
className="p-0 bg-transparent rounded border-none mb-0"
|
||||
>
|
||||
<Button loading={loading} className="h-[40px] w-full inline-flex justify-center items-center" type="default" onClick={loginAsGuest}>
|
||||
{$t('访客模式')} <Tooltip title={$t('您可通过访客模式查看所有页面和功能,但是无法编辑数据。访客模式仅用于了解产品功能,您可以在正式产品中关闭该功能。')}><Icon icon="ic:baseline-help" height={18} width={18} /></Tooltip>
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</>
|
||||
}
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -59,7 +59,7 @@ const LogSettings = ()=>{
|
||||
|
||||
return (
|
||||
<>
|
||||
<Skeleton className='m-btnbase w-[calc(100%-20px)]' active loading={loading}>
|
||||
<Skeleton className='m-btnbase w-calc-100vw-minus-padding-r' active loading={loading}>
|
||||
<InsidePage
|
||||
pageTitle={$t('日志配置')}
|
||||
description={$t("APIPark 提供详尽的 API 调用日志,帮助企业监控、分析和审计 API 的运行状况。")}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import { App, Form, Input, Select, Button } from "antd";
|
||||
import { useEffect } from "react";
|
||||
import { PartitionDashboardConfigFieldType } from "../../const/partitions/types";
|
||||
import { DASHBOARD_SETTING_DRIVER_OPTION_LIST } from "../../const/partitions/const";
|
||||
import WithPermission from "@common/components/aoplatform/WithPermission";
|
||||
import { BasicResponse, PLACEHOLDER, STATUS_CODE, VALIDATE_MESSAGE } from "@common/const/const";
|
||||
import { useFetch } from "@common/hooks/http";
|
||||
|
||||
export type DashboardPageShowStatus = 'view'|'edit'
|
||||
|
||||
export type DashboardSettingEditHandle = {
|
||||
save:()=>void
|
||||
}
|
||||
export type DashboardSettingEditProps = {
|
||||
changeStatus:(status:DashboardPageShowStatus)=>void
|
||||
refreshData:()=>void
|
||||
data?:PartitionDashboardConfigFieldType
|
||||
}
|
||||
|
||||
const DashboardSettingEdit = (props:DashboardSettingEditProps)=>{
|
||||
|
||||
const {changeStatus,refreshData,data} = props
|
||||
const { message } = App.useApp()
|
||||
const [ form ] = Form.useForm();
|
||||
const { fetchData} = useFetch()
|
||||
const onFinish = () => {
|
||||
form.validateFields().then((value)=>{
|
||||
fetchData<BasicResponse<{info: PartitionDashboardConfigFieldType}>>('monitor/config',{method: 'POST',body:JSON.stringify(value),eoParams:{}}).then(response=>{
|
||||
const {code,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
message.success(msg || '操作成功,即将刷新页面')
|
||||
refreshData?.()
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(()=>{form.setFieldsValue(data)},[data])
|
||||
|
||||
useEffect(() => {
|
||||
return (form.setFieldsValue({}))
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="overflow-auto h-full">
|
||||
<WithPermission access={''} >
|
||||
<Form
|
||||
form={form}
|
||||
className="mx-auto flex flex-col justify-between h-full"
|
||||
labelCol={{ span: 7 }}
|
||||
wrapperCol={{ span: 17}}
|
||||
onFinish={onFinish}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item<PartitionDashboardConfigFieldType>
|
||||
label="数据源类型"
|
||||
name="driver"
|
||||
rules={[{ required: true, message: VALIDATE_MESSAGE.required }]}
|
||||
>
|
||||
<Select className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.select} options={[...DASHBOARD_SETTING_DRIVER_OPTION_LIST]}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<PartitionDashboardConfigFieldType>
|
||||
label="数据源地址"
|
||||
name={['config','addr']}
|
||||
rules={[{ required: true, message: VALIDATE_MESSAGE.required }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<PartitionDashboardConfigFieldType>
|
||||
label="Organization"
|
||||
name={['config','org']}
|
||||
rules={[{ required: true, message: VALIDATE_MESSAGE.required }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<PartitionDashboardConfigFieldType>
|
||||
label="鉴权 Token"
|
||||
name={['config','token']}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<div className="flex gap-btnbase">
|
||||
<WithPermission access=''>
|
||||
<Button type="primary" htmlType="submit">
|
||||
保存
|
||||
</Button>
|
||||
</WithPermission>
|
||||
<Button type="default" onClick={()=>changeStatus('view')}>
|
||||
取消
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</WithPermission>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default DashboardSettingEdit
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FC, useEffect, useRef, useState} from "react";
|
||||
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
|
||||
import {App, Button, Card, Col, Row, Spin, Tag} from "antd";
|
||||
import {BasicResponse, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import { ClusterPageShowStatus, NodeModalHandle, PartitionClusterNodeTableListItem } from "../../const/partitions/types.ts";
|
||||
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
|
||||
@@ -12,7 +12,7 @@ import { $t } from "@common/locales/index.ts";
|
||||
|
||||
const PartitionInsideCluster:FC = ()=> {
|
||||
const {setBreadcrumb} = useBreadcrumb()
|
||||
const {modal, message} = App.useApp()
|
||||
const { message} = App.useApp()
|
||||
const {fetchData} = useFetch()
|
||||
const [nodeData, setNodeData] = useState<PartitionClusterNodeTableListItem>()
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
@@ -65,7 +65,7 @@ const PartitionInsideCluster:FC = ()=> {
|
||||
<div className="h-full overflow-auto">
|
||||
<Card
|
||||
classNames={{
|
||||
body: 'overflow-auto',
|
||||
body: `overflow-auto ${!nodeData && showStatus === 'view' ? 'hidden': ''}`,
|
||||
}}
|
||||
className="overflow-hidden w-full max-h-full flex flex-col justify-between"
|
||||
title={<div><span className="text-MAIN_TEXT my-btnybase mr-btnbase" > APIPark Node</span>
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import { FC, useEffect, useState} from "react";
|
||||
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
|
||||
import {App, Button, Card, Col, Row, Spin, Tag} from "antd";
|
||||
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import InsidePage from "@common/components/aoplatform/InsidePage.tsx";
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
import DashboardSettingEdit, { DashboardPageShowStatus } from "./DashboardSettingEdit.tsx";
|
||||
import { PartitionDashboardConfigFieldType } from "@core/const/partitions/types.ts";
|
||||
|
||||
const PartitionInsideDashboardSetting:FC = ()=> {
|
||||
const {setBreadcrumb} = useBreadcrumb()
|
||||
const {message} = App.useApp()
|
||||
const {fetchData} = useFetch()
|
||||
const [data, setData] = useState<PartitionDashboardConfigFieldType>()
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [showStatus, setShowStatus] = useState<DashboardPageShowStatus>('view')
|
||||
|
||||
const getDashboardSettingInfo = () => {
|
||||
setLoading(true)
|
||||
return fetchData<BasicResponse<{ nodes:PartitionDashboardConfigFieldType[] }>>('monitor/config', {method: 'GET',eoTransformKeys:[]}).then(response => {
|
||||
const {code, data, msg} = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
data?.info?.driver && setData(data.info)
|
||||
setShowStatus('view')
|
||||
} else {
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch(() => {
|
||||
return {data: [], success: false}
|
||||
}).finally(()=>{
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumb([
|
||||
{title: $t('监控报表')}
|
||||
])
|
||||
getDashboardSettingInfo()
|
||||
}, []);
|
||||
|
||||
const setDashboardSettingBtn = ()=>{
|
||||
return (<>
|
||||
{showStatus === 'view' && <WithPermission access="" key="changeClusterConfig">
|
||||
<Button type="primary" onClick={() => setShowStatus('edit')}>{$t('修改配置')}</Button>
|
||||
</WithPermission> }</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<InsidePage
|
||||
pageTitle={$t('监控报表')}
|
||||
description={$t("设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。")}
|
||||
showBorder={false}
|
||||
scrollPage={true}
|
||||
>
|
||||
<div className="flex flex-col h-full overflow-auto pb-PAGE_INSIDE_B pr-PAGE_INSIDE_X">
|
||||
<Spin wrapperClassName=" h-full flex-1" indicator={<LoadingOutlined style={{ fontSize: 24 }} spin/>} spinning={loading}>
|
||||
<div className="h-full overflow-auto">
|
||||
<Card
|
||||
classNames={{
|
||||
body: `overflow-auto ${(!data || !data?.driver) && showStatus === 'view' ? 'hidden': ''}`,
|
||||
}}
|
||||
className="overflow-hidden w-full max-h-full flex flex-col justify-between"
|
||||
title={<div><span className="text-MAIN_TEXT my-btnybase mr-btnbase" > {$t('统计图表')}</span>
|
||||
{!loading && !data?.driver && <Tag color='#f50'>{ $t('未配置')}
|
||||
</Tag>}</div>}
|
||||
|
||||
extra={setDashboardSettingBtn()}>
|
||||
{showStatus === 'view'&& data && data.driver && DashboardConfigPreview(data) }
|
||||
{showStatus !== 'view' && <DashboardSettingEdit data={data} changeStatus={setShowStatus} refreshData={getDashboardSettingInfo} />}
|
||||
</Card>
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
</InsidePage>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function DashboardConfigPreview (x:PartitionDashboardConfigFieldType){
|
||||
return <div className="flex flex-col gap-[4px] ">
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('数据源')}:</Col><Col>{x?.driver}</Col></Row>
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('地址(IP:端口)')}:</Col><Col>{x?.config?.addr}</Col></Row>
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('组织(Organization)')}:</Col><Col>{x?.config?.org}</Col></Row>
|
||||
</div>}
|
||||
|
||||
export default PartitionInsideDashboardSetting
|
||||
@@ -58,7 +58,7 @@ const LogSettings = ()=>{
|
||||
|
||||
return (
|
||||
<>
|
||||
<Skeleton className='m-btnbase w-[calc(100%-20px)]' active loading={loading}>
|
||||
<Skeleton className='m-btnbase w-calc-100vw-minus-padding-r' active loading={loading}>
|
||||
<InsidePage
|
||||
pageTitle={$t('资源配置')}
|
||||
>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PageList from "@common/components/aoplatform/PageList.tsx"
|
||||
import Tour from "@common/components/aoplatform/Tour.tsx"
|
||||
import {ActionType} from "@ant-design/pro-components";
|
||||
import {FC, useEffect, useMemo, useRef, useState} from "react";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
@@ -13,6 +14,7 @@ import { DrawerWithFooter } from "@common/components/aoplatform/DrawerWithFooter
|
||||
import SystemConfig from "./SystemConfig.tsx";
|
||||
import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx";
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
import Joyride from "react-joyride";
|
||||
|
||||
const SystemList:FC = ()=>{
|
||||
const navigate = useNavigate();
|
||||
@@ -114,15 +116,28 @@ const SystemList:FC = ()=>{
|
||||
return res
|
||||
},[memberValueEnum,teamList])
|
||||
|
||||
const steps = [
|
||||
{
|
||||
target: '.my-first-step',
|
||||
content: '点击按钮新建服务',
|
||||
},
|
||||
{
|
||||
target: '.ant-table-tbody',
|
||||
content: '点击表格查看详情',
|
||||
placement: 'top'
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="h-full w-full pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B">
|
||||
|
||||
<Joyride steps={steps} run={true} />
|
||||
<PageList
|
||||
id="global_system"
|
||||
ref={pageListRef}
|
||||
columns={[...columns]}
|
||||
request={()=>getSystemList()}
|
||||
addNewBtnTitle={$t("添加服务")}
|
||||
addNewBtnWrapperClass={'my-first-step'}
|
||||
searchPlaceholder={$t("输入名称、ID、所属团队、负责人查找服务")}
|
||||
onAddNewBtnClick={() => {
|
||||
setOpen(true)
|
||||
@@ -140,7 +155,6 @@ const SystemList:FC = ()=>{
|
||||
<SystemConfig ref={drawerFormRef} />
|
||||
</DrawerWithFooter>
|
||||
</div>
|
||||
// </Skeleton>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"@core/*": ["./src/*"],
|
||||
"@common/*": ["../common/src/*"],
|
||||
"@market/*": ["../market/src/*"],
|
||||
"@dashboard/*": ["../dashboard/src/*"],
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../common/src/components/aoplatform/ScrollableSection.tsx", "../common/src/utils/postcat.tsx", "../common/src/utils/curl.ts", "../common/src/components/aoplatform/ResetPsw.tsx", "../common/src/components/aoplatform/SubscribeApprovalModalContent.tsx", "../common/src/components/aoplatform/InsidePageForHub.tsx", "src/components/aoplatform/RenderRoutes.tsx", "../common/src/components/aoplatform/PublishApprovalModalContent.tsx", "../common/src/components/aoplatform/InsidePage.tsx", "../common/src/const/type.ts", "../common/src/components/aoplatform/intelligent-plugin", "../common/src/const/domain"],
|
||||
|
||||
@@ -57,6 +57,7 @@ export default defineConfig({
|
||||
{ find: '@common', replacement: path.resolve(__dirname, '../common/src') },
|
||||
{ find: '@market', replacement: path.resolve(__dirname, '../market/src') },
|
||||
{ find: '@core', replacement: path.resolve(__dirname, './src') },
|
||||
{ find: '@dashboard', replacement: path.resolve(__dirname, '../dashboard/src') },
|
||||
]
|
||||
},
|
||||
server: {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getTime } from "../utils/dashboard";
|
||||
import ScrollableSection from "@common/components/aoplatform/ScrollableSection";
|
||||
import TimeRangeSelector, { RangeValue, TimeRange, TimeRangeButton } from "@common/components/aoplatform/TimeRangeSelector";
|
||||
import MonitorTable, { MonitorTableHandler } from "./MonitorTable";
|
||||
import { BasicResponse, STATUS_CODE } from "@common/const/const";
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
|
||||
import { DefaultOptionType } from "antd/es/select";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { RouterParams } from "@core/components/aoplatform/RenderRoutes";
|
||||
@@ -15,6 +15,7 @@ import { useExcelExport } from "@common/hooks/excel";
|
||||
import { API_TABLE_GLOBAL_COLUMNS_CONFIG } from "@dashboard/const/const";
|
||||
import { useFetch } from "@common/hooks/http";
|
||||
import { EntityItem } from "@common/const/type";
|
||||
import { $t } from "@common/locales";
|
||||
export type MonitorApiPageProps = {
|
||||
fetchTableData:(body:SearchBody)=>Promise<BasicResponse<{statistics:MonitorApiData[]}>>
|
||||
detailDrawerContent:React.ReactNode
|
||||
@@ -55,7 +56,7 @@ export default function MonitorApiPage(props:MonitorApiPageProps){
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
setApiOptionList(data.apis?.map((x:EntityItem)=>({label:x.name, value:x.id})))
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
return setApiOptionList([])
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -69,7 +70,7 @@ export default function MonitorApiPage(props:MonitorApiPageProps){
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
setProjectOptionList(data.projects?.map((x:EntityItem)=>({label:x.name, value:x.id})))
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
return setProjectOptionList([])
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -110,9 +111,9 @@ export default function MonitorApiPage(props:MonitorApiPageProps){
|
||||
fetchTableData(data).then((resp) => {
|
||||
const {code,data,msg} = resp
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
exportExcel('API调用统计', [query!.start!, query!.end!], 'API调用统计', 'dashboard_api', API_TABLE_GLOBAL_COLUMNS_CONFIG, data.statistics)
|
||||
exportExcel($t('API调用统计'), [query!.start!, query!.end!], $t('API调用统计'), 'dashboard_api', API_TABLE_GLOBAL_COLUMNS_CONFIG, data.statistics)
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
}
|
||||
})
|
||||
};
|
||||
@@ -134,7 +135,7 @@ export default function MonitorApiPage(props:MonitorApiPageProps){
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
return {data:data.statistics?.map((x:MonitorApiData)=>{x.proxyRate = Number((x.proxyRate*100).toFixed(2));x.requestRate = Number((x.requestRate*100).toFixed(2));return x}), success: true}
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
return {data:[], success:false}
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -160,7 +161,7 @@ export default function MonitorApiPage(props:MonitorApiPageProps){
|
||||
initialDatePickerValue={datePickerValue}
|
||||
onTimeRangeChange={handleTimeRangeChange}/>
|
||||
<div className="flex flex-nowrap items-center pt-btnybase mr-btnybase">
|
||||
<label className=" whitespace-nowrap inline-block">服务:</label>
|
||||
<label className=" whitespace-nowrap inline-block">{$t('服务')}:</label>
|
||||
<Select
|
||||
className="w-[346px]"
|
||||
value={queryData?.projects}
|
||||
@@ -168,7 +169,7 @@ export default function MonitorApiPage(props:MonitorApiPageProps){
|
||||
mode="multiple"
|
||||
allowClear
|
||||
maxCount={3}
|
||||
placeholder="选择服务"
|
||||
placeholder={$t("选择服务")}
|
||||
onChange={(value)=>{setQueryData(prevData=>({...prevData || {}, projects:value}));getApiList(value)}}
|
||||
/>
|
||||
</div>
|
||||
@@ -181,22 +182,22 @@ export default function MonitorApiPage(props:MonitorApiPageProps){
|
||||
mode="multiple"
|
||||
allowClear
|
||||
maxCount={3}
|
||||
placeholder="选择API"
|
||||
placeholder={$t("选择API")}
|
||||
onChange={(value)=>{setQueryData(prevData=>({...prevData || {}, apis:value}))}}
|
||||
/>
|
||||
<label className="ml-btnybase whitespace-nowrap">路径:</label>
|
||||
<label className="ml-btnybase whitespace-nowrap">{$t('路径')}:</label>
|
||||
<div className="w-[346px] inline-block">
|
||||
{/* <SearchInputGroup eoSingle={false} eoInputVal={queryData.path} eoClick={() => setQueryData({ ...queryData, path: '' })} /> */}
|
||||
<Input value={queryData?.path} onChange={(e) => debounce((e)=>{setQueryData(prevData=>({...prevData || {}, path:e.target.value}))}, 100)(e)} allowClear placeholder='请输入请求路径进行搜索' prefix={<SearchOutlined className="cursor-pointer"/>}/>
|
||||
<Input value={queryData?.path} onChange={(e) => debounce((e)=>{setQueryData(prevData=>({...prevData || {}, path:e.target.value}))}, 100)(e)} allowClear placeholder={$t('请输入请求路径进行搜索')} prefix={<SearchOutlined className="cursor-pointer"/>}/>
|
||||
</div>
|
||||
<Button className="ml-btnybase" onClick={clearSearch}>
|
||||
重置
|
||||
{$t('重置')}
|
||||
</Button>
|
||||
<Button type="primary" loading={queryBtnLoading} className="ml-btnybase" onClick={()=>{setQueryBtnLoading(true);getApiTableList()}}>
|
||||
查询
|
||||
{$t('查询')}
|
||||
</Button>
|
||||
<Button className="ml-btnybase" loading={exportLoading} onClick={exportData}>
|
||||
导出
|
||||
{$t('导出')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -212,9 +213,9 @@ export default function MonitorApiPage(props:MonitorApiPageProps){
|
||||
mask={!fullScreen}
|
||||
title={<>
|
||||
{fullScreen && <a className="mr-btnrbase text-[14px]" onClick={()=>{setFullScreen?.(false)}}>
|
||||
<CloseOutlined className="mr-[4px]"/>退出全屏
|
||||
<CloseOutlined className="mr-[4px]"/>{$t('退出全屏')}
|
||||
</a>}
|
||||
<span className="mr-btnrbase">{detailEntityName}调用详情</span>
|
||||
<span className="mr-btnrbase">{$t('(0)调用详情',[detailEntityName])}</span>
|
||||
{!fullScreen && <ExpandOutlined className="text-MAIN_TEXT hover:text-MAIN_HOVER_TEXT" onClick={()=>{setFullScreen?.(true)}}/>}
|
||||
</>}
|
||||
width={fullScreen ? '100%' : '60%'}
|
||||
|
||||
@@ -5,13 +5,14 @@ import { EntityItem } from "@common/const/type";
|
||||
import TimeRangeSelector, { RangeValue, TimeRange, TimeRangeButton } from "@common/components/aoplatform/TimeRangeSelector";
|
||||
import MonitorTable, { MonitorTableHandler } from "./MonitorTable";
|
||||
import { DefaultOptionType } from "antd/es/select";
|
||||
import { BasicResponse, STATUS_CODE } from "@common/const/const";
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
|
||||
import { getTime } from "../utils/dashboard";
|
||||
import { useExcelExport } from "@common/hooks/excel";
|
||||
import { APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG } from "@dashboard/const/const";
|
||||
import { CloseOutlined, ExpandOutlined } from "@ant-design/icons";
|
||||
import { useFetch } from "@common/hooks/http";
|
||||
import { MonitorSubQueryData } from "./MonitorSubPage";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export type MonitorAppPageProps = {
|
||||
fetchTableData:(body:SearchBody)=>Promise<BasicResponse<{statistics:MonitorSubscriberData[]}>>
|
||||
@@ -60,7 +61,7 @@ export default function MonitorAppPage(props:MonitorAppPageProps){
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
setListOfApps(data.projects?.map((x:EntityItem)=>({label:x.name, value:x.id})))
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
return setListOfApps([])
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -98,9 +99,9 @@ export default function MonitorAppPage(props:MonitorAppPageProps){
|
||||
fetchTableData(data).then((resp) => {
|
||||
const {code,data,msg} = resp
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
exportExcel('应用调用统计', [query!.start!, query!.end!], '应用调用统计', 'dashboard_application', APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG, data.statistics)
|
||||
exportExcel($t('应用调用统计'), [query!.start!, query!.end!], $t('应用调用统计'), 'dashboard_application', APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG, data.statistics)
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
}
|
||||
})
|
||||
};
|
||||
@@ -117,7 +118,7 @@ export default function MonitorAppPage(props:MonitorAppPageProps){
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
return {data:data.statistics?.map((x:MonitorSubscriberData)=>{x.proxyRate = Number((x.proxyRate*100).toFixed(2));x.requestRate = Number((x.requestRate*100).toFixed(2));return x}), success: true}
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
return {data:[], success:false}
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -143,13 +144,13 @@ export default function MonitorAppPage(props:MonitorAppPageProps){
|
||||
onTimeRangeChange={handleTimeRangeChange}/>
|
||||
<div className="flex flex-wrap items-center row-gap-[12px] pt-btnybase mr-btnybase">
|
||||
<div>
|
||||
<label className="inline-block whitespace-nowrap">应用:</label>
|
||||
<label className="inline-block whitespace-nowrap">{$t('应用')}:</label>
|
||||
<Select
|
||||
className="w-[346px]"
|
||||
mode="multiple"
|
||||
maxTagCount={1}
|
||||
// maxTagPlaceholder={(selectedList) => `and ${selectedList.length} more selected`}
|
||||
placeholder="请选择"
|
||||
placeholder={$t("请选择应用")}
|
||||
value={queryData?.projects}
|
||||
options={listOfApps}
|
||||
onChange={(value)=>{setQueryData(prevData=>({...prevData || {}, projects:value}))}}
|
||||
@@ -157,13 +158,13 @@ export default function MonitorAppPage(props:MonitorAppPageProps){
|
||||
</div>
|
||||
<div>
|
||||
<Button className="ml-btnybase" onClick={clearSearch}>
|
||||
重置
|
||||
{$t('重置')}
|
||||
</Button>
|
||||
<Button type="primary" loading={queryBtnLoading} className="ml-btnybase" onClick={()=>{setQueryBtnLoading(true);getAppTableList()}}>
|
||||
查询
|
||||
{$t('查询')}
|
||||
</Button>
|
||||
<Button className="ml-btnybase" loading={exportLoading} onClick={exportData}>
|
||||
导出
|
||||
{$t('导出')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,13 +3,14 @@ import { useState, useEffect, useRef } from "react";
|
||||
import { InvokeData, MonitorApiData, MonitorSubscriberData, SearchBody } from "@dashboard/const/type";
|
||||
import TimeRangeSelector, { RangeValue, TimeRange, TimeRangeButton } from "@common/components/aoplatform/TimeRangeSelector";
|
||||
import MonitorLineGraph from "./MonitorLineGraph";
|
||||
import { BasicResponse, STATUS_CODE } from "@common/const/const";
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
|
||||
import { getTime, getTimeUnit } from "../utils/dashboard";
|
||||
import MonitorTable, { MonitorTableHandler } from "./MonitorTable";
|
||||
import { DashboardDetailInvokeType } from "@dashboard/pages/DashboardDetail";
|
||||
import { MonitorApiQueryData } from "./MonitorApiPage";
|
||||
import { MonitorSubQueryData } from "./MonitorSubPage";
|
||||
import dayjs from "dayjs";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
type MonitorDetailPageProps = {
|
||||
fetchInvokeData:(body:SearchBody)=>Promise<BasicResponse<DashboardDetailInvokeType>>
|
||||
@@ -38,7 +39,7 @@ export default function MonitorDetailPage(props:MonitorDetailPageProps){
|
||||
const [timeUnit, setTimeUnit] = useState<string>()
|
||||
const [invokeStaticError,setInvokeStaticError] = useState<boolean>(false)
|
||||
const monitorTableRef = useRef<MonitorTableHandler>(null)
|
||||
const [modalTitle, setModalTitle] = useState<string>('调用趋势')
|
||||
const [modalTitle, setModalTitle] = useState<string>($t('调用趋势'))
|
||||
const [queryBtnLoading, setQueryBtnLoading] = useState<boolean>(false)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -71,7 +72,7 @@ export default function MonitorDetailPage(props:MonitorDetailPageProps){
|
||||
// this.invokeLineRef?.changeLineChart()
|
||||
}else{
|
||||
setInvokeStaticError(true)
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
}
|
||||
}).catch(()=>{setQueryBtnLoading(false)})
|
||||
};
|
||||
@@ -83,7 +84,7 @@ export default function MonitorDetailPage(props:MonitorDetailPageProps){
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
return {data:data.statistics?.map((x:(MonitorApiData|MonitorSubscriberData))=>{x.proxyRate = Number((x.proxyRate*100).toFixed(2));x.requestRate = Number((x.requestRate*100).toFixed(2));return x}), success: true}
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
return {data:[], success:false}
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -108,18 +109,13 @@ export default function MonitorDetailPage(props:MonitorDetailPageProps){
|
||||
setDetailInvokeStatic(tendency)
|
||||
setDetailInvokeError(false)
|
||||
setTimeUnit(getTimeUnit(timeInterval!))
|
||||
// this.invokeLineRef?.changeLineChart()
|
||||
setModalTitle(`${entity.name}-${detailName}调用趋势`);
|
||||
setModalTitle($t('(0)-(1)调用趋势', [entity.name, detailName]))
|
||||
setModalVisible(true);
|
||||
}else{
|
||||
setInvokeStaticError(true)
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
}
|
||||
})
|
||||
|
||||
// setModalTitle(`${entity.name}-${detailName}调用趋势`);
|
||||
// setModalVisible(true);
|
||||
|
||||
};
|
||||
|
||||
const handleCloseModal = () => {
|
||||
@@ -144,10 +140,10 @@ export default function MonitorDetailPage(props:MonitorDetailPageProps){
|
||||
onTimeRangeChange={handleTimeRangeChange}
|
||||
hideTitle={!fullScreen}/>
|
||||
<Button className="ml-btnybase mt-btnybase" onClick={clearSearch}>
|
||||
重置
|
||||
{$t('重置')}
|
||||
</Button>
|
||||
<Button className="ant-btn-primary ml-btnybase mt-btnybase" loading={queryBtnLoading} onClick={()=>{setQueryBtnLoading(true);getMonitorData();}}>
|
||||
查询
|
||||
{$t('查询')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -156,7 +152,7 @@ export default function MonitorDetailPage(props:MonitorDetailPageProps){
|
||||
{/* 这里应该添加图表组件 */}
|
||||
{invokeStaticError ? <Empty className="mt-[20%]" image={Empty.PRESENTED_IMAGE_SIMPLE}/>: <MonitorLineGraph
|
||||
lineData={invokeStatic}
|
||||
titles={['调用量统计']}
|
||||
titles={[$t('调用量统计')]}
|
||||
yAxisTitle={timeUnit || '-'}
|
||||
type="invoke"
|
||||
/>}
|
||||
@@ -175,11 +171,11 @@ export default function MonitorDetailPage(props:MonitorDetailPageProps){
|
||||
maskClosable={false}
|
||||
>
|
||||
<div className=" pb-btnybase flex flex-nowrap flex-col w-full items-center justify-between">
|
||||
<div className="w-full flex flex-row-reverse"><Checkbox checked={compareTotal} onChange={(e) => {setCompareTotal(e.target.checked)}}>加入总体数据对比</Checkbox></div>
|
||||
<div className="w-full flex flex-row-reverse"><Checkbox checked={compareTotal} onChange={(e) => {setCompareTotal(e.target.checked)}}>{$t('加入总体数据对比')}</Checkbox></div>
|
||||
{(detailInvokeError||!modalVisible) ? <Empty className="w-[calc(100%-20px)]" image={Empty.PRESENTED_IMAGE_SIMPLE}/>: <MonitorLineGraph
|
||||
className="w-[calc(100%-22px)] w-min-[300px]"
|
||||
lineData={detailInvokeStatic!}
|
||||
titles={['调用量统计']}
|
||||
titles={[$t('调用量统计')]}
|
||||
yAxisTitle={timeUnit || '-'}
|
||||
type="invoke"
|
||||
/>}
|
||||
@@ -188,7 +184,7 @@ export default function MonitorDetailPage(props:MonitorDetailPageProps){
|
||||
(invokeStaticError ||!modalVisible ) ? <Empty className="w-[calc(100%-20px)]" image={Empty.PRESENTED_IMAGE_SIMPLE}/>: <MonitorLineGraph
|
||||
className="w-[calc(100%-20px)]"
|
||||
lineData={invokeStatic}
|
||||
titles={['调用量统计']}
|
||||
titles={[$t('调用量统计')]}
|
||||
yAxisTitle={timeUnit || '-'}
|
||||
type="invoke"
|
||||
/>
|
||||
|
||||
@@ -4,6 +4,7 @@ import ECharts, { EChartsOption } from 'echarts-for-react';
|
||||
import { InvokeData, LineGraphType, MessageData } from '@dashboard/const/type';
|
||||
import { MONITOR_LINE_CHART_BASIC_INVOKE_SELECTED, MONITOR_LINE_CHART_BASIC_MESSAGE_SELECTED, MONITOR_LINE_CHART_OPTION_CONFIG, MONITOR_NAME_MAP } from '@dashboard/const/const';
|
||||
import { yUnitFormatter } from '../utils/dashboard';
|
||||
import { $t } from '@common/locales';
|
||||
|
||||
type LineGraphProps = {
|
||||
className?:string
|
||||
@@ -133,7 +134,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
},
|
||||
yAxis: [{
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用量` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用量',[yAxisTitle]) : '',
|
||||
nameLocation: 'end',
|
||||
nameTextStyle: {
|
||||
align: 'left'
|
||||
@@ -148,7 +149,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用成功率` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用成功率',[yAxisTitle]) : '',
|
||||
position: 'right',
|
||||
min: 0,
|
||||
max: 100,
|
||||
@@ -165,12 +166,12 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
}
|
||||
}],
|
||||
series: [
|
||||
{ type: 'line', symbol: 'none', name: '请求总数', data: (lineData as InvokeData)?.requestTotal, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: '请求成功率', data: (lineData as InvokeData)?.requestRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], yAxisIndex: 1 },
|
||||
{ type: 'line', symbol: 'none', name: '转发总数', data: (lineData as InvokeData)?.proxyTotal, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: '转发成功率', data: (lineData as InvokeData)?.proxyRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], yAxisIndex: 1 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: '状态码4xx数', data: (lineData as InvokeData)?.status_4xx, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: '状态码5xx数', data: (lineData as InvokeData)?.status_5xx, yAxisIndex: 0 }
|
||||
{ type: 'line', symbol: 'none', name: $t('请求总数'), data: (lineData as InvokeData)?.requestTotal, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: $t('请求成功率'), data: (lineData as InvokeData)?.requestRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], yAxisIndex: 1 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发总数'), data: (lineData as InvokeData)?.proxyTotal, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发成功率'), data: (lineData as InvokeData)?.proxyRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], yAxisIndex: 1 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: $t('状态码4xx数'), data: (lineData as InvokeData)?.status_4xx, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: $t('状态码5xx数'), data: (lineData as InvokeData)?.status_5xx, yAxisIndex: 0 }
|
||||
]
|
||||
})
|
||||
|
||||
@@ -185,11 +186,11 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
// echarts会根据你定义的颜色返回一个生成好的带颜色的标记,直接实用即可
|
||||
let str = ''
|
||||
if (i === Math.floor(params.length / 2)) {
|
||||
str = '<br/><div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + (params[0].seriesIndex === 0 ? dataTitle + '调用总体趋势' :modalTitle) + '</span>   <span>' + params[0].axisValue + '</span></div><div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + item.marker
|
||||
str = '<br/><div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + (params[0].seriesIndex === 0 ? dataTitle + $t('调用总体趋势') :modalTitle) + '</span>   <span>' + params[0].axisValue + '</span></div><div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + item.marker
|
||||
} else {
|
||||
str = '<div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + item.marker
|
||||
}
|
||||
if (item.seriesName === '请求成功率' || item.seriesName === '转发成功率') {
|
||||
if (item.seriesName === $t('请求成功率') || item.seriesName === $t('转发成功率')) {
|
||||
str += (item.seriesName + '    </span><span style="font-weight:bold"> ' + item.value + '% </span></section></div>')
|
||||
} else {
|
||||
str += (item.seriesName + '    </span><span style="font-weight:bold"> ' + item.value + '</span></section></div>')
|
||||
@@ -258,7 +259,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用量` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用量',[yAxisTitle]) : '',
|
||||
nameLocation: 'end',
|
||||
nameTextStyle: {
|
||||
align: 'left'
|
||||
@@ -274,7 +275,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用成功率` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用成功率',[yAxisTitle]) : '',
|
||||
position: 'right',
|
||||
min: 0,
|
||||
max: 100,
|
||||
@@ -294,7 +295,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
{
|
||||
gridIndex: 1,
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用量` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用量',[yAxisTitle]) : '',
|
||||
nameLocation: 'end',
|
||||
nameTextStyle: {
|
||||
align: 'left'
|
||||
@@ -311,7 +312,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
{
|
||||
gridIndex: 1,
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用成功率` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用成功率',[yAxisTitle]): '',
|
||||
position: 'right',
|
||||
min: 0,
|
||||
max: 100,
|
||||
@@ -329,18 +330,18 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
}
|
||||
}],
|
||||
series: [
|
||||
{ type: 'line', symbol: 'none', name: '请求总数', data: (lineData as InvokeData)?.requestTotal, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: '请求成功率', data: (lineData as InvokeData)?.requestRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], xAxisIndex: 0, yAxisIndex: 1 },
|
||||
{ type: 'line', symbol: 'none', name: '转发总数', data: (lineData as InvokeData)?.proxyTotal, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: '转发成功率', data: (lineData as InvokeData)?.proxyRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], xAxisIndex: 0, yAxisIndex: 1 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: '状态码4xx数', data: (lineData as InvokeData)?.status_4xx, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: '状态码5xx数', data: (lineData as InvokeData)?.status_5xx, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: '请求总数', data: (compareData as InvokeData)?.requestTotal, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', symbol: 'none', name: '请求成功率', data: (compareData as InvokeData)?.requestRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], xAxisIndex: 1, yAxisIndex: 3 },
|
||||
{ type: 'line', symbol: 'none', name: '转发总数', data: (compareData as InvokeData)?.proxyTotal, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', symbol: 'none', name: '转发成功率', data: (compareData as InvokeData)?.proxyRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], xAxisIndex: 1, yAxisIndex: 3 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: '状态码4xx数', data: (compareData as InvokeData)?.status_4xx, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: '状态码5xx数', data: (compareData as InvokeData)?.status_5xx, xAxisIndex: 1, yAxisIndex: 2 }
|
||||
{ type: 'line', symbol: 'none', name: $t('请求总数'), data: (lineData as InvokeData)?.requestTotal, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: $t('请求成功率'), data: (lineData as InvokeData)?.requestRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], xAxisIndex: 0, yAxisIndex: 1 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发总数'), data: (lineData as InvokeData)?.proxyTotal, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发成功率'), data: (lineData as InvokeData)?.proxyRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], xAxisIndex: 0, yAxisIndex: 1 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: $t('状态码4xx数'), data: (lineData as InvokeData)?.status_4xx, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: $t('状态码5xx数'), data: (lineData as InvokeData)?.status_5xx, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: $t('请求总数'), data: (compareData as InvokeData)?.requestTotal, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', symbol: 'none', name: $t('请求成功率'), data: (compareData as InvokeData)?.requestRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], xAxisIndex: 1, yAxisIndex: 3 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发总数'), data: (compareData as InvokeData)?.proxyTotal, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发成功率'), data: (compareData as InvokeData)?.proxyRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], xAxisIndex: 1, yAxisIndex: 3 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: $t('状态码4xx数'), data: (compareData as InvokeData)?.status_4xx, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: $t('状态码5xx数'), data: (compareData as InvokeData)?.status_5xx, xAxisIndex: 1, yAxisIndex: 2 }
|
||||
]
|
||||
})
|
||||
|
||||
@@ -381,7 +382,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用量` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ?$t('(0)调用量',[yAxisTitle]) : '',
|
||||
nameLocation: 'end',
|
||||
nameTextStyle: {
|
||||
align: 'left'
|
||||
@@ -398,7 +399,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用成功率` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用成功率',[yAxisTitle]) : '',
|
||||
position: 'right',
|
||||
min: 0,
|
||||
max: 100,
|
||||
@@ -415,10 +416,10 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
}
|
||||
}],
|
||||
series: [
|
||||
{ type: 'line', symbol: 'none', name: '转发总数', data: (lineData as InvokeData)?.proxyTotal, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: '转发成功率', data: (lineData as InvokeData)?.proxyRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], yAxisIndex: 1 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: '状态码4xx数', data: (lineData as InvokeData)?.status_4xx, yAxisIndex: 0 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: '状态码5xx数', data: (lineData as InvokeData)?.status_5xx, yAxisIndex: 0 }
|
||||
{ type: 'line', symbol: 'none', name: $t('转发总数'), data: (lineData as InvokeData)?.proxyTotal, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发成功率'), data: (lineData as InvokeData)?.proxyRate?.map((x) => Number((Number(x) * 100).toFixed(2))) || [], yAxisIndex: 1 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: $t('状态码4xx数'), data: (lineData as InvokeData)?.status_4xx, yAxisIndex: 0 },
|
||||
{ type: 'line', lineStyle: { type: 'dashed' }, symbol: 'none', name: $t('状态码5xx数'), data: (lineData as InvokeData)?.status_5xx, yAxisIndex: 0 }
|
||||
]})
|
||||
|
||||
const generateInvokeServiceCompareLineChartOption = ()=>({
|
||||
@@ -452,18 +453,18 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (params:Array<Record<string,unknown>>) => {
|
||||
const startHtml = '<div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + (params[0].seriesIndex === 0 ? modalTitle : dataTitle + '调用总体趋势') + '</span>   <span>' + params[0].axisValue + '</span></div>'
|
||||
const startHtml = '<div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + (params[0].seriesIndex === 0 ? modalTitle : dataTitle + $t('调用总体趋势')) + '</span>   <span>' + params[0].axisValue + '</span></div>'
|
||||
const listArr = []
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
const item = params[i]
|
||||
// echarts会根据你定义的颜色返回一个生成好的带颜色的标记,直接实用即可
|
||||
let str = ''
|
||||
if (i === Math.floor(params.length / 2)) {
|
||||
str = '<br/><div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + (params[0].seriesIndex === 0 ? dataTitle + '调用总体趋势' : modalTitle) + '</span>   <span>' + params[0].axisValue + '</span></div><div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + item.marker
|
||||
str = '<br/><div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + (params[0].seriesIndex === 0 ? dataTitle + $t('调用总体趋势') : modalTitle) + '</span>   <span>' + params[0].axisValue + '</span></div><div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + item.marker
|
||||
} else {
|
||||
str = '<div><section style="align-items: center;display:flex; justify-content: space-between;flex-wrap: nowrap;"><span> ' + item.marker
|
||||
}
|
||||
if (item.seriesName === '请求成功率' || item.seriesName === '转发成功率') {
|
||||
if (item.seriesName === $t('请求成功率') || item.seriesName === $t('转发成功率')) {
|
||||
str += (item.seriesName + '    </span><span style="font-weight:bold"> ' + item.value + '% </span></section></div>')
|
||||
} else {
|
||||
str += (item.seriesName + '    </span><span style="font-weight:bold"> ' + item.value + '</span></section></div>')
|
||||
@@ -513,7 +514,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用量` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用量',[yAxisTitle]) : '',
|
||||
nameLocation: 'end',
|
||||
nameTextStyle: {
|
||||
align: 'left'
|
||||
@@ -529,7 +530,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用成功率` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用成功率',[yAxisTitle]) : '',
|
||||
position: 'right',
|
||||
min: 0,
|
||||
max: 100,
|
||||
@@ -549,7 +550,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
{
|
||||
gridIndex: 1,
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用量` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用量',[yAxisTitle]): '',
|
||||
nameLocation: 'end',
|
||||
nameTextStyle: {
|
||||
align: 'left'
|
||||
@@ -566,7 +567,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
{
|
||||
gridIndex: 1,
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用成功率` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用成功率',[yAxisTitle]) : '',
|
||||
position: 'right',
|
||||
min: 0,
|
||||
max: 100,
|
||||
@@ -584,14 +585,14 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
}
|
||||
}],
|
||||
series: [
|
||||
{ type: 'line', symbol: 'none', name: '转发总数', data: (lineData as InvokeData)?.proxyTotal, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: '转发成功率', data: (lineData as InvokeData)?.proxyRate, xAxisIndex: 0, yAxisIndex: 1 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: '状态码4xx数', data: (lineData as InvokeData)?.status_4xx, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: '状态码5xx数', data: (lineData as InvokeData)?.status_5xx, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: '转发总数', data: (compareData as InvokeData)?.proxyTotal, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', symbol: 'none', name: '转发成功率', data: (compareData as InvokeData)?.proxyRate, xAxisIndex: 1, yAxisIndex: 3 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: '状态码4xx数', data: (compareData as InvokeData)?.status_4xx, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: '状态码5xx数', data: (compareData as InvokeData)?.status_5xx, xAxisIndex: 1, yAxisIndex: 2 }
|
||||
{ type: 'line', symbol: 'none', name: $t('转发总数'), data: (lineData as InvokeData)?.proxyTotal, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发成功率'), data: (lineData as InvokeData)?.proxyRate, xAxisIndex: 0, yAxisIndex: 1 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: $t('状态码4xx数'), data: (lineData as InvokeData)?.status_4xx, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: $t('状态码5xx数'), data: (lineData as InvokeData)?.status_5xx, xAxisIndex: 0, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发总数'), data: (compareData as InvokeData)?.proxyTotal, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', symbol: 'none', name: $t('转发成功率'), data: (compareData as InvokeData)?.proxyRate, xAxisIndex: 1, yAxisIndex: 3 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: $t('状态码4xx数'), data: (compareData as InvokeData)?.status_4xx, xAxisIndex: 1, yAxisIndex: 2 },
|
||||
{ type: 'line', symbol: 'none', lineStyle: { type: 'dashed' }, name: $t('状态码5xx数'), data: (compareData as InvokeData)?.status_5xx, xAxisIndex: 1, yAxisIndex: 2 }
|
||||
]})
|
||||
|
||||
const generateTrafficLineChartOption = ()=>({
|
||||
@@ -645,7 +646,7 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? `${yAxisTitle}调用成功率` : '',
|
||||
name: (lineData as InvokeData)?.date.length > 0 ? $t('(0)调用成功率',[yAxisTitle]) : '',
|
||||
position: 'right',
|
||||
min: 0,
|
||||
max: 100,
|
||||
@@ -663,8 +664,8 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
}
|
||||
}],
|
||||
series: [
|
||||
{ type: 'line', symbol: 'none', name: '请求报文量', data: (lineData as MessageData).requestMessage, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: '响应报文量', data: (lineData as MessageData).responseMessage, yAxisIndex: 0 }
|
||||
{ type: 'line', symbol: 'none', name: $t('请求报文量'), data: (lineData as MessageData).requestMessage, yAxisIndex: 0 },
|
||||
{ type: 'line', symbol: 'none', name: $t('响应报文量'), data: (lineData as MessageData).responseMessage, yAxisIndex: 0 }
|
||||
]})
|
||||
|
||||
|
||||
@@ -694,9 +695,9 @@ const MonitorLineGraph: FC<LineGraphProps> = ({ className, lineData, titles, yAx
|
||||
}
|
||||
// 当勾选请求成功率或转发成功率其中之一时,显示右侧y轴
|
||||
if (legendSelected && lineData?.date && lineData?.date.length > 0) {
|
||||
if (!legendSelected['转发成功率'] && !legendSelected['请求成功率'] && (option.yAxis as Array<unknown>)?.length > 1 && option.yAxis[1].show !== false) {
|
||||
if (!legendSelected[$t('转发成功率')] && !legendSelected[$t('请求成功率')] && (option.yAxis as Array<unknown>)?.length > 1 && option.yAxis[1].show !== false) {
|
||||
option.yAxis[1].show = false
|
||||
} else if ((legendSelected['转发成功率'] || legendSelected['请求成功率']) && (option.yAxis as Array<unknown>)?.length > 1 && option.yAxis[1].show !== true) {
|
||||
} else if ((legendSelected[$t('转发成功率')] || legendSelected[$t('请求成功率')]) && (option.yAxis as Array<unknown>)?.length > 1 && option.yAxis[1].show !== true) {
|
||||
option.yAxis[1].show = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {FC} from 'react';
|
||||
import ECharts,{EChartsOption} from 'echarts-for-react';
|
||||
import { changeNumberUnit } from '../utils/dashboard';
|
||||
import { $t } from '@common/locales';
|
||||
|
||||
type PieGraphProps = {
|
||||
className?:string,
|
||||
@@ -98,13 +99,13 @@ const MonitorPieGraph: FC<PieGraphProps> = ({ className,title, pieData, labelNam
|
||||
<ul className="list-none truncate my-0 ps-[10px]">
|
||||
<li className="h-[18px]"></li>
|
||||
<li className="text-[#999999] mt-[16px]">
|
||||
状态码4XX数
|
||||
{$t('状态码4XX数')}
|
||||
<span className="text-[#999999] inline-block w-[50px] ml-[10px] text-right">
|
||||
{changeNumberUnit(status4xxCount)}
|
||||
</span>
|
||||
</li>
|
||||
<li className="text-[#999999] mt-[18px]">
|
||||
状态码5XX数
|
||||
{$t('状态码5XX数')}
|
||||
<span className="text-[#999999] inline-block w-[50px] ml-[10px] text-right">
|
||||
{changeNumberUnit(status5xxCount)}
|
||||
</span>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { EntityItem } from "@common/const/type";
|
||||
import TimeRangeSelector, { RangeValue, TimeRange, TimeRangeButton } from "@common/components/aoplatform/TimeRangeSelector";
|
||||
import MonitorTable, { MonitorTableHandler } from "./MonitorTable";
|
||||
import { DefaultOptionType } from "antd/es/select";
|
||||
import { BasicResponse, STATUS_CODE } from "@common/const/const";
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
|
||||
import { getTime } from "../utils/dashboard";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { RouterParams } from "@core/components/aoplatform/RenderRoutes";
|
||||
@@ -13,6 +13,7 @@ import { useExcelExport } from "@common/hooks/excel";
|
||||
import { SERVICE_TABLE_GLOBAL_COLUMNS_CONFIG } from "@dashboard/const/const";
|
||||
import { CloseOutlined, ExpandOutlined } from "@ant-design/icons";
|
||||
import { useFetch } from "@common/hooks/http";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export type MonitorSubQueryData = SearchBody & { projects?:string[] ,type?:'subscriber'|'provider'}
|
||||
|
||||
@@ -64,7 +65,7 @@ export default function MonitorSubPage(props:MonitorSubPageProps){
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
setListOfProjects(data.projects?.map((x:EntityItem)=>({label:x.name, value:x.id})))
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
return setListOfProjects([])
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -102,9 +103,9 @@ export default function MonitorSubPage(props:MonitorSubPageProps){
|
||||
fetchTableData(data).then((resp) => {
|
||||
const {code,data,msg} = resp
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
exportExcel('服务调用统计', [query!.start!, query!.end!], '服务调用统计', 'dashboard_service', SERVICE_TABLE_GLOBAL_COLUMNS_CONFIG, data.statistics)
|
||||
exportExcel($t('服务调用统计'), [query!.start!, query!.end!], $t('服务调用统计'), 'dashboard_service', SERVICE_TABLE_GLOBAL_COLUMNS_CONFIG, data.statistics)
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
}
|
||||
})
|
||||
};
|
||||
@@ -121,7 +122,7 @@ export default function MonitorSubPage(props:MonitorSubPageProps){
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
return {data:data.statistics?.map((x:MonitorSubscriberData)=>{x.proxyRate = Number((x.proxyRate*100).toFixed(2));x.requestRate = Number((x.requestRate*100).toFixed(2));return x}), success: true}
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
return {data:[], success:false}
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -152,8 +153,7 @@ export default function MonitorSubPage(props:MonitorSubPageProps){
|
||||
className="w-[346px]"
|
||||
mode="multiple"
|
||||
maxTagCount={1}
|
||||
// maxTagPlaceholder={(selectedList) => `and ${selectedList.length} more selected`}
|
||||
placeholder="请选择"
|
||||
placeholder={$t("请选择服务")}
|
||||
value={queryData?.projects}
|
||||
options={listOfProjects}
|
||||
onChange={(value)=>{setQueryData(prevData=>({...prevData || {}, projects:value}))}}
|
||||
@@ -161,13 +161,13 @@ export default function MonitorSubPage(props:MonitorSubPageProps){
|
||||
</div>
|
||||
<div>
|
||||
<Button className="ml-btnybase" onClick={clearSearch}>
|
||||
重置
|
||||
{$t('重置')}
|
||||
</Button>
|
||||
<Button type="primary" loading={queryBtnLoading} className="ml-btnybase" onClick={()=>{setQueryBtnLoading(true);getAppTableList()}}>
|
||||
查询
|
||||
{$t('查询')}
|
||||
</Button>
|
||||
<Button className="ml-btnybase" loading={exportLoading} onClick={exportData}>
|
||||
导出
|
||||
{$t('导出')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -182,9 +182,9 @@ export default function MonitorSubPage(props:MonitorSubPageProps){
|
||||
mask={!fullScreen}
|
||||
title={<>
|
||||
{fullScreen && <a className="mr-btnrbase text-[14px]" onClick={()=>{setFullScreen?.(false)}}>
|
||||
<CloseOutlined className="mr-[4px]"/>退出全屏
|
||||
<CloseOutlined className="mr-[4px]"/>{$t('退出全屏')}
|
||||
</a>}
|
||||
<span className="mr-btnrbase">{detailEntityName}调用详情</span>
|
||||
<span className="mr-btnrbase">{detailEntityName}{$t('调用详情')}</span>
|
||||
{!fullScreen && <ExpandOutlined className="text-MAIN_TEXT hover:text-MAIN_HOVER_TEXT" onClick={()=>{setFullScreen?.(true)}}/>}
|
||||
</>}
|
||||
width={fullScreen ? '100%' : '60%'}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
|
||||
import { ActionType, ProColumns } from "@ant-design/pro-components"
|
||||
import { ActionType } from "@ant-design/pro-components"
|
||||
import { useImperativeHandle, useRef, useState } from "react"
|
||||
import PageList from "@common/components/aoplatform/PageList"
|
||||
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList"
|
||||
import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission"
|
||||
import { API_TABLE_GLOBAL_COLUMNS_CONFIG,SERVICE_TABLE_GLOBAL_COLUMNS_CONFIG, APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG } from "@dashboard/const/const"
|
||||
import {forwardRef} from "react"
|
||||
import { COLUMNS_TITLE } from "@common/const/const"
|
||||
|
||||
const TableType = {
|
||||
api :API_TABLE_GLOBAL_COLUMNS_CONFIG,
|
||||
provider :SERVICE_TABLE_GLOBAL_COLUMNS_CONFIG,
|
||||
subscribers :APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG
|
||||
}
|
||||
const APP_MODE = import.meta.env.VITE_APP_MODE;
|
||||
|
||||
|
||||
type MonitorTableProps<T> = {
|
||||
type:'api'|'subscribers'|'provider'
|
||||
@@ -60,17 +63,17 @@ const MonitorTable = forwardRef<MonitorTableHandler, MonitorTableProps<unknown>>
|
||||
})
|
||||
}
|
||||
|
||||
const operation:ProColumns<unknown>[] =[
|
||||
const operation:PageProColumns<unknown>[] =[
|
||||
{
|
||||
title: '操作',
|
||||
title: COLUMNS_TITLE.operate,
|
||||
key: 'option',
|
||||
width: 98,
|
||||
btnNums:2,
|
||||
fixed:'right',
|
||||
hideInSetting:true,
|
||||
valueType: 'option',
|
||||
render: (_: React.ReactNode, entity: unknown) => [
|
||||
// <TableBtnWithPermission access="system.dashboard.self.view" key="view" onClick={()=>onRowClick(entity)} btnTitle="查看"/>,
|
||||
<TableBtnWithPermission access="" key="view" onClick={()=>onRowClick(entity)} btnTitle="查看"/>,
|
||||
<TableBtnWithPermission access="" key="view" btnType="view" onClick={()=>onRowClick(entity)} btnTitle="查看"/>,
|
||||
],
|
||||
}
|
||||
]
|
||||
@@ -83,7 +86,7 @@ const MonitorTable = forwardRef<MonitorTableHandler, MonitorTableProps<unknown>>
|
||||
besidesTableHeight={inModal ? 64+56+258: undefined}
|
||||
ref={tableRef}
|
||||
showPagination={showPagination}
|
||||
columns = {[...(TableType[type] || []),...operation]}
|
||||
columns = {[...(TableType[type] || []),...(APP_MODE === 'pro' ? operation : [])]}
|
||||
request={getTableDataSource}
|
||||
dataSource={tableListDataSource}
|
||||
// tableClickAccess="system.dashboard.self.view"
|
||||
|
||||
@@ -16,8 +16,10 @@ import MonitorPieGraph from "./MonitorPieGraph";
|
||||
import MonitorTable, { MonitorTableHandler } from "./MonitorTable";
|
||||
import { CloseOutlined, ExpandOutlined, LoadingOutlined } from "@ant-design/icons";
|
||||
import DashboardDetail from "@dashboard/pages/DashboardDetail";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
dayjs.extend(customParseFormat);
|
||||
const APP_MODE = import.meta.env.VITE_APP_MODE;
|
||||
|
||||
export type MonitorTotalPageProps = {
|
||||
fetchPieData:(body:SearchBody)=>Promise<BasicResponse<PieData>>
|
||||
@@ -127,7 +129,7 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
|
||||
setTotalEmpty(data.requestSummary.total === 0 && data.proxySummary.total === 0)
|
||||
}else{
|
||||
setPieError(true)
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
}
|
||||
}).finally(()=>{
|
||||
dispatch({ type: ACTIONS.REQUEST_COMPLETE, payload: 'getPieData' });
|
||||
@@ -146,7 +148,7 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
|
||||
// this.invokeLineRef?.changeLineChart()
|
||||
}else{
|
||||
setInvokeStaticError(true)
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
}
|
||||
}).finally(()=>{
|
||||
dispatch({ type: ACTIONS.REQUEST_COMPLETE, payload: 'getInvokeData' });
|
||||
@@ -163,7 +165,7 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
|
||||
// this.trafficLineRef?.changeLineChart()
|
||||
}else{
|
||||
setTrafficStaticError(true)
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
}
|
||||
}).finally(()=>{
|
||||
dispatch({ type: ACTIONS.REQUEST_COMPLETE, payload: 'getMessageData' });
|
||||
@@ -178,7 +180,7 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
return {data:data.top10.map((x:MonitorApiData | MonitorSubscriberData)=>{x.proxyRate = Number((x.proxyRate*100).toFixed(2));x.requestRate = Number((x.requestRate*100).toFixed(2));return x}), success: true}
|
||||
}else{
|
||||
message.error(msg || '获取数据失败,请重试')
|
||||
message.error(msg || RESPONSE_TIPS.dataError)
|
||||
return {data:[], success:false}
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -205,19 +207,19 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
|
||||
|
||||
const monitorTopDataTabItems:TabsProps['items'] = [
|
||||
{
|
||||
label:'API 请求量 Top10',
|
||||
label:$t('API 请求量 Top10'),
|
||||
key:'api',
|
||||
children:<MonitorTable className="pb-[10px]" ref={monitorApiTableRef} type='api' id="dashboard_top10_api" onRowClick={(record)=>{getDetailData(record as MonitorApiData,'api')}} request={()=>getTablesData(queryData||{},'api')}/>
|
||||
children:<MonitorTable className="pb-[10px]" ref={monitorApiTableRef} type='api' id="dashboard_top10_api" onRowClick={(record)=>{APP_MODE !== 'pro' ? null : getDetailData(record as MonitorApiData,'api')}} request={()=>getTablesData(queryData||{},'api')}/>
|
||||
},
|
||||
{
|
||||
label:'应用调用量 Top10',
|
||||
label:$t('应用调用量 Top10'),
|
||||
key:'subscribers',
|
||||
children:<MonitorTable className="pb-[10px]" ref={monitorSubTableRef} type='subscribers' id="dashboard_top10_subscriber" onRowClick={(record)=>{getDetailData(record as MonitorSubscriberData,'subscriber')}} request={()=>getTablesData(queryData||{},'subscriber')} />
|
||||
children:<MonitorTable className="pb-[10px]" ref={monitorSubTableRef} type='subscribers' id="dashboard_top10_subscriber" onRowClick={(record)=>{APP_MODE !== 'pro' ? null : getDetailData(record as MonitorSubscriberData,'subscriber')}} request={()=>getTablesData(queryData||{},'subscriber')} />
|
||||
},
|
||||
{
|
||||
label:'服务被调用量 Top10',
|
||||
label:$t('服务被调用量 Top10'),
|
||||
key:'providers',
|
||||
children:<MonitorTable className="pb-[10px]" ref={monitorSubTableRef} type='provider' id="dashboard_top10_provider" onRowClick={(record)=>{getDetailData(record as MonitorSubscriberData,'provider')}} request={()=>getTablesData(queryData||{},'provider')} />
|
||||
children:<MonitorTable className="pb-[10px]" ref={monitorSubTableRef} type='provider' id="dashboard_top10_provider" onRowClick={(record)=>{APP_MODE !== 'pro' ? null : getDetailData(record as MonitorSubscriberData,'provider')}} request={()=>getTablesData(queryData||{},'provider')} />
|
||||
}
|
||||
]
|
||||
|
||||
@@ -230,31 +232,17 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
|
||||
|
||||
return (
|
||||
<div className={`h-[calc(100vh-140px)] overflow-hidden pb-btnybase flex flex-col ${totalEmpty ? 'bg-[#fff]' : 'bg-MENU_BG'}`}>
|
||||
{/* 筛选区域 */}
|
||||
<ScrollableSection>
|
||||
<div className="flex items-center flex-wrap pb-[10px] px-btnbase content-before bg-MAIN_BG">
|
||||
{/* 筛选集群 */}
|
||||
{/* <div className="flex flex-nowrap items-center pt-btnybase mr-btnybase">
|
||||
<label className="whitespace-nowrap">集群:</label>
|
||||
<Select
|
||||
className="w-INPUT_NORMAL"
|
||||
mode="multiple"
|
||||
placeholder="请选择"
|
||||
value={queryData?.clusters}
|
||||
options={clusterList}
|
||||
onChange={(value)=>{setQueryData(prevData=>({...prevData || {}, clusters:value}))}}
|
||||
/>
|
||||
</div> */}
|
||||
<TimeRangeSelector
|
||||
labelSize="small"
|
||||
initialTimeButton={timeButton}
|
||||
onTimeButtonChange={setTimeButton}
|
||||
initialDatePickerValue={datePickerValue}
|
||||
onTimeRangeChange={handleTimeRangeChange}/>
|
||||
{/* 重置和查询按钮 */}
|
||||
<div className="flex flex-nowrap items-center pt-btnybase">
|
||||
<Button onClick={resetQuery}>重置</Button>
|
||||
<Button className="ml-btnybase" type="primary" loading={queryBtnLoading} onClick={() => {getMonitorData();setQueryBtnLoading(true)}}>查询</Button>
|
||||
<Button onClick={resetQuery}>{$t('重置')}</Button>
|
||||
<Button className="ml-btnybase" type="primary" loading={queryBtnLoading} onClick={() => {getMonitorData();setQueryBtnLoading(true)}}>{$t('查询')}</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Spin wrapperClassName={`flex-1 ${totalEmpty ?'':'overflow-auto'}`} indicator={<LoadingOutlined style={{ fontSize: 24 }} spin/>} spinning={queryBtnLoading}>
|
||||
@@ -263,25 +251,25 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
|
||||
{/* 图表区域 */}
|
||||
<div className=" px-btnbase mt-[12px] mb-[16px] grid gap-[20px]" style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(570px, 1fr))'}}>
|
||||
{/* 请求统计饼图 */}
|
||||
{pieError ? <Empty className="pt-[80px] bg-MAIN_BG w-[50%] h-[200px] m-0 mr-[16px]" image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无请求统计数据"/>: <MonitorPieGraph
|
||||
{pieError ? <Empty className="pt-[80px] bg-MAIN_BG w-[50%] h-[200px] m-0 mr-[16px]" image={Empty.PRESENTED_IMAGE_SIMPLE} description={$t("暂无请求统计数据")}/>: <MonitorPieGraph
|
||||
className="bg-MAIN_BG"
|
||||
title="请求统计"
|
||||
title={$t("请求统计")}
|
||||
pieData={requestPie}
|
||||
labelName="请求成功率"
|
||||
labelName={$t("请求成功率")}
|
||||
labelValue={requestSucRate}
|
||||
subText="请求总数"
|
||||
subText={$t("请求总数")}
|
||||
subValue={changeNumberUnit(requestStatic?.total)}
|
||||
status4xxCount={requestStatic?.status_4xx}
|
||||
status5xxCount={requestStatic?.status_5xx}
|
||||
/>}
|
||||
{/* 转发统计饼图 */}
|
||||
{pieError ? <Empty className="pt-[80px] bg-MAIN_BG w-[50%] h-[200px] m-0" image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无转发统计数据"/>: <MonitorPieGraph
|
||||
{pieError ? <Empty className="pt-[80px] bg-MAIN_BG w-[50%] h-[200px] m-0" image={Empty.PRESENTED_IMAGE_SIMPLE} description={$t("暂无转发统计数据")}/>: <MonitorPieGraph
|
||||
className=" bg-MAIN_BG"
|
||||
title="转发统计"
|
||||
title={$t("转发统计")}
|
||||
pieData={proxyPie}
|
||||
labelName="转发成功率"
|
||||
labelName={$t("转发成功率")}
|
||||
labelValue={proxySucRate}
|
||||
subText="转发总数"
|
||||
subText={$t("转发总数")}
|
||||
subValue={changeNumberUnit(proxyStatic?.total)}
|
||||
status4xxCount={proxyStatic?.status_4xx}
|
||||
status5xxCount={proxyStatic?.status_5xx}
|
||||
@@ -289,18 +277,18 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
|
||||
</div>
|
||||
{/* 折线图区域 */}
|
||||
{/* 调用量统计折线图 */}
|
||||
{invokeStaticError ? <Empty className="pt-[80px] m-btnbase mb-[16px] h-[200px] bg-MAIN_BG" image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无调用量统计数据"/>: <MonitorLineGraph
|
||||
{invokeStaticError ? <Empty className="pt-[80px] m-btnbase mb-[16px] h-[200px] bg-MAIN_BG" image={Empty.PRESENTED_IMAGE_SIMPLE} description={$t("暂无调用量统计数据")}/>: <MonitorLineGraph
|
||||
className=" bg-MAIN_BG pt-[16px]"
|
||||
lineData={invokeStatic}
|
||||
titles={['调用量统计']}
|
||||
titles={[$t('调用量统计')]}
|
||||
yAxisTitle={timeUnit || '-'}
|
||||
type="invoke"
|
||||
/>}
|
||||
{/* 报文量统计折线图 */}
|
||||
{trafficStaticError ? <Empty className=" bg-MAIN_BG pt-[80px] m-btnbase mb-0 h-[200px]" image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无报文量统计数据"/>:<MonitorLineGraph
|
||||
{trafficStaticError ? <Empty className=" bg-MAIN_BG pt-[80px] m-btnbase mb-0 h-[200px]" image={Empty.PRESENTED_IMAGE_SIMPLE} description={$t("暂无报文量统计数据")}/>:<MonitorLineGraph
|
||||
className=" bg-MAIN_BG pt-[16px]"
|
||||
lineData={trafficStatic}
|
||||
titles={['报文量统计']}
|
||||
titles={[$t('报文量统计')]}
|
||||
yAxisTitle={timeUnit || '-'}
|
||||
type="traffic"
|
||||
/>}
|
||||
@@ -314,9 +302,9 @@ const MonitorTotalPage = (props:MonitorTotalPageProps) => {
|
||||
mask={!fullScreen}
|
||||
title={<>
|
||||
{fullScreen && <a className="mr-btnrbase text-[14px]" onClick={()=>{setFullScreen(false)}}>
|
||||
<CloseOutlined className="mr-[4px]"/>退出全屏
|
||||
<CloseOutlined className="mr-[4px]"/>{$t('退出全屏')}
|
||||
</a>}
|
||||
<span className="mr-btnrbase">{detailEntityName}调用详情</span>
|
||||
<span className="mr-btnrbase">{detailEntityName}{$t('调用详情')}</span>
|
||||
{!fullScreen && <ExpandOutlined className="text-MAIN_TEXT hover:text-MAIN_HOVER_TEXT" onClick={()=>{setFullScreen(true)}}/>}
|
||||
</>}
|
||||
width={fullScreen ? '100%' : '60%'}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { ProColumns } from "@ant-design/pro-components"
|
||||
import { MonitorApiData, MonitorData } from "./type"
|
||||
import { EChartsOption } from "echarts-for-react"
|
||||
import { Tooltip } from "antd"
|
||||
import { $t } from "@common/locales"
|
||||
import { PageProColumns } from "@common/components/aoplatform/PageList"
|
||||
|
||||
// 监控表格参数
|
||||
export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:string})[] = [
|
||||
export const DASHBOARD_BASE_COLUMNS_CONFIG:(PageProColumns<MonitorData>&{eoTitle:string})[] = [
|
||||
{
|
||||
title: '请求总数',
|
||||
eoTitle:'请求总数',
|
||||
title:$t('请求总数'),
|
||||
eoTitle:$t('请求总数'),
|
||||
dataIndex: 'requestTotal',
|
||||
sorter: (a,b)=> {
|
||||
return a.requestTotal - b.requestTotal
|
||||
@@ -16,9 +17,8 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
width: 96
|
||||
},
|
||||
{
|
||||
// title: '请求成功数',
|
||||
title: <Tooltip title="请求成功数" >请求成功数</Tooltip>,
|
||||
eoTitle:'请求成功数',
|
||||
title: <Tooltip title={$t("请求成功数")} >{$t('请求成功数')}</Tooltip>,
|
||||
eoTitle:$t('请求成功数'),
|
||||
dataIndex: 'requestSuccess',
|
||||
width: 106,
|
||||
ellipsis:true,
|
||||
@@ -27,9 +27,9 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '请求成功率',
|
||||
title: <Tooltip title="请求成功率" >请求成功率</Tooltip>,
|
||||
eoTitle:'请求成功率',
|
||||
// title:$t('请求成功率',
|
||||
title: <Tooltip title={$t('请求成功率')} >{$t('请求成功率')}</Tooltip>,
|
||||
eoTitle:$t('请求成功率'),
|
||||
dataIndex: 'requestRate',
|
||||
valueType:'percent',
|
||||
ellipsis:true,
|
||||
@@ -39,9 +39,9 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
width: 106
|
||||
},
|
||||
{
|
||||
title: '转发总数',
|
||||
eoTitle:'转发总数',
|
||||
width: 96,
|
||||
title:$t('转发总数'),
|
||||
eoTitle:$t('转发总数'),
|
||||
width: 96,
|
||||
dataIndex: 'proxyTotal',
|
||||
ellipsis:true,
|
||||
sorter: (a,b)=> {
|
||||
@@ -49,10 +49,10 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '转发成功数',
|
||||
title: <Tooltip title="转发成功数" >转发成功数</Tooltip>,
|
||||
eoTitle:'转发成功数',
|
||||
width: 106,
|
||||
// title:$t('转发成功数',
|
||||
title: <Tooltip title={$t("转发成功数")} >{$t('转发成功数')}</Tooltip>,
|
||||
eoTitle:$t('转发成功数'),
|
||||
width: 106,
|
||||
dataIndex: 'proxySuccess',
|
||||
ellipsis:true,
|
||||
sorter: (a,b)=> {
|
||||
@@ -60,10 +60,10 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '转发成功率',
|
||||
title: <Tooltip title="转发成功率" >转发成功率</Tooltip>,
|
||||
eoTitle:'转发成功率',
|
||||
width: 106,
|
||||
// title:$t('转发成功率',
|
||||
title: <Tooltip title={$t("转发成功率")} >{$t('转发成功率')}</Tooltip>,
|
||||
eoTitle:$t('转发成功率'),
|
||||
width: 106,
|
||||
dataIndex: 'proxyRate',
|
||||
valueType:'percent',
|
||||
ellipsis:true,
|
||||
@@ -72,10 +72,10 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '失败状态码数',
|
||||
title: <Tooltip title="失败状态码数" >失败状态码数</Tooltip>,
|
||||
eoTitle:'失败状态码数',
|
||||
width: 120,
|
||||
// title:$t('失败状态码数',
|
||||
title: <Tooltip title={$t("失败状态码数")} >{$t('失败状态码数')}</Tooltip>,
|
||||
eoTitle:$t('失败状态码数'),
|
||||
width: 120,
|
||||
dataIndex: 'statusFail',
|
||||
ellipsis:true,
|
||||
sorter: (a,b)=> {
|
||||
@@ -83,9 +83,9 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '平均响应时间(ms)',
|
||||
title: <Tooltip title="平均响应时间(ms)" >平均响应时间(ms)</Tooltip>,
|
||||
eoTitle:'平均响应时间(ms)',
|
||||
// title:$t('平均响应时间(ms)',
|
||||
title: <Tooltip title={$t("平均响应时间(ms)")} >{$t('平均响应时间(ms)')}</Tooltip>,
|
||||
eoTitle:$t('平均响应时间(ms)'),
|
||||
width: 148,
|
||||
dataIndex: 'avgResp',
|
||||
valueType:'digit',
|
||||
@@ -95,9 +95,9 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '最大响应时间(ms)',
|
||||
title: <Tooltip title="最大响应时间(ms)" >最大响应时间(ms)</Tooltip>,
|
||||
eoTitle:'最大响应时间(ms)',
|
||||
// title:$t('最大响应时间(ms)',
|
||||
title: <Tooltip title={$t("最大响应时间(ms)")} >{$t('最大响应时间(ms)')}</Tooltip>,
|
||||
eoTitle:$t('最大响应时间(ms)'),
|
||||
width: 148,
|
||||
dataIndex: 'maxResp',
|
||||
valueType:'digit',
|
||||
@@ -107,9 +107,9 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '最小响应时间(ms)',
|
||||
title: <Tooltip title="最小响应时间(ms)" >最小响应时间(ms)</Tooltip>,
|
||||
eoTitle:'最小响应时间(ms)',
|
||||
// title:$t('最小响应时间(ms)',
|
||||
title: <Tooltip title={$t("最小响应时间(ms)")} >{$t('最小响应时间(ms)')}</Tooltip>,
|
||||
eoTitle:$t('最小响应时间(ms)'),
|
||||
width: 148,
|
||||
dataIndex: 'minResp',
|
||||
valueType:'digit',
|
||||
@@ -119,9 +119,9 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '平均请求流量(KB)',
|
||||
title: <Tooltip title="平均请求流量(KB)" >平均请求流量(KB)</Tooltip>,
|
||||
eoTitle:'平均请求流量(KB)',
|
||||
// title:$t('平均请求流量(KB)',
|
||||
title: <Tooltip title={$t("平均请求流量(KB)")} >{$t('平均请求流量(KB)')}</Tooltip>,
|
||||
eoTitle:$t('平均请求流量(KB)'),
|
||||
width: 148,
|
||||
dataIndex: 'avgTraffic',
|
||||
valueType:'digit',
|
||||
@@ -131,9 +131,9 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '最大请求流量(KB)',
|
||||
title: <Tooltip title="最大请求流量(KB)" >最大请求流量(KB)</Tooltip>,
|
||||
eoTitle:'最大请求流量(KB)',
|
||||
// title:$t('最大请求流量(KB)',
|
||||
title: <Tooltip title={$t("最大请求流量(KB)")} >{$t('最大请求流量(KB)')}</Tooltip>,
|
||||
eoTitle:$t('最大请求流量(KB)'),
|
||||
width: 148,
|
||||
dataIndex: 'maxTraffic',
|
||||
valueType:'digit',
|
||||
@@ -143,9 +143,9 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
},
|
||||
},
|
||||
{
|
||||
// title: '最小请求流量(KB)',
|
||||
title: <Tooltip title="最小请求流量(KB)" >最小请求流量(KB)</Tooltip>,
|
||||
eoTitle:'最小请求流量(KB)',
|
||||
// title:$t('最小请求流量(KB)',
|
||||
title: <Tooltip title={$t("最小请求流量(KB)")} >{$t('最小请求流量(KB)')}</Tooltip>,
|
||||
eoTitle:$t('最小请求流量(KB)'),
|
||||
width: 148,
|
||||
dataIndex: 'minTraffic',
|
||||
valueType:'digit',
|
||||
@@ -156,11 +156,11 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
}]
|
||||
|
||||
|
||||
export const API_TABLE_GLOBAL_COLUMNS_CONFIG:(ProColumns<MonitorApiData>&{eoTitle:string})[] = [
|
||||
export const API_TABLE_GLOBAL_COLUMNS_CONFIG:(PageProColumns<MonitorApiData>&{eoTitle:string})[] = [
|
||||
|
||||
{
|
||||
title: 'API 名称',
|
||||
eoTitle:'API 名称',
|
||||
title:$t('API 名称'),
|
||||
eoTitle:$t('API 名称'),
|
||||
dataIndex: 'name',
|
||||
width:120,
|
||||
ellipsis:true,
|
||||
@@ -168,29 +168,29 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
disable:true
|
||||
},
|
||||
{
|
||||
title: '请求路径',
|
||||
eoTitle:'请求路径',
|
||||
title:$t('请求路径'),
|
||||
eoTitle:$t('请求路径'),
|
||||
dataIndex: 'path',
|
||||
ellipsis:true,
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
title: '所属服务',
|
||||
eoTitle:'所属服务',
|
||||
title:$t('所属服务'),
|
||||
eoTitle:$t('所属服务'),
|
||||
dataIndex: ['project','name'],
|
||||
ellipsis:true,
|
||||
width: 80
|
||||
},
|
||||
...DASHBOARD_BASE_COLUMNS_CONFIG as (ProColumns<MonitorApiData>&{eoTitle:string})[]
|
||||
...DASHBOARD_BASE_COLUMNS_CONFIG as (PageProColumns<MonitorApiData>&{eoTitle:string})[]
|
||||
]
|
||||
|
||||
|
||||
|
||||
export const APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG:(ProColumns<MonitorApiData>&{eoTitle:string})[] = [
|
||||
export const APPLICATION_TABLE_GLOBAL_COLUMNS_CONFIG:(PageProColumns<MonitorApiData>&{eoTitle:string})[] = [
|
||||
|
||||
{
|
||||
title: '应用名称',
|
||||
eoTitle:'应用名称',
|
||||
title:$t('应用名称'),
|
||||
eoTitle:$t('应用名称'),
|
||||
dataIndex: 'name',
|
||||
width:160,
|
||||
ellipsis:true,
|
||||
@@ -198,21 +198,21 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
disable:true
|
||||
},
|
||||
{
|
||||
title: '应用 ID',
|
||||
eoTitle:'应用 ID',
|
||||
title:$t('应用 ID'),
|
||||
eoTitle:$t('应用 ID'),
|
||||
dataIndex: 'id',
|
||||
width: 140,
|
||||
ellipsis:true,
|
||||
fixed: 'left'
|
||||
},
|
||||
...DASHBOARD_BASE_COLUMNS_CONFIG as (ProColumns<MonitorApiData>&{eoTitle:string})[]
|
||||
...DASHBOARD_BASE_COLUMNS_CONFIG as (PageProColumns<MonitorApiData>&{eoTitle:string})[]
|
||||
]
|
||||
|
||||
export const SERVICE_TABLE_GLOBAL_COLUMNS_CONFIG:(ProColumns<MonitorApiData>&{eoTitle:string})[] = [
|
||||
export const SERVICE_TABLE_GLOBAL_COLUMNS_CONFIG:(PageProColumns<MonitorApiData>&{eoTitle:string})[] = [
|
||||
|
||||
{
|
||||
title: '服务名称',
|
||||
eoTitle:'服务名称',
|
||||
title:$t('服务名称'),
|
||||
eoTitle:$t('服务名称'),
|
||||
dataIndex: 'name',
|
||||
width:160,
|
||||
ellipsis:true,
|
||||
@@ -220,14 +220,14 @@ export const DASHBOARD_BASE_COLUMNS_CONFIG:(ProColumns<MonitorData>&{eoTitle:str
|
||||
disable:true
|
||||
},
|
||||
{
|
||||
title: '服务 ID',
|
||||
eoTitle:'服务 ID',
|
||||
title:$t('服务 ID'),
|
||||
eoTitle:$t('服务 ID'),
|
||||
dataIndex: 'id',
|
||||
width: 140,
|
||||
ellipsis:true,
|
||||
fixed: 'left'
|
||||
},
|
||||
...DASHBOARD_BASE_COLUMNS_CONFIG as (ProColumns<MonitorApiData>&{eoTitle:string})[]
|
||||
...DASHBOARD_BASE_COLUMNS_CONFIG as (PageProColumns<MonitorApiData>&{eoTitle:string})[]
|
||||
]
|
||||
|
||||
export const MONITOR_LINE_CHART_BASIC_INVOKE_SELECTED = {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useEffect } from "react";
|
||||
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext";
|
||||
import DashboardPage from "./DashboardTabPage";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export default function Dashboard(){
|
||||
const { setBreadcrumb } = useBreadcrumb()
|
||||
@@ -9,7 +10,7 @@ export default function Dashboard(){
|
||||
useEffect(() => {
|
||||
setBreadcrumb([
|
||||
{
|
||||
title:'运行视图'
|
||||
title:$t('运行视图')
|
||||
},
|
||||
])
|
||||
|
||||
@@ -17,8 +18,9 @@ export default function Dashboard(){
|
||||
|
||||
return (
|
||||
<>
|
||||
<DashboardPage />
|
||||
|
||||
<div className="h-full w-full pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B ">
|
||||
<DashboardPage />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -4,6 +4,9 @@ import DashboardTotal from "./DashboardTotal";
|
||||
import { Outlet, useNavigate, useParams } from "react-router-dom";
|
||||
import { RouterParams } from "@core/components/aoplatform/RenderRoutes";
|
||||
import { useEffect, useState } from "react";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
const APP_MODE = import.meta.env.VITE_APP_MODE;
|
||||
|
||||
export default function DashboardTabPage(){
|
||||
const { dashboardType} = useParams<RouterParams>()
|
||||
@@ -16,32 +19,32 @@ export default function DashboardTabPage(){
|
||||
|
||||
const monitorTabItems:TabsProps['items'] = [
|
||||
{
|
||||
label:'监控总览',
|
||||
label:$t('监控总览'),
|
||||
key:'total',
|
||||
children:<DashboardTotal />
|
||||
},
|
||||
{
|
||||
label:'服务被调用统计',
|
||||
label:$t('服务被调用统计'),
|
||||
key:'subscriber',
|
||||
children:<Outlet />
|
||||
},
|
||||
{
|
||||
label:'应用调用统计',
|
||||
label:$t('应用调用统计'),
|
||||
key:'provider',
|
||||
children:<Outlet />
|
||||
},
|
||||
{
|
||||
label:'API 调用统计',
|
||||
label:$t('API 调用统计'),
|
||||
key:'api',
|
||||
children:<Outlet />
|
||||
}
|
||||
]
|
||||
|
||||
return (<>
|
||||
<Tabs activeKey={activeKey} onChange={(val)=>{
|
||||
{APP_MODE === 'pro' ? <Tabs activeKey={activeKey} onChange={(val)=>{
|
||||
setActiveKey(val);
|
||||
navigateTo(`/dashboard/${val === 'total' ? val :`${val}/list`}`)
|
||||
}}
|
||||
items={monitorTabItems} className="h-auto mt-[6px]" size="small" tabBarStyle={{paddingLeft:'10px',marginTop:'0px',marginBottom:'0px'}} />
|
||||
</>)
|
||||
: <Outlet />} </>)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
import { RangeValue } from "@common/components/aoplatform/TimeRangeSelector";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export function getTime (
|
||||
timeButton: string,
|
||||
@@ -45,23 +46,23 @@ export function getTime (
|
||||
// 相差秒数
|
||||
switch (timeInterval) {
|
||||
case '1m': {
|
||||
timeUnit = '每分钟'
|
||||
timeUnit = $t('每分钟')
|
||||
break
|
||||
}
|
||||
case '5m': {
|
||||
timeUnit = '每5分钟'
|
||||
timeUnit = $t('每5分钟')
|
||||
break
|
||||
}
|
||||
case '1h': {
|
||||
timeUnit = '每小时'
|
||||
timeUnit = $t('每小时')
|
||||
break
|
||||
}
|
||||
case '1d': {
|
||||
timeUnit = '每天'
|
||||
timeUnit = $t('每天')
|
||||
break
|
||||
}
|
||||
case '1w': {
|
||||
timeUnit = '每周'
|
||||
timeUnit = $t('每周')
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -71,23 +72,23 @@ export function getTime (
|
||||
// 当数据超过10万时,保留两个小数点,单位为万,如123212,显示12.32万;
|
||||
export function changeNumberUnit (value?:number):string {
|
||||
if (value && value > 1000000000) {
|
||||
return (value && value / 100000000).toFixed(2) + '亿'
|
||||
return (value && value / 100000000).toFixed(2) + $t('亿')
|
||||
} else if (value && value > 1000000) {
|
||||
return (value && value / 10000).toFixed(0) + '万'
|
||||
return (value && value / 10000).toFixed(0) + $t('万')
|
||||
} else if (value && value > 10000) {
|
||||
return (value && value / 10000).toFixed(2) + '万'
|
||||
return (value && value / 10000).toFixed(2) + $t('万')
|
||||
}
|
||||
return (value ?? '-') + ' 次'
|
||||
return (value ?? '-') + $t(' 次')
|
||||
}
|
||||
|
||||
export function yUnitFormatter (value:number):string {
|
||||
let res:string = ''
|
||||
if (value > 100000000) {
|
||||
res = (value / 100000000).toFixed(2) + '亿'
|
||||
res = (value / 100000000).toFixed(2) + $t('亿')
|
||||
} else if (value > 1000000) {
|
||||
res = (value / 10000).toFixed(0) + '万'
|
||||
res = (value / 10000).toFixed(0) + $t('万')
|
||||
} else if (value > 100000) {
|
||||
res = (value / 10000).toFixed(2) + '万'
|
||||
res = (value / 10000).toFixed(2) + $t('万')
|
||||
} else {
|
||||
res = value.toFixed(0)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
"@dashboard/*": ["./src/*"]
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TransferTable.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/Navigation.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/GroupTree.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ const generateRoutes = (routerConfig: RouteConfig[]) => {
|
||||
const LazyComponent = route.lazy as React.ExoticComponent<unknown>;
|
||||
|
||||
routeElement = (
|
||||
<Suspense fallback={ <div className=''><Skeleton className='m-btnbase w-[calc(100%-20px)]' active /></div>}>
|
||||
<Suspense fallback={ <div className=''><Skeleton className='m-btnbase w-calc-100vw-minus-padding-r' active /></div>}>
|
||||
{route.provider ? (
|
||||
createElement(route.provider, {}, <LazyComponent />)
|
||||
) : (
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
|
||||
import { ProColumns } from "@ant-design/pro-components";
|
||||
import { MenuProps } from "antd";
|
||||
import { getItem } from "@common/utils/navigation";
|
||||
import { ServiceHubTableListItem } from "./type";
|
||||
import { $t } from "@common/locales";
|
||||
import { PageProColumns } from "@common/components/aoplatform/PageList";
|
||||
|
||||
export const SERVICE_HUB_TABLE_COLUMNS: ProColumns<ServiceHubTableListItem>[] = [
|
||||
export const SERVICE_HUB_TABLE_COLUMNS: PageProColumns<ServiceHubTableListItem>[] = [
|
||||
{
|
||||
title: '服务名称',
|
||||
title:$t('服务名称'),
|
||||
dataIndex: 'name',
|
||||
ellipsis:true,
|
||||
width:160,
|
||||
@@ -16,29 +17,29 @@ export const SERVICE_HUB_TABLE_COLUMNS: ProColumns<ServiceHubTableListItem>[] =
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '服务ID',
|
||||
title:$t('服务ID'),
|
||||
dataIndex: 'id',
|
||||
width: 140,
|
||||
ellipsis:true
|
||||
},
|
||||
{
|
||||
title: '服务标签',
|
||||
title:$t('服务标签'),
|
||||
dataIndex: 'tags',
|
||||
ellipsis:true,
|
||||
renderText:(_,entity:ServiceHubTableListItem)=>entity.tags?.map(x=>x.name).join(',') || '-'
|
||||
},
|
||||
{
|
||||
title: '所属系统',
|
||||
title:$t('所属系统'),
|
||||
dataIndex: ['app','name'],
|
||||
ellipsis:true
|
||||
},
|
||||
{
|
||||
title: '所属团队',
|
||||
title:$t('所属团队'),
|
||||
dataIndex: ['team','name'],
|
||||
ellipsis:true
|
||||
},
|
||||
{
|
||||
title: '服务分类',
|
||||
title:$t('服务分类'),
|
||||
dataIndex: ['catalogue','name'],
|
||||
ellipsis:true
|
||||
}
|
||||
@@ -47,7 +48,7 @@ export const SERVICE_HUB_TABLE_COLUMNS: ProColumns<ServiceHubTableListItem>[] =
|
||||
|
||||
export const TENANT_MANAGEMENT_APP_MENU: MenuProps['items'] = [
|
||||
|
||||
getItem('订阅的服务', 'service'),
|
||||
getItem('访问授权', 'authorization'),
|
||||
getItem('应用管理', 'setting'),
|
||||
getItem($t('订阅的服务'), 'service'),
|
||||
getItem($t('访问授权'), 'authorization'),
|
||||
getItem($t('应用管理'), 'setting'),
|
||||
];
|
||||
|
||||
@@ -93,7 +93,7 @@ export type ServiceHubAppListItem = {
|
||||
export type TenantManagementServiceListItem = {
|
||||
id:string
|
||||
service:EntityItem
|
||||
applyStatus:SubscribeEnum
|
||||
applyStatus:typeof SubscribeEnum
|
||||
app:EntityItem
|
||||
team:EntityItem
|
||||
from:SubscribeFromEnum
|
||||
|
||||
@@ -353,13 +353,13 @@ p{
|
||||
color:var(--primary-color) !important;
|
||||
}
|
||||
|
||||
button.ant-btn:not(:disabled):not(.text-table_text){
|
||||
/* button.ant-btn:not(:disabled):not(.text-table_text){
|
||||
color:var(--primary-color);
|
||||
}
|
||||
|
||||
button.ant-btn:not(:disabled):not(.text-table_text):hover{
|
||||
color:var(--button-primary-hover-background-color) !important;
|
||||
}
|
||||
} */
|
||||
|
||||
}
|
||||
.ant-popover .ant-popover-inner{
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
import {FC, useCallback, useEffect, useRef, useState} from "react";
|
||||
import {App, Button, Form, FormInstance, Input} from "antd";
|
||||
import {useGlobalContext} from "@common/contexts/GlobalStateContext.tsx";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import {BasicResponse, STATUS_CODE} from "@common/const/const.ts";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
// import {useCrypto} from "../hooks/crypto.ts";
|
||||
import Logo from '@common/assets/logo.png'
|
||||
|
||||
const Login:FC = ()=> {
|
||||
const {state, dispatch} = useGlobalContext()
|
||||
const {fetchData} = useFetch()
|
||||
const { message } = App.useApp()
|
||||
const navigate = useNavigate();
|
||||
const formRef = useRef<FormInstance>(null);
|
||||
const [loading,setLoading] = useState<boolean>()
|
||||
// const { encryptByEnAES } = useCrypto();
|
||||
|
||||
|
||||
const check = useCallback(()=>{
|
||||
fetchData<BasicResponse<{channel:Array<{name:string}>, status:string}>>('account/login',{method:'GET'}).then(response=>{
|
||||
const {code,data} = response
|
||||
if(code === STATUS_CODE.SUCCESS && data.status !== 'anonymous'){
|
||||
dispatch({type:'LOGIN'})
|
||||
//console.log('校验成功')
|
||||
navigate('/serviceHub/list')
|
||||
}else{
|
||||
dispatch({type:'LOGOUT'})
|
||||
}
|
||||
})
|
||||
},[])
|
||||
|
||||
|
||||
const getSystemInfo = useCallback(()=>{
|
||||
fetchData<BasicResponse<{version:string, buildTime:string}>>('common/version',{method:'GET', eoTransformKeys:['build_time']}).then(response=>{
|
||||
const {code,data} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
dispatch({type:'UPDATE_VERSION',version:data.version})
|
||||
dispatch({type:'UPDATE_DATE',updateDate:data.buildTime})
|
||||
}
|
||||
})
|
||||
},[])
|
||||
|
||||
const login = async () => {
|
||||
if (formRef.current) {
|
||||
try {
|
||||
const values = await formRef.current.validateFields();
|
||||
setLoading(true);
|
||||
|
||||
const { username, password } = values;
|
||||
// const encryptedPassword = encryptByEnAES(username, password);
|
||||
|
||||
const body = {
|
||||
name:username,
|
||||
password: password
|
||||
// client: 1,
|
||||
// type: 1,
|
||||
// app_type: 4,
|
||||
};
|
||||
|
||||
const {code,msg } = await fetchData<BasicResponse<null>>('account/login/username',{method:'POST',eoBody:(body)})
|
||||
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
dispatch({type:'LOGIN'})
|
||||
message.success('登录成功');
|
||||
const callbackUrl = new URLSearchParams(window.location.search).get('callbackUrl');
|
||||
if (callbackUrl && callbackUrl !== 'null') {
|
||||
navigate(callbackUrl);
|
||||
} else {
|
||||
navigate('/serviceHub/list')
|
||||
}
|
||||
}else{
|
||||
dispatch({type:'LOGOUT'})
|
||||
//console.log(msg)
|
||||
message.error(msg)
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
check()
|
||||
getSystemInfo()
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="h-full w-full flex bg-[#f5f7fa] items-center overflow-auto min-h-[490px]">
|
||||
<div className="w-[410px] mx-auto">
|
||||
<div className="mx-auto">
|
||||
<span className="flex items-center justify-center">
|
||||
<img
|
||||
className="h-[40px] mr-[8px]"
|
||||
src={Logo}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<section className="block w-[410px] mx-auto mt-[46px] bg-MAIN_BG px-[30px] pt-[30px] box-border rounded-[10px] shadow-[0_5px_20px_0_rgba(0,0,0,5%)]">
|
||||
<div className="h-full">
|
||||
<div>
|
||||
<div className="flex justify-center items-center">
|
||||
<span className="text-[24px] text-[#101010]">登录</span>
|
||||
</div>
|
||||
|
||||
<Form onFinish={login} className="w-[350px] pt-[28px] pb-[8px]"
|
||||
ref={formRef}>
|
||||
<Form.Item
|
||||
className="p-0 bg-transparent rounded border-none"
|
||||
name="username"
|
||||
rules={[{ required: true, message: '请输入账号' ,whitespace:true }]}
|
||||
>
|
||||
<Input
|
||||
className="w-[350px] h-[40px]"
|
||||
placeholder="账号"
|
||||
autoComplete="on"
|
||||
autoFocus
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
className="p-0 bg-transparent rounded border-none"
|
||||
name="password"
|
||||
rules={[{ required: true, message: '请输入密码' }]}
|
||||
>
|
||||
<Input.Password
|
||||
className="w-[350px] h-[40px]"
|
||||
placeholder="密码"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<div className=" justify-center">
|
||||
<Form.Item
|
||||
className="p-0 bg-transparent rounded border-none"
|
||||
>
|
||||
<Button loading={loading} className="h-[40px] mt-mbase w-full inline-flex justify-center items-center" type="primary" htmlType="submit">
|
||||
登录
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="flex flex-col items-center mt-[46px] text-SECOND_TEXT">
|
||||
<p className="leading-[28px]">Version {state.version}-{state.updateDate}</p>
|
||||
<p className="leading-[28px]">{state.powered}</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default Login;
|
||||
@@ -7,6 +7,7 @@ import {DataNode} from "antd/es/tree";
|
||||
import {ApiDetail} from "@common/const/api-detail";
|
||||
import ApiTest from "@common/components/postcat/ApiTest.tsx";
|
||||
import DirectoryTree from "antd/es/tree/DirectoryTree";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
type ApiTestGroupType = {
|
||||
apiInfoList:ApiDetail[]
|
||||
@@ -62,7 +63,7 @@ export default function ApiTestGroup({apiInfoList,selectedApiId }:ApiTestGroupTy
|
||||
<div className="flex flex-1 h-full w-full">
|
||||
<div className="w-[220px] p-btnbase border-0 border-solid border-r-[1px] border-r-BORDER">
|
||||
<Input className=" my-btnybase" onChange={(e) => debounce(onSearchWordChange, 100)(e)}
|
||||
allowClear placeholder="搜索分类或标签"
|
||||
allowClear placeholder={$t("搜索分类或标签")}
|
||||
prefix={<SearchOutlined className="cursor-pointer" onClick={(e) => {
|
||||
onSearchWordChange(e)
|
||||
}}/>}/>
|
||||
@@ -78,7 +79,7 @@ export default function ApiTestGroup({apiInfoList,selectedApiId }:ApiTestGroupTy
|
||||
</div>
|
||||
{selectedApiInfo ?
|
||||
<ApiTest apiInfo={selectedApiInfo} /> :
|
||||
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无API数据"/>
|
||||
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={$t("暂无API数据")}/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
import { App, Form, Row, Col, Select, Input } from "antd";
|
||||
import { forwardRef, useEffect, useImperativeHandle, useMemo } from "react";
|
||||
import WithPermission from "@common/components/aoplatform/WithPermission";
|
||||
import { BasicResponse, STATUS_CODE } from "@common/const/const";
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE } from "@common/const/const";
|
||||
import { ApplyServiceHandle, ApplyServiceProps } from "../../const/serviceHub/type";
|
||||
import { useFetch } from "@common/hooks/http";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export const ApplyServiceModal = forwardRef<ApplyServiceHandle,ApplyServiceProps>((props,ref)=>{
|
||||
const { message } = App.useApp()
|
||||
@@ -22,11 +23,11 @@ export const ApplyServiceModal = forwardRef<ApplyServiceHandle,ApplyServiceProps
|
||||
fetchData<BasicResponse<null>>('catalogue/service/subscribe',{method:'POST',eoParams:{team:entity?.team?.id}, eoBody:({...value,service:entity.id})}).then(response=>{
|
||||
const {code,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
message.success(msg || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
reject(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
reject(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
@@ -48,23 +49,23 @@ export const ApplyServiceModal = forwardRef<ApplyServiceHandle,ApplyServiceProps
|
||||
autoComplete="off"
|
||||
>
|
||||
<Row className="mb-btnybase h-[32px]" >
|
||||
<Col span={6} className="pb-[8px] text-left">服务名称:</Col>
|
||||
<Col span={6} className="pb-[8px] text-left">{$t('服务名称')}:</Col>
|
||||
<Col span={18}>{entity.name}</Col>
|
||||
</Row>
|
||||
<Row className="h-[32px] mb-btnybase">
|
||||
<Col span={6} className="pb-[8px] text-left">服务 ID:</Col>
|
||||
<Col span={6} className="pb-[8px] text-left">{$t('服务 ID')}:</Col>
|
||||
<Col span={18}>{entity.id}</Col>
|
||||
</Row>
|
||||
<Form.Item
|
||||
label="应用"
|
||||
label={$t("应用")}
|
||||
name="applications"
|
||||
rules={[{ required: true, message: '必填项' }]}
|
||||
rules={[{ required: true, message: VALIDATE_MESSAGE.required }]}
|
||||
>
|
||||
<Select className="w-INPUT_NORMAL" disabled={reApply} placeholder="搜索或选择应用" mode="multiple" options={mySystemOptionList?.filter((x)=>x.value !== entity.id)}/>
|
||||
<Select className="w-INPUT_NORMAL" disabled={reApply} placeholder={$t("搜索或选择应用")} mode="multiple" options={mySystemOptionList?.filter((x)=>x.value !== entity.id)}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="申请理由"
|
||||
label={$t("申请理由")}
|
||||
name="reason"
|
||||
>
|
||||
<Input.TextArea className="w-INPUT_NORMAL" placeholder=""/>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {ApiDetail} from "@common/const/api-detail";
|
||||
import {ServiceDetailType } from "../../const/serviceHub/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 { $t } from "@common/locales/index.ts";
|
||||
|
||||
const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
|
||||
const {serviceId} = useParams<RouterParams>();
|
||||
@@ -28,7 +29,7 @@ const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
|
||||
{
|
||||
key: 'apiDocument-list',
|
||||
href: '#apiDocument-list',
|
||||
title: 'API 列表',
|
||||
title:$t('API 列表'),
|
||||
children:apiDocs?.map((x)=>({
|
||||
key:x.id,
|
||||
href:`#apiDocument-${x.id}`,
|
||||
@@ -38,7 +39,7 @@ const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
|
||||
// {
|
||||
// key: 'apiDocument-statusCode',
|
||||
// href: '#apiDocument-statusCode',
|
||||
// title: '状态码',
|
||||
// title:$t('状态码',
|
||||
// },
|
||||
], [apiDocs]);
|
||||
|
||||
@@ -63,9 +64,6 @@ const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col p-btnbase pt-[4px] h-full flex-1 overflow-auto" id='layout-ref'>
|
||||
{/* <div className="bg-[#fff] rounded p-btnbase pl-0 mb-[16px]">
|
||||
<Descriptions className="bg-bar-theme p-[16px] rounded service-hub-description" title="" items={getBasicInfo} column={4} labelStyle={{width:'80px',justifyContent:'flex-end',fontWeight:'bold'}} contentStyle={{color:'#333'}}/>
|
||||
</div> */}
|
||||
<div className='bg-[#fff] rounded p-btnbase pl-0 flex justify-between'>
|
||||
<div className="w-[calc(100%-220px)]" >
|
||||
<p className="font-bold text-[20px] leading-[32px] mb-[12px] h-[32px]" id="apiDocument-list">API 列表</p>
|
||||
@@ -83,23 +81,20 @@ const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
|
||||
readOnly
|
||||
addonBefore={apiDetail?.method}
|
||||
value={apiDetail?.path}
|
||||
// enterButton={<SearchBtn entity={apiDetail}/>}
|
||||
// onSearch={handleTest}
|
||||
/>
|
||||
</Space>
|
||||
{
|
||||
apiDetail?.match && apiDetail.match?.length > 0 &&
|
||||
<ApiMatch title='高级匹配' rows={apiDetail?.match} />
|
||||
<ApiMatch title={$t('高级匹配')} rows={apiDetail?.match} />
|
||||
}
|
||||
|
||||
{
|
||||
apiDetail?.proxy && Object.keys(apiDetail?.proxy).length > 0 &&
|
||||
<ApiProxy title='转发规则' proxyInfo={apiDetail?.proxy} />
|
||||
<ApiProxy title={$t('转发规则')} proxyInfo={apiDetail?.proxy} />
|
||||
}
|
||||
|
||||
{apiDetail && <ApiPreview entity={{...apiDetail.doc,name:apiDetail.name, method:apiDetail.method,uri:apiDetail.path, protocol:apiDetail.protocol||'HTTP'}} />}
|
||||
</div>
|
||||
// <ApiPreview testClick={()=>testClick(apiDocs.id)} entity={doc} />
|
||||
}]}
|
||||
activeKey={activeKey}
|
||||
onChange={(val)=>{setActiveKey(val as string[])}}
|
||||
@@ -108,18 +103,10 @@ const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
|
||||
))}
|
||||
|
||||
</div>
|
||||
{/* <div className="h-[16px] bg-[#f7f8fa] mx-[-16px]"></div>
|
||||
<div className='bg-[#fff] rounded pt-btnbase'>
|
||||
<p className="font-bold text-[20px] leading-[32px] mb-[12px] h-[32px]" id="apiDocument-statusCode">状态码</p>
|
||||
<CodePage />
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
<FloatButton.Group shape="circle" style={floatButtonStyle}>
|
||||
<Anchor
|
||||
// className='absolute py-5 px-btnbase left-0 z-[13]'
|
||||
// affix={false}
|
||||
// showInkInFixed={true}
|
||||
targetOffset={60}
|
||||
getContainer = {()=> document.getElementById('layout-ref')!}
|
||||
items={category}
|
||||
@@ -133,7 +120,7 @@ const ServiceHubApiDocument = ({service}:{service:ServiceDetailType})=>{
|
||||
maskClosable={false}
|
||||
width="100%" placement="right" onClose={onClose} open={apiTestDrawOpen}
|
||||
extra={
|
||||
<Button onClick={onClose}>退出测试</Button>
|
||||
<Button onClick={onClose}>{$t('退出测试')}</Button>
|
||||
}
|
||||
closeIcon={false}
|
||||
>
|
||||
|
||||
@@ -3,17 +3,18 @@ import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx";
|
||||
import { App, Avatar, Button, Descriptions, Divider, Tabs} from "antd";
|
||||
import { useEffect, useRef, useState} from "react";
|
||||
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
|
||||
import {BasicResponse, STATUS_CODE} from "@common/const/const.ts";
|
||||
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import {DefaultOptionType} from "antd/es/cascader";
|
||||
import { ApplyServiceHandle, ServiceBasicInfoType, ServiceDetailType } from "../../const/serviceHub/type.ts";
|
||||
import { EntityItem } from "@common/const/type.ts";
|
||||
import { ApplyServiceModal } from "./ApplyServiceModal.tsx";
|
||||
import ServiceHubApiDocument from "./ServiceHubApiDocument.tsx";
|
||||
import { ApiFilled, ArrowLeftOutlined, LeftOutlined } from "@ant-design/icons";
|
||||
import { ApiFilled, ArrowLeftOutlined } from "@ant-design/icons";
|
||||
import { SimpleSystemItem } from "@core/const/system/type.ts";
|
||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||
import DOMPurify from 'dompurify';
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
|
||||
|
||||
const ServiceHubDetail = ()=>{
|
||||
@@ -44,7 +45,7 @@ const ServiceHubDetail = ()=>{
|
||||
setServiceDoc(DOMPurify.sanitize(data.service.document))
|
||||
setActiveKey(data.service.apis.map((x)=>x.id))
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -61,8 +62,8 @@ const ServiceHubDetail = ()=>{
|
||||
getMySelectList()
|
||||
setBreadcrumb(
|
||||
[
|
||||
{title:<Link to={`/serviceHub/list`}>服务市场</Link>},
|
||||
{title:'服务详情'}
|
||||
{title:<Link to={`/serviceHub/list`}>{$t('服务市场')}</Link>},
|
||||
{title:$t('服务详情')}
|
||||
]
|
||||
)
|
||||
|
||||
@@ -78,7 +79,7 @@ const ServiceHubDetail = ()=>{
|
||||
label:x.name, value:x.id
|
||||
}}))
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -86,15 +87,15 @@ const ServiceHubDetail = ()=>{
|
||||
|
||||
const openModal = (type:'apply')=>{
|
||||
modal.confirm({
|
||||
title:'申请服务',
|
||||
title:$t('申请服务'),
|
||||
content:<ApplyServiceModal ref={applyRef} entity={{...serviceBasicInfo!, name:serviceName!, id:serviceId!}} mySystemOptionList={mySystemOptionList!}/>,
|
||||
onOk:()=>{
|
||||
return applyRef.current?.apply().then((res)=>{
|
||||
if(res === true) setApplied(true)
|
||||
})
|
||||
},
|
||||
okText:'确认',
|
||||
cancelText:'取消',
|
||||
okText:$t('确认'),
|
||||
cancelText:$t('取消'),
|
||||
closable:true,
|
||||
icon:<></>,
|
||||
width:600
|
||||
@@ -104,13 +105,13 @@ const ServiceHubDetail = ()=>{
|
||||
const items = [
|
||||
{
|
||||
key: 'introduction',
|
||||
label: '介绍',
|
||||
label: $t('介绍'),
|
||||
children: <><div className="p-btnbase preview-document" dangerouslySetInnerHTML={{__html: serviceDoc || ''}}></div></>,
|
||||
icon: <Icon icon="ic:baseline-space-dashboard" width="14" height="14"/>,
|
||||
},
|
||||
{
|
||||
key: 'api-document',
|
||||
label: 'API 文档',
|
||||
label: $t('API 文档'),
|
||||
children: <div className="p-btnbase"><ServiceHubApiDocument service={service!} /></div>,
|
||||
icon: <ApiFilled />
|
||||
}
|
||||
@@ -122,7 +123,7 @@ const ServiceHubDetail = ()=>{
|
||||
<section className="flex flex-col gap-btnbase p-btnbase ">
|
||||
|
||||
<div className="text-[18px] leading-[25px] pb-[12px]">
|
||||
<Button type="text" onClick={()=>navigate(`/serviceHub/list`)}><ArrowLeftOutlined className="max-h-[14px]" />返回</Button>
|
||||
<Button type="text" onClick={()=>navigate(`/serviceHub/list`)}><ArrowLeftOutlined className="max-h-[14px]" />{$t('返回')}</Button>
|
||||
</div>
|
||||
<div className="flex">
|
||||
{/* <Avatar shape="square" size={50} className=" bg-[linear-gradient(135deg,white,#f0f0f0)] text-[#333] rounded-[12px]" > {service?.name?.substring(0,1)}</Avatar> */}
|
||||
@@ -137,7 +138,7 @@ const ServiceHubDetail = ()=>{
|
||||
<div className="mt-[10px] flex flex-col gap-btnrbase font-normal">
|
||||
{serviceDesc || '-'}
|
||||
<div>
|
||||
<Button type="primary" onClick={()=>openModal('apply')}>申请</Button>
|
||||
<Button type="primary" onClick={()=>openModal('apply')}>{$t('申请')}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -151,16 +152,16 @@ const ServiceHubDetail = ()=>{
|
||||
|
||||
</section>
|
||||
<section className="col-span-1 p-btnbase px-btnrbase">
|
||||
<Descriptions title="服务信息" column={1} size={'small'}>
|
||||
<Descriptions.Item label="接入应用">{serviceBasicInfo?.appNum ?? '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="供应方">{serviceBasicInfo?.team?.name || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="分类">{serviceBasicInfo?.catalogue?.name || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="标签">{serviceBasicInfo?.tags?.map(x=>x.name)?.join(',') || '-'}</Descriptions.Item>
|
||||
<Descriptions title={$t("服务信息")} column={1} size={'small'}>
|
||||
<Descriptions.Item label={$t("接入应用")}>{serviceBasicInfo?.appNum ?? '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label={$t("供应方")}>{serviceBasicInfo?.team?.name || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label={$t("分类")}>{serviceBasicInfo?.catalogue?.name || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label={$t("标签")}>{serviceBasicInfo?.tags?.map(x=>x.name)?.join(',') || '-'}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
<Divider />
|
||||
<Descriptions column={1} >
|
||||
<Descriptions.Item label="版本">{ serviceBasicInfo?.version || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="更新时间"><span className="truncate" title={serviceBasicInfo?.updateTime}>{serviceBasicInfo?.updateTime || '-'}</span></Descriptions.Item>
|
||||
<Descriptions.Item label={$t("版本")}>{ serviceBasicInfo?.version || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label={$t("更新时间")}><span className="truncate" title={serviceBasicInfo?.updateTime}>{serviceBasicInfo?.updateTime || '-'}</span></Descriptions.Item>
|
||||
</Descriptions>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -3,11 +3,12 @@ import {SearchOutlined} from "@ant-design/icons";
|
||||
import {App, Divider, Input, TreeDataNode} from "antd";
|
||||
import {useCallback, useEffect, useState} from "react";
|
||||
import Tree, {DataNode} from "antd/es/tree";
|
||||
import {BasicResponse, STATUS_CODE} from "@common/const/const.ts";
|
||||
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import { CategorizesType } from "../../const/serviceHub/type.ts";
|
||||
import { filterServiceList, initialServiceHubListState, SERVICE_HUB_LIST_ACTIONS, ServiceHubListActionType } from "./ServiceHubList.tsx";
|
||||
import { EntityItem } from "@common/const/type.ts";
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
|
||||
type ServiceHubGroup = {
|
||||
children:JSX.Element
|
||||
@@ -35,11 +36,11 @@ export const ServiceHubGroup = ({children,filterOption,dispatch}:ServiceHubGroup
|
||||
const {code,data,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
dispatch({type:SERVICE_HUB_LIST_ACTIONS.GET_CATEGORIES,payload:data.catalogues})
|
||||
dispatch({type:SERVICE_HUB_LIST_ACTIONS.GET_TAGS,payload:[...data.tags,{id:'empty',name:'无标签'}]})
|
||||
dispatch({type:SERVICE_HUB_LIST_ACTIONS.GET_TAGS,payload:[...data.tags,{id:'empty',name:$t('无标签')}]})
|
||||
dispatch({type:SERVICE_HUB_LIST_ACTIONS.SET_SELECTED_CATE,payload:[...data.catalogues.map((x:CategorizesType)=>x.id)]})
|
||||
dispatch({type:SERVICE_HUB_LIST_ACTIONS.SET_SELECTED_TAG,payload:[...data.tags.map((x:EntityItem)=>x.id),'empty']})
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -75,11 +76,11 @@ export const ServiceHubGroup = ({children,filterOption,dispatch}:ServiceHubGroup
|
||||
<div className="w-[220px] border-0 border-solid border-r-[1px] border-r-BORDER">
|
||||
<div className=" h-full">
|
||||
<Input className="rounded-SEARCH_RADIUS m-[10px] h-[40px] bg-[#f8f8f8] w-[200px]" onChange={(e) => debounce(onSearchWordChange, 500)(e.target.value)}
|
||||
allowClear placeholder="搜索服务"
|
||||
allowClear placeholder={$t("搜索服务")}
|
||||
prefix={<SearchOutlined className="cursor-pointer"/>}/>
|
||||
<div className="h-[calc(100%-60px)] overflow-auto">
|
||||
<div className="mt-[20px] ml-[20px] pr-[10px] ">
|
||||
<p className="text-[18px] h-[25px] leading-[25px] font-bold mb-[15px]">分类</p>
|
||||
<p className="text-[18px] h-[25px] leading-[25px] font-bold mb-[15px]">{$t('分类')}</p>
|
||||
<Tree
|
||||
className={`no-selected-tree ${transferToTreeData(filterOption.categoriesList).filter(x=>x.children && x.children.length > 0).length > 0 ? '' : 'no-first-switch-tree'}`}
|
||||
checkable
|
||||
@@ -93,7 +94,7 @@ export const ServiceHubGroup = ({children,filterOption,dispatch}:ServiceHubGroup
|
||||
</div>
|
||||
<Divider className="my-[20px]" />
|
||||
<div className="ml-[20px] pr-[10px]">
|
||||
<p className="text-[18px] h-[25px] leading-[25px] font-bold mb-[15px]">标签</p>
|
||||
<p className="text-[18px] h-[25px] leading-[25px] font-bold mb-[15px]">{$t('标签')}</p>
|
||||
<Tree
|
||||
className="no-first-switch-tree no-selected-tree"
|
||||
checkable
|
||||
|
||||
@@ -3,7 +3,7 @@ import {FC, forwardRef, useEffect, useReducer, useRef} from "react";
|
||||
import { useNavigate, useParams} from "react-router-dom";
|
||||
import {App,Card, Avatar, Tag, Empty, Spin, Tooltip} from "antd";
|
||||
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
|
||||
import {BasicResponse, STATUS_CODE} from "@common/const/const.ts";
|
||||
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import {RouterParams} from "@core/components/aoplatform/RenderRoutes.tsx";
|
||||
import { CategorizesType, ServiceHubTableListItem } from "../../const/serviceHub/type.ts";
|
||||
@@ -11,6 +11,7 @@ import { VirtuosoGrid } from 'react-virtuoso';
|
||||
import { ApiOutlined,LoadingOutlined } from "@ant-design/icons";
|
||||
import ServiceHubGroup from "./ServiceHubGroup.tsx";
|
||||
import { EntityItem } from "@common/const/type.ts";
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
|
||||
export enum SERVICE_HUB_LIST_ACTIONS {
|
||||
GET_CATEGORIES = 'GET_CATEGORIES',
|
||||
@@ -102,7 +103,7 @@ const ServiceHubList:FC = ()=>{
|
||||
dispatch({type:SERVICE_HUB_LIST_ACTIONS.SET_SERVICES,payload: filterServiceList({...filterOption, servicesList:data.services})})
|
||||
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).finally(()=>{ dispatch({type:SERVICE_HUB_LIST_ACTIONS.LIST_LOADING,payload:false})})
|
||||
}
|
||||
@@ -117,7 +118,7 @@ const ServiceHubList:FC = ()=>{
|
||||
useEffect(() => {
|
||||
setBreadcrumb(
|
||||
[
|
||||
{title:'服务市场'}
|
||||
{title:$t('服务市场')}
|
||||
]
|
||||
)
|
||||
getServiceList()
|
||||
@@ -137,7 +138,7 @@ const ServiceHubList:FC = ()=>{
|
||||
<div className="pt-[20px]">
|
||||
<Card title={CardTitle(item)} className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] m-0 transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{header:'border-b-[0px] p-[20px] ', body:"pt-0"}} onClick={()=>showDocumentDetail(item)}>
|
||||
<span className="line-clamp-3 text-[12px] text-[#666] "
|
||||
style={{'word-break':'auto-phrase'}}>{item.description || '暂无服务描述'}</span>
|
||||
style={{'word-break':'auto-phrase'}}>{item.description || $t('暂无服务描述')}</span>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
@@ -182,10 +183,10 @@ const CardTitle = (service:ServiceHubTableListItem)=>{
|
||||
<div className="mt-[10px] h-[20px] flex items-center font-normal">
|
||||
<Tag color="#7371fc1b" className="text-theme font-normal border-0 mr-[12px] max-w-[150px] truncate" key={service.id} bordered={false} title={service.catalogue?.name || '-'}>{service.catalogue?.name || '-'}</Tag>
|
||||
|
||||
<Tooltip title='API 数量'>
|
||||
<Tooltip title={$t('API 数量')}>
|
||||
<span className="mr-[12px]"><ApiOutlined className="mr-[1px] text-[14px] h-[14px] w-[14px]"/><span className="font-normal text-[14px]">{service.apiNum ?? '-'}</span></span>
|
||||
</Tooltip>
|
||||
<Tooltip title='接入应用数量'>
|
||||
<Tooltip title={$t('接入应用数量')}>
|
||||
<span className="mr-[12px] flex items-center"><span className="h-[14px] mr-[4px] flex items-center"><iconpark-icon className="max-h-[14px] h-[14px] w-[14px]" name="auto-generate-api"></iconpark-icon></span><span className="font-normal text-[14px]">{service.subscriberNum ?? '-'}</span></span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
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 { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, 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"
|
||||
import { $t } from "@common/locales"
|
||||
|
||||
type FieldType = {
|
||||
reason: string
|
||||
@@ -28,11 +29,11 @@ export const ApprovalModalContent = forwardRef<SubSubscribeApprovalModalHandle,S
|
||||
fetchData<BasicResponse<null>>('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 || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
reject(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
reject(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
@@ -59,8 +60,6 @@ export const ApprovalModalContent = forwardRef<SubSubscribeApprovalModalHandle,S
|
||||
form={form}
|
||||
className="mx-auto "
|
||||
name="subSubscribeApprovalDetailModalContent"
|
||||
// labelCol={{ span: 8 }}
|
||||
// wrapperCol={{ span: 12}}
|
||||
autoComplete="off"
|
||||
disabled={type === 'view'}
|
||||
>
|
||||
@@ -69,22 +68,21 @@ export const ApprovalModalContent = forwardRef<SubSubscribeApprovalModalHandle,S
|
||||
return (
|
||||
<Row key={x.key} className="leading-[32px] mb-btnbase">
|
||||
<Col className="text-left" span={8}>{x.title}:</Col>
|
||||
{/* <Col >{showData(x)}</Col> */}
|
||||
<Col >{x.nested ? data?.[x.key]?.[x.nested] : ( (data as {[k:string]:unknown})?.[x.key] || '-')}</Col>
|
||||
</Row>)
|
||||
})}
|
||||
|
||||
<Form.Item<FieldType>
|
||||
label="申请原因"
|
||||
label={$t("申请原因")}
|
||||
name="reason"
|
||||
>
|
||||
<Input.TextArea className="w-INPUT_NORMAL" disabled={type === 'view'} placeholder="请输入" />
|
||||
<Input.TextArea className="w-INPUT_NORMAL" disabled={type === 'view'} placeholder={PLACEHOLDER.input} />
|
||||
</Form.Item>
|
||||
<Form.Item<FieldType>
|
||||
label="审核意见"
|
||||
label={$t("审核意见")}
|
||||
name="opinion"
|
||||
>
|
||||
<Input.TextArea className="w-INPUT_NORMAL" placeholder="请输入" disabled={true} />
|
||||
<Input.TextArea className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input} disabled={true} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</WithPermission>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { RouterParams } from "@core/components/aoplatform/RenderRoutes";
|
||||
import { useParams } from "react-router-dom";
|
||||
import ManagementConfig from "./ManagementConfig";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export default function ManagementAppSetting(){
|
||||
const {teamId,appId} = useParams<RouterParams>()
|
||||
|
||||
return (
|
||||
<div className=" h-full pt-[32px]">
|
||||
<div className="flex items-center justify-between w-full ml-[10px] text-[18px] leading-[25px] pb-[16px]" ><span className="font-bold">应用管理</span></div>
|
||||
<div className="flex items-center justify-between w-full ml-[10px] text-[18px] leading-[25px] pb-[16px]" ><span className="font-bold">{$t('应用管理')}</span></div>
|
||||
<div className="h-[calc(100%-41px)] flex flex-col ">
|
||||
<ManagementConfig type='edit' teamId={teamId!} appId={appId!}/>
|
||||
</div>
|
||||
|
||||
+53
-54
@@ -1,13 +1,13 @@
|
||||
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 {App, Checkbox, DatePicker, Form, Input, Select,Switch} from "antd";
|
||||
import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE} from "@common/const/const.tsx";
|
||||
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";
|
||||
import { RangePickerProps } from "antd/es/date-picker";
|
||||
import dayjs from 'dayjs';
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export type ManagementAuthorityConfigProps = {
|
||||
type:'add'|'edit'
|
||||
@@ -35,11 +35,11 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
|
||||
fetchData<BasicResponse<null>>('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 || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
reject(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
reject(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
@@ -70,18 +70,17 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
|
||||
}
|
||||
|
||||
|
||||
const disabledDate = (current: moment.Moment | null): boolean => {
|
||||
// 禁用今天以前的日期,包括今天
|
||||
// 使用current?.startOf('day')是为了获取日期的开始时间点,以确保整个今天都被禁用
|
||||
// 如果只需要禁用今天之前的日期(今天可选),则可以将`isBefore`的第二个参数设置为 'day'
|
||||
return current ? current.startOf('day') < moment().startOf('day') : false;
|
||||
|
||||
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
|
||||
// Can not select days before today and today
|
||||
return current && current.isBefore(dayjs().endOf('day'), 'day');
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
//console.log(data)
|
||||
if(type === 'edit' && data){
|
||||
form.setFieldsValue({...data,expireTime:data.expireTime === 0 ? '' : moment(data.expireTime *1000)})
|
||||
form.setFieldsValue({...data,expireTime:data.expireTime === 0 ? '' : dayjs(data.expireTime * 1000)})
|
||||
forceUpdate({})
|
||||
}else{
|
||||
form.setFieldsValue({driver, position:'Header',tokenName:'Authorization'})
|
||||
@@ -106,29 +105,29 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="名称"
|
||||
label={$t("名称")}
|
||||
name="name"
|
||||
rules={[{required: true, message: '必填项',whitespace:true }]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required,whitespace:true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入鉴权名称"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="鉴权类型"
|
||||
label={$t("鉴权类型")}
|
||||
name="driver"
|
||||
rules={[{required: true, message: '必填项'}]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required}]}
|
||||
>
|
||||
<Select disabled={type === 'edit'} className="w-INPUT_NORMAL" options={[
|
||||
{label:'Basic',value:'basic'},
|
||||
{label:'Jwt',value:'jwt'},
|
||||
{label:'AkSk',value:'aksk'},
|
||||
{label:'Apikey',value:'apikey'}]} onChange={(e)=>onDriverChange(e)} placeholder="请输入鉴权类型"/>
|
||||
{label:'Apikey',value:'apikey'}]} onChange={(e)=>onDriverChange(e)} placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="tokenName"
|
||||
label="参数位置"
|
||||
rules={[{required: true, message: '必填项',whitespace:true }]}
|
||||
label={$t("参数位置")}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required,whitespace:true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" addonBefore={prefixSelector} style={{width: '100%'}}/>
|
||||
</Form.Item>
|
||||
@@ -138,70 +137,70 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
|
||||
case 'basic':
|
||||
return <>
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="用户名"
|
||||
label={$t("用户名")}
|
||||
name={['config','userName']}
|
||||
rules={[{required: true, message: '必填项',whitespace:true }]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required,whitespace:true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="英文数字下划线任意一种,首字母必须为英文"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.startWithAlphabet}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="密码"
|
||||
label={$t("密码")}
|
||||
name={['config','password']}
|
||||
rules={[{required: true, message: '必填项',whitespace:true }]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required,whitespace:true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
</>
|
||||
case 'jwt':
|
||||
return <>
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="Iss"
|
||||
label={$t("Iss")}
|
||||
name={['config','iss']}
|
||||
rules={[{required: true, message: '必填项'}]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required}]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="签名算法"
|
||||
label={$t("签名算法")}
|
||||
name={['config','algorithm']}
|
||||
rules={[{required: true, message: '必填项'}]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required}]}
|
||||
>
|
||||
<Select className="w-INPUT_NORMAL" options={ALGORITHM_ITEM} onChange={(value)=>{onAlgorithmChange(value)}}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label={ algorithm.includes('HS') ? 'Secret':'RSA 公钥'}
|
||||
label={ algorithm.includes('HS') ? $t('Secret'):$t('RSA 公钥')}
|
||||
name={algorithm.includes('HS') ? ['config','secret']:['config','publicKey']}
|
||||
rules={[{required: true, message: '必填项'}]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required}]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="用户名"
|
||||
label={$t("用户名")}
|
||||
name={['config','user']}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="用户名 JsonPath"
|
||||
label={$t("用户名 JsonPath")}
|
||||
name={['config','userPath']}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="校验字段"
|
||||
label={$t("校验字段")}
|
||||
name={['config','claimsToVerify']}
|
||||
>
|
||||
<Select className="w-INPUT_NORMAL" mode="multiple" options={[{label:'exp',value:'exp'},{label:'nbf',value:'nbf'}]} placeholder="请输入"/>
|
||||
<Select className="w-INPUT_NORMAL" mode="multiple" options={[{label:'exp',value:'exp'},{label:'nbf',value:'nbf'}]} placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
{algorithm.includes('HS') && <Form.Item<EditAuthFieldType>
|
||||
label="是否 Base64 加密"
|
||||
label={$t("是否 Base64 加密")}
|
||||
name={['config', 'signatureIsBase64']}
|
||||
>
|
||||
<Switch />
|
||||
@@ -210,29 +209,29 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
|
||||
case 'aksk':
|
||||
return <>
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="AK"
|
||||
label={$t("AK")}
|
||||
name={['config','ak']}
|
||||
rules={[{required: true, message: '必填项'}]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required}]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="SK"
|
||||
label={$t("SK")}
|
||||
name={['config','sk']}
|
||||
rules={[{required: true, message: '必填项'}]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required}]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
</>
|
||||
case 'apikey':
|
||||
return <>
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="Apikey"
|
||||
label={$t("Apikey")}
|
||||
name={['config','apikey']}
|
||||
rules={[{required: true, message: '必填项',whitespace:true }]}
|
||||
rules={[{required: true, message: VALIDATE_MESSAGE.required,whitespace:true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
</>
|
||||
}
|
||||
@@ -240,7 +239,7 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
|
||||
})()}
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="过期时间"
|
||||
label={$t("过期时间")}
|
||||
name="expireTime"
|
||||
>
|
||||
<DatePicker
|
||||
@@ -250,7 +249,7 @@ export const ManagementAuthorityConfig = forwardRef<ManagementAuthorityConfigHan
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<EditAuthFieldType>
|
||||
label="隐藏鉴权信息"
|
||||
label={$t("隐藏鉴权信息")}
|
||||
name="hideCredential" valuePropName="checked"
|
||||
>
|
||||
<Checkbox/>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
|
||||
import {App, Button, Divider, Form, Input, Row} from "antd";
|
||||
import {App, Button, Form, Input, Row} from "antd";
|
||||
import {forwardRef, useEffect, useImperativeHandle, useState} from "react";
|
||||
import {v4 as uuidv4} from 'uuid'
|
||||
import WithPermission from "@common/components/aoplatform/WithPermission";
|
||||
import { BasicResponse, STATUS_CODE } from "@common/const/const";
|
||||
import { BasicResponse, DELETE_TIPS, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE } from "@common/const/const";
|
||||
import { useFetch } from "@common/hooks/http";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTenantManagementContext } from "@market/contexts/TenantManagementContext";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export type ManagementConfigFieldType = {
|
||||
name:string
|
||||
@@ -41,13 +42,13 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
|
||||
fetchData<BasicResponse<{apps:ManagementConfigFieldType}>>(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 || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
form.setFieldsValue(data.apps)
|
||||
type === 'edit' && setAppName(data.apps.name)
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
reject(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
reject(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
@@ -62,7 +63,7 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
|
||||
setAppName(data.app.name)
|
||||
setTimeout(()=>{form.setFieldsValue({...data.app})},0)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
})
|
||||
};
|
||||
@@ -70,20 +71,20 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
|
||||
const deleteApplicationModal = async ()=>{
|
||||
setDelBtnLoading(true)
|
||||
modal.confirm({
|
||||
title:'删除',
|
||||
content:'该数据删除后将无法找回,请确认是否删除?',
|
||||
title:$t('删除'),
|
||||
content:DELETE_TIPS.default,
|
||||
onOk:()=> {
|
||||
return deleteApplication()
|
||||
},
|
||||
width:600,
|
||||
okText:'确认',
|
||||
okText:$t('确认'),
|
||||
okButtonProps:{
|
||||
danger:true
|
||||
},
|
||||
onCancel:()=>{
|
||||
setDelBtnLoading(false)
|
||||
},
|
||||
cancelText:'取消',
|
||||
cancelText:$t('取消'),
|
||||
closable:true,
|
||||
icon:<></>
|
||||
})
|
||||
@@ -94,10 +95,10 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
|
||||
fetchData<BasicResponse<null>>('app',{method:'DELETE',eoParams:{app:appId,team:teamId}}).then(response=>{
|
||||
const {code,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
message.success(msg || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
navigate(`/tenantManagement/list`)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -125,41 +126,38 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
|
||||
form={form}
|
||||
className="mx-auto w-full pb-[20px]"
|
||||
name="managementConfig"
|
||||
// labelCol={{ offset:1, span: 4 }}
|
||||
// wrapperCol={{ span: 19}}
|
||||
autoComplete="off"
|
||||
onFinish={save}
|
||||
>
|
||||
<div>
|
||||
<Form.Item<ManagementConfigFieldType>
|
||||
label="应用名称"
|
||||
label={$t("应用名称")}
|
||||
name="name"
|
||||
rules={[{ required: true, message: '必填项',whitespace:true }]}
|
||||
rules={[{ required: true, message: VALIDATE_MESSAGE.required,whitespace:true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<ManagementConfigFieldType>
|
||||
label="应用 ID"
|
||||
label={$t("应用 ID")}
|
||||
name="id"
|
||||
rules={[{ required: true, message: '必填项' ,whitespace:true }]}
|
||||
rules={[{ required: true, message: VALIDATE_MESSAGE.required ,whitespace:true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入" disabled={type === 'edit'}/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input} disabled={type === 'edit'}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="描述"
|
||||
label={$t("描述")}
|
||||
name="description"
|
||||
>
|
||||
<Input.TextArea className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input.TextArea className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
{type === 'edit' && <>
|
||||
<Row className="mb-[10px]"
|
||||
// wrapperCol={{ offset: 5, span: 19 }}
|
||||
>
|
||||
<WithPermission access={type === 'edit'? 'team.application.application.edit' :'team.application.application.add'}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
保存
|
||||
{$t('保存')}
|
||||
</Button>
|
||||
</WithPermission>
|
||||
</Row> </>
|
||||
@@ -169,10 +167,10 @@ const ManagementConfig = forwardRef<ManagementConfigHandle,ManagementConfigProps
|
||||
|
||||
<WithPermission access="team.application.application.delete" showDisabled={false}>
|
||||
<div className="bg-[rgb(255_120_117_/_5%)] rounded-[10px] mt-[50px] p-btnrbase pb-0">
|
||||
<p className="text-left"><span className="font-bold">删除应用:</span>删除操作不可恢复,请谨慎操作!</p>
|
||||
<p className="text-left"><span className="font-bold">{$t('删除应用')}:</span>{$t('删除操作不可恢复,请谨慎操作!')}</p>
|
||||
<div className="text-left">
|
||||
<WithPermission access="team.application.application.delete">
|
||||
<Button className="m-auto mt-[16px] mb-[20px]" type="default" danger={true} onClick={deleteApplicationModal} loading={delBtnLoading}>删除应用</Button>
|
||||
<Button className="m-auto mt-[16px] mb-[20px]" type="default" danger={true} onClick={deleteApplicationModal} loading={delBtnLoading}>{$t('删除应用')}</Button>
|
||||
</WithPermission>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,18 +2,18 @@ import { MoreOutlined } from "@ant-design/icons"
|
||||
import { message, Card, Button, Tag, Dropdown, App, Empty } from "antd"
|
||||
import { useState, useEffect, forwardRef, useRef } from "react"
|
||||
import { VirtuosoGrid } from "react-virtuoso"
|
||||
import { BasicResponse, STATUS_CODE } from "@common/const/const"
|
||||
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"
|
||||
import { BasicResponse, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const"
|
||||
import { useFetch } from "@common/hooks/http"
|
||||
import { EditAuthFieldType, SystemAuthorityTableListItem } from "@core/const/system/type"
|
||||
import { Link, useParams } from "react-router-dom"
|
||||
import { useParams } from "react-router-dom"
|
||||
import { RouterParams } from "@core/components/aoplatform/RenderRoutes"
|
||||
import moment from "moment"
|
||||
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"
|
||||
import dayjs from 'dayjs';
|
||||
import { $t } from "@common/locales"
|
||||
|
||||
export default function ManagementInsideAuth(){
|
||||
const {modal} = App.useApp()
|
||||
@@ -22,7 +22,6 @@ export default function ManagementInsideAuth(){
|
||||
const {appId,teamId} = useParams<RouterParams>()
|
||||
const addRef = useRef<ManagementAuthorityConfigHandle>(null)
|
||||
const editRef = useRef<ManagementAuthorityConfigHandle>(null)
|
||||
const {appName} = useTenantManagementContext()
|
||||
const {accessData} = useGlobalContext()
|
||||
|
||||
|
||||
@@ -32,7 +31,7 @@ export default function ManagementInsideAuth(){
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
setAuthList(data.authorizations)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch(() => {
|
||||
return {data:[], success:false}
|
||||
@@ -49,11 +48,11 @@ export default function ManagementInsideAuth(){
|
||||
fetchData<BasicResponse<null>>('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 || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
reject(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
reject(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
})
|
||||
@@ -65,36 +64,36 @@ export default function ManagementInsideAuth(){
|
||||
let content:string|React.ReactNode = ''
|
||||
switch (type){
|
||||
case 'view':{
|
||||
title='鉴权详情'
|
||||
message.loading('正在加载数据')
|
||||
title=$t('鉴权详情')
|
||||
message.loading(RESPONSE_TIPS.loading)
|
||||
const {code,data,msg} = await fetchData<BasicResponse<{details:{[k:string]:string}}>>('app/authorization/details',{method:'GET',eoParams:{authorization:entity!.id,app:appId, team:teamId}})
|
||||
message.destroy()
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
content=<ManagementAuthorityView entity={data.details}/>
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
return
|
||||
}}
|
||||
break;
|
||||
case 'add':
|
||||
title='添加鉴权'
|
||||
title=$t('添加鉴权')
|
||||
content=<ManagementAuthorityConfig ref={addRef} type={type} appId={appId!} teamId={teamId!}/>
|
||||
break;
|
||||
case 'edit':{
|
||||
title='编辑鉴权'
|
||||
message.loading('正在加载数据')
|
||||
title=$t('编辑鉴权')
|
||||
message.loading(RESPONSE_TIPS.loading)
|
||||
const {code,data,msg} = await fetchData<BasicResponse<{authorization:EditAuthFieldType}>>('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=<ManagementAuthorityConfig ref={editRef} type={type} data={data.authorization} appId={appId!} teamId={teamId!}/>
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
return
|
||||
}}
|
||||
break;
|
||||
case 'delete':
|
||||
title='删除'
|
||||
content='该数据删除后将无法找回,请确认是否删除?'
|
||||
title=$t('删除')
|
||||
content=DELETE_TIPS.default
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -114,11 +113,11 @@ export default function ManagementInsideAuth(){
|
||||
}
|
||||
},
|
||||
width:600,
|
||||
okText: '确认',
|
||||
okText: $t('确认'),
|
||||
okButtonProps:{
|
||||
disabled : !checkAccess( `team.application.authorization.${type}`, accessData)
|
||||
},
|
||||
cancelText:type === 'view'? '关闭':'取消',
|
||||
cancelText:type === 'view'? $t('关闭'):$t('取消'),
|
||||
closable:true,
|
||||
icon:<></>,
|
||||
footer:(_, { OkBtn, CancelBtn }) =>{
|
||||
@@ -136,28 +135,24 @@ export default function ManagementInsideAuth(){
|
||||
{
|
||||
key: 'edit',
|
||||
label: (
|
||||
// <WithPermission access="system.organization.member.department.add" key="addChildPermission">
|
||||
<Button key="edit" type="text" className="h-[32px] border-none p-0 flex items-center bg-transparent " onClick={()=>openModal('edit',entity)}>
|
||||
修改
|
||||
{$t('修改')}
|
||||
</Button>
|
||||
// </WithPermission>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
label: (
|
||||
// <WithPermission access="system.organization.member.department.delete" key="deletePermission">
|
||||
<Button key="delete" type="text" className="h-[32px] border-none p-0 flex items-center bg-transparent " onClick={()=>openModal('delete',entity)}>
|
||||
删除
|
||||
{$t('删除')}
|
||||
</Button>
|
||||
// </WithPermission>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
return (<div className=" h-full pt-[32px]">
|
||||
<div className="flex items-center justify-between w-full ml-[10px] text-[18px] leading-[25px] pb-[16px]" ><span className="font-bold">访问授权</span></div>
|
||||
<div><Button className="mb-[20px] ml-[10px]" type="primary" onClick={()=>openModal('add')}>添加授权</Button></div>
|
||||
<div className="flex items-center justify-between w-full ml-[10px] text-[18px] leading-[25px] pb-[16px]" ><span className="font-bold">{$t('访问授权')}</span></div>
|
||||
<div><Button className="mb-[20px] ml-[10px]" type="primary" onClick={()=>openModal('add')}>{$t('添加授权')}</Button></div>
|
||||
{authList && authList.length > 0 ? <VirtuosoGrid
|
||||
style={{ height: 'calc(100% - 93px)'}}
|
||||
data={authList}
|
||||
@@ -166,12 +161,12 @@ export default function ManagementInsideAuth(){
|
||||
const item = authList[index];
|
||||
return (<Card className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] m-[10px]" classNames={{body:' flex items-center justify-center p-[20px]'}} >
|
||||
<div className="w-full">
|
||||
<div className="flex items-center justify-between w-full"><span>{item.name}</span><div><Button type="text" className="bg-[#7371fc20] hover:bg-[#7371fc19] text-theme" onClick={()=>openModal('view',item)}>查看</Button><Dropdown className="ml-btnbase" menu={{items:dropdownMenu(item)}} trigger={['hover']} >
|
||||
<div className="flex items-center justify-between w-full"><span>{item.name}</span><div><Button type="text" className="bg-[#7371fc20] hover:bg-[#7371fc19] text-theme" onClick={()=>openModal('view',item)}>{$t('查看')}</Button><Dropdown className="ml-btnbase" menu={{items:dropdownMenu(item)}} trigger={['hover']} >
|
||||
<Button type="text" className="px-[7px]" onClick={(e)=>{ e.stopPropagation();}}><MoreOutlined rotate={90} className="tree-title-more" /></Button>
|
||||
</Dropdown></div></div>
|
||||
<div>
|
||||
<Tag bordered={false} color="orange">{`${item.driver.substring(0,1).toLocaleUpperCase()}${item.driver.substring(1)}`}</Tag>
|
||||
<Tag bordered={false}>{item.expireTime === 0 ? '永不过期' : `到期时间:${moment(item.expireTime * 1000).format('YYYY-MM-DD hh:mm:ss')}`}</Tag></div>
|
||||
<Tag bordered={false}>{item.expireTime === 0 ?$t('永不过期') : `${$t('到期时间')}:${dayjs(item.expireTime * 1000).format('YYYY-MM-DD hh:mm:ss')}`}</Tag></div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
@@ -183,9 +178,6 @@ export default function ManagementInsideAuth(){
|
||||
{...props}
|
||||
style={{
|
||||
display: 'grid',
|
||||
// gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',
|
||||
// gap: '20px',
|
||||
// padding:'30px',
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -12,6 +12,7 @@ import { RouterParams } from "@core/components/aoplatform/RenderRoutes";
|
||||
import { useTenantManagementContext } from "@market/contexts/TenantManagementContext";
|
||||
import { ManagementConfigFieldType } from "./ManagementConfig";
|
||||
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export default function ManagementInsidePage(){
|
||||
const { message } = App.useApp()
|
||||
@@ -51,7 +52,7 @@ export default function ManagementInsidePage(){
|
||||
}
|
||||
setBreadcrumb(
|
||||
[
|
||||
{title:<Link to={`/tenantManagement/list/${teamId}`}>应用</Link>},
|
||||
{title:<Link to={`/tenantManagement/list/${teamId}`}>{$t('应用')}</Link>},
|
||||
...(_appName ? [{title:_appName}] : [])
|
||||
]
|
||||
)
|
||||
@@ -75,7 +76,7 @@ useEffect(()=>{
|
||||
<div className="flex flex-1 h-full">
|
||||
<div className="w-[220px] border-0 border-solid border-r-[1px] border-r-BORDER">
|
||||
<div className="text-[18px] leading-[25px] pl-[12px] py-[12px]">
|
||||
<Button type="text" onClick={()=>navigateTo(`/tenantManagement/list/${teamId}`)}><ArrowLeftOutlined className="max-h-[14px]" />返回</Button>
|
||||
<Button type="text" onClick={()=>navigateTo(`/tenantManagement/list/${teamId}`)}><ArrowLeftOutlined className="max-h-[14px]" />{$t('返回')}</Button>
|
||||
</div>
|
||||
<Menu
|
||||
onClick={onMenuClick}
|
||||
|
||||
+26
-34
@@ -3,45 +3,40 @@ import { Card, Input,Button ,Dropdown,App, Tag, Empty } from "antd"
|
||||
import { debounce } from "lodash-es"
|
||||
import { forwardRef, useEffect, useState } from "react"
|
||||
import { VirtuosoGrid } from "react-virtuoso"
|
||||
import { BasicResponse, STATUS_CODE } from "@common/const/const"
|
||||
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext"
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const"
|
||||
import { useFetch } from "@common/hooks/http"
|
||||
import { SubscribeApprovalInfoType } from "@common/const/approval/type"
|
||||
import { Link, useNavigate, useOutletContext, useParams } from "react-router-dom"
|
||||
import { 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"
|
||||
import { $t } from "@common/locales"
|
||||
|
||||
export default function ManagementInsideService(){
|
||||
const {message, modal} = App.useApp()
|
||||
const [serviceList, setServiceList] = useState<TenantManagementServiceListItem[]>([])
|
||||
const {fetchData} = useFetch()
|
||||
const { setBreadcrumb} = useBreadcrumb()
|
||||
const {teamId,appId} = useParams<RouterParams>()
|
||||
const navigateTo = useNavigate()
|
||||
const [keyword, setKeyword] = useState<string>('')
|
||||
const { refreshGroup} = useOutletContext<{refreshGroup:()=>void,appName:string}>()
|
||||
const {appName} = useTenantManagementContext()
|
||||
const { refreshGroup} = useOutletContext<{refreshGroup:()=>void}>()
|
||||
const {accessData} = useGlobalContext()
|
||||
|
||||
const onSearchWordChange = (e)=>{
|
||||
setKeyword(e.target.value)
|
||||
}
|
||||
|
||||
|
||||
const cancelSubscribeApply = (entity:TenantManagementServiceListItem) => {
|
||||
return new Promise((resolve, reject)=>{
|
||||
fetchData<BasicResponse<null>>('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 || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
reject(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
reject(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
})
|
||||
@@ -52,11 +47,11 @@ export default function ManagementInsideService(){
|
||||
fetchData<BasicResponse<null>>('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 || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
reject(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
reject(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
})
|
||||
@@ -67,25 +62,25 @@ export default function ManagementInsideService(){
|
||||
let content:string|React.ReactNode = ''
|
||||
switch (type){
|
||||
case 'view':{
|
||||
message.loading('正在加载数据')
|
||||
message.loading(RESPONSE_TIPS.loading)
|
||||
const {code,data,msg} = await fetchData<BasicResponse<{approval:SubscribeApprovalInfoType}>>('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='审批详情'
|
||||
title=$t('审批详情')
|
||||
content = <ApprovalModalContent data={data.approval} type={type} systemId={appId}/>;
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
return
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'cancelSub':
|
||||
title='取消订阅'
|
||||
content='请确认是否取消订阅?'
|
||||
title=$t('取消订阅')
|
||||
content=$t('请确认是否取消订阅?')
|
||||
break;
|
||||
case 'cancelSubApply':
|
||||
title='取消订阅申请'
|
||||
content='请确认是否取消订阅申请?'
|
||||
title=$t('取消订阅申请')
|
||||
content=$t('请确认是否取消订阅申请?')
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -103,11 +98,11 @@ export default function ManagementInsideService(){
|
||||
}
|
||||
},
|
||||
width:600,
|
||||
okText:'确认',
|
||||
okText:$t('确认'),
|
||||
okButtonProps:{
|
||||
disabled : !checkAccess( `team.application.authorization.${type}`, accessData)
|
||||
},
|
||||
cancelText:'取消',
|
||||
cancelText:$t('取消'),
|
||||
closable:true,
|
||||
icon:<></>,
|
||||
})
|
||||
@@ -130,7 +125,7 @@ export default function ManagementInsideService(){
|
||||
label: (
|
||||
// <WithPermission access="system.organization.member.department.delete" key="deletePermission">
|
||||
<Button key="cancelSubApply" type="text" className="h-[32px] border-none p-0 flex items-center bg-transparent " onClick={()=>openModal('cancelSubApply',entity)}>
|
||||
取消订阅申请
|
||||
{$t('取消订阅申请')}
|
||||
</Button>
|
||||
// </WithPermission>
|
||||
),
|
||||
@@ -139,7 +134,7 @@ export default function ManagementInsideService(){
|
||||
label: (
|
||||
// <WithPermission access="system.organization.member.department.delete" key="deletePermission">
|
||||
<Button key="cancelSub" type="text" className="h-[32px] border-none p-0 flex items-center bg-transparent " onClick={()=>openModal('cancelSub',entity)}>
|
||||
取消订阅
|
||||
{$t('取消订阅')}
|
||||
</Button>
|
||||
// </WithPermission>
|
||||
),
|
||||
@@ -153,7 +148,7 @@ export default function ManagementInsideService(){
|
||||
setServiceList(data.subscriptions && data.subscriptions.length > 0 ? [...data.subscriptions] : [])
|
||||
// return {data:data.services, success: true,total:data.total}
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
// return {data:[], success:false}
|
||||
}
|
||||
})
|
||||
@@ -166,8 +161,8 @@ export default function ManagementInsideService(){
|
||||
|
||||
return (<div className=" mx-auto h-full pt-[32px]">
|
||||
<div className="flex items-center justify-between w-full ml-[10px] text-[18px] leading-[25px] pb-[18px]" >
|
||||
<span className="font-bold">服务</span>
|
||||
<Input className="w-[200px] mr-[20px] rounded-[20px]" onChange={ onSearchWordChange ? (e) => debounce(onSearchWordChange, 100)(e) : undefined } onPressEnter={()=>getServiceList()} allowClear placeholder='搜索服务' prefix={<SearchOutlined className="cursor-pointer" onClick={()=>{getServiceList()}}/>}/>
|
||||
<span className="font-bold">{$t('服务')}</span>
|
||||
<Input className="w-[200px] mr-[20px] rounded-[20px]" onChange={ onSearchWordChange ? (e) => debounce(onSearchWordChange, 100)(e) : undefined } onPressEnter={()=>getServiceList()} allowClear placeholder={$t('搜索服务')} prefix={<SearchOutlined className="cursor-pointer" onClick={()=>{getServiceList()}}/>}/>
|
||||
</div>
|
||||
{ (keyword ? serviceList.filter(x=>x.service.name.includes(keyword)) :serviceList)?.length > 0 ?
|
||||
<VirtuosoGrid
|
||||
@@ -178,10 +173,10 @@ export default function ManagementInsideService(){
|
||||
const item = (keyword ? serviceList.filter(x=>x.service.name.includes(keyword)) :serviceList)[index];
|
||||
return (<Card className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] m-[10px]" classNames={{body:' flex items-center justify-center'}} >
|
||||
<div className="flex items-center justify-between w-full"><span><span>{item.service.name}</span>{ item.applyStatus === 1 &&
|
||||
<Tag className="ml-[8px]" bordered={false} color="orange">审批中</Tag>
|
||||
<Tag className="ml-[8px]" bordered={false} color="orange">{$t('审批中')}</Tag>
|
||||
}</span>
|
||||
<div>
|
||||
<Button type="text" className="bg-[#7371fc20] hover:bg-[#7371fc19] text-theme" onClick={()=>window.open(`/serviceHub/detail/${item.service.id}`,'_blank')}>API 文档</Button>
|
||||
<Button type="text" className="bg-[#7371fc20] hover:bg-[#7371fc19] text-theme" onClick={()=>window.open(`/serviceHub/detail/${item.service.id}`,'_blank')}>{$t('API 文档')}</Button>
|
||||
<Dropdown className="ml-btnbase" menu={{items:dropdownMenu(item)}} trigger={['hover']} >
|
||||
<Button type="text" className="px-[7px]" onClick={(e)=>{ e.stopPropagation();}}><MoreOutlined rotate={90} className="tree-title-more" onClick={(e)=>{ e.stopPropagation();}} /></Button></Dropdown></div></div>
|
||||
</Card>
|
||||
@@ -194,9 +189,6 @@ export default function ManagementInsideService(){
|
||||
{...props}
|
||||
style={{
|
||||
display: 'grid',
|
||||
// gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
|
||||
// gap: '20px',
|
||||
// padding:'30px',
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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";
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
|
||||
import { ServiceHubAppListItem } from "../../../const/serviceHub/type";
|
||||
import { useFetch } from "@common/hooks/http";
|
||||
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext";
|
||||
@@ -12,6 +12,7 @@ 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";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export default function ServiceHubManagement() {
|
||||
const { message ,modal} = App.useApp()
|
||||
@@ -30,14 +31,13 @@ export default function ServiceHubManagement() {
|
||||
|
||||
|
||||
const getServiceList = ()=>{
|
||||
//console.log(pagination,sorter,categoryId,tagId)
|
||||
setServiceLoading(true)
|
||||
return fetchData<BasicResponse<{apps:ServiceHubAppListItem}>>(!checkPermission('system.workspace.application.view_all') ? 'my_apps':'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.apps,{type:'addNewItem'}])
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).finally(()=>{
|
||||
setServiceLoading(false)
|
||||
@@ -59,7 +59,7 @@ const getServiceList = ()=>{
|
||||
navigateTo(data.teams[0].id)
|
||||
}
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).finally(()=>{
|
||||
setPageLoading(false)
|
||||
@@ -73,7 +73,7 @@ const getServiceList = ()=>{
|
||||
let content:string|React.ReactNode = ''
|
||||
switch (type){
|
||||
case 'add':
|
||||
title='添加应用'
|
||||
title=$t('添加应用')
|
||||
content=<ManagementConfig ref={addManagementRef} type={type} teamId={teamId!} />
|
||||
break;
|
||||
// case 'edit':{
|
||||
@@ -84,7 +84,7 @@ const getServiceList = ()=>{
|
||||
// if(code === STATUS_CODE.SUCCESS){
|
||||
// content=<ManagementConfig ref={editManagementRef} type={type} entity={data.app}/>
|
||||
// }else{
|
||||
// message.error(msg || '操作失败')
|
||||
// message.error(msg || RESPONSE_TIPS.error)
|
||||
// return
|
||||
// }
|
||||
// break;}
|
||||
@@ -108,8 +108,8 @@ const getServiceList = ()=>{
|
||||
}
|
||||
},
|
||||
width:600,
|
||||
okText:'确认',
|
||||
cancelText:'取消',
|
||||
okText:$t('确认'),
|
||||
cancelText:$t('取消'),
|
||||
closable:true,
|
||||
icon:<></>,
|
||||
})
|
||||
@@ -128,7 +128,7 @@ useEffect(()=>{
|
||||
useEffect(() => {
|
||||
setBreadcrumb(
|
||||
[
|
||||
{title:'应用'}
|
||||
{title:$t('应用')}
|
||||
]
|
||||
)
|
||||
getTeamsList()
|
||||
@@ -139,7 +139,7 @@ useEffect(() => {
|
||||
teamList && teamList.length > 0 ?
|
||||
<div className="flex flex-1 h-full">
|
||||
<div className="w-[220px] border-0 border-solid border-r-[1px] border-r-BORDER h-full overflow-hidden">
|
||||
<div className="text-[18px] leading-[25px] pl-[20px] pt-[20px] pb-[10px] font-bold">团队</div>
|
||||
<div className="text-[18px] leading-[25px] pl-[20px] pt-[20px] pb-[10px] font-bold">{$t('团队')}</div>
|
||||
<Menu
|
||||
onClick={onClick}
|
||||
style={{ width: 220}}
|
||||
@@ -150,7 +150,7 @@ useEffect(() => {
|
||||
/>
|
||||
</div>
|
||||
<div className="w-[calc(100%-220px)] padding-top-20">
|
||||
<div className="mt-[20px] ml-[40px] text-[18px] leading-[25px] font-bold">应用</div>
|
||||
<div className="mt-[20px] ml-[40px] text-[18px] leading-[25px] font-bold">{$t('应用')}</div>
|
||||
<VirtuosoGrid
|
||||
style={{ height: 'calc(100% - 45px)'}}
|
||||
data={serviceList}
|
||||
@@ -160,9 +160,9 @@ useEffect(() => {
|
||||
return (
|
||||
<div className="pt-[20px]">{
|
||||
item.type === 'addNewItem' ?<Card className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{body:'h-[180px] flex items-center justify-center cursor-pointer'}} onClick={()=>{openModal('add')}}>
|
||||
<div className="flex items-center"><Icon icon="ic:baseline-add" width="18" height="18"/><span>添加应用</span></div>
|
||||
<div className="flex items-center"><Icon icon="ic:baseline-add" width="18" height="18"/><span>{$t('添加应用')}</span></div>
|
||||
</Card> : <Card title={CardTitle(item)} className="shadow-[0_5px_10px_0_rgba(0,0,0,0.05)] rounded-[10px] overflow-visible cursor-pointer h-[180px] transition duration-500 hover:shadow-[0_5px_20px_0_rgba(0,0,0,0.15)] hover:scale-[1.05]" classNames={{header:'border-b-[0px] p-[20px] ', body:"pt-0"}} onClick={()=>{setAppName(item.name);navigateTo(`/tenantManagement/${teamId}/inside/${item.id}/service`)}}>
|
||||
<span className="line-clamp-3 break-all">{item.description || '暂无服务描述'}</span>
|
||||
<span className="line-clamp-3 break-all">{item.description || $t('暂无服务描述')}</span>
|
||||
|
||||
</Card>}</div>
|
||||
);
|
||||
@@ -204,7 +204,7 @@ const CardTitle = (service:ServiceHubAppListItem)=>{
|
||||
<div className="pl-[20px] w-[calc(100%-50px)]">
|
||||
<p className="text-[14px] h-[20px] leading-[20px] truncate">{service.name}</p>
|
||||
<div className="mt-[10px] h-[20px] flex items-center font-normal">
|
||||
<Tooltip title={`订阅的服务数量:已通过 ${service.subscribeNum ?? '-'} 个,申请中 ${service.subscribeVerifyNum ?? '-'} 个`}>
|
||||
<Tooltip title={$t('订阅的服务数量:已通过 (0) 个,申请中 (1) 个',[service.subscribeNum ?? '-', service.subscribeVerifyNum ?? '-'])}>
|
||||
<span className="mr-[12px] flex items-center"><span className="h-[14px] mr-[4px] flex items-center"><iconpark-icon className="max-h-[14px] h-[14px] w-[14px]" name="auto-generate-api"></iconpark-icon></span><span className="font-normal text-[14px]">{(service.subscribeNum + service.subscribeVerifyNum)?? '-'}</span></span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
"@market/*": ["./src/*"]
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TransferTable.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/Navigation.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/GroupTree.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { PageProColumns } from "@common/components/aoplatform/PageList";
|
||||
import { OpenApiTableListItem } from "./type";
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
|
||||
|
||||
export const OPENAPI_LIST_COLUMNS: PageProColumns<OpenApiTableListItem>[] = [
|
||||
{
|
||||
title:$t('应用名称'),
|
||||
dataIndex: 'name',
|
||||
ellipsis:true,
|
||||
width:160,
|
||||
fixed:'left'
|
||||
},
|
||||
{
|
||||
title:$t('应用 ID'),
|
||||
dataIndex: 'id',
|
||||
ellipsis:true,
|
||||
width: 140,
|
||||
},
|
||||
{
|
||||
title:$t('鉴权 Token'),
|
||||
dataIndex: 'token',
|
||||
ellipsis:{
|
||||
showTitle:true
|
||||
}
|
||||
},
|
||||
{
|
||||
title:$t('关联标签'),
|
||||
dataIndex: 'tag'
|
||||
},
|
||||
{
|
||||
title:$t('启用'),
|
||||
dataIndex: 'status'
|
||||
},
|
||||
{
|
||||
title:$t('更新者'),
|
||||
dataIndex: ['operator','name'],
|
||||
filters: true,
|
||||
onFilter: true,
|
||||
valueType: 'select',
|
||||
filterSearch: true
|
||||
},
|
||||
{
|
||||
title:$t('更新时间'),
|
||||
width:182,
|
||||
dataIndex: 'updateTime',
|
||||
sorter: (a,b)=>(new Date(a.updateTime)).getTime() - (new Date(b.updateTime)).getTime()
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,11 @@
|
||||
import { EntityItem } from "@common/const/type";
|
||||
|
||||
export type OpenApiTableListItem = {
|
||||
id:string;
|
||||
name: string;
|
||||
token:string;
|
||||
tags:string;
|
||||
status:boolean;
|
||||
operator:EntityItem;
|
||||
updateTime:string;
|
||||
};
|
||||
@@ -1,10 +1,11 @@
|
||||
|
||||
import {App, Form, Input} from "antd";
|
||||
import {forwardRef, useEffect, useImperativeHandle} from "react";
|
||||
import {BasicResponse, STATUS_CODE} from "@common/const/const.ts";
|
||||
import {BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE, VALIDATE_MESSAGE} from "@common/const/const.tsx";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
|
||||
import {v4 as uuidv4} from 'uuid'
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
export type OpenApiConfigFieldType = {
|
||||
id?:string
|
||||
@@ -33,11 +34,11 @@ export const OpenApiConfig = forwardRef<OpenApiConfigHandle,OpenApiConfigProps>(
|
||||
fetchData<BasicResponse<null>>('external-app',{method:type === 'add'? 'POST' : 'PUT',eoBody:(value), eoParams:type === 'add' ? {}:{id:entity!.id}}).then(response=>{
|
||||
const {code,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
message.success(msg || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
reject(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
reject(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
@@ -65,31 +66,29 @@ export const OpenApiConfig = forwardRef<OpenApiConfigHandle,OpenApiConfigProps>(
|
||||
form={form}
|
||||
className="mx-auto "
|
||||
name="OpenApiConfig"
|
||||
// labelCol={{ offset:1, span: 4 }}
|
||||
// wrapperCol={{ span: 19}}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item<OpenApiConfigFieldType>
|
||||
label="应用名称"
|
||||
label={$t("应用名称")}
|
||||
name="name"
|
||||
rules={[{ required: true, message: '必填项',whitespace:true }]}
|
||||
rules={[{ required: true, message: VALIDATE_MESSAGE.required,whitespace:true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<OpenApiConfigFieldType>
|
||||
label="应用 ID"
|
||||
label={$t("应用 ID")}
|
||||
name="id"
|
||||
rules={[{ required: true, message: '必填项' ,whitespace:true }]}
|
||||
rules={[{ required: true, message: VALIDATE_MESSAGE.required ,whitespace:true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder="请输入" disabled={type === 'edit'}/>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input} disabled={type === 'edit'}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="描述"
|
||||
label={$t("描述")}
|
||||
name="desc"
|
||||
>
|
||||
<Input.TextArea className="w-INPUT_NORMAL" placeholder="请输入"/>
|
||||
<Input.TextArea className="w-INPUT_NORMAL" placeholder={PLACEHOLDER.input}/>
|
||||
</Form.Item>
|
||||
|
||||
</Form>
|
||||
|
||||
@@ -1,71 +1,18 @@
|
||||
import PageList from "@common/components/aoplatform/PageList.tsx";
|
||||
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList.tsx";
|
||||
import {useEffect, useRef, useState} from "react";
|
||||
import {ActionType, ProColumns} from "@ant-design/pro-components";
|
||||
import {ActionType} from "@ant-design/pro-components";
|
||||
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
|
||||
import { App, Divider, Switch} from "antd";
|
||||
import copy from "copy-to-clipboard";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import {BasicResponse, STATUS_CODE} from "@common/const/const.ts";
|
||||
import {BasicResponse, COLUMNS_TITLE, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import {OpenApiConfig, OpenApiConfigFieldType, OpenApiConfigHandle} from "./OpenApiConfig.tsx";
|
||||
import { EntityItem } from "@common/const/type.ts";
|
||||
import { SimpleMemberItem } from "@common/const/type.ts";
|
||||
import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission.tsx";
|
||||
import { frontendTimeSorter } from "@common/utils/dataTransfer.ts";
|
||||
|
||||
type OpenApiTableListItem = {
|
||||
id:string;
|
||||
name: string;
|
||||
token:string;
|
||||
tags:string;
|
||||
status:boolean;
|
||||
operator:EntityItem;
|
||||
updateTime:string;
|
||||
};
|
||||
|
||||
const OPENAPI_LIST_COLUMNS: ProColumns<OpenApiTableListItem>[] = [
|
||||
{
|
||||
title: '应用名称',
|
||||
dataIndex: 'name',
|
||||
ellipsis:true,
|
||||
width:160,
|
||||
fixed:'left'
|
||||
},
|
||||
{
|
||||
title: '应用 ID',
|
||||
dataIndex: 'id',
|
||||
ellipsis:true,
|
||||
width: 140,
|
||||
},
|
||||
{
|
||||
title: '鉴权 Token',
|
||||
dataIndex: 'token',
|
||||
ellipsis:{
|
||||
showTitle:true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '关联标签',
|
||||
dataIndex: 'tag'
|
||||
},
|
||||
{
|
||||
title: '启用',
|
||||
dataIndex: 'status'
|
||||
},
|
||||
{
|
||||
title: '更新者',
|
||||
dataIndex: ['operator','name'],
|
||||
filters: true,
|
||||
onFilter: true,
|
||||
valueType: 'select',
|
||||
filterSearch: true
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
width:182,
|
||||
dataIndex: 'updateTime',
|
||||
sorter: (a,b)=>(new Date(a.updateTime)).getTime() - (new Date(b.updateTime)).getTime()
|
||||
}
|
||||
];
|
||||
import { OPENAPI_LIST_COLUMNS } from "@market/consts/const.tsx";
|
||||
import { OpenApiTableListItem } from "@market/consts/type.ts";
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
|
||||
|
||||
export default function OpenApiList(){
|
||||
@@ -74,7 +21,7 @@ export default function OpenApiList(){
|
||||
const [init, setInit] = useState<boolean>(true)
|
||||
const [tableListDataSource, setTableListDataSource] = useState<OpenApiTableListItem[]>([]);
|
||||
const [tableHttpReload, setTableHttpReload] = useState(true);
|
||||
const [columns,setColumns] = useState<ProColumns<OpenApiTableListItem>[] >([])
|
||||
const [columns,setColumns] = useState<PageProColumns<OpenApiTableListItem>[] >([])
|
||||
const pageListRef = useRef<ActionType>(null);
|
||||
const addOpenApiRef = useRef<OpenApiConfigHandle>(null)
|
||||
const editOpenApiRef = useRef<OpenApiConfigHandle>(null)
|
||||
@@ -82,21 +29,21 @@ export default function OpenApiList(){
|
||||
const { setBreadcrumb } = useBreadcrumb()
|
||||
const [memberValueEnum, setMemberValueEnum] = useState<{[k:string]:{text:string}}>({})
|
||||
|
||||
const operation:ProColumns<OpenApiTableListItem>[] =[
|
||||
const operation:PageProColumns<OpenApiTableListItem>[] =[
|
||||
{
|
||||
title: '操作',
|
||||
title: COLUMNS_TITLE.operate,
|
||||
key: 'option',
|
||||
width: 266,
|
||||
btnNums:4,
|
||||
valueType: 'option',
|
||||
fixed:'right',
|
||||
render: (_: React.ReactNode, entity: OpenApiTableListItem) => [
|
||||
<TableBtnWithPermission access="system.openapi.self.updateToken" key="refreshToken" onClick={()=>{refreshToken(entity)}} btnTitle="更新token"/>,
|
||||
<TableBtnWithPermission access="system.openapi.self.updateToken" key="refresh" btnType="refresh" onClick={()=>{refreshToken(entity)}} btnTitle="更新token"/>,
|
||||
<Divider type="vertical" className="mx-0" key="div1"/>,
|
||||
<TableBtnWithPermission access="system.openapi.self.view" key="copyToken" onClick={()=>{copyToken(entity)}} btnTitle="复制token"/>,
|
||||
<TableBtnWithPermission access="system.openapi.self.view" key="copy" btnType="copy" onClick={()=>{copyToken(entity)}} btnTitle="复制token"/>,
|
||||
<Divider type="vertical" className="mx-0" key="div2"/>,
|
||||
<TableBtnWithPermission access="system.openapi.self.edit" key="edit" onClick={()=>{openModal('edit',entity)}} btnTitle="编辑"/>,
|
||||
<TableBtnWithPermission access="system.openapi.self.edit" key="edit" btnType="edit" onClick={()=>{openModal('edit',entity)}} btnTitle="编辑"/>,
|
||||
<Divider type="vertical" className="mx-0" key="div3"/>,
|
||||
<TableBtnWithPermission access="system.openapi.self.delete" key="delete" onClick={()=>{openModal('delete',entity)}} btnTitle="删除"/>
|
||||
<TableBtnWithPermission access="system.openapi.self.delete" key="delete" btnType="delete" onClick={()=>{openModal('delete',entity)}} btnTitle="删除"/>
|
||||
],
|
||||
}
|
||||
]
|
||||
@@ -118,7 +65,7 @@ export default function OpenApiList(){
|
||||
setTableHttpReload(false)
|
||||
return {data:data.apps, success: true}
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
return {data:[], success:false}
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -130,19 +77,19 @@ export default function OpenApiList(){
|
||||
fetchData<BasicResponse<null>>('external-app/token',{method:'PUT',eoParams:{id:entity.id}}).then(response=>{
|
||||
const {code,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
message.success(msg || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
manualReloadTable()
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const copyToken = (entity: OpenApiTableListItem)=>{
|
||||
if(copy(entity.token)){
|
||||
message.success('复制成功')
|
||||
message.success(RESPONSE_TIPS.copySuccess)
|
||||
}else{
|
||||
message.error('复制失败,请重试')
|
||||
message.error(RESPONSE_TIPS.copyError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,11 +103,11 @@ export default function OpenApiList(){
|
||||
fetchData<BasicResponse<null>>('external-app',{method:'DELETE',eoParams:{id:entity!.id}}).then(response=>{
|
||||
const {code,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
message.success(msg || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
reject(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
reject(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
})
|
||||
@@ -172,24 +119,24 @@ export default function OpenApiList(){
|
||||
let content:string|React.ReactNode = ''
|
||||
switch (type){
|
||||
case 'add':
|
||||
title='添加 Open Api'
|
||||
title=$t('添加 Open Api')
|
||||
content=<OpenApiConfig ref={addOpenApiRef} type={type} />
|
||||
break;
|
||||
case 'edit':{
|
||||
title='配置 Open Api'
|
||||
message.loading('正在加载数据')
|
||||
title=$t('配置 Open Api')
|
||||
message.loading(RESPONSE_TIPS.loading)
|
||||
const {code,data,msg} = await fetchData<BasicResponse<{app:OpenApiConfigFieldType}>>('external-app',{method:'GET',eoParams:{id:entity!.id}})
|
||||
message.destroy()
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
content=<OpenApiConfig ref={editOpenApiRef} type={type} entity={data.app}/>
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
return
|
||||
}
|
||||
break;}
|
||||
case 'delete':
|
||||
title='删除'
|
||||
content='该数据删除后将无法找回,请确认是否删除?'
|
||||
title=$t('删除')
|
||||
content=DELETE_TIPS.default
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -207,8 +154,8 @@ export default function OpenApiList(){
|
||||
}
|
||||
},
|
||||
width:600,
|
||||
okText:'确认',
|
||||
cancelText:'取消',
|
||||
okText:$t('确认'),
|
||||
cancelText:$t('取消'),
|
||||
closable:true,
|
||||
icon:<></>,
|
||||
})
|
||||
@@ -218,10 +165,10 @@ export default function OpenApiList(){
|
||||
fetchData<BasicResponse<null>>(`external-app/${enabled ? 'disable' :'enable'}`,{method:'PUT',eoParams:{id:entity.id}}).then(response=>{
|
||||
const {code,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
message.success(msg || '操作成功!')
|
||||
message.success(msg || RESPONSE_TIPS.success)
|
||||
manualReloadTable()
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -237,13 +184,13 @@ export default function OpenApiList(){
|
||||
})
|
||||
setMemberValueEnum(tmpValueEnum)
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumb([{ title: 'Open Api'}])
|
||||
setBreadcrumb([{ title:$t('Open Api')}])
|
||||
getMemberList()
|
||||
setColumns(OPENAPI_LIST_COLUMNS
|
||||
.map((x)=>{
|
||||
@@ -269,7 +216,7 @@ export default function OpenApiList(){
|
||||
dataSource={tableListDataSource}
|
||||
showPagination={false}
|
||||
primaryKey="id"
|
||||
addNewBtnTitle="添加应用"
|
||||
addNewBtnTitle={$t("添加应用")}
|
||||
addNewBtnAccess="system.openapi.self.add"
|
||||
onChange={() => {
|
||||
setTableHttpReload(false)
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
"@market/*": ["./src/*"]
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TransferTable.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/Navigation.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/GroupTree.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
||||
@@ -11,9 +11,10 @@ import { PictureTypeEnum, NodeClickItem, GraphData } from "@core/const/system-ru
|
||||
import { UnionFind, edgesFormatter, getNodeSpacing, nodesFormatter } from "@common/utils/systemRunning.ts";
|
||||
import { EDGE_STYLE, END_ARROW_STYLE, OUT_SPACE_CONTENT_EDGE_COLOR, RELATIVE_PICTURE_NODE_FONTSIZE, SELF_SPACE_CONTENT_EDGE_COLOR, SYSTEM_TUNNING_CONFIG } from "@core/const/system-running/const.ts";
|
||||
import ReactDOM from "react-dom";
|
||||
import {BasicResponse, STATUS_CODE} from "@common/const/const.ts";
|
||||
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import SystemRunningInstruction from "./SystemRunningInstruction.tsx";
|
||||
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext.tsx";
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
|
||||
export type TopologyItem = {
|
||||
projects:TopologyProjectItem[]
|
||||
@@ -114,9 +115,6 @@ export default function SystemRunning(){
|
||||
const newNodes = nodesFormatter(projects)
|
||||
const newEdges = edgesFormatter(tmpProjectConnectMap)
|
||||
|
||||
// 从 edges 中提取所有唯一的节点
|
||||
// const allNodeIds = tmpProjectConnectMap.map(({ source, target }) => source || []).concat(tmpProjectConnectMap.map(({ source, target }) => target || [])).filter(Boolean);
|
||||
// const nodes: Node[] = allNodeIds.map(id => ({ id }));
|
||||
// 从 edges 中提取所有唯一的节点,并将 Set 转换为数组
|
||||
const allNodeIds:string[] = Array.from(new Set(newEdges.flatMap(edge => [edge.source, edge.target]))) as string[];
|
||||
|
||||
@@ -239,7 +237,7 @@ export default function SystemRunning(){
|
||||
setShowGraph(newGraphData?.nodes?.length > 0)
|
||||
|
||||
}else{
|
||||
message.error(msg || '操作失败')
|
||||
message.error(msg || RESPONSE_TIPS.error)
|
||||
}
|
||||
}).finally(()=>setLoading(false))
|
||||
}
|
||||
@@ -351,7 +349,7 @@ export default function SystemRunning(){
|
||||
},
|
||||
defaultEdge: {
|
||||
// type: 'quadratic',
|
||||
label: '调用服务',
|
||||
label: $t('调用服务'),
|
||||
labelCfg: {
|
||||
style: {
|
||||
fill: '5B8FF9',
|
||||
@@ -544,24 +542,24 @@ export default function SystemRunning(){
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumb([{title:'系统拓扑图'}])
|
||||
setBreadcrumb([{title:$t('系统拓扑图')}])
|
||||
getNodeData()
|
||||
}, []);
|
||||
|
||||
return (<>
|
||||
{
|
||||
showGraph ?
|
||||
<div className="h-full overflow-hidden w-full">
|
||||
<div className="mt-[10px] ml-[10px] absolute top-navbar-height right-0">
|
||||
<div className="flex justify-between">
|
||||
<div>
|
||||
</div>
|
||||
<div className="border border-solid border-color-base rounded mr-[20px] z-[999] h-8 bg-[#fff]">
|
||||
<Button id="zoom-in-button" type="text" title="放大" icon={<ZoomInOutlined />} onClick={()=>updateZoomTo(true)}/>
|
||||
<Button id="zoom-out-button" type="text" title="缩小" icon={<ZoomOutOutlined />} onClick={()=>updateZoomTo(false)} />
|
||||
<div className="h-full overflow-hidden w-full pb-PAGE_INSIDE_B pr-PAGE_INSIDE_X relative">
|
||||
<div className=" absolute top-[10px] right-PAGE_INSIDE_X">
|
||||
<div className="flex justify-between">
|
||||
<div>
|
||||
</div>
|
||||
<div className="border border-solid border-color-base rounded z-[999] h-8 bg-[#fff]">
|
||||
<Button id="zoom-in-button" type="text" title={$t("放大")} icon={<ZoomInOutlined />} onClick={()=>updateZoomTo(true)}/>
|
||||
<Button id="zoom-out-button" type="text" title={$t("缩小")} icon={<ZoomOutOutlined />} onClick={()=>updateZoomTo(false)} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-full w-full" ref={graphContainerRef} >
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext";
|
||||
import { $t } from "@common/locales";
|
||||
import { useEffect } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
export default function SystemRunningInstruction() {
|
||||
@@ -6,7 +7,7 @@ export default function SystemRunningInstruction() {
|
||||
|
||||
useEffect(()=>{
|
||||
setBreadcrumb([
|
||||
{title:'系统拓扑图'}
|
||||
{title:$t('系统拓扑图')}
|
||||
])
|
||||
},[])
|
||||
return (
|
||||
|
||||
@@ -23,6 +23,6 @@
|
||||
"@core/*": ["../core/src/*"],
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TransferTable.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/Navigation.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/GroupTree.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user