chore: docker add worker command
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import AlertInfo from '@/components/alert-info';
|
||||
import IconFont from '@/components/icon-font';
|
||||
import FieldComponent from '@/components/seal-form/field-component';
|
||||
import SealInput from '@/components/seal-form/seal-input';
|
||||
import SealSelect from '@/components/seal-form/seal-select';
|
||||
@@ -25,7 +26,7 @@ import React, {
|
||||
useState
|
||||
} from 'react';
|
||||
import { CREAT_IMAGE_API } from '../apis';
|
||||
import { OpenAIViewCode } from '../config';
|
||||
import { OpenAIViewCode, promptList } from '../config';
|
||||
import {
|
||||
ImageAdvancedParamsConfig,
|
||||
ImageconstExtraConfig,
|
||||
@@ -124,6 +125,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
const requestToken = useRef<any>(null);
|
||||
const [currentPrompt, setCurrentPrompt] = useState<string>('');
|
||||
const form = useRef<any>(null);
|
||||
const inputRef = useRef<any>(null);
|
||||
|
||||
const size = Form.useWatch('size', form.current?.form);
|
||||
|
||||
@@ -142,6 +144,20 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
};
|
||||
});
|
||||
|
||||
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 setImageSize = useCallback(() => {
|
||||
let size: Record<string, string | number> = {
|
||||
with: 256,
|
||||
@@ -497,10 +513,15 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
)}
|
||||
<div className="ground-left-footer">
|
||||
<MessageInput
|
||||
ref={inputRef}
|
||||
placeholer={intl.formatMessage({
|
||||
id: 'playground.input.prompt.holder'
|
||||
})}
|
||||
actions={['clear']}
|
||||
defaultSize={{
|
||||
minRows: 6,
|
||||
maxRows: 6
|
||||
}}
|
||||
loading={loading}
|
||||
disabled={!parameters.model}
|
||||
isEmpty={!imageList.length}
|
||||
@@ -509,9 +530,23 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
shouldResetMessage={false}
|
||||
clearAll={handleClear}
|
||||
tools={
|
||||
<span className="p-l-8 font-600">
|
||||
{intl.formatMessage({ id: 'playground.image.prompt' })}
|
||||
</span>
|
||||
<>
|
||||
<span className="p-l-8 font-600">
|
||||
{intl.formatMessage({ id: 'playground.image.prompt' })}
|
||||
</span>
|
||||
<Tooltip
|
||||
title={intl.formatMessage({
|
||||
id: 'playground.image.prompt.random'
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
onClick={handleRandomPrompt}
|
||||
size="middle"
|
||||
type="text"
|
||||
icon={<IconFont type="icon-random"></IconFont>}
|
||||
></Button>
|
||||
</Tooltip>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -270,7 +270,7 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
</div>
|
||||
|
||||
{audioData ? (
|
||||
<div className="flex-between flex-center justify-center">
|
||||
<div className="flex-between flex-center justify-center relative">
|
||||
<div style={{ width: 600 }}>
|
||||
<AudioPlayer
|
||||
url={audioData.url}
|
||||
@@ -278,6 +278,31 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
duration={audioData.duration}
|
||||
></AudioPlayer>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
padding: '16px 32px',
|
||||
textAlign: 'right',
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)'
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
title={intl.formatMessage({
|
||||
id: 'playground.audio.button.generate'
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
style={{ width: 46 }}
|
||||
size="middle"
|
||||
disabled={!audioData}
|
||||
type="primary"
|
||||
onClick={handleOnGenerate}
|
||||
icon={<SendOutlined></SendOutlined>}
|
||||
></Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
renderAniamtion()
|
||||
@@ -327,22 +352,6 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ padding: '16px 32px', textAlign: 'right' }}>
|
||||
<Tooltip
|
||||
title={intl.formatMessage({
|
||||
id: 'playground.audio.button.generate'
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
style={{ width: 46 }}
|
||||
size="middle"
|
||||
disabled={!audioData}
|
||||
type="primary"
|
||||
onClick={handleOnGenerate}
|
||||
icon={<SendOutlined></SendOutlined>}
|
||||
></Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -4,7 +4,14 @@ import { ClearOutlined, SendOutlined, SwapOutlined } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Checkbox, Divider, Input, Tooltip } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import React, {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useImperativeHandle,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState
|
||||
} from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { Roles } from '../config';
|
||||
import { MessageItem } from '../config/types';
|
||||
@@ -64,6 +71,7 @@ const layoutOptions = [
|
||||
];
|
||||
|
||||
interface MessageInputProps {
|
||||
ref?: any;
|
||||
handleSubmit: (params: CurrentMessage) => void;
|
||||
handleAbortFetch: () => void;
|
||||
updateLayout?: (value: { span: number; count: number }) => void;
|
||||
@@ -89,411 +97,425 @@ interface MessageInputProps {
|
||||
defaultSize?: { minRows: number; maxRows: number };
|
||||
}
|
||||
|
||||
const MessageInput: React.FC<MessageInputProps> = ({
|
||||
handleSubmit,
|
||||
handleAbortFetch,
|
||||
presetPrompt,
|
||||
clearAll,
|
||||
updateLayout,
|
||||
addMessage,
|
||||
onCheck,
|
||||
loading,
|
||||
disabled,
|
||||
isEmpty,
|
||||
submitIcon,
|
||||
placeholer,
|
||||
tools,
|
||||
style,
|
||||
checkLabel,
|
||||
defaultSize = { minRows: 3, maxRows: 8 },
|
||||
shouldResetMessage = true,
|
||||
actions = ['clear', 'layout', 'role', 'upload', 'add', 'paste']
|
||||
}) => {
|
||||
const { TextArea } = Input;
|
||||
const intl = useIntl();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [focused, setFocused] = useState(false);
|
||||
const [message, setMessage] = useState<CurrentMessage>({
|
||||
role: Roles.User,
|
||||
content: '',
|
||||
imgs: []
|
||||
});
|
||||
const imgCountRef = useRef(0);
|
||||
const inputRef = useRef<any>(null);
|
||||
|
||||
const isDisabled = useMemo(() => {
|
||||
return disabled
|
||||
? true
|
||||
: !message.content && isEmpty && !message.imgs?.length;
|
||||
}, [disabled, message, isEmpty]);
|
||||
|
||||
const resetMessage = () => {
|
||||
setMessage({
|
||||
role: message.role,
|
||||
content: '',
|
||||
imgs: []
|
||||
});
|
||||
};
|
||||
|
||||
const handleInputChange = (e: any) => {
|
||||
console.log('input change:', e.target?.value);
|
||||
setMessage({
|
||||
...message,
|
||||
content: e.target?.value
|
||||
});
|
||||
};
|
||||
const handleSendMessage = () => {
|
||||
handleSubmit({ ...message });
|
||||
if (shouldResetMessage) {
|
||||
resetMessage();
|
||||
}
|
||||
};
|
||||
const onStop = () => {
|
||||
handleAbortFetch();
|
||||
};
|
||||
const handleLayoutChange = (value: { span: number; count: number }) => {
|
||||
updateLayout?.(value);
|
||||
};
|
||||
|
||||
const handleToggleRole = () => {
|
||||
setMessage({
|
||||
...message,
|
||||
role: message.role === Roles.User ? Roles.Assistant : Roles.User
|
||||
});
|
||||
};
|
||||
|
||||
const handleClearAll = (e: any) => {
|
||||
e.stopPropagation();
|
||||
clearAll();
|
||||
setMessage({
|
||||
const MessageInput: React.FC<MessageInputProps> = forwardRef(
|
||||
(
|
||||
{
|
||||
handleSubmit,
|
||||
handleAbortFetch,
|
||||
presetPrompt,
|
||||
clearAll,
|
||||
updateLayout,
|
||||
addMessage,
|
||||
onCheck,
|
||||
loading,
|
||||
disabled,
|
||||
isEmpty,
|
||||
submitIcon,
|
||||
placeholer,
|
||||
tools,
|
||||
style,
|
||||
checkLabel,
|
||||
defaultSize = { minRows: 3, maxRows: 8 },
|
||||
shouldResetMessage = true,
|
||||
actions = ['clear', 'layout', 'role', 'upload', 'add', 'paste']
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const { TextArea } = Input;
|
||||
const intl = useIntl();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [focused, setFocused] = useState(false);
|
||||
const [message, setMessage] = useState<CurrentMessage>({
|
||||
role: Roles.User,
|
||||
content: '',
|
||||
imgs: []
|
||||
});
|
||||
};
|
||||
const imgCountRef = useRef(0);
|
||||
const inputRef = useRef<any>(null);
|
||||
|
||||
const handleAddMessage = (e?: any) => {
|
||||
e?.preventDefault();
|
||||
addMessage?.({ ...message });
|
||||
resetMessage();
|
||||
setFocused(true);
|
||||
setTimeout(() => {
|
||||
inputRef.current?.focus?.();
|
||||
}, 100);
|
||||
};
|
||||
const isDisabled = useMemo(() => {
|
||||
return disabled
|
||||
? true
|
||||
: !message.content && isEmpty && !message.imgs?.length;
|
||||
}, [disabled, message, isEmpty]);
|
||||
|
||||
const getPasteContent = useCallback(
|
||||
async (event: any) => {
|
||||
const clipboardData = event.clipboardData || window.clipboardData;
|
||||
const items = clipboardData.items;
|
||||
const imgPromises: Promise<string>[] = [];
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let item = items[i];
|
||||
|
||||
if (item.kind === 'file' && item.type.indexOf('image') !== -1) {
|
||||
const file = item.getAsFile();
|
||||
const imgPromise = new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
const base64String = event.target?.result as string;
|
||||
if (base64String) {
|
||||
resolve(base64String);
|
||||
} else {
|
||||
reject('Failed to convert image to base64');
|
||||
}
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
imgPromises.push(imgPromise);
|
||||
} else if (item.kind === 'string') {
|
||||
// string
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const imgs = await Promise.all(imgPromises);
|
||||
|
||||
if (imgs.length) {
|
||||
const list = _.map(imgs, (img: string) => {
|
||||
imgCountRef.current += 1;
|
||||
return {
|
||||
uid: imgCountRef.current,
|
||||
dataUrl: img
|
||||
};
|
||||
});
|
||||
setMessage({
|
||||
...message,
|
||||
imgs: [...(message.imgs || []), ...list]
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error processing images:', error);
|
||||
}
|
||||
},
|
||||
[message]
|
||||
);
|
||||
|
||||
// ========== upload image ==========
|
||||
const handleUpdateImgList = (
|
||||
list: { uid: number | string; dataUrl: string }[]
|
||||
) => {
|
||||
setMessage({
|
||||
...message,
|
||||
imgs: [...(message.imgs || []), ...list]
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteImg = (uid: number | string) => {
|
||||
const list = _.filter(
|
||||
message.imgs,
|
||||
(item: MessageItem) => item.uid !== uid
|
||||
);
|
||||
setMessage({
|
||||
...message,
|
||||
imgs: list
|
||||
});
|
||||
};
|
||||
|
||||
const handleOnPaste = (e: any) => {
|
||||
const text = e.clipboardData.getData('text');
|
||||
if (!text) {
|
||||
e.preventDefault();
|
||||
getPasteContent(e);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteLastImage = useCallback(() => {
|
||||
if (message.imgs && message.imgs?.length > 0) {
|
||||
const newImgList = [...(message.imgs || [])];
|
||||
const lastImage = newImgList.pop();
|
||||
if (lastImage) {
|
||||
handleDeleteImg(lastImage.uid);
|
||||
}
|
||||
}
|
||||
}, [message.imgs, handleDeleteImg]);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(event: any) => {
|
||||
if (
|
||||
event.key === 'Backspace' &&
|
||||
message.content === '' &&
|
||||
message.imgs &&
|
||||
message.imgs?.length > 0
|
||||
) {
|
||||
// inputref blur
|
||||
event.preventDefault();
|
||||
handleDeleteLastImage();
|
||||
}
|
||||
},
|
||||
[message, handleDeleteLastImage]
|
||||
);
|
||||
|
||||
const handleSelectPrompt = (list: CurrentMessage[]) => {
|
||||
presetPrompt?.(list);
|
||||
};
|
||||
|
||||
useHotkeys(
|
||||
HotKeys.SUBMIT,
|
||||
(e: any) => {
|
||||
console.log('submit message', loading);
|
||||
e.preventDefault();
|
||||
handleSendMessage();
|
||||
},
|
||||
{
|
||||
enabled: !loading && !isDisabled,
|
||||
enableOnFormTags: focused,
|
||||
preventDefault: true
|
||||
}
|
||||
);
|
||||
useHotkeys(
|
||||
HotKeys.ADD,
|
||||
(e: any) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleAddMessage();
|
||||
},
|
||||
{
|
||||
enabled: !loading,
|
||||
enableOnFormTags: focused,
|
||||
preventDefault: true
|
||||
}
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
HotKeys.FOCUS,
|
||||
() => {
|
||||
inputRef.current?.focus?.({
|
||||
cursor: 'end'
|
||||
const resetMessage = () => {
|
||||
setMessage({
|
||||
role: message.role,
|
||||
content: '',
|
||||
imgs: []
|
||||
});
|
||||
},
|
||||
{ preventDefault: true }
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="messageInput" style={{ ...style }}>
|
||||
<div className="tool-bar">
|
||||
<div className="actions">
|
||||
{
|
||||
<>
|
||||
{actions.includes('role') && (
|
||||
<>
|
||||
<Button
|
||||
type="text"
|
||||
size="middle"
|
||||
onClick={handleToggleRole}
|
||||
icon={<SwapOutlined rotate={90} />}
|
||||
>
|
||||
{intl.formatMessage({ id: `playground.${message.role}` })}
|
||||
</Button>
|
||||
<Divider type="vertical" style={{ margin: 0 }} />
|
||||
</>
|
||||
)}
|
||||
{actions.includes('upload') && message.role === Roles.User && (
|
||||
<UploadImg
|
||||
handleUpdateImgList={handleUpdateImgList}
|
||||
size="middle"
|
||||
></UploadImg>
|
||||
)}
|
||||
</>
|
||||
const handleInputChange = (e: any) => {
|
||||
console.log('input change:', e.target?.value);
|
||||
setMessage({
|
||||
...message,
|
||||
content: e.target?.value
|
||||
});
|
||||
};
|
||||
const handleSendMessage = () => {
|
||||
handleSubmit({ ...message });
|
||||
if (shouldResetMessage) {
|
||||
resetMessage();
|
||||
}
|
||||
};
|
||||
const onStop = () => {
|
||||
handleAbortFetch();
|
||||
};
|
||||
const handleLayoutChange = (value: { span: number; count: number }) => {
|
||||
updateLayout?.(value);
|
||||
};
|
||||
|
||||
const handleToggleRole = () => {
|
||||
setMessage({
|
||||
...message,
|
||||
role: message.role === Roles.User ? Roles.Assistant : Roles.User
|
||||
});
|
||||
};
|
||||
|
||||
const handleClearAll = (e: any) => {
|
||||
e.stopPropagation();
|
||||
clearAll();
|
||||
setMessage({
|
||||
role: Roles.User,
|
||||
content: '',
|
||||
imgs: []
|
||||
});
|
||||
};
|
||||
|
||||
const handleAddMessage = (e?: any) => {
|
||||
e?.preventDefault();
|
||||
addMessage?.({ ...message });
|
||||
resetMessage();
|
||||
setFocused(true);
|
||||
setTimeout(() => {
|
||||
inputRef.current?.focus?.();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
const getPasteContent = useCallback(
|
||||
async (event: any) => {
|
||||
const clipboardData = event.clipboardData || window.clipboardData;
|
||||
const items = clipboardData.items;
|
||||
const imgPromises: Promise<string>[] = [];
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let item = items[i];
|
||||
|
||||
if (item.kind === 'file' && item.type.indexOf('image') !== -1) {
|
||||
const file = item.getAsFile();
|
||||
const imgPromise = new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
const base64String = event.target?.result as string;
|
||||
if (base64String) {
|
||||
resolve(base64String);
|
||||
} else {
|
||||
reject('Failed to convert image to base64');
|
||||
}
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
imgPromises.push(imgPromise);
|
||||
} else if (item.kind === 'string') {
|
||||
// string
|
||||
}
|
||||
{tools}
|
||||
{actions.includes('check') && (
|
||||
<Checkbox onChange={onCheck} defaultChecked={true}>
|
||||
{checkLabel}
|
||||
</Checkbox>
|
||||
)}
|
||||
{actions.includes('clear') && (
|
||||
<Tooltip title={intl.formatMessage({ id: 'common.button.clear' })}>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<ClearOutlined />}
|
||||
size="middle"
|
||||
onClick={handleClearAll}
|
||||
></Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
}
|
||||
|
||||
{actions.includes('layout') && updateLayout && (
|
||||
<>
|
||||
<Divider type="vertical" style={{ margin: 0 }} />
|
||||
{layoutOptions.map((option) => (
|
||||
<Tooltip
|
||||
title={intl.formatMessage({ id: option.tips })}
|
||||
key={option.icon}
|
||||
>
|
||||
<Button
|
||||
key={option.icon}
|
||||
type="text"
|
||||
icon={<IconFont type={option.icon}></IconFont>}
|
||||
try {
|
||||
const imgs = await Promise.all(imgPromises);
|
||||
|
||||
if (imgs.length) {
|
||||
const list = _.map(imgs, (img: string) => {
|
||||
imgCountRef.current += 1;
|
||||
return {
|
||||
uid: imgCountRef.current,
|
||||
dataUrl: img
|
||||
};
|
||||
});
|
||||
setMessage({
|
||||
...message,
|
||||
imgs: [...(message.imgs || []), ...list]
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error processing images:', error);
|
||||
}
|
||||
},
|
||||
[message]
|
||||
);
|
||||
|
||||
// ========== upload image ==========
|
||||
const handleUpdateImgList = (
|
||||
list: { uid: number | string; dataUrl: string }[]
|
||||
) => {
|
||||
setMessage({
|
||||
...message,
|
||||
imgs: [...(message.imgs || []), ...list]
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteImg = (uid: number | string) => {
|
||||
const list = _.filter(
|
||||
message.imgs,
|
||||
(item: MessageItem) => item.uid !== uid
|
||||
);
|
||||
setMessage({
|
||||
...message,
|
||||
imgs: list
|
||||
});
|
||||
};
|
||||
|
||||
const handleOnPaste = (e: any) => {
|
||||
const text = e.clipboardData.getData('text');
|
||||
if (!text) {
|
||||
e.preventDefault();
|
||||
getPasteContent(e);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteLastImage = useCallback(() => {
|
||||
if (message.imgs && message.imgs?.length > 0) {
|
||||
const newImgList = [...(message.imgs || [])];
|
||||
const lastImage = newImgList.pop();
|
||||
if (lastImage) {
|
||||
handleDeleteImg(lastImage.uid);
|
||||
}
|
||||
}
|
||||
}, [message.imgs, handleDeleteImg]);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(event: any) => {
|
||||
if (
|
||||
event.key === 'Backspace' &&
|
||||
message.content === '' &&
|
||||
message.imgs &&
|
||||
message.imgs?.length > 0
|
||||
) {
|
||||
// inputref blur
|
||||
event.preventDefault();
|
||||
handleDeleteLastImage();
|
||||
}
|
||||
},
|
||||
[message, handleDeleteLastImage]
|
||||
);
|
||||
|
||||
const handleSelectPrompt = (list: CurrentMessage[]) => {
|
||||
presetPrompt?.(list);
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleInputChange: handleInputChange
|
||||
}));
|
||||
|
||||
useHotkeys(
|
||||
HotKeys.SUBMIT,
|
||||
(e: any) => {
|
||||
console.log('submit message', loading);
|
||||
e.preventDefault();
|
||||
handleSendMessage();
|
||||
},
|
||||
{
|
||||
enabled: !loading && !isDisabled,
|
||||
enableOnFormTags: focused,
|
||||
preventDefault: true
|
||||
}
|
||||
);
|
||||
useHotkeys(
|
||||
HotKeys.ADD,
|
||||
(e: any) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleAddMessage();
|
||||
},
|
||||
{
|
||||
enabled: !loading,
|
||||
enableOnFormTags: focused,
|
||||
preventDefault: true
|
||||
}
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
HotKeys.FOCUS,
|
||||
() => {
|
||||
inputRef.current?.focus?.({
|
||||
cursor: 'end'
|
||||
});
|
||||
},
|
||||
{ preventDefault: true }
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="messageInput" style={{ ...style }}>
|
||||
<div className="tool-bar">
|
||||
<div className="actions">
|
||||
{
|
||||
<>
|
||||
{actions.includes('role') && (
|
||||
<>
|
||||
<Button
|
||||
type="text"
|
||||
size="middle"
|
||||
onClick={handleToggleRole}
|
||||
icon={<SwapOutlined rotate={90} />}
|
||||
>
|
||||
{intl.formatMessage({ id: `playground.${message.role}` })}
|
||||
</Button>
|
||||
<Divider type="vertical" style={{ margin: 0 }} />
|
||||
</>
|
||||
)}
|
||||
{actions.includes('upload') && message.role === Roles.User && (
|
||||
<UploadImg
|
||||
handleUpdateImgList={handleUpdateImgList}
|
||||
size="middle"
|
||||
onClick={() => handleLayoutChange(option.value)}
|
||||
></Button>
|
||||
</Tooltip>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="actions">
|
||||
{actions.includes('add') && (
|
||||
<Tooltip
|
||||
title={
|
||||
<span>
|
||||
[{KeyMap.ADD.textKeybinding}]{' '}
|
||||
></UploadImg>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
{tools}
|
||||
{actions.includes('check') && (
|
||||
<Checkbox onChange={onCheck} defaultChecked={true}>
|
||||
{checkLabel}
|
||||
</Checkbox>
|
||||
)}
|
||||
{actions.includes('clear') && (
|
||||
<Tooltip
|
||||
title={intl.formatMessage({ id: 'common.button.clear' })}
|
||||
>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<ClearOutlined />}
|
||||
size="middle"
|
||||
onClick={handleClearAll}
|
||||
></Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{actions.includes('layout') && updateLayout && (
|
||||
<>
|
||||
<Divider type="vertical" style={{ margin: 0 }} />
|
||||
{layoutOptions.map((option) => (
|
||||
<Tooltip
|
||||
title={intl.formatMessage({ id: option.tips })}
|
||||
key={option.icon}
|
||||
>
|
||||
<Button
|
||||
key={option.icon}
|
||||
type="text"
|
||||
icon={<IconFont type={option.icon}></IconFont>}
|
||||
size="middle"
|
||||
onClick={() => handleLayoutChange(option.value)}
|
||||
></Button>
|
||||
</Tooltip>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="actions">
|
||||
{actions.includes('add') && (
|
||||
<Tooltip
|
||||
title={
|
||||
<span>
|
||||
[{KeyMap.ADD.textKeybinding}]{' '}
|
||||
{intl.formatMessage({ id: 'common.button.add' })}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Button type="default" size="middle" onClick={handleAddMessage}>
|
||||
{intl.formatMessage({ id: 'common.button.add' })}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Button type="default" size="middle" onClick={handleAddMessage}>
|
||||
{intl.formatMessage({ id: 'common.button.add' })}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!loading ? (
|
||||
<Tooltip
|
||||
title={
|
||||
<span>
|
||||
[{KeyMap.SUBMIT.textKeybinding}]{' '}
|
||||
{intl.formatMessage({ id: 'common.button.submit' })}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!loading ? (
|
||||
<Tooltip
|
||||
title={
|
||||
<span>
|
||||
[{KeyMap.SUBMIT.textKeybinding}]{' '}
|
||||
{intl.formatMessage({ id: 'common.button.submit' })}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Button
|
||||
style={{ width: 46 }}
|
||||
type="primary"
|
||||
onClick={handleSendMessage}
|
||||
size="middle"
|
||||
disabled={isDisabled}
|
||||
>
|
||||
{submitIcon ?? (
|
||||
<SendOutlined rotate={0} className="font-size-14" />
|
||||
)}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Button
|
||||
style={{ width: 46 }}
|
||||
type="primary"
|
||||
onClick={handleSendMessage}
|
||||
onClick={onStop}
|
||||
size="middle"
|
||||
disabled={isDisabled}
|
||||
>
|
||||
{submitIcon ?? (
|
||||
<SendOutlined rotate={0} className="font-size-14" />
|
||||
)}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
icon={
|
||||
<IconFont
|
||||
type="icon-stop1"
|
||||
className="font-size-14"
|
||||
></IconFont>
|
||||
}
|
||||
></Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<ThumbImg
|
||||
dataList={message.imgs || []}
|
||||
onDelete={handleDeleteImg}
|
||||
editable={true}
|
||||
></ThumbImg>
|
||||
<div className="input-box">
|
||||
{actions.includes('paste') ? (
|
||||
<TextArea
|
||||
ref={inputRef}
|
||||
autoSize={{ minRows: 3, maxRows: 8 }}
|
||||
onChange={handleInputChange}
|
||||
value={message.content}
|
||||
size="large"
|
||||
variant="borderless"
|
||||
onFocus={() => setFocused(true)}
|
||||
onBlur={() => setFocused(false)}
|
||||
onPaste={handleOnPaste}
|
||||
></TextArea>
|
||||
) : (
|
||||
<Button
|
||||
style={{ width: 46 }}
|
||||
type="primary"
|
||||
onClick={onStop}
|
||||
size="middle"
|
||||
icon={
|
||||
<IconFont type="icon-stop1" className="font-size-14"></IconFont>
|
||||
}
|
||||
></Button>
|
||||
<TextArea
|
||||
ref={inputRef}
|
||||
autoSize={{
|
||||
minRows: defaultSize.minRows,
|
||||
maxRows: defaultSize.maxRows
|
||||
}}
|
||||
onChange={handleInputChange}
|
||||
value={message.content}
|
||||
size="large"
|
||||
variant="borderless"
|
||||
onFocus={() => setFocused(true)}
|
||||
onBlur={() => setFocused(false)}
|
||||
></TextArea>
|
||||
)}
|
||||
{!message.content && !focused && (
|
||||
<span
|
||||
className="holder"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
placeholer ??
|
||||
intl.formatMessage({ id: 'playground.input.holder' })
|
||||
}}
|
||||
></span>
|
||||
)}
|
||||
</div>
|
||||
<PromptModal
|
||||
open={open}
|
||||
onCancel={() => setOpen(false)}
|
||||
onSelect={handleSelectPrompt}
|
||||
></PromptModal>
|
||||
</div>
|
||||
<ThumbImg
|
||||
dataList={message.imgs || []}
|
||||
onDelete={handleDeleteImg}
|
||||
editable={true}
|
||||
></ThumbImg>
|
||||
<div className="input-box">
|
||||
{actions.includes('paste') ? (
|
||||
<TextArea
|
||||
ref={inputRef}
|
||||
autoSize={{ minRows: 3, maxRows: 8 }}
|
||||
onChange={handleInputChange}
|
||||
value={message.content}
|
||||
size="large"
|
||||
variant="borderless"
|
||||
onFocus={() => setFocused(true)}
|
||||
onBlur={() => setFocused(false)}
|
||||
onPaste={handleOnPaste}
|
||||
></TextArea>
|
||||
) : (
|
||||
<TextArea
|
||||
ref={inputRef}
|
||||
autoSize={{
|
||||
minRows: defaultSize.minRows,
|
||||
maxRows: defaultSize.maxRows
|
||||
}}
|
||||
onChange={handleInputChange}
|
||||
value={message.content}
|
||||
size="large"
|
||||
variant="borderless"
|
||||
onFocus={() => setFocused(true)}
|
||||
onBlur={() => setFocused(false)}
|
||||
></TextArea>
|
||||
)}
|
||||
{!message.content && !focused && (
|
||||
<span
|
||||
className="holder"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
placeholer ??
|
||||
intl.formatMessage({ id: 'playground.input.holder' })
|
||||
}}
|
||||
></span>
|
||||
)}
|
||||
</div>
|
||||
<PromptModal
|
||||
open={open}
|
||||
onCancel={() => setOpen(false)}
|
||||
onSelect={handleSelectPrompt}
|
||||
></PromptModal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default MessageInput;
|
||||
|
||||
Reference in New Issue
Block a user