refactor: adjust playground pages dir

This commit is contained in:
jialin
2026-03-17 16:35:55 +08:00
committed by jialin
parent 64955c26a7
commit 9447088f89
25 changed files with 262 additions and 317 deletions
+112
View File
@@ -0,0 +1,112 @@
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';
import { useHotkeys } from 'react-hotkeys-hook';
import { PageContainerInner } from '../../_components/page-box';
import { queryModelsList } from '../apis';
import ViewCodeButtons from '../components/view-code-buttons';
import useCollapseLayout from '../hooks/use-collapse-layout';
import '../style/play-ground.less';
import GroundVideo from './page';
const PlaygroundRerank: React.FC = () => {
const intl = useIntl();
const groundVideoRef = useRef<any>(null);
const [modelList, setModelList] = useState<Global.BaseOption<string>[]>([]);
const [loaded, setLoaded] = useState(false);
useCollapseLayout({
handler: () => {
groundVideoRef.current?.setCollapse?.();
},
triggeredRef: groundVideoRef.current
});
const handleViewCode = useMemoizedFn(() => {
groundVideoRef.current?.viewCode?.();
});
const handleToggleCollapse = useMemoizedFn(() => {
groundVideoRef.current?.setCollapse?.();
});
useEffect(() => {
const getModelList = async () => {
try {
const params = {
categories: modelCategoriesMap.llm,
with_meta: true
};
const res = await queryModelsList(params);
const list = _.map(res.data || [], (item: any) => {
return {
value: item.id,
label: item.id,
meta: item.meta
};
}) as Global.BaseOption<string>[];
return list;
} catch (error) {
console.error(error);
return [];
}
};
const fetchData = async () => {
try {
const [modelList] = await Promise.all([getModelList()]);
setModelList(modelList);
} catch (error) {
setLoaded(true);
}
};
fetchData();
}, []);
useHotkeys(
HotKeys.RIGHT.join(','),
() => {
groundVideoRef.current?.setCollapse?.();
},
{
preventDefault: true
}
);
return (
<PageContainerInner
className={classNames('playground-container chat')}
extra={[
<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" />
]}
>
<div className="play-ground">
<div className="chat">
<GroundVideo
ref={groundVideoRef}
modelList={modelList}
loaded={loaded}
></GroundVideo>
</div>
</div>
</PageContainerInner>
);
};
export default PlaygroundRerank;
+262
View File
@@ -0,0 +1,262 @@
import { setRouteCache } from '@/atoms/route-cache';
import AlertInfo from '@/components/alert-info';
import routeCachekey from '@/config/route-cachekey';
import { VideoCameraOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Spin } from 'antd';
import _ from 'lodash';
import 'overlayscrollbars/overlayscrollbars.css';
import React, {
forwardRef,
useCallback,
useImperativeHandle,
useMemo,
useRef,
useState
} from 'react';
import { CREATE_VIDEO_API } from '../apis';
import DynamicParams from '../components/dynamic-params';
import MessageInput from '../components/message-input';
import RightContainer from '../components/right-container';
import ViewCommonCode from '../components/view-common-code';
import { useInitVideoMeta } from '../hooks/use-init-video-meta';
import useTextVideo from '../hooks/use-text-video';
import '../style/ground-llm.less';
import '../style/system-message-wrap.less';
import { generateCode } from '../view-code/video';
interface MessageProps {
modelList: Global.BaseOption<string>[];
loaded?: boolean;
ref?: any;
}
const GroundVideo: React.FC<MessageProps> = forwardRef((props, ref) => {
const { modelList } = props;
const intl = useIntl();
const [show, setShow] = useState(false);
const [collapse, setCollapse] = useState(false);
const scroller = useRef<any>(null);
const paramsRef = useRef<any>(null);
const inputRef = useRef<any>(null);
const {
handleOnValuesChange,
handleToggleParamsStyle,
setParams,
form,
formFields,
paramsConfig,
initialValues,
parameters,
isOpenaiCompatible
} = useInitVideoMeta(props, {
type: 'create'
});
const {
loading,
tokenResult,
videoList,
promptList,
currentPrompt,
setCurrentPrompt,
handleClear,
handleStopConversation,
submitMessage
} = useTextVideo({
scroller,
API: CREATE_VIDEO_API
});
useImperativeHandle(ref, () => {
return {
viewCode() {
setShow(true);
},
setCollapse() {
setCollapse(!collapse);
},
collapse: collapse
};
});
const generateNumber = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min + 1) + min);
};
const handleRandomPrompt = useCallback(() => {
const randomIndex = generateNumber(0, promptList.length - 1);
const randomPrompt = promptList[randomIndex];
inputRef.current?.handleInputChange({
target: {
value: randomPrompt
}
});
}, []);
const finalParameters = useMemo(() => {
if (parameters.size === 'custom') {
return {
..._.omit(parameters, ['width', 'height', 'random_seed', 'seed']),
size:
parameters.width && parameters.height
? `${parameters.width}x${parameters.height}`
: ''
};
}
return {
..._.omit(parameters, ['width', 'height', 'random_seed', 'seed'])
};
}, [parameters]);
const viewCodeContent = useMemo(() => {
return generateCode({
api: CREATE_VIDEO_API,
isFormdata: true,
parameters: {
...finalParameters,
prompt: currentPrompt
}
});
}, [finalParameters, isOpenaiCompatible, currentPrompt]);
const handleInputChange = (e: any) => {
setCurrentPrompt(e.target.value);
};
const generateParams = () => {
const params = {
..._.omitBy(finalParameters, (value: string) => !value),
prompt: currentPrompt
};
return params;
};
const handleSendMessage = async () => {
try {
await form.current?.form?.validateFields();
if (!parameters.model) return;
const params = generateParams();
console.log('generateParams:', params);
setParams({
...parameters
});
console.log('params:', params, parameters);
setRouteCache(routeCachekey['/playground/video'], true);
await submitMessage(params);
} catch (error) {
// console.log('error:', error);
} finally {
console.log('finally---------');
setRouteCache(routeCachekey['/playground/video'], false);
}
};
const handleCloseViewCode = useCallback(() => {
setShow(false);
}, []);
return (
<div className="ground-left-wrapper">
<div className="ground-left">
<div
className="message-list-wrap"
ref={scroller}
style={{ paddingBottom: 16 }}
>
<>
<div className="content" style={{ height: '100%' }}>
{videoList.length > 0 && (
<div
style={{
width: '100%',
maxWidth: 720,
margin: '24px auto',
aspectRatio: '16 / 9',
background: '#000',
borderRadius: 8,
overflow: 'hidden',
boxShadow: '0 4px 24px rgba(0,0,0,0.12)'
}}
>
<Spin spinning={loading}>
<video
src={videoList[0]?.dataUrl}
poster="https://placehold.co/640x360.png?text=GPUStack"
controls
disablePictureInPicture
style={{
width: '100%',
height: '100%',
objectFit: 'contain'
}}
/>
</Spin>
</div>
)}
{!videoList.length && (
<div className="flex-column font-size-14 flex-center gap-20 justify-center hold-wrapper">
<VideoCameraOutlined className="font-size-32 text-secondary" />
<span>
{intl.formatMessage({
id: 'playground.video.empty.tips'
})}
</span>
</div>
)}
</div>
</>
</div>
{tokenResult && (
<div style={{ height: 40 }}>
<AlertInfo
type="danger"
message={tokenResult?.errorMessage}
></AlertInfo>
</div>
)}
<div className="ground-left-footer">
<MessageInput
ref={inputRef}
placeholer={intl.formatMessage({
id: 'playground.input.prompt.holder'
})}
actions={[]}
defaultSize={{
minRows: 5,
maxRows: 5
}}
title={intl.formatMessage({ id: 'playground.image.prompt' })}
loading={loading}
disabled={!parameters.model}
isEmpty={!videoList.length}
handleSubmit={handleSendMessage}
handleAbortFetch={handleStopConversation}
onInputChange={handleInputChange}
shouldResetMessage={false}
clearAll={handleClear}
/>
</div>
</div>
<RightContainer collapsed={collapse}>
<DynamicParams
ref={form}
onValuesChange={handleOnValuesChange}
paramsConfig={paramsConfig}
initialValues={initialValues}
modelList={modelList}
/>
</RightContainer>
<ViewCommonCode
open={show}
viewCodeContent={viewCodeContent}
onCancel={handleCloseViewCode}
title={intl.formatMessage({ id: 'playground.viewcode' })}
></ViewCommonCode>
</div>
);
});
export default GroundVideo;