refactor: page layout

This commit is contained in:
jialin
2025-11-05 10:02:25 +08:00
parent 219f9871a7
commit 4c22d08da5
43 changed files with 784 additions and 513 deletions
+49
View File
@@ -0,0 +1,49 @@
import {
PageContainer,
type PageContainerProps
} from '@ant-design/pro-components';
import styled from 'styled-components';
const paddingInlinePageContainerContent = 32;
const StyledPageContainer = styled(PageContainer)`
.ant-affix {
top: 0 !important;
height: auto;
}
.ant-page-header {
padding-block-end: 8px;
.ant-page-header-heading {
padding-block-start: 0;
}
}
.ant-pro-page-container-warp-page-header {
padding-inline: ${paddingInlinePageContainerContent}px;
}
.ant-page-header-heading-title {
font-size: 16px;
}
`;
export const PageContainerInner: React.FC<PageContainerProps> = ({
children,
...rest
}) => {
return (
<StyledPageContainer
{...rest}
fixedHeader
token={{
paddingInlinePageContainerContent: paddingInlinePageContainerContent
}}
>
{children}
</StyledPageContainer>
);
};
const PageBox: React.FC<{ children: React.ReactNode }> = ({ children }) => {
return <div>{children}</div>;
};
export default PageBox;
@@ -0,0 +1,27 @@
import IconFont from '@/components/icon-font';
import { Breadcrumb, type BreadcrumbProps } from 'antd';
import React from 'react';
import styled from 'styled-components';
const StyledBreadcrumb = styled(Breadcrumb)`
.ant-breadcrumb-link {
font-size: 16px;
font-weight: 500;
a {
background: unset;
}
}
.ant-breadcrumb-separator {
display: flex;
align-items: center;
}
`;
const App: React.FC<BreadcrumbProps> = ({ items }) => (
<StyledBreadcrumb
separator={<IconFont type="icon-down2" rotate={-90} />}
items={items}
/>
);
export default App;
@@ -0,0 +1,20 @@
import { PageContainerProps } from '@ant-design/pro-components';
import { createContext, useContext } from 'react';
interface PageContainerContextProps extends Partial<PageContainerProps> {
[key: string]: any;
}
export const PageContainerContext = createContext<PageContainerContextProps>(
{}
);
export function usePageContainerContext() {
const context = useContext(PageContainerContext);
if (!context) {
throw new Error(
'usePageContainerContext must be used within a PageContainerProvider'
);
}
return context;
}
+3 -13
View File
@@ -4,12 +4,12 @@ import { FilterBar } from '@/components/page-tools';
import { PageAction } from '@/config';
import type { PageActionType } from '@/config/types';
import useTableFetch from '@/hooks/use-table-fetch';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
import { Button, ConfigProvider, Table } from 'antd';
import { useState } from 'react';
import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box';
import { deleteApisKey, queryApisKeysList } from './apis';
import AddAPIKeyModal from './components/add-apikey-modal';
import { ListItem } from './config/types';
@@ -123,17 +123,7 @@ const APIKeys: React.FC = () => {
return (
<>
<PageContainer
ghost
header={{
title: intl.formatMessage({ id: 'apikeys.title' }),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<PageBox>
<FilterBar
marginBottom={22}
marginTop={30}
@@ -163,7 +153,7 @@ const APIKeys: React.FC = () => {
}}
></Table>
</ConfigProvider>
</PageContainer>
</PageBox>
<AddAPIKeyModal
open={openAddModal.open}
action={openAddModal.action}
+3 -13
View File
@@ -3,7 +3,6 @@ import IconFont from '@/components/icon-font';
import { FilterBar } from '@/components/page-tools';
import { PageActionType } from '@/config/types';
import useTableFetch from '@/hooks/use-table-fetch';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
import { Button } from 'antd';
@@ -11,6 +10,7 @@ import _ from 'lodash';
import { useState } from 'react';
import { ScrollerContext } from '../_components/infinite-scroller/use-scroller-context';
import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box';
import {
createBackend,
createBackendFromYAML,
@@ -170,17 +170,7 @@ const BackendList = () => {
});
return (
<PageContainer
ghost
header={{
title: intl.formatMessage({ id: 'menu.resources.backendsList' }),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<PageBox>
<FilterBar
showDeleteButton={false}
marginBottom={22}
@@ -255,7 +245,7 @@ const BackendList = () => {
}
></VersionInfoModal>
<DeleteModal ref={modalRef}></DeleteModal>
</PageContainer>
</PageBox>
);
};
+20 -35
View File
@@ -1,10 +1,11 @@
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import { PageContainer } from '@ant-design/pro-components';
import PageBreadcrumb from '@/pages/_components/page-breadcrumb';
import { useIntl, useNavigate, useSearchParams } from '@umijs/max';
import _ from 'lodash';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import styled from 'styled-components';
import { PageContainerInner } from '../_components/page-box';
import { createCluster, queryClusterToken, queryCredentialList } from './apis';
import ClusterSteps from './components/cluster-steps';
import FooterButtons from './components/footer-buttons';
@@ -25,7 +26,6 @@ const Container = styled.div`
const Nav = styled.div`
display: flex;
align-items: center;
height: 72px;
font-weight: 400;
font-size: 20px;
color: var(--ant-color-text-tertiary);
@@ -280,9 +280,18 @@ const ClusterCreate = () => {
navigate(-1);
};
const breadcrumbItems = [
{
title: <a>{intl.formatMessage({ id: 'clusters.title' })}</a>,
onClick: () => navigate(-1)
},
{
title: intl.formatMessage({ id: 'common.button.create' })
}
];
return (
<PageContainer
ghost
<PageContainerInner
footer={[
<FooterButtons
key="buttons"
@@ -294,38 +303,14 @@ const ClusterCreate = () => {
/>
]}
header={{
title: false,
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
title: <PageBreadcrumb items={breadcrumbItems} />
}}
pageHeaderRender={() => (
<HeaderContainer>
<Nav>
<span className="level-1">
{intl.formatMessage({ id: 'clusters.title' })}
</span>
<span
style={{
marginInline: 20,
color: 'var(--ant-color-split)'
}}
>
/
</span>
<span className="level-2">
{intl.formatMessage({ id: 'common.button.create' })}
</span>
</Nav>
<ClusterSteps
steps={steps}
currentStep={currentStep}
onChange={handleStepChange}
></ClusterSteps>
</HeaderContainer>
)}
>
<ClusterSteps
steps={steps}
currentStep={currentStep}
onChange={handleStepChange}
></ClusterSteps>
{currentStep === startStep && (
<ProviderCatalog
dataList={providerList}
@@ -339,7 +324,7 @@ const ClusterCreate = () => {
<Container>
<Content>{renderForms()}</Content>
</Container>
</PageContainer>
</PageContainerInner>
);
};
+19 -16
View File
@@ -1,30 +1,33 @@
import { PageContainer } from '@ant-design/pro-components';
import { useSearchParams } from '@umijs/max';
import { useIntl, useNavigate, useSearchParams } from '@umijs/max';
import { PageContainerInner } from '../_components/page-box';
import PageBreadcrumb from '../_components/page-breadcrumb';
import ClusterMetrics from './components/cluster-metrics';
const ClusterDetailModal = () => {
const navigate = useNavigate();
const intl = useIntl();
const [searchParams] = useSearchParams();
const provider = searchParams.get('provider');
const clusterName = searchParams.get('name');
const breadcrumbItems = [
{
title: <a>{intl.formatMessage({ id: 'clusters.title' })}</a>,
onClick: () => navigate(-1)
},
{
title: clusterName
}
];
return (
<PageContainer
ghost
<PageContainerInner
header={{
title: (
<span className="flex-center">
<span>{clusterName}</span>
</span>
),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
title: <PageBreadcrumb items={breadcrumbItems} />
}}
extra={[]}
>
<ClusterMetrics />
{/* {provider === ProviderValueMap.DigitalOcean && <WorkerPools />} */}
</PageContainer>
</PageContainerInner>
);
};
+3 -15
View File
@@ -10,13 +10,13 @@ import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
import useTableFetch from '@/hooks/use-table-fetch';
import useWatchList from '@/hooks/use-watch-list';
import AddWorker from '@/pages/cluster-management/components/add-worker';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useNavigate, useSearchParams } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Button, message } from 'antd';
import { useAtom } from 'jotai';
import { useEffect, useState } from 'react';
import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box';
import {
CLUSTERS_API,
createWorkerPool,
@@ -327,19 +327,7 @@ const Clusters: React.FC = () => {
return (
<>
<PageContainer
ghost
header={{
title: intl.formatMessage({
id: 'menu.clusterManagement.clusters'
}),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<PageBox>
<FilterBar
showSelect={false}
showPrimaryButton={true}
@@ -404,7 +392,7 @@ const Clusters: React.FC = () => {
}}
></SealTable>
</TableContext.Provider>
</PageContainer>
</PageBox>
<AddCluster
provider={openAddModal.provider}
open={openAddModal.open}
@@ -53,6 +53,15 @@ interface ClusterDetailProps {
data: ClusterListItem | null;
}
const titleConfig = {
textStyle: {
color: '#000',
fontSize: 14,
fontWeight: 600
},
top: -5
};
const gaugeConfig = {
radius: '100%',
progress: {
@@ -140,7 +149,10 @@ const ClusterMetrics = () => {
<Row gutter={16} style={{ width: '100%' }}>
<Col span={6}>
<GaugeChart
title="GPU Utilization"
title={{
text: 'GPU Utilization',
...titleConfig
}}
value={formatValue(detailContent.current.gpu)}
height={chartHeight}
gaugeConfig={gaugeConfig}
@@ -148,7 +160,10 @@ const ClusterMetrics = () => {
</Col>
<Col span={6}>
<GaugeChart
title="CPU Utilization"
title={{
text: 'CPU Utilization',
...titleConfig
}}
value={formatValue(detailContent.current.cpu)}
height={chartHeight}
gaugeConfig={gaugeConfig}
@@ -156,7 +171,10 @@ const ClusterMetrics = () => {
</Col>
<Col span={6}>
<GaugeChart
title="RAM Utilization"
title={{
text: 'RAM Utilization',
...titleConfig
}}
value={formatValue(detailContent.current.ram)}
height={chartHeight}
gaugeConfig={gaugeConfig}
@@ -164,7 +182,10 @@ const ClusterMetrics = () => {
</Col>
<Col span={6}>
<GaugeChart
title="VRAM Utilization"
title={{
text: 'VRAM Utilization',
...titleConfig
}}
value={formatValue(detailContent.current.vram)}
height={chartHeight}
gaugeConfig={gaugeConfig}
+4 -16
View File
@@ -5,13 +5,13 @@ import { FilterBar } from '@/components/page-tools';
import { PageAction } from '@/config';
import type { PageActionType } from '@/config/types';
import useTableFetch from '@/hooks/use-table-fetch';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useNavigate } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Button, ConfigProvider, Table, message } from 'antd';
import { useAtom } from 'jotai';
import { useState } from 'react';
import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box';
import {
createCredential,
deleteCredential,
@@ -178,26 +178,14 @@ const Credentials: React.FC = () => {
return (
<>
<PageContainer
ghost
header={{
title: intl.formatMessage({
id: 'menu.clusterManagement.credentials'
}),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<PageBox>
<FilterBar
actionItems={addActions}
actionType="dropdown"
showSelect={false}
showPrimaryButton={true}
marginBottom={22}
marginTop={30}
marginTop={0}
buttonText={intl.formatMessage({
id: 'clusters.button.addCredential'
})}
@@ -228,7 +216,7 @@ const Credentials: React.FC = () => {
}}
></Table>
</ConfigProvider>
</PageContainer>
</PageBox>
<AddModal
provider={openModalStatus.provider}
open={openModalStatus.open}
@@ -55,6 +55,7 @@ const SystemLoad = () => {
<Row style={{ height: largeChartHeight }}>
<Col span={12} style={{ height: smallChartHeight }}>
<GaugeChart
name="GPU"
height={smallChartHeight}
value={chartData.gpu.data}
title={intl.formatMessage({
@@ -64,6 +65,7 @@ const SystemLoad = () => {
</Col>
<Col span={12} style={{ height: smallChartHeight }}>
<GaugeChart
name="VRAM"
title={intl.formatMessage({
id: 'dashboard.vramutilization'
})}
@@ -73,6 +75,7 @@ const SystemLoad = () => {
</Col>
<Col span={12} style={{ height: smallChartHeight }}>
<GaugeChart
name="CPU"
title={intl.formatMessage({
id: 'dashboard.cpuutilization'
})}
@@ -82,6 +85,7 @@ const SystemLoad = () => {
</Col>
<Col span={12} style={{ height: smallChartHeight }}>
<GaugeChart
name="RAM"
title={intl.formatMessage({
id: 'dashboard.memoryutilization'
})}
+3 -11
View File
@@ -1,6 +1,6 @@
import { PageContainer } from '@ant-design/pro-components';
import { Spin } from 'antd';
import { useState } from 'react';
import PageBox from '../_components/page-box';
import DashboardInner from './components/dahboard-inner';
const Dashboard: React.FC = () => {
@@ -8,19 +8,11 @@ const Dashboard: React.FC = () => {
return (
<>
<PageContainer
ghost
extra={[]}
header={{
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
}
}}
>
<PageBox>
<Spin spinning={loading}>
<DashboardInner setLoading={setLoading} />
</Spin>
</PageContainer>
</PageBox>
</>
);
};
+4 -13
View File
@@ -7,7 +7,6 @@ import useBodyScroll from '@/hooks/use-body-scroll';
import { ScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context';
import { IS_FIRST_LOGIN, writeState } from '@/utils/localstore/index';
import { SearchOutlined, SyncOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useNavigate } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Button, Input, Space, message } from 'antd';
@@ -16,6 +15,7 @@ import _ from 'lodash';
import React, { useCallback, useEffect, useState } from 'react';
import styled from 'styled-components';
import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box';
import { createModel, queryCatalogList } from './apis';
import CatalogList from './components/catalog-list';
import DelopyBuiltInModal from './components/deploy-builtin-modal';
@@ -219,19 +219,10 @@ const Catalog: React.FC = () => {
}, [fetchData]);
return (
<PageContainer
ghost
header={{
title: intl.formatMessage({ id: 'menu.modelCatalog' }),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<PageBox>
<PageTools
marginBottom={22}
marginTop={0}
left={
<Space>
<Input
@@ -311,7 +302,7 @@ const Catalog: React.FC = () => {
onCancel={handleDeployModalCancel}
onOk={handleCreateModel}
></DelopyBuiltInModal>
</PageContainer>
</PageBox>
);
};
+4 -14
View File
@@ -14,10 +14,10 @@ import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
import useTableRowSelection from '@/hooks/use-table-row-selection';
import useTableSort from '@/hooks/use-table-sort';
import NoResult from '@/pages/_components/no-result';
import PageBox from '@/pages/_components/page-box';
import { ListItem as WorkerListItem } from '@/pages/resources/config/types';
import { handleBatchRequest } from '@/utils';
import { DownOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useNavigate } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Button, Input, Space, message } from 'antd';
@@ -596,20 +596,10 @@ const Models: React.FC<ModelsProps> = ({
return (
<>
<PageContainer
className="models-page-container"
ghost
header={{
title: intl.formatMessage({ id: 'menu.models.deployment' }),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<PageBox>
<PageTools
marginBottom={22}
marginTop={0}
left={
<Space>
<Input
@@ -742,7 +732,7 @@ const Models: React.FC<ModelsProps> = ({
onChange: handlePageChange
}}
></SealTable>
</PageContainer>
</PageBox>
<UpdateModelModal
open={openAddModal}
action={PageAction.EDIT}
+3 -3
View File
@@ -5,13 +5,13 @@ import CardList from '@/components/templates/card-list';
import CardSkeleton from '@/components/templates/card-skelton';
import useTableFetch from '@/hooks/use-table-fetch';
import { SyncOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useNavigate } from '@umijs/max';
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
import { Button, Input, Space } from 'antd';
import React, { useCallback, useMemo } from 'react';
import { ScrollerContext } from '../_components/infinite-scroller/use-scroller-context';
import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box';
import { MY_MODELS_API, queryMyModels } from './apis';
import ModelItem from './components/model-item';
import {
@@ -172,7 +172,7 @@ const UserModels: React.FC = () => {
}, [dataSource.dataList, status]);
return (
<PageContainer
<PageBox
ghost
header={{
title: intl.formatMessage({ id: 'menu.models.userModels' }),
@@ -261,7 +261,7 @@ const UserModels: React.FC = () => {
subTitle={intl.formatMessage({ id: 'noresult.mymodels.subTitle' })}
></NoResult>
</ScrollerContext.Provider>
</PageContainer>
</PageBox>
);
};
+1 -1
View File
@@ -23,7 +23,7 @@ export const login = async (
});
};
export const logout = async (userInfo: any) => {
export const logout = async (userInfo?: any) => {
await request(`${AUTH_API}/logout`, {
method: 'POST'
});
@@ -5,6 +5,7 @@ import AudioPlayer from '@/components/audio-player';
import CopyButton from '@/components/copy-button';
import IconFont from '@/components/icon-font';
import UploadAudio from '@/components/upload-audio';
import { HEADER_HEIGHT } from '@/config/constants';
import routeCachekey from '@/config/route-cachekey';
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import { useCancelToken } from '@/hooks/use-request-token';
@@ -13,7 +14,6 @@ import { SendOutlined } from '@ant-design/icons';
import { useIntl, useSearchParams } from '@umijs/max';
import { Button, Spin, Tooltip } from 'antd';
import classNames from 'classnames';
import 'overlayscrollbars/overlayscrollbars.css';
import React, {
forwardRef,
useCallback,
@@ -289,7 +289,7 @@ const GroundSTT: React.FC<MessageProps> = forwardRef((props, ref) => {
<div
className="ground-left-wrapper"
style={{
height: 'calc(100vh - 72px)'
height: `calc(100vh - ${HEADER_HEIGHT}px)`
}}
>
<div className="ground-left">
@@ -1,6 +1,6 @@
import { HEADER_HEIGHT } from '@/config/constants';
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import _ from 'lodash';
import 'overlayscrollbars/overlayscrollbars.css';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import CompareContext from '../../config/compare-context';
import {
@@ -39,7 +39,7 @@ const MultiCompare: React.FC<MultiCompareProps> = ({ modelList, loaded }) => {
const modelsCounterMap = useRef<Record<string, number>>({});
const modelRefs = useRef<any>({});
const chatListScrollRef = useRef<any>(null);
const boxHeight = 'calc(100vh - 72px)';
const boxHeight = `calc(100vh - ${HEADER_HEIGHT}px)`;
const [actions, setActions] = useState<MessageItemAction[]>([
'upload',
'delete',
@@ -0,0 +1,40 @@
import { useIntl } from '@umijs/max';
import { Button, Space } from 'antd';
import React from 'react';
import IconFont from '../../../components/icon-font';
const ViewCodeButtons: React.FC<{
handleViewCode: () => void;
handleToggleCollapse: () => void;
activeKey: string;
}> = ({ handleViewCode, handleToggleCollapse, activeKey }) => {
const intl = useIntl();
if (activeKey === 'compare') {
return null;
}
return (
<Space key="buttons" style={{ marginRight: 8 }}>
<Button
size="middle"
onClick={handleViewCode}
icon={<IconFont type="icon-code" className="font-size-16"></IconFont>}
>
{intl.formatMessage({ id: 'playground.viewcode' })}
</Button>
<Button
size="middle"
onClick={handleToggleCollapse}
icon={
<IconFont
type="icon-a-layout6-line"
className="font-size-16"
></IconFont>
}
></Button>
</Space>
);
};
export default ViewCodeButtons;
+26 -43
View File
@@ -1,15 +1,17 @@
import IconFont from '@/components/icon-font';
import HotKeys from '@/config/hotkeys';
import { ExtraContent } from '@/layouts/extraRender';
import { modelCategoriesMap } from '@/pages/llmodels/config';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Space } from 'antd';
import { useMemoizedFn } from 'ahooks';
import { Divider } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { PageContainerInner } from '../_components/page-box';
import { queryModelsList } from './apis';
import GroundEmbedding from './components/ground-embedding';
import ViewCodeButtons from './components/view-code-buttons';
import useCollapseLayout from './hooks/use-collapse-layout';
import './style/play-ground.less';
@@ -27,12 +29,12 @@ const PlaygroundEmbedding: React.FC = () => {
triggeredRef: groundLeftRef.current
});
const handleViewCode = useCallback(() => {
const handleViewCode = useMemoizedFn(() => {
groundLeftRef.current?.viewCode?.();
}, [groundLeftRef.current]);
const handleToggleCollapse = useCallback(() => {
});
const handleToggleCollapse = useMemoizedFn(() => {
groundLeftRef.current?.setCollapse?.();
}, [groundLeftRef.current]);
});
useEffect(() => {
const getModelListByEmbedding = async () => {
@@ -66,30 +68,6 @@ const PlaygroundEmbedding: React.FC = () => {
fetchData();
}, []);
const renderExtra = () => {
return (
<Space key="buttons">
<Button
size="middle"
onClick={handleViewCode}
icon={<IconFont type="icon-code" className="font-size-16"></IconFont>}
>
{intl.formatMessage({ id: 'playground.viewcode' })}
</Button>
<Button
size="middle"
onClick={handleToggleCollapse}
icon={
<IconFont
type="icon-a-layout6-line"
className="font-size-16"
></IconFont>
}
></Button>
</Space>
);
};
useHotkeys(
HotKeys.RIGHT.join(','),
() => {
@@ -101,17 +79,22 @@ const PlaygroundEmbedding: React.FC = () => {
);
return (
<PageContainer
ghost
header={{
title: intl.formatMessage({ id: 'menu.playground.embedding' }),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={renderExtra()}
<PageContainerInner
className={classNames('playground-container chat')}
extra={[
<ViewCodeButtons
activeKey=""
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
key="view-code-buttons"
/>,
<Divider
key="divider"
type="vertical"
style={{ height: 24, marginInline: 16 }}
/>,
<ExtraContent key="extra-content" />
]}
>
<div className="play-ground">
<div className="chat">
@@ -122,7 +105,7 @@ const PlaygroundEmbedding: React.FC = () => {
></GroundEmbedding>
</div>
</div>
</PageContainer>
</PageContainerInner>
);
};
+27 -41
View File
@@ -1,19 +1,21 @@
import IconFont from '@/components/icon-font';
import breakpoints from '@/config/breakpoints';
import HotKeys from '@/config/hotkeys';
import useWindowResize from '@/hooks/use-window-resize';
import { ExtraContent } from '@/layouts/extraRender';
import { modelCategoriesMap } from '@/pages/llmodels/config';
import { DiffOutlined, HighlightOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Segmented, Space, Tabs, TabsProps } from 'antd';
import { useMemoizedFn } from 'ahooks';
import { Divider, Segmented, Tabs, TabsProps } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { PageContainerInner } from '../_components/page-box';
import { queryModelsList } from './apis';
import GroundImages from './components/ground-images';
import ImageEdit from './components/image-edit';
import ViewCodeButtons from './components/view-code-buttons';
import './style/play-ground.less';
const TabsValueMap = {
@@ -44,21 +46,21 @@ const TextToImages: React.FC = () => {
];
}, [intl]);
const handleViewCode = useCallback(() => {
const handleViewCode = useMemoizedFn(() => {
if (activeKey === TabsValueMap.Tab1) {
groundTabRef1.current?.viewCode?.();
} else if (activeKey === TabsValueMap.Tab2) {
groundTabRef2.current?.viewCode?.();
}
}, [activeKey]);
});
const handleToggleCollapse = useCallback(() => {
const handleToggleCollapse = useMemoizedFn(() => {
if (activeKey === TabsValueMap.Tab1) {
groundTabRef1.current?.setCollapse?.();
return;
}
groundTabRef2.current?.setCollapse?.();
}, [activeKey]);
});
const items: TabsProps['items'] = useMemo(() => {
return [
@@ -124,30 +126,6 @@ const TextToImages: React.FC = () => {
fetchData();
}, []);
const renderExtra = useMemo(() => {
return (
<Space key="buttons">
<Button
size="middle"
onClick={handleViewCode}
icon={<IconFont type="icon-code" className="font-size-16"></IconFont>}
>
{intl.formatMessage({ id: 'playground.viewcode' })}
</Button>
<Button
size="middle"
onClick={handleToggleCollapse}
icon={
<IconFont
type="icon-a-layout6-line"
className="font-size-16"
></IconFont>
}
></Button>
</Space>
);
}, [intl, handleViewCode, handleToggleCollapse]);
const header = useMemo(() => {
return {
title: (
@@ -164,11 +142,7 @@ const TextToImages: React.FC = () => {
></Segmented>
}
</div>
),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
)
};
}, [optionsList]);
@@ -183,10 +157,22 @@ const TextToImages: React.FC = () => {
);
return (
<PageContainer
ghost
<PageContainerInner
header={header}
extra={renderExtra}
extra={[
<ViewCodeButtons
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
activeKey={activeKey}
key="view-code-buttons"
></ViewCodeButtons>,
<Divider
key="divider"
type="vertical"
style={{ height: 24, marginInline: 16 }}
/>,
<ExtraContent key="extra-content" />
]}
className={classNames('playground-container chat')}
>
<div className="play-ground">
@@ -194,7 +180,7 @@ const TextToImages: React.FC = () => {
<Tabs items={items} activeKey={activeKey}></Tabs>
</div>
</div>
</PageContainer>
</PageContainerInner>
);
};
+39 -45
View File
@@ -1,21 +1,32 @@
import IconFont from '@/components/icon-font';
import breakpoints from '@/config/breakpoints';
import HotKeys from '@/config/hotkeys';
import useWindowResize from '@/hooks/use-window-resize';
import { ExtraContent } from '@/layouts/extraRender';
import { modelCategoriesMap } from '@/pages/llmodels/config';
import { MessageOutlined, OneToOneOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Segmented, Space, Tabs, TabsProps } from 'antd';
import { useMemoizedFn } from 'ahooks';
import { Divider, Segmented, Tabs, TabsProps } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import styled from 'styled-components';
import { PageContainerInner } from '../_components/page-box';
import { queryModelsList } from './apis';
import GroundLeft from './components/ground-left';
import MultipleChat from './components/multiple-chat';
import ViewCodeButtons from './components/view-code-buttons';
import './style/play-ground.less';
const Header = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 16px;
padding-inline: 32px;
`;
const Playground: React.FC = () => {
const intl = useIntl();
const { size } = useWindowResize();
@@ -40,27 +51,28 @@ const Playground: React.FC = () => {
];
}, [intl]);
const handleViewCode = useCallback(() => {
const handleViewCode = useMemoizedFn(() => {
if (activeKey === 'reranker') {
groundRerankerRef.current?.viewCode?.();
} else if (activeKey === 'chat') {
groundLeftRef.current?.viewCode?.();
}
}, [activeKey]);
});
const handleToggleCollapse = useCallback(() => {
const handleToggleCollapse = useMemoizedFn(() => {
if (activeKey === 'reranker') {
groundRerankerRef.current?.setCollapse?.();
return;
}
groundLeftRef.current?.setCollapse?.();
}, [activeKey]);
});
const items: TabsProps['items'] = useMemo(() => {
return [
{
key: 'chat',
label: 'Chat',
icon: <MessageOutlined />,
children: (
<GroundLeft ref={groundLeftRef} modelList={modelList}></GroundLeft>
)
@@ -68,6 +80,7 @@ const Playground: React.FC = () => {
{
key: 'compare',
label: 'Compare',
icon: <OneToOneOutlined />,
children: <MultipleChat modelList={modelList} loaded={loaded} />
}
];
@@ -105,33 +118,6 @@ const Playground: React.FC = () => {
fetchData();
}, []);
const renderExtra = useMemo(() => {
if (activeKey === 'compare') {
return false;
}
return (
<Space key="buttons">
<Button
size="middle"
onClick={handleViewCode}
icon={<IconFont type="icon-code" className="font-size-16"></IconFont>}
>
{intl.formatMessage({ id: 'playground.viewcode' })}
</Button>
<Button
size="middle"
onClick={handleToggleCollapse}
icon={
<IconFont
type="icon-a-layout6-line"
className="font-size-16"
></IconFont>
}
></Button>
</Space>
);
}, [activeKey, intl, handleViewCode, handleToggleCollapse]);
const header = useMemo(() => {
return {
title: (
@@ -148,11 +134,7 @@ const Playground: React.FC = () => {
></Segmented>
}
</div>
),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
)
};
}, [optionsList]);
@@ -169,21 +151,33 @@ const Playground: React.FC = () => {
);
return (
<PageContainer
ghost
header={header}
extra={renderExtra}
<PageContainerInner
className={classNames('playground-container', {
compare: activeKey === 'compare',
chat: activeKey !== 'compare'
})}
header={header}
extra={[
<ViewCodeButtons
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
activeKey={activeKey}
key="view-code-buttons"
/>,
<Divider
key="divider"
type="vertical"
style={{ height: 24, marginInline: 16 }}
/>,
<ExtraContent key="extra-content" />
]}
>
<div className="play-ground">
<div className="chat">
<Tabs items={items} activeKey={activeKey}></Tabs>
</div>
</div>
</PageContainer>
</PageContainerInner>
);
};
+26 -44
View File
@@ -1,21 +1,22 @@
import IconFont from '@/components/icon-font';
import HotKeys from '@/config/hotkeys';
import { ExtraContent } from '@/layouts/extraRender';
import { modelCategoriesMap } from '@/pages/llmodels/config';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Space } from 'antd';
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
import { Divider } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { PageContainerInner } from '../_components/page-box';
import { queryModelsList } from './apis';
import GroundReranker from './components/ground-reranker';
import ViewCodeButtons from './components/view-code-buttons';
import useCollapseLayout from './hooks/use-collapse-layout';
import './style/play-ground.less';
const PlaygroundRerank: React.FC = () => {
const intl = useIntl();
const groundLeftRef = useRef<any>(null);
const groundRerankerRef = useRef<any>(null);
const [rerankerModelList, setRerankerModelList] = useState<
Global.BaseOption<string>[]
@@ -29,13 +30,13 @@ const PlaygroundRerank: React.FC = () => {
triggeredRef: groundRerankerRef.current
});
const handleViewCode = useCallback(() => {
const handleViewCode = useMemoizedFn(() => {
groundRerankerRef.current?.viewCode?.();
}, [groundRerankerRef]);
});
const handleToggleCollapse = useCallback(() => {
const handleToggleCollapse = useMemoizedFn(() => {
groundRerankerRef.current?.setCollapse?.();
}, [groundRerankerRef]);
});
useEffect(() => {
const getModelListByReranker = async () => {
@@ -71,30 +72,6 @@ const PlaygroundRerank: React.FC = () => {
fetchData();
}, []);
const renderExtra = () => {
return (
<Space key="buttons">
<Button
size="middle"
onClick={handleViewCode}
icon={<IconFont type="icon-code" className="font-size-16"></IconFont>}
>
{intl.formatMessage({ id: 'playground.viewcode' })}
</Button>
<Button
size="middle"
onClick={handleToggleCollapse}
icon={
<IconFont
type="icon-a-layout6-line"
className="font-size-16"
></IconFont>
}
></Button>
</Space>
);
};
useHotkeys(
HotKeys.RIGHT.join(','),
() => {
@@ -106,17 +83,22 @@ const PlaygroundRerank: React.FC = () => {
);
return (
<PageContainer
ghost
header={{
title: intl.formatMessage({ id: 'menu.playground.rerank' }),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={renderExtra()}
<PageContainerInner
className={classNames('playground-container chat')}
extra={[
<ViewCodeButtons
activeKey=""
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
key="view-code-buttons"
></ViewCodeButtons>,
<Divider
key="divider"
type="vertical"
style={{ height: 24, marginInline: 16 }}
/>,
<ExtraContent key="extra-content" />
]}
>
<div className="play-ground">
<div className="chat">
@@ -127,7 +109,7 @@ const PlaygroundRerank: React.FC = () => {
></GroundReranker>
</div>
</div>
</PageContainer>
</PageContainerInner>
);
};
+27 -40
View File
@@ -2,18 +2,21 @@ import IconFont from '@/components/icon-font';
import breakpoints from '@/config/breakpoints';
import HotKeys from '@/config/hotkeys';
import useWindowResize from '@/hooks/use-window-resize';
import { ExtraContent } from '@/layouts/extraRender';
import { modelCategoriesMap } from '@/pages/llmodels/config';
import { AudioOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useSearchParams } from '@umijs/max';
import { Button, Segmented, Space, Tabs, TabsProps } from 'antd';
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
import { Divider, Segmented, Tabs, TabsProps } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { PageContainerInner } from '../_components/page-box';
import { queryModelsList } from './apis';
import GroundSTT from './components/ground-stt';
import GroundTTS from './components/ground-tts';
import ViewCodeButtons from './components/view-code-buttons';
import './style/play-ground.less';
const TabsValueMap = {
@@ -53,21 +56,21 @@ const Playground: React.FC = () => {
];
}, [intl]);
const handleViewCode = useCallback(() => {
const handleViewCode = useMemoizedFn(() => {
if (activeKey === TabsValueMap.Tab1) {
groundTabRef1.current?.viewCode?.();
} else if (activeKey === TabsValueMap.Tab2) {
groundTabRef2.current?.viewCode?.();
}
}, [activeKey]);
});
const handleToggleCollapse = useCallback(() => {
const handleToggleCollapse = useMemoizedFn(() => {
if (activeKey === TabsValueMap.Tab1) {
groundTabRef1.current?.setCollapse?.();
return;
}
groundTabRef2.current?.setCollapse?.();
}, [activeKey]);
});
const items: TabsProps['items'] = useMemo(() => {
return [
@@ -160,30 +163,6 @@ const Playground: React.FC = () => {
fetchData();
}, []);
const renderExtra = useMemo(() => {
return (
<Space key="buttons">
<Button
size="middle"
onClick={handleViewCode}
icon={<IconFont type="icon-code" className="font-size-16"></IconFont>}
>
{intl.formatMessage({ id: 'playground.viewcode' })}
</Button>
<Button
size="middle"
onClick={handleToggleCollapse}
icon={
<IconFont
type="icon-a-layout6-line"
className="font-size-16"
></IconFont>
}
></Button>
</Space>
);
}, [handleToggleCollapse, handleViewCode, intl]);
const header = useMemo(() => {
return {
title: (
@@ -201,11 +180,7 @@ const Playground: React.FC = () => {
></Segmented>
}
</div>
),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
)
};
}, [activeKey, optionsList]);
@@ -220,10 +195,22 @@ const Playground: React.FC = () => {
);
return (
<PageContainer
ghost
<PageContainerInner
header={header}
extra={renderExtra}
extra={[
<ViewCodeButtons
activeKey=""
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
key="view-code-buttons"
></ViewCodeButtons>,
<Divider
key="divider"
type="vertical"
style={{ height: 24, marginInline: 16 }}
/>,
<ExtraContent key="extra-content" />
]}
className={classNames('playground-container', {
compare: activeKey === 'compare',
chat: activeKey !== 'compare'
@@ -234,7 +221,7 @@ const Playground: React.FC = () => {
<Tabs items={items} activeKey={activeKey}></Tabs>
</div>
</div>
</PageContainer>
</PageContainerInner>
);
};
+4 -2
View File
@@ -1,3 +1,5 @@
@HEADER_HEIGHT: 56px;
.ground-left-wrapper {
display: flex;
@@ -7,7 +9,7 @@
width: 390px;
border-left: 1px solid var(--ant-color-split);
transition: width 0.3s ease;
height: calc(100vh - 72px);
height: calc(100vh - @HEADER_HEIGHT);
padding-top: 16px;
overflow-y: auto;
@@ -40,7 +42,7 @@
justify-content: space-between;
flex-direction: column;
position: relative;
height: calc(100vh - 72px);
height: calc(100vh - @HEADER_HEIGHT);
width: calc(100% - 390px);
.message-list-wrap {
+12 -11
View File
@@ -1,3 +1,5 @@
@HEADER_HEIGHT: 56px;
.play-ground {
display: flex;
align-items: flex-start;
@@ -37,7 +39,7 @@
.params {
overflow: hidden;
height: calc(100vh - 72px);
height: calc(100vh - @HEADER_HEIGHT);
.collapse {
width: 0;
@@ -81,20 +83,19 @@
.ant-page-header {
position: relative;
height: 72px;
}
&.chat {
.ant-page-header {
&::after {
position: absolute;
content: '';
left: 32px;
right: 32px;
bottom: 0;
height: 1px;
border-bottom: 1px solid var(--ant-color-split);
}
// &::after {
// position: absolute;
// content: '';
// left: 32px;
// right: 32px;
// bottom: 0;
// height: 1px;
// border-bottom: 1px solid var(--ant-color-split);
// }
}
}
+10 -23
View File
@@ -1,9 +1,9 @@
import useTabActive from '@/hooks/use-tab-active';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useModel } from '@umijs/max';
import { TabsProps } from 'antd';
import { Tabs, TabsProps } from 'antd';
import React, { useCallback, useMemo, useState } from 'react';
import styled from 'styled-components';
import PageBox from '../_components/page-box';
import Appearance from './components/appearance';
import ModifyPasswordn from './components/modify-password';
@@ -53,27 +53,14 @@ const Profile: React.FC = () => {
}, []);
return (
<Wrapper>
<PageContainer
ghost
header={{
title: intl.formatMessage({ id: 'users.settings.title' }),
style: {
paddingInline: 'var(--layout-content-inlinepadding)'
}
}}
tabList={items}
onTabChange={handleChangeTab}
tabActiveKey={activeKey}
tabProps={{
type: 'card',
style: {
marginTop: 78
}
}}
extra={[]}
></PageContainer>
</Wrapper>
<PageBox>
<Tabs
activeKey={activeKey}
onChange={handleChangeTab}
items={items}
type="card"
/>
</PageBox>
);
};
+3 -13
View File
@@ -2,8 +2,8 @@ import IconFont from '@/components/icon-font';
import { FilterBar } from '@/components/page-tools';
import useTableFetch from '@/hooks/use-table-fetch';
import NoResult from '@/pages/_components/no-result';
import PageBox from '@/pages/_components/page-box';
import { queryClusterList } from '@/pages/cluster-management/apis';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { ConfigProvider, Table } from 'antd';
import React, { useEffect, useState } from 'react';
@@ -76,17 +76,7 @@ const GPUList: React.FC = () => {
return (
<>
<PageContainer
ghost
header={{
title: 'GPUs',
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<PageBox>
<FilterBar
marginBottom={22}
marginTop={30}
@@ -116,7 +106,7 @@ const GPUList: React.FC = () => {
}}
></Table>
</ConfigProvider>
</PageContainer>
</PageBox>
</>
);
};
+3 -13
View File
@@ -7,6 +7,7 @@ import useAppUtils from '@/hooks/use-app-utils';
import useBodyScroll from '@/hooks/use-body-scroll';
import useTableFetch from '@/hooks/use-table-fetch';
import NoResult from '@/pages/_components/no-result';
import PageBox from '@/pages/_components/page-box';
import { createModel } from '@/pages/llmodels/apis';
import DeployModal from '@/pages/llmodels/components/deploy-modal';
import { modelSourceMap } from '@/pages/llmodels/config';
@@ -20,7 +21,6 @@ import DownloadModal from '@/pages/llmodels/download';
import useCheckBackend from '@/pages/llmodels/hooks/use-check-backend';
import { useGenerateWorkerOptions } from '@/pages/llmodels/hooks/use-form-initial-values';
import useRecognizeAudio from '@/pages/llmodels/hooks/use-recognize-audio';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useNavigate } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { ConfigProvider, Table, message } from 'antd';
@@ -290,17 +290,7 @@ const ModelFiles = () => {
return (
<>
<PageContainer
ghost
header={{
title: intl.formatMessage({ id: 'resources.modelfiles.modelfile' }),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<PageBox>
<FilterBar
marginBottom={22}
marginTop={30}
@@ -365,7 +355,7 @@ const ModelFiles = () => {
isGGUF={openDeployModal.isGGUF}
clusterList={clusterList}
></DeployModal>
</PageContainer>
</PageBox>
</>
);
};
+3 -11
View File
@@ -2,8 +2,8 @@ import DeleteModal from '@/components/delete-modal';
import IconFont from '@/components/icon-font';
import { FilterBar } from '@/components/page-tools';
import useTableFetch from '@/hooks/use-table-fetch';
import PageBox from '@/pages/_components/page-box';
import { queryClusterList } from '@/pages/cluster-management/apis';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useNavigate } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Button, ConfigProvider, Table, message } from 'antd';
@@ -227,7 +227,7 @@ const Workers: React.FC = () => {
return (
<>
<PageContainer
<PageBox
ghost
footer={[
<TerminalTabs
@@ -239,14 +239,6 @@ const Workers: React.FC = () => {
onClose={handleTerminalClose}
/>
]}
header={{
title: intl.formatMessage({ id: 'resources.nodes' }),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<FilterBar
showSelect={true}
@@ -300,7 +292,7 @@ const Workers: React.FC = () => {
setWorkerDetailStatus({ currentData: null, open: false })
}
/>
</PageContainer>
</PageBox>
</>
);
};
+3 -13
View File
@@ -4,12 +4,12 @@ import { FilterBar } from '@/components/page-tools';
import { PageAction } from '@/config';
import type { PageActionType } from '@/config/types';
import useTableFetch from '@/hooks/use-table-fetch';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl, useModel } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Button, ConfigProvider, message, Table } from 'antd';
import { useMemo, useState } from 'react';
import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box';
import { createUser, deleteUser, queryUsersList, updateUser } from './apis';
import AddModal from './components/add-modal';
import { FormData, ListItem } from './config/types';
@@ -165,17 +165,7 @@ const Users: React.FC = () => {
return (
<>
<PageContainer
ghost
header={{
title: intl.formatMessage({ id: 'users.title' }),
style: {
paddingInline: 'var(--layout-content-header-inlinepadding)'
},
breadcrumb: {}
}}
extra={[]}
>
<PageBox>
<FilterBar
marginBottom={22}
marginTop={30}
@@ -205,7 +195,7 @@ const Users: React.FC = () => {
}}
></Table>
</ConfigProvider>
</PageContainer>
</PageBox>
<AddModal
open={openAddModalStatus.open}
action={openAddModalStatus.action}