From 26a4d5474dae7ed57fe353ce3eb9bb21b0c929a5 Mon Sep 17 00:00:00 2001 From: jialin Date: Thu, 20 Nov 2025 20:27:35 +0800 Subject: [PATCH] fix(style): gpu_selector position --- .../_components/column-wrapper/index.tsx | 18 ++++++++-- .../column-wrapper/use-wrapper-context.ts | 1 + .../llmodels/components/api-access-info.tsx | 2 +- src/pages/llmodels/forms/schedule-type.tsx | 36 +++++++++++++++++-- src/request-config.ts | 2 +- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/pages/_components/column-wrapper/index.tsx b/src/pages/_components/column-wrapper/index.tsx index 70fa45f5..be772fc0 100644 --- a/src/pages/_components/column-wrapper/index.tsx +++ b/src/pages/_components/column-wrapper/index.tsx @@ -1,5 +1,5 @@ import useOverlayScroller from '@/hooks/use-overlay-scroller'; -import React from 'react'; +import React, { useCallback } from 'react'; import './style.less'; import { WrapperContext } from './use-wrapper-context'; @@ -60,6 +60,15 @@ const ColumnWrapper: React.FC = ({ return () => observer.disconnect(); }, []); + const setContentPaddingBottom = useCallback((padding: number) => { + if (footerRef.current) { + const height = footerRef.current.getBoundingClientRect().height; + contentRef.current!.style.paddingBottom = `${height + padding - 22}px`; + } else { + contentRef.current!.style.paddingBottom = `${padding}px`; + } + }, []); + return ( = ({ scrollEventElement, getScrollElementScrollableHeight, scrollToBottom, - scrollToTarget + scrollToTarget, + setSScrollContentPaddingBottom: setContentPaddingBottom }} >
= ({ ref={scroller} style={{ padding: '16px 24px', ...styles.container }} > -
{children}
+
+ {children} +
{footer && (
diff --git a/src/pages/_components/column-wrapper/use-wrapper-context.ts b/src/pages/_components/column-wrapper/use-wrapper-context.ts index 50d62bae..7b403beb 100644 --- a/src/pages/_components/column-wrapper/use-wrapper-context.ts +++ b/src/pages/_components/column-wrapper/use-wrapper-context.ts @@ -12,6 +12,7 @@ interface WrapperContextProps { }; scrollToTarget?: (target: any, offset?: number) => void; getScrollElement?: () => HTMLElement | null; + setSScrollContentPaddingBottom?: (padding: number) => void; } export const WrapperContext = createContext( diff --git a/src/pages/llmodels/components/api-access-info.tsx b/src/pages/llmodels/components/api-access-info.tsx index 32d47040..f1d86fc8 100644 --- a/src/pages/llmodels/components/api-access-info.tsx +++ b/src/pages/llmodels/components/api-access-info.tsx @@ -48,7 +48,7 @@ const ApiAccessInfoWrapper = styled.div` display: grid; padding-left: 20px; grid-template-columns: max-content 1fr max-content; - gap: 12px 0px; + gap: 8px 0px; justify-items: start; align-items: center; .label { diff --git a/src/pages/llmodels/forms/schedule-type.tsx b/src/pages/llmodels/forms/schedule-type.tsx index b7e58ca6..79456e02 100644 --- a/src/pages/llmodels/forms/schedule-type.tsx +++ b/src/pages/llmodels/forms/schedule-type.tsx @@ -4,6 +4,7 @@ import SealCascader from '@/components/seal-form/seal-cascader'; import SealSelect from '@/components/seal-form/seal-select'; import TooltipList from '@/components/tooltip-list'; import useAppUtils from '@/hooks/use-app-utils'; +import { useWrapperContext } from '@/pages/_components/column-wrapper/use-wrapper-context'; import { useIntl } from '@umijs/max'; import { Form, InputNumber } from 'antd'; import _ from 'lodash'; @@ -71,6 +72,8 @@ const ScheduleTypeForm: React.FC = () => { clearCacheFormValues, initialValues } = useFormContext(); + const { setSScrollContentPaddingBottom, getScrollElementScrollableHeight } = + useWrapperContext(); const { getRuleMessage } = useAppUtils(); const form = Form.useFormInstance(); const scheduleType = Form.useWatch('scheduleType', form); @@ -79,15 +82,41 @@ const ScheduleTypeForm: React.FC = () => { ['gpu_selector', 'gpus_per_replica'], form ); + const gpuSekectorElRef = React.useRef(null); + + const setContentPaddingBottom = () => { + if (!gpuSekectorElRef.current) { + gpuSekectorElRef.current = document.querySelector( + '[data-field="gpu_selector.gpu_ids"]' + ); + } + if (gpuSekectorElRef.current) { + const { scrollHeight, scrollTop } = + getScrollElementScrollableHeight?.() || { + scrollHeight: 0, + scrollTop: 0 + }; + + const rect = gpuSekectorElRef.current.getBoundingClientRect(); + const bottomSpace = + window.innerHeight - rect.bottom + (scrollHeight - scrollTop); + if (bottomSpace < 340) { + setSScrollContentPaddingBottom?.(340 - bottomSpace); + } + } + }; const handleScheduleTypeChange = async (value: string) => { + await new Promise((resolve) => { + setTimeout(resolve, 100); + }); if (value === ScheduleValueMap.Auto) { - await new Promise((resolve) => { - setTimeout(resolve, 100); - }); onValuesChange?.({}, form.getFieldsValue()); } else if (value === ScheduleValueMap.Manual) { form.setFieldValue(['gpu_selector', 'gpus_per_replica'], null); + requestAnimationFrame(() => { + setContentPaddingBottom(); + }); } }; const handleGpusPerReplicasChange = (val: string | number | null) => { @@ -161,6 +190,7 @@ const ScheduleTypeForm: React.FC = () => { !form.getFieldValue('fix_gpu_type') && ( <>