fix(style): gpu_selector position

This commit is contained in:
jialin
2025-11-20 20:49:19 +08:00
parent af3e03230a
commit 26a4d5474d
5 changed files with 51 additions and 8 deletions
+15 -3
View File
@@ -1,5 +1,5 @@
import useOverlayScroller from '@/hooks/use-overlay-scroller'; import useOverlayScroller from '@/hooks/use-overlay-scroller';
import React from 'react'; import React, { useCallback } from 'react';
import './style.less'; import './style.less';
import { WrapperContext } from './use-wrapper-context'; import { WrapperContext } from './use-wrapper-context';
@@ -60,6 +60,15 @@ const ColumnWrapper: React.FC<ColumnWrapperProps> = ({
return () => observer.disconnect(); 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 ( return (
<WrapperContext.Provider <WrapperContext.Provider
value={{ value={{
@@ -68,7 +77,8 @@ const ColumnWrapper: React.FC<ColumnWrapperProps> = ({
scrollEventElement, scrollEventElement,
getScrollElementScrollableHeight, getScrollElementScrollableHeight,
scrollToBottom, scrollToBottom,
scrollToTarget scrollToTarget,
setSScrollContentPaddingBottom: setContentPaddingBottom
}} }}
> >
<div <div
@@ -80,7 +90,9 @@ const ColumnWrapper: React.FC<ColumnWrapperProps> = ({
ref={scroller} ref={scroller}
style={{ padding: '16px 24px', ...styles.container }} style={{ padding: '16px 24px', ...styles.container }}
> >
<div ref={contentRef}>{children}</div> <div ref={contentRef} className="child-content">
{children}
</div>
</div> </div>
{footer && ( {footer && (
<div className="footer" ref={footerRef}> <div className="footer" ref={footerRef}>
@@ -12,6 +12,7 @@ interface WrapperContextProps {
}; };
scrollToTarget?: (target: any, offset?: number) => void; scrollToTarget?: (target: any, offset?: number) => void;
getScrollElement?: () => HTMLElement | null; getScrollElement?: () => HTMLElement | null;
setSScrollContentPaddingBottom?: (padding: number) => void;
} }
export const WrapperContext = createContext<WrapperContextProps>( export const WrapperContext = createContext<WrapperContextProps>(
@@ -48,7 +48,7 @@ const ApiAccessInfoWrapper = styled.div`
display: grid; display: grid;
padding-left: 20px; padding-left: 20px;
grid-template-columns: max-content 1fr max-content; grid-template-columns: max-content 1fr max-content;
gap: 12px 0px; gap: 8px 0px;
justify-items: start; justify-items: start;
align-items: center; align-items: center;
.label { .label {
+33 -3
View File
@@ -4,6 +4,7 @@ import SealCascader from '@/components/seal-form/seal-cascader';
import SealSelect from '@/components/seal-form/seal-select'; import SealSelect from '@/components/seal-form/seal-select';
import TooltipList from '@/components/tooltip-list'; import TooltipList from '@/components/tooltip-list';
import useAppUtils from '@/hooks/use-app-utils'; import useAppUtils from '@/hooks/use-app-utils';
import { useWrapperContext } from '@/pages/_components/column-wrapper/use-wrapper-context';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Form, InputNumber } from 'antd'; import { Form, InputNumber } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
@@ -71,6 +72,8 @@ const ScheduleTypeForm: React.FC = () => {
clearCacheFormValues, clearCacheFormValues,
initialValues initialValues
} = useFormContext(); } = useFormContext();
const { setSScrollContentPaddingBottom, getScrollElementScrollableHeight } =
useWrapperContext();
const { getRuleMessage } = useAppUtils(); const { getRuleMessage } = useAppUtils();
const form = Form.useFormInstance(); const form = Form.useFormInstance();
const scheduleType = Form.useWatch('scheduleType', form); const scheduleType = Form.useWatch('scheduleType', form);
@@ -79,15 +82,41 @@ const ScheduleTypeForm: React.FC = () => {
['gpu_selector', 'gpus_per_replica'], ['gpu_selector', 'gpus_per_replica'],
form form
); );
const gpuSekectorElRef = React.useRef<HTMLElement | null>(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) => { const handleScheduleTypeChange = async (value: string) => {
await new Promise((resolve) => {
setTimeout(resolve, 100);
});
if (value === ScheduleValueMap.Auto) { if (value === ScheduleValueMap.Auto) {
await new Promise((resolve) => {
setTimeout(resolve, 100);
});
onValuesChange?.({}, form.getFieldsValue()); onValuesChange?.({}, form.getFieldsValue());
} else if (value === ScheduleValueMap.Manual) { } else if (value === ScheduleValueMap.Manual) {
form.setFieldValue(['gpu_selector', 'gpus_per_replica'], null); form.setFieldValue(['gpu_selector', 'gpus_per_replica'], null);
requestAnimationFrame(() => {
setContentPaddingBottom();
});
} }
}; };
const handleGpusPerReplicasChange = (val: string | number | null) => { const handleGpusPerReplicasChange = (val: string | number | null) => {
@@ -161,6 +190,7 @@ const ScheduleTypeForm: React.FC = () => {
!form.getFieldValue('fix_gpu_type') && ( !form.getFieldValue('fix_gpu_type') && (
<> <>
<Form.Item <Form.Item
data-field="gpu_selector.gpu_ids"
name={['gpu_selector', 'gpu_ids']} name={['gpu_selector', 'gpu_ids']}
rules={[ rules={[
{ {
+1 -1
View File
@@ -4,7 +4,7 @@ import { RequestConfig, history } from '@umijs/max';
import { message } from 'antd'; import { message } from 'antd';
import { DEFAULT_ENTER_PAGE } from './config/settings'; import { DEFAULT_ENTER_PAGE } from './config/settings';
// no GPUSTACK BASE API // these APIs do not via the GPUSTACK_API_BASE_URL
const NoBaseURLAPIs = ['/auth', '/v1', '/version', '/proxy', '/update']; const NoBaseURLAPIs = ['/auth', '/v1', '/version', '/proxy', '/update'];
export const requestConfig: RequestConfig = { export const requestConfig: RequestConfig = {