diff --git a/service-web/client/package.json b/service-web/client/package.json index d07a6fd..ced2c40 100644 --- a/service-web/client/package.json +++ b/service-web/client/package.json @@ -11,7 +11,6 @@ "dependencies": { "@ant-design/icons": "^6.0.0", "@ant-design/pro-components": "^2.8.7", - "@ant-design/pro-layout": "^7.22.4", "@ant-design/x": "^1.2.0", "@fortawesome/fontawesome-free": "^6.7.2", "@tinyflow-ai/react": "^0.1.6", diff --git a/service-web/client/pnpm-lock.yaml b/service-web/client/pnpm-lock.yaml index 5c83b20..1ac0a36 100644 --- a/service-web/client/pnpm-lock.yaml +++ b/service-web/client/pnpm-lock.yaml @@ -14,9 +14,6 @@ importers: '@ant-design/pro-components': specifier: ^2.8.7 version: 2.8.7(antd@5.25.0(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@ant-design/pro-layout': - specifier: ^7.22.4 - version: 7.22.4(antd@5.25.0(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@ant-design/x': specifier: ^1.2.0 version: 1.2.0(antd@5.25.0(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) diff --git a/service-web/client/src/components/Flow.scss b/service-web/client/src/components/Flow.scss deleted file mode 100644 index e69de29..0000000 diff --git a/service-web/client/src/components/Flow.tsx b/service-web/client/src/components/Flow.tsx deleted file mode 100644 index e739610..0000000 --- a/service-web/client/src/components/Flow.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import {Tinyflow} from '@tinyflow-ai/react' -import {type FormControlProps, FormItem} from 'amis' -import React from 'react' -import './Flow.scss' -import '@tinyflow-ai/react/dist/index.css' - -const Flow: React.FC = props => { - const {onChange} = props - return ( -
- { - onChange(value) - }} - /> -
- ) -} - -FormItem({ - type: 'flow', - autoVar: true, -})(Flow) diff --git a/service-web/client/src/components/Registry.ts b/service-web/client/src/components/Registry.ts index 9e03b9f..e69de29 100644 --- a/service-web/client/src/components/Registry.ts +++ b/service-web/client/src/components/Registry.ts @@ -1 +0,0 @@ -import './Flow.tsx' \ No newline at end of file diff --git a/service-web/client/src/index.tsx b/service-web/client/src/index.tsx index 5ec21f3..f5c8a41 100644 --- a/service-web/client/src/index.tsx +++ b/service-web/client/src/index.tsx @@ -1,10 +1,10 @@ import {createRoot} from 'react-dom/client' -import {createHashRouter, RouterProvider} from 'react-router' +import {createBrowserRouter, RouterProvider} from 'react-router' import './components/Registry.ts' import {routes} from './route.tsx' createRoot(document.getElementById('root')!).render( - , + , ) diff --git a/service-web/client/src/pages/Ai.tsx b/service-web/client/src/pages/Ai.tsx deleted file mode 100644 index 897ed8b..0000000 --- a/service-web/client/src/pages/Ai.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import {amisRender} from '../util/amis.ts' - -function Ai() { - return ( -
- {amisRender( - { - type: 'wrapper', - body: [ - '逗你的,什么都没做,哎嘿!', - ], - }, - )} -
- ) -} - -export default Ai \ No newline at end of file diff --git a/service-web/client/src/pages/App.tsx b/service-web/client/src/pages/App.tsx index d7ceb0f..c96299a 100644 --- a/service-web/client/src/pages/App.tsx +++ b/service-web/client/src/pages/App.tsx @@ -28,19 +28,13 @@ const App: React.FC = () => { route={menus} location={{pathname: location.pathname}} menu={{type: 'sub'}} - menuItemRender={(item, dom) => ( -
{ - navigate(item.path ?? '/') - }} - > - {dom} -
- )} + menuItemRender={(item, dom) => { + return
navigate(item.path || '/')}>{dom}
+ }} fixSiderbar={true} layout="mix" splitMenus={true} - style={{height: '100vh'}} + style={{minHeight: '100vh'}} contentStyle={{backgroundColor: 'white', padding: '10px 10px 10px 20px'}} > diff --git a/service-web/client/src/pages/ai/Conversation.tsx b/service-web/client/src/pages/ai/Conversation.tsx index 82da636..53b0d98 100644 --- a/service-web/client/src/pages/ai/Conversation.tsx +++ b/service-web/client/src/pages/ai/Conversation.tsx @@ -1,16 +1,7 @@ -import {amisRender} from '../../util/amis.ts' - function Conversation() { return (
- {amisRender( - { - type: 'wrapper', - body: [ - "逗你的,什么都没做,哎嘿!" - ], - }, - )} + Conversation
) } diff --git a/service-web/client/src/pages/ai/Inspection.tsx b/service-web/client/src/pages/ai/Inspection.tsx new file mode 100644 index 0000000..ce3b550 --- /dev/null +++ b/service-web/client/src/pages/ai/Inspection.tsx @@ -0,0 +1,9 @@ +function Inspection() { + return ( +
+ 逗你的,什么都没做,哎嘿! +
+ ) +} + +export default Inspection \ No newline at end of file diff --git a/service-web/client/src/pages/overview/Cloud.tsx b/service-web/client/src/pages/overview/Cloud.tsx index 76525f6..d7c6583 100644 --- a/service-web/client/src/pages/overview/Cloud.tsx +++ b/service-web/client/src/pages/overview/Cloud.tsx @@ -79,7 +79,7 @@ const cloudCrud = (title: string, path: string) => { const Cloud: React.FC = () => { return ( -
+
{amisRender( { type: 'wrapper', diff --git a/service-web/client/src/pages/Overview.tsx b/service-web/client/src/pages/overview/Overview.tsx similarity index 60% rename from service-web/client/src/pages/Overview.tsx rename to service-web/client/src/pages/overview/Overview.tsx index 3c5c5df..e242b0e 100644 --- a/service-web/client/src/pages/Overview.tsx +++ b/service-web/client/src/pages/overview/Overview.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {amisRender, commonInfo, crudCommonOptions, readOnlyDialogOptions} from '../util/amis.ts' +import {amisRender, commonInfo, crudCommonOptions, readOnlyDialogOptions} from '../../util/amis.ts' const color = (number: number) => { let color = 'text-success' @@ -169,91 +169,142 @@ const tableDetailDialog = (variable: string, targetList: any) => { const overviewYarnJob = (cluster: string, search: string, queue: string | undefined, yarnQueue: string) => { return { - className: 'font-mono', - type: 'service', - api: `${commonInfo.baseUrl}/overview/yarn-job?cluster=${cluster}&search=${search}`, - interval: 10000, - silentPolling: true, - body: [ + className: 'text-base leading-none', + type: 'table-view', + border: false, + padding: '0 10px 0 15px', + trs: [ { - type: 'tpl', - className: 'mr-1 font-bold', - tpl: `\${PADSTART('${cluster}', 3)}`, - }, - queue === undefined ? {} : { - type: 'service', - className: 'inline ml-2', - api: `${commonInfo.baseUrl}/overview/queue?queue=compaction-queue-${cluster}`, - interval: 10000, - silentPolling: true, - body: [ + tds: [ { - type: 'tpl', - tpl: '${PADSTART(size, 2)}', + body: `${cluster}`, }, - ], - }, - ' ', - { - type: 'service', - className: 'inline', - api: { - method: 'get', - url: `${commonInfo.baseUrl}/overview/yarn-cluster`, - data: { - cluster: cluster, - queue: yarnQueue, + { + padding: '0px', + body: queue === undefined ? {} : { + type: 'service', + api: `${commonInfo.baseUrl}/overview/queue?queue=${queue}`, + interval: 10000, + silentPolling: true, + body: [ + { + type: 'tpl', + tpl: '${size}', + }, + ], + }, + width: 100, + align: 'center', }, - // @ts-ignore - adaptor: function (payload, response) { - let rootUsed = (payload['data']['root']['usedCapacity'] * 100 / payload['data']['root']['capacity']) - let targetUsed = (payload['data']['target']['absoluteUsedCapacity'] * 100 / payload['data']['target']['absoluteMaxCapacity']) - return { - ...payload, - data: { - ...payload.data, - rootUsed: rootUsed, - rootUsedColor: color(rootUsed), - targetUsed: targetUsed, - targetUsedColor: color(targetUsed), + { + padding: '0px', + width: 200, + body: { + type: 'service', + api: { + method: 'get', + url: `${commonInfo.baseUrl}/overview/yarn-cluster`, + data: { + cluster: cluster, + queue: yarnQueue, + }, + // @ts-ignore + adaptor: function (payload, response) { + let rootUsed = (payload['data']['root']['usedCapacity'] * 100 / payload['data']['root']['capacity']) + let targetUsed = (payload['data']['target']['absoluteUsedCapacity'] * 100 / payload['data']['target']['absoluteMaxCapacity']) + return { + ...payload, + data: { + ...payload.data, + rootUsed: rootUsed, + rootUsedColor: color(rootUsed), + targetUsed: targetUsed, + targetUsedColor: color(targetUsed), + }, + } + }, }, - } + interval: 10000, + silentPolling: true, + body: { + type: 'table-view', + border: false, + trs: [ + { + tds: [ + { + body: { + type: 'tpl', + tpl: '${ROUND(rootUsed, 0)}%', + }, + width: 100, + align: 'center', + }, + { + body: { + type: 'tpl', + tpl: '${ROUND(targetUsed, 0)}%', + }, + width: 100, + align: 'center', + }, + ], + }, + ], + }, + }, }, - }, - interval: 10000, - silentPolling: true, - body: [ - '(', { - type: 'tpl', - tpl: '${PADSTART(ROUND(rootUsed), 3)}%', + padding: '0px', + width: 200, + body: { + type: 'service', + api: { + url: `${commonInfo.baseUrl}/overview/yarn-job`, + data: { + cluster: cluster, + search: search, + }, + }, + interval: 10000, + silentPolling: true, + body: { + type: 'table-view', + border: false, + trs: [ + { + tds: [ + { + body: { + type: 'tpl', + tpl: '${scheduling}', + }, + width: 100, + align: 'center', + }, + { + body: { + type: 'tpl', + tpl: '${running}', + }, + width: 100, + align: 'center', + }, + ], + }, + ], + }, + }, }, - ',', - { - type: 'tpl', - tpl: '${PADSTART(ROUND(targetUsed), 3)}%', - }, - ')', ], }, - '(', - { - type: 'tpl', - tpl: '${PADSTART(scheduling, 2)}', - }, - ',', - { - type: 'tpl', - tpl: '${PADSTART(running, 3)}', - }, - ')', ], } } const Overview: React.FC = () => { return ( -
+
{amisRender( { type: 'wrapper', @@ -346,24 +397,126 @@ const Overview: React.FC = () => { }, ], }, - {type: 'divider'}, - '集群 (集群总资源使用,队列资源使用)(调度中任务数,运行中任务数)', - overviewYarnJob(commonInfo.clusters.sync_names(), 'Sync', undefined, 'default'), - {type: 'divider'}, { - className: 'my-2', - type: 'service', - api: `${commonInfo.baseUrl}/overview/queue?queue=compaction-queue-pre`, - interval: 10000, - silentPolling: true, - body: [ + className: 'pl-2 my-5', + type: 'wrapper', + size: 'none', + body: { + type: 'tpl', + tpl: '同步集群资源用量情况', + }, + }, + { + type: 'table-view', + border: false, + trs: [ { - type: 'tpl', - tpl: '预调度队列:${size}', + background: '#F9F9F9', + tds: [ + { + bold: true, + body: '集群', + }, + { + bold: true, + body: '集群资源', + width: 100, + align: 'center', + }, + { + bold: true, + body: '队列资源', + width: 100, + align: 'center', + }, + { + bold: true, + body: '调度中', + width: 100, + align: 'center', + }, + { + bold: true, + body: '运行中', + width: 100, + align: 'center', + }, + ], + }, + ], + }, + overviewYarnJob(commonInfo.clusters.sync_names(), 'Sync', undefined, 'default'), + {type: 'divider'}, + { + className: 'pl-2 my-5', + type: 'wrapper', + size: 'none', + body: [ + { + type: 'tpl', + tpl: '压缩集群资源用量情况', + }, + { + className: 'mt-2', + type: 'service', + api: `${commonInfo.baseUrl}/overview/queue?queue=compaction-queue-pre`, + interval: 10000, + silentPolling: true, + body: [ + { + type: 'tpl', + tpl: '预调度队列:${size}', + }, + ], + }, + ], + }, + { + type: 'table-view', + border: false, + bold: true, + trs: [ + { + background: '#F9F9F9', + tds: [ + { + bold: true, + body: '集群', + }, + { + bold: true, + body: '队列', + width: 100, + align: 'center', + }, + { + bold: true, + body: '集群资源', + width: 100, + align: 'center', + }, + { + bold: true, + body: '队列资源', + width: 100, + align: 'center', + }, + { + bold: true, + body: '调度中', + width: 100, + align: 'center', + }, + { + bold: true, + body: '运行中', + width: 100, + align: 'center', + }, + ], }, ], }, - '集群 压缩队列任务数(集群总资源使用,队列资源使用)(调度中任务数,运行中任务数)', // @ts-ignore ...Object.keys(commonInfo.clusters.compaction).map(name => overviewYarnJob(name, 'Compaction', `compaction-queue-${name}`, commonInfo.clusters.compaction[name])), {type: 'divider'}, @@ -379,7 +532,7 @@ const Overview: React.FC = () => { source: '${items}', ...crudCommonOptions(), headerToolbar: [ - '${version}' + '${version}', ], columns: [ { diff --git a/service-web/client/src/pages/overview/Queue.tsx b/service-web/client/src/pages/overview/Queue.tsx index 6bc6a5a..7d0581e 100644 --- a/service-web/client/src/pages/overview/Queue.tsx +++ b/service-web/client/src/pages/overview/Queue.tsx @@ -12,7 +12,7 @@ const queueCrud = (name: string) => { return { type: 'crud', title: name, - api: `\${base}/queue/all?name=${name}`, + api: `${commonInfo.baseUrl}/queue/all?name=${name}`, ...crudCommonOptions(), interval: 10000, loadDataOnce: true, @@ -79,7 +79,7 @@ const Queue = () => { items.push(queueCrud(`compaction-queue-${name}`)) } return ( -
+
{amisRender( { type: 'wrapper', diff --git a/service-web/client/src/pages/overview/Table.tsx b/service-web/client/src/pages/overview/Table.tsx index 8df4912..01b1903 100644 --- a/service-web/client/src/pages/overview/Table.tsx +++ b/service-web/client/src/pages/overview/Table.tsx @@ -18,7 +18,7 @@ import { function Table() { return ( -
+
{amisRender( { type: 'wrapper', diff --git a/service-web/client/src/pages/overview/Task.tsx b/service-web/client/src/pages/overview/Task.tsx index 01e0b6c..62a61c6 100644 --- a/service-web/client/src/pages/overview/Task.tsx +++ b/service-web/client/src/pages/overview/Task.tsx @@ -3,7 +3,7 @@ import {amisRender, commonInfo, paginationCommonOptions, serviceLogByAppName, ya const Task: React.FC = () => { return ( -
+
{amisRender( { type: 'wrapper', diff --git a/service-web/client/src/pages/overview/Tool.tsx b/service-web/client/src/pages/overview/Tool.tsx index 506892b..af86bb1 100644 --- a/service-web/client/src/pages/overview/Tool.tsx +++ b/service-web/client/src/pages/overview/Tool.tsx @@ -14,7 +14,7 @@ import { const Tool: React.FC = () => { return ( -
+
{amisRender( { type: 'wrapper', diff --git a/service-web/client/src/pages/overview/Yarn.tsx b/service-web/client/src/pages/overview/Yarn.tsx index ca72648..3803b3d 100644 --- a/service-web/client/src/pages/overview/Yarn.tsx +++ b/service-web/client/src/pages/overview/Yarn.tsx @@ -13,7 +13,7 @@ const Yarn: React.FC = () => { const {clusters, queue, search} = useParams() const location = useLocation() return ( -
+
{amisRender( { type: 'wrapper', diff --git a/service-web/client/src/pages/overview/YarnCluster.tsx b/service-web/client/src/pages/overview/YarnCluster.tsx index 400cf8a..bdabe67 100644 --- a/service-web/client/src/pages/overview/YarnCluster.tsx +++ b/service-web/client/src/pages/overview/YarnCluster.tsx @@ -3,7 +3,7 @@ import {amisRender, commonInfo, yarnQueueCrud} from '../../util/amis.ts' const YarnCluster: React.FC = () => { return ( -
+
{amisRender( { type: 'wrapper', diff --git a/service-web/client/src/route.tsx b/service-web/client/src/route.tsx index 7d391e2..cc5007a 100644 --- a/service-web/client/src/route.tsx +++ b/service-web/client/src/route.tsx @@ -4,17 +4,19 @@ import { ClusterOutlined, CompressOutlined, InfoCircleOutlined, + OpenAIOutlined, + QuestionOutlined, SunOutlined, SyncOutlined, TableOutlined, ToolOutlined, } from '@ant-design/icons' -import type {Route} from '@ant-design/pro-layout/es/typing' -import type {RouteObject} from 'react-router' -import Ai from './pages/Ai.tsx' +import {Navigate, type RouteObject} from 'react-router' +import Conversation from './pages/ai/Conversation.tsx' +import Inspection from './pages/ai/Inspection.tsx' import App from './pages/App.tsx' import Cloud from './pages/overview/Cloud.tsx' -import Overview from './pages/Overview.tsx' +import Overview from './pages/overview/Overview.tsx' import Queue from './pages/overview/Queue.tsx' import Table from './pages/overview/Table.tsx' import Task from './pages/overview/Task.tsx' @@ -30,54 +32,67 @@ export const routes: RouteObject[] = [ Component: App, children: [ { - children: [ - { - index: true, - Component: Overview, - }, - { - path: 'table', - Component: Table, - }, - { - path: 'queue', - Component: Queue, - }, - { - path: 'version', - Component: Version, - }, - { - path: 'yarn/:clusters/:queue/:search?', - Component: Yarn, - }, - { - path: 'cloud', - Component: Cloud, - }, - { - path: 'yarn_cluster', - Component: YarnCluster, - }, - { - path: 'tool', - Component: Tool, - }, - { - path: 'task', - Component: Task, - }, - ], + index: true, + element: , + }, + { + path: 'overview', + Component: Overview, + }, + { + path: 'table', + Component: Table, + }, + { + path: 'queue', + Component: Queue, + }, + { + path: 'version', + Component: Version, + }, + { + path: 'yarn/:clusters/:queue/:search?', + Component: Yarn, + }, + { + path: 'cloud', + Component: Cloud, + }, + { + path: 'yarn_cluster', + Component: YarnCluster, + }, + { + path: 'tool', + Component: Tool, + }, + { + path: 'task', + Component: Task, }, { path: 'ai', - Component: Ai, + children: [ + { + index: true, + element: , + }, + { + path: 'inspection', + Component: Inspection, + }, + { + path: 'conversation', + Component: Conversation, + }, + ], }, ], }, ] -export const menus: Route = { +export const menus = { routes: [ { path: '/', @@ -85,7 +100,7 @@ export const menus: Route = { icon: , routes: [ { - path: '/', + path: '/overview', name: '概览', icon: , }, @@ -120,7 +135,7 @@ export const menus: Route = { icon: , }, { - path: '/yarn_cluster', + path: 'a86f7c51-ae60-4ca4-8c4d-40b86b445a04', name: '集群', icon: , routes: [ @@ -152,6 +167,19 @@ export const menus: Route = { { path: '/ai', name: 'AI', - } + icon: , + routes: [ + { + path: '/ai/inspection', + name: '智能巡检', + icon: , + }, + { + path: '/ai/conversation', + name: '智慧问答', + icon: , + }, + ], + }, ], }