refactor: ui/ux

This commit is contained in:
jialin
2026-04-08 18:54:06 +08:00
committed by jialin
parent 06160546a6
commit 1c09cc6c8c
22 changed files with 325 additions and 167 deletions
+54 -31
View File
@@ -1,44 +1,67 @@
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import {
PageContainer,
RouteContext,
type PageContainerProps
} from '@ant-design/pro-components';
import styled from 'styled-components';
import classNames from 'classnames';
import { useContext, useEffect, useRef } from 'react';
import pageBoxCss from './styles/page-box.less';
const paddingInlinePageContainerContent = 32;
const paddingInlinePageContainerContent = 24;
const StyledPageContainer = styled(PageContainer)`
.ant-affix {
top: 0 !important;
height: auto;
export const PageContainerInner: React.FC<
PageContainerProps & {
leftContent?: React.ReactNode;
rightContent?: React.ReactNode;
styles?: {
containerWrapper?: React.CSSProperties;
};
}
.ant-page-header {
padding-block-end: 8px;
.ant-page-header-heading {
padding-block-start: 0;
> = ({ children, styles, title, leftContent, rightContent, ...rest }) => {
const { initialize: initialize } = useOverlayScroller({
defer: false
});
const pageContext = useContext(RouteContext);
const contentWrapperRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (contentWrapperRef.current) {
const ins = initialize(contentWrapperRef.current);
window.__GPUSTACK_BODY_SCROLLER__ = ins;
}
}
.ant-pro-page-container-warp-page-header {
padding-inline: ${paddingInlinePageContainerContent}px;
}
.ant-page-header-heading-title {
font-size: 16px;
}
`;
}, [initialize, contentWrapperRef]);
export const PageContainerInner: React.FC<PageContainerProps> = ({
children,
...rest
}) => {
return (
<StyledPageContainer
{...rest}
fixedHeader={true}
token={{
paddingInlinePageContainerContent: paddingInlinePageContainerContent
}}
>
{children}
</StyledPageContainer>
<div className={pageBoxCss.containerWrapper}>
<PageContainer
{...rest}
fixedHeader={false}
title={false}
style={{
flex: 1
}}
token={{
paddingInlinePageContainerContent: paddingInlinePageContainerContent
}}
>
<div className={pageBoxCss.title}>
<div className={pageBoxCss.left}>
{leftContent || pageContext.title}
</div>
{rightContent && (
<div className={pageBoxCss.right}>{rightContent}</div>
)}
</div>
<div
className={classNames(pageBoxCss.contentWrapper)}
style={styles?.containerWrapper}
ref={contentWrapperRef}
>
{children}
</div>
</PageContainer>
</div>
);
};
@@ -0,0 +1,62 @@
.containerWrapper {
:global {
.ant-affix {
top: 0 !important;
height: auto;
}
.ant-page-header {
padding-block-end: 8px;
.ant-page-header-heading {
padding-block-start: 0;
}
}
.ant-page-header-heading-title {
font-size: 16px;
}
.ant-pro-page-container-children-container {
height: calc(100vh - 56px);
display: flex;
flex-direction: column;
border: 1px solid rgb(237, 237, 237);
border-radius: 8px;
overflow: hidden;
background-color: var(--ant-color-bg-container);
padding: 0;
}
}
.contentWrapper {
flex: 1;
overflow-y: auto;
padding-block: var(--layout-content-blockpadding);
padding-inline: var(--layout-content-inlinepadding);
}
.title {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding-inline: var(--layout-content-inlinepadding);
font-size: 16px;
color: var(--ant-color-text);
font-weight: 600;
padding-block: 9px 8px;
height: 56px;
border-bottom: 1px solid var(--ant-color-split);
.left {
display: flex;
align-items: center;
}
.right {
display: flex;
align-items: center;
}
}
}
+31 -29
View File
@@ -46,34 +46,36 @@ const LLModels: React.FC = () => {
setActiveKey(key);
});
const header = useMemo(() => {
return {
title: (
<div className="flex items-center">
<span className="font-600">
{intl.formatMessage({ id: 'menu.models.deployment' })}
</span>
<Segmented
options={[
{
label: intl.formatMessage({ id: 'models.table.modelView' }),
value: TabsValueMap.ModelView,
icon: <IconFont type={'icon-models'}></IconFont>
},
{
label: intl.formatMessage({ id: 'models.table.instanceView' }),
value: TabsValueMap.InstanceView,
icon: <IconFont type={'icon-instance-outline'}></IconFont>
}
]}
size="middle"
className="m-l-24 font-600"
value={activeKey}
onChange={handleTabChange}
></Segmented>
</div>
)
};
const title = useMemo(() => {
return (
<div className="flex items-center">
<span className="font-600 flex-center">
{intl.formatMessage({ id: 'menu.models.deployment' })}
</span>
<Segmented
shape="round"
style={{
backgroundColor: 'var(--ant-color-fill-secondary)'
}}
size="middle"
className="m-l-24 font-400"
options={[
{
label: intl.formatMessage({ id: 'models.table.modelView' }),
value: TabsValueMap.ModelView,
icon: <IconFont type={'icon-models'}></IconFont>
},
{
label: intl.formatMessage({ id: 'models.table.instanceView' }),
value: TabsValueMap.InstanceView,
icon: <IconFont type={'icon-instance-outline'}></IconFont>
}
]}
value={activeKey}
onChange={handleTabChange}
></Segmented>
</div>
);
}, [activeKey, intl]);
useEffect(() => {
@@ -103,7 +105,7 @@ const LLModels: React.FC = () => {
}, [activeKey]);
return (
<PageContainerInner header={header}>
<PageContainerInner leftContent={title}>
<DeploymentsContext.Provider
value={{
generateFormValues,
@@ -131,7 +131,7 @@ const useProviderColumns = (options: {
{
title: intl.formatMessage({ id: 'clusters.title' }),
dataIndex: 'cluster_id',
minWidth: 200,
width: 200,
render: (text: number) => (
<AutoTooltip ghost>
{text
@@ -157,6 +157,7 @@ const useProviderColumns = (options: {
title: intl.formatMessage({ id: 'models.table.vram.allocated' }),
dataIndex: 'allocated_vram',
sorter: tableSorter(6),
width: 160,
render: (text, record) => (
<AutoTooltip ghost>
{convertFileSize(
+41 -22
View File
@@ -1,12 +1,11 @@
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 { useIntl } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Divider, Segmented, Tabs, TabsProps } from 'antd';
import { Segmented, Tabs, TabsProps } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useEffect, useMemo, useRef, useState } from 'react';
@@ -109,11 +108,11 @@ const Playground: React.FC = () => {
fetchData();
}, []);
const header = useMemo(() => {
return {
title: (
const title = useMemo(() => {
return (
<div className="flex justify-between items-center">
<div className="flex items-center">
<span className="font-600">
<span className="font-600 flex-center">
{intl.formatMessage({ id: 'menu.playground.chat' })}
</span>
{
@@ -126,8 +125,14 @@ const Playground: React.FC = () => {
></Segmented>
}
</div>
)
};
<ViewCodeButtons
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
activeKey={activeKey}
key="view-code-buttons"
/>
</div>
);
}, [activeKey, optionsList, intl]);
useHotkeys(
@@ -148,25 +153,39 @@ const Playground: React.FC = () => {
compare: activeKey === 'compare',
chat: activeKey !== 'compare'
})}
header={header}
extra={[
styles={{
containerWrapper: {
padding: 0
}
}}
leftContent={
<div className="flex items-center">
<span className="font-600 flex-center">
{intl.formatMessage({ id: 'menu.playground.chat' })}
</span>
{
<Segmented
shape="round"
style={{
backgroundColor: 'var(--ant-color-fill-secondary)'
}}
size="middle"
className="m-l-24 font-400"
options={optionsList}
value={activeKey}
onChange={(key) => setActiveKey(key)}
></Segmented>
}
</div>
}
rightContent={
<ViewCodeButtons
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
activeKey={activeKey}
key="view-code-buttons"
/>,
<div key="divider-wrapper">
{activeKey === 'chat' && (
<Divider
key="divider"
orientation="vertical"
style={{ height: 16, marginInline: 16 }}
/>
)}
</div>,
<ExtraContent key="extra-content" />
]}
/>
}
>
<div className="play-ground">
<div className="chat">
@@ -15,7 +15,7 @@ const ViewCodeButtons: React.FC<{
}
return (
<Space key="buttons" style={{ marginRight: 8 }}>
<Space key="buttons">
<Button
size="middle"
onClick={handleViewCode}
+8 -11
View File
@@ -1,9 +1,7 @@
import HotKeys from '@/config/hotkeys';
import { ExtraContent } from '@/layouts/extraRender';
import { modelCategoriesMap } from '@/pages/llmodels/config';
import { useIntl } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Divider } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useEffect, useRef, useState } from 'react';
@@ -81,20 +79,19 @@ const PlaygroundEmbedding: React.FC = () => {
return (
<PageContainerInner
className={classNames('playground-container chat')}
extra={[
styles={{
containerWrapper: {
padding: 0
}
}}
rightContent={
<ViewCodeButtons
activeKey=""
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
key="view-code-buttons"
/>,
<Divider
key="divider"
orientation="vertical"
style={{ height: 16, marginInline: 16 }}
/>,
<ExtraContent key="extra-content" />
]}
/>
}
>
<div className="play-ground">
<div className="chat">
+1 -1
View File
@@ -622,7 +622,7 @@ const GroundEmbedding: React.FC<MessageProps> = forwardRef((props, ref) => {
className="ground-left-footer"
style={{
width: '100%',
padding: '0 32px 16px'
padding: '0 var(--layout-content-inlinepadding) 16px'
}}
>
<h3 className="m-l-10 flex-between flex-center font-size-14 line-24 m-b-16">
+23 -12
View File
@@ -1,12 +1,11 @@
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 { useIntl } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { Divider, Segmented, Tabs, TabsProps } from 'antd';
import { Segmented, Tabs, TabsProps } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useEffect, useMemo, useRef, useState } from 'react';
@@ -156,21 +155,33 @@ const TextToImages: React.FC = () => {
return (
<PageContainerInner
header={header}
extra={[
leftContent={
<div className="flex items-center">
<span className="font-600 flex-center">
{intl.formatMessage({ id: 'menu.playground.text2images' })}
</span>
<Segmented
shape="round"
style={{
backgroundColor: 'var(--ant-color-fill-secondary)'
}}
size="middle"
className="m-l-24 font-400"
options={optionsList}
value={activeKey}
onChange={(key) => setActiveKey(key)}
></Segmented>
</div>
}
rightContent={
<ViewCodeButtons
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
activeKey={activeKey}
key="view-code-buttons"
></ViewCodeButtons>,
<Divider
key="divider"
orientation="vertical"
style={{ height: 16, marginInline: 16 }}
/>,
<ExtraContent key="extra-content" />
]}
></ViewCodeButtons>
}
styles={{ containerWrapper: { padding: 0 } }}
className={classNames('playground-container chat')}
>
<div className="play-ground">
+8 -11
View File
@@ -1,9 +1,7 @@
import HotKeys from '@/config/hotkeys';
import { ExtraContent } from '@/layouts/extraRender';
import { modelCategoriesMap } from '@/pages/llmodels/config';
import { useIntl } from '@umijs/max';
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
import { Divider } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useEffect, useRef, useState } from 'react';
@@ -85,20 +83,19 @@ const PlaygroundRerank: React.FC = () => {
return (
<PageContainerInner
className={classNames('playground-container chat')}
extra={[
styles={{
containerWrapper: {
padding: 0
}
}}
rightContent={
<ViewCodeButtons
activeKey=""
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
key="view-code-buttons"
></ViewCodeButtons>,
<Divider
key="divider"
orientation="vertical"
style={{ height: 16, marginInline: 16 }}
/>,
<ExtraContent key="extra-content" />
]}
></ViewCodeButtons>
}
>
<div className="play-ground">
<div className="chat">
+5 -2
View File
@@ -41,7 +41,7 @@ import { fieldConfig } from './params-config';
const { Text } = Typography;
const SearchInputWrapper = styled.div`
margin: 16px 32px 10px;
margin: 16px var(--layout-content-inlinepadding) 10px;
position: relative;
`;
@@ -477,7 +477,10 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
<div className="ground-left-footer">
<h3
className="m-l-10 flex-between flex-center font-size-14 line-24 m-b-0"
style={{ padding: '0 32px', marginTop: 16 }}
style={{
padding: '0 var(--layout-content-inlinepadding)',
marginTop: 16
}}
>
<span>{intl.formatMessage({ id: 'playground.rerank.query' })}</span>
</h3>
+24 -12
View File
@@ -2,12 +2,11 @@ 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 { useIntl, useSearchParams } from '@umijs/max';
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
import { Divider, Segmented, Tabs, TabsProps } from 'antd';
import { Segmented, Tabs, TabsProps } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { useEffect, useMemo, useRef, useState } from 'react';
@@ -196,21 +195,34 @@ const Playground: React.FC = () => {
return (
<PageContainerInner
header={header}
extra={[
leftContent={
<div className="flex items-center">
<span className="font-600 flex-center">
{intl.formatMessage({ id: 'menu.playground.speech' })}
</span>
{
<Segmented
shape="round"
style={{
backgroundColor: 'var(--ant-color-fill-secondary)'
}}
size="middle"
className="m-l-24 font-400"
options={optionsList}
value={activeKey}
onChange={(key) => setActiveKey(key)}
></Segmented>
}
</div>
}
rightContent={
<ViewCodeButtons
activeKey=""
handleViewCode={handleViewCode}
handleToggleCollapse={handleToggleCollapse}
key="view-code-buttons"
></ViewCodeButtons>,
<Divider
key="divider"
orientation="vertical"
style={{ height: 16, marginInline: 16 }}
/>,
<ExtraContent key="extra-content" />
]}
></ViewCodeButtons>
}
className={classNames('playground-container', {
compare: activeKey === 'compare',
chat: activeKey !== 'compare'
+4 -1
View File
@@ -9,7 +9,10 @@
justify-content: space-between;
flex-direction: column;
position: relative;
height: calc(100vh - @HEADER_HEIGHT);
height: calc(
100vh - @HEADER_HEIGHT - var(--page-content-padding) -
var(--page-header-height)
);
width: calc(100% - 390px);
.message-list-wrap {
@@ -5,7 +5,10 @@
width: 390px;
border-left: 1px solid var(--ant-color-split);
transition: width 0.3s ease;
height: calc(100vh - @HEADER_HEIGHT);
height: calc(
100vh - @HEADER_HEIGHT - var(--page-content-padding) -
var(--page-header-height)
);
padding-top: 16px;
display: flex;
flex-direction: column;
+10 -18
View File
@@ -1,4 +1,4 @@
@HEADER_HEIGHT: 56px;
@HEADER_HEIGHT: 48px;
.play-ground {
display: flex;
@@ -39,7 +39,10 @@
.params {
overflow: hidden;
height: calc(100vh - @HEADER_HEIGHT);
height: calc(
100vh - var(--page-header-height) - var(--page-content-padding) -
@HEADER_HEIGHT
);
.collapse {
width: 0;
@@ -48,7 +51,7 @@
}
.params-box {
padding-inline: 32px;
padding-inline: var(--layout-content-inlinepadding);
height: 100%;
width: 390px;
overflow-y: auto;
@@ -70,7 +73,10 @@
.ant-divider {
margin: 0;
height: calc(100vh - 136px);
height: calc(
100vh - var(--page-header-height) - var(--page-content-padding) -
@HEADER_HEIGHT
);
}
}
}
@@ -85,20 +91,6 @@
position: relative;
}
&.chat {
.ant-page-header {
// &::after {
// position: absolute;
// content: '';
// left: 32px;
// right: 32px;
// bottom: 0;
// height: 1px;
// border-bottom: 1px solid var(--ant-color-split);
// }
}
}
&.compare {
.ant-pro-page-container-children-container {
padding-inline: 0;
+1 -1
View File
@@ -3,7 +3,7 @@
display: flex;
flex-direction: column;
height: 100%;
padding-inline: 32px;
padding-inline: var(--layout-content-inlinepadding);
padding-bottom: 16px;
.documents {
@@ -1,5 +1,5 @@
.speech-to-text {
padding: 32px;
padding: var(--layout-content-inlinepadding);
height: 100%;
display: flex;
gap: 30px;