diff --git a/src/components/icon-font/index.tsx b/src/components/icon-font/index.tsx index c31ffbe4..54c73cd6 100644 --- a/src/components/icon-font/index.tsx +++ b/src/components/icon-font/index.tsx @@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons'; // import './iconfont/iconfont.js'; const IconFont = createFromIconfontCN({ - scriptUrl: '//at.alicdn.com/t/c/font_4613488_djdkmiu9k3b.js' + scriptUrl: '//at.alicdn.com/t/c/font_4613488_pr3u3llgke.js' }); export default IconFont; diff --git a/src/components/image-editor/index.less b/src/components/image-editor/index.less index a201c70b..875eed40 100644 --- a/src/components/image-editor/index.less +++ b/src/components/image-editor/index.less @@ -20,4 +20,16 @@ .overlay-canvas:hover { cursor: 'none !important'; } + + .upload-mask { + &:hover { + .close-btn { + display: block; + } + } + } + + .close-btn { + display: none; + } } diff --git a/src/components/image-editor/index.tsx b/src/components/image-editor/index.tsx index 4b76696b..01fe0baa 100644 --- a/src/components/image-editor/index.tsx +++ b/src/components/image-editor/index.tsx @@ -1,8 +1,9 @@ import { + ClearOutlined, + CloseOutlined, DownloadOutlined, ExpandOutlined, FormatPainterOutlined, - SyncOutlined, UndoOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; @@ -20,6 +21,8 @@ type CanvasImageEditorProps = { imageSrc: string; disabled?: boolean; imguid: string | number; + maskUpload?: any[]; + clearUploadMask?: () => void; onSave: (imageData: { mask: string | null; img: string }) => void; onScaleImageSize?: (data: { width: number; height: number }) => void; uploadButton: React.ReactNode; @@ -37,10 +40,12 @@ const CanvasImageEditor: React.FC = ({ imageSrc, disabled, imageStatus, + clearUploadMask, onSave, onScaleImageSize, imguid, - uploadButton + uploadButton, + maskUpload }) => { const MIN_SCALE = 0.5; const MAX_SCALE = 8; @@ -52,20 +57,18 @@ const CanvasImageEditor: React.FC = ({ const [lineWidth, setLineWidth] = useState(60); const isDrawing = useRef(false); const currentStroke = useRef([]); - const resizeObserver = useRef(null); const strokesRef = useRef([]); const offscreenCanvasRef = useRef(null); const autoScale = useRef(1); const baseScale = useRef(1); const cursorRef = useRef(null); - const [imgLoaded, setImgLoaded] = useState(false); const translatePos = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); const contentPos = useRef<{ x: number; y: number }>({ x: 0, y: 0 }); - const animationFrameIdRef = useRef(null); const strokeCache = useRef({}); const preImguid = useRef(''); const [activeScale, setActiveScale] = useState(1); const negativeMaskRef = useRef(false); + const mouseDownState = useRef(false); const getTransformedPoint = useCallback( (offsetX: number, offsetY: number) => { @@ -110,10 +113,14 @@ const CanvasImageEditor: React.FC = ({ }; const handleMouseEnter = (e: React.MouseEvent) => { + console.log('mouse enter:', mouseDownState.current); if (disabled) { overlayCanvasRef.current!.style.cursor = 'default'; return; } + // if (mouseDownState.current) { + // isDrawing.current = true; + // } overlayCanvasRef.current!.style.cursor = 'none'; cursorRef.current!.style.display = 'block'; cursorRef.current!.style.top = `${e.clientY - (lineWidth / 2) * autoScale.current}px`; @@ -134,6 +141,7 @@ const CanvasImageEditor: React.FC = ({ if (disabled) { return; } + isDrawing.current = false; overlayCanvasRef.current!.style.cursor = 'default'; cursorRef.current!.style.display = 'none'; }; @@ -335,12 +343,18 @@ const CanvasImageEditor: React.FC = ({ if (disabled) { return; } - if (!isDrawing.current) return; + console.log( + 'Drawing:', + isDrawing.current, + currentStroke.current, + strokesRef.current + ); + if (!isDrawing.current || !mouseDownState.current) return; const { offsetX, offsetY } = e.nativeEvent; const currentX = offsetX; const currentY = offsetY; - + console.log('currentStroke:', currentStroke.current); currentStroke.current.push({ x: currentX, y: currentY, @@ -369,6 +383,7 @@ const CanvasImageEditor: React.FC = ({ if (disabled) { return; } + isDrawing.current = true; currentStroke.current = []; @@ -393,7 +408,6 @@ const CanvasImageEditor: React.FC = ({ }; const endDrawing = (e: React.MouseEvent) => { - console.log('End Drawing:', e); if (disabled) { return; } @@ -401,6 +415,8 @@ const CanvasImageEditor: React.FC = ({ return; } + console.log('End Drawing:', e); + isDrawing.current = false; strokesRef.current.push(_.cloneDeep(currentStroke.current)); @@ -440,9 +456,9 @@ const CanvasImageEditor: React.FC = ({ const onReset = useCallback(() => { clearOverlayCanvas(); - console.log('Resetting strokes'); setStrokes([]); currentStroke.current = []; + console.log('Resetting strokes', currentStroke.current); }, []); const redrawStrokes = useCallback( @@ -599,13 +615,11 @@ const CanvasImageEditor: React.FC = ({ return; } - setImgLoaded(false); await drawImage(); onScaleImageSize?.({ width: canvasRef.current!.width, height: canvasRef.current!.height }); - setImgLoaded(true); if (strokeCache.current[imguid]) { strokeCache.current[preImguid.current] = strokesRef.current; @@ -616,12 +630,16 @@ const CanvasImageEditor: React.FC = ({ resetCanvas(); } preImguid.current = imguid; - - if (strokesRef.current.length) { + console.log( + 'Image initialized:', + strokesRef.current.length, + imageStatus.isOriginal + ); + if (strokesRef.current.length && imageStatus.isOriginal) { redrawStrokes(strokesRef.current); + saveImage(); } updateCursorSize(); - saveImage(); }, [drawImage, onReset, redrawStrokes, imguid]); const updateZoom = (scaleChange: number, mouseX: number, mouseY: number) => { @@ -707,12 +725,24 @@ const CanvasImageEditor: React.FC = ({ } }; + const handleMouseDown = (e: MouseEvent) => { + mouseDownState.current = true; + }; + + const handleMouseUp = (e: MouseEvent) => { + mouseDownState.current = false; + }; + window.addEventListener('keydown', handleUndoShortcut); + // mouse down + window.addEventListener('mousedown', handleMouseDown); + + // mouse up + window.addEventListener('mouseup', handleMouseUp); return () => { window.removeEventListener('keydown', handleUndoShortcut); - if (animationFrameIdRef.current !== null) { - cancelAnimationFrame(animationFrameIdRef.current); - } + window.removeEventListener('mousedown', handleMouseDown); + window.removeEventListener('mouseup', handleMouseUp); }; }, []); @@ -769,17 +799,17 @@ const CanvasImageEditor: React.FC = ({ - {uploadButton} - + + {uploadButton} @@ -794,22 +824,50 @@ const CanvasImageEditor: React.FC = ({
- - - {intl.formatMessage({ id: 'playground.image.negativeMask' })} + {maskUpload?.length ? ( + + + {intl.formatMessage({ id: 'playground.image.mask.uploaded' })} + ... + + - - - - + ) : ( + <> + {imageStatus.isOriginal && ( + <> + + + {intl.formatMessage({ + id: 'playground.image.negativeMask' + })} + + + + + + + )} + + )} @@ -834,8 +892,14 @@ const CanvasImageEditor: React.FC = ({ ref={overlayCanvasRef} className="overlay-canvas" style={{ position: 'absolute', zIndex: 10, cursor: 'none' }} - onMouseDown={startDrawing} - onMouseUp={endDrawing} + onMouseDown={(event) => { + mouseDownState.current = true; + startDrawing(event); + }} + onMouseUp={(event) => { + mouseDownState.current = false; + endDrawing(event); + }} onMouseEnter={handleMouseEnter} onWheel={handleOnWheel} onMouseMove={(e) => { @@ -843,8 +907,8 @@ const CanvasImageEditor: React.FC = ({ draw(e); }} onMouseLeave={(e) => { - handleMouseLeave(); endDrawing(e); + handleMouseLeave(); }} />
= forwardRef((props, ref) => { const chunkRequedtRef = useRef(null); const [logs, setLogs] = useState([]); const logParseWorker = useRef(null); - const tail = useRef(pageSize - 1); + const tail = useRef(defaultTail); const [loading, setLoading] = useState(false); const [isAtTop, setIsAtTop] = useState(false); const [scrollPos, setScrollPos] = useState([]); diff --git a/src/hooks/use-body-scroll.ts b/src/hooks/use-body-scroll.ts index bd471459..c9b0164b 100644 --- a/src/hooks/use-body-scroll.ts +++ b/src/hooks/use-body-scroll.ts @@ -43,7 +43,7 @@ export default function useBodyScroll() { y: 'scroll' } }); - }, 1000); + }, 500); }, []); React.useEffect(() => { diff --git a/src/hooks/use-chunk-fetch.ts b/src/hooks/use-chunk-fetch.ts index debe7f25..7fcac4b4 100644 --- a/src/hooks/use-chunk-fetch.ts +++ b/src/hooks/use-chunk-fetch.ts @@ -7,7 +7,6 @@ interface RequestConfig { handler: (data: any) => any; beforeReconnect?: () => void; params?: object; - byLine?: boolean; watch?: boolean; contentType?: 'json' | 'text'; } @@ -16,8 +15,6 @@ const useSetChunkFetch = () => { const axiosToken = useRef(null); const requestConfig = useRef({}); const chunkDataRef = useRef([]); - const bufferCacheRef = useRef(''); - const readTextEventStreamData = async ( reader: ReadableStreamDefaultReader, decoder: TextDecoder, @@ -74,7 +71,6 @@ const useSetChunkFetch = () => { url, handler, watch, - byLine = false, params = {} }: RequestConfig) => { axiosToken.current?.abort?.(); diff --git a/src/locales/en-US/playground.ts b/src/locales/en-US/playground.ts index 22ae7f8c..c3dfbc81 100644 --- a/src/locales/en-US/playground.ts +++ b/src/locales/en-US/playground.ts @@ -139,5 +139,7 @@ export default { 'playground.image.generate': 'Generate', 'playground.image.edit': 'Edit', 'playground.image.fitview': 'Fit View', - 'playground.chat.aithought': 'CoT' + 'playground.chat.aithought': 'CoT', + 'playground.image.mask.uploaded': 'Mask Uploaded', + 'playground.image.mask.upload': 'Upload Mask' }; diff --git a/src/locales/zh-CN/playground.ts b/src/locales/zh-CN/playground.ts index b39e8fa8..8f03a585 100644 --- a/src/locales/zh-CN/playground.ts +++ b/src/locales/zh-CN/playground.ts @@ -134,5 +134,7 @@ export default { 'playground.image.generate': '生成图片', 'playground.image.edit': '编辑图片', 'playground.image.fitview': '适应视图', - 'playground.chat.aithought': '思考过程' + 'playground.chat.aithought': '思考过程', + 'playground.image.mask.uploaded': '遮罩已上传', + 'playground.image.mask.upload': '上传遮罩' }; diff --git a/src/pages/llmodels/components/table-list.tsx b/src/pages/llmodels/components/table-list.tsx index cea2e54b..984327b8 100644 --- a/src/pages/llmodels/components/table-list.tsx +++ b/src/pages/llmodels/components/table-list.tsx @@ -479,7 +479,7 @@ const Models: React.FC = ({ modelId: row.model_id, tail: InstanceRealtimeLogStatus.includes(row.state) ? undefined - : PageSize + : PageSize - 1 }); setOpenLogModal(true); onViewLogs(); @@ -840,21 +840,6 @@ const Models: React.FC = ({ {intl?.formatMessage?.({ id: 'models.button.deploy' })} - - - + + + } > diff --git a/src/pages/llmodels/config/index.ts b/src/pages/llmodels/config/index.ts index f8253147..3fbae452 100644 --- a/src/pages/llmodels/config/index.ts +++ b/src/pages/llmodels/config/index.ts @@ -198,7 +198,8 @@ export const InstanceStatusMap = { export const InstanceRealtimeLogStatus = [ InstanceStatusMap.Downloading, - InstanceStatusMap.Initializing + InstanceStatusMap.Initializing, + InstanceStatusMap.Starting ]; export const InstanceStatusMapValue = { diff --git a/src/pages/playground/components/image-edit.tsx b/src/pages/playground/components/image-edit.tsx index ddf7ceda..f862b2bb 100644 --- a/src/pages/playground/components/image-edit.tsx +++ b/src/pages/playground/components/image-edit.tsx @@ -125,6 +125,7 @@ const GroundImages: React.FC = forwardRef((props, ref) => { const [image, setImage] = useState(''); const [mask, setMask] = useState(null); const [uploadList, setUploadList] = useState([]); + const [maskUpload, setMaskUpload] = useState([]); const [modelMeta, setModelMeta] = useState({}); const [imageStatus, setImageStatus] = useState<{ isOriginal: boolean; @@ -299,15 +300,14 @@ const GroundImages: React.FC = forwardRef((props, ref) => { setMessageId(); setTokenResult(null); setCurrentPrompt(current?.content || ''); - setUploadList((pre) => { - return pre.map((item) => { - return { - ...item, - uid: activeImgUid, - dataUrl: image - }; - }); - }); + // setUploadList((pre) => { + // return pre.map((item) => { + // return { + // ...item, + // uid: activeImgUid + // }; + // }); + // }); setRouteCache(routeCachekey['/playground/text-to-image'], true); const imgSize = _.split(finalParameters.size, 'x').map((item: string) => @@ -659,11 +659,12 @@ const GroundImages: React.FC = forwardRef((props, ref) => { const handleUpdateImageList = useCallback((base64List: any) => { const currentImg = _.get(base64List, '[0]', {}); const img = _.get(currentImg, 'dataUrl', ''); + handleOnScaleImageSize(currentImg); setUploadList(base64List); setImage(img); setActiveImgUid(_.get(base64List, '[0].uid', '')); setImageStatus({ - isOriginal: false, + isOriginal: true, isResetNeeded: true, width: _.get(currentImg, 'width', 512), height: _.get(currentImg, 'height', 512) @@ -671,6 +672,17 @@ const GroundImages: React.FC = forwardRef((props, ref) => { setImageList([]); }, []); + const handleUpdateMaskList = useCallback((base64List: any) => { + setMaskUpload(base64List); + const mask = _.get(base64List, '[0].dataUrl', ''); + setMask(mask); + }, []); + + const handleClearUploadMask = useCallback(() => { + setMaskUpload([]); + setMask(null); + }, []); + const handleOnSave = useCallback( (data: { img: string; mask: string | null }) => { setImageStatus((pre) => { @@ -680,7 +692,7 @@ const GroundImages: React.FC = forwardRef((props, ref) => { }; }); setMask(data.mask || null); - setImage(data.img); + setImage(data.img || maskUpload[0]?.dataUrl || null); }, [] ); @@ -692,17 +704,29 @@ const GroundImages: React.FC = forwardRef((props, ref) => { imguid={activeImgUid} imageStatus={imageStatus} imageSrc={image} - disabled={loading} + disabled={loading || !imageStatus.isOriginal} onSave={handleOnSave} + clearUploadMask={handleClearUploadMask} + maskUpload={maskUpload} uploadButton={ - + <> + } + disabled={loading} + handleUpdateImgList={handleUpdateMaskList} + size="middle" + accept="image/*" > - + } > ); @@ -728,7 +752,14 @@ const GroundImages: React.FC = forwardRef((props, ref) => { ); - }, [image, loading, imageStatus, handleOnSave, handleUpdateImageList]); + }, [ + image, + loading, + maskUpload, + imageStatus, + handleOnSave, + handleUpdateImageList + ]); const handleOnImgClick = useCallback((item: any, isOrigin: boolean) => { if (item.progress < 100) { @@ -909,7 +940,11 @@ const GroundImages: React.FC = forwardRef((props, ref) => { overflow: 'hidden' }} > -
+
= forwardRef((props, ref) => { placeholer={intl.formatMessage({ id: 'playground.input.prompt.holder' })} - actions={['clear']} + actions={[]} title={ {intl.formatMessage({ id: 'playground.image.prompt' })} diff --git a/src/pages/playground/components/upload-img.tsx b/src/pages/playground/components/upload-img.tsx index 72a5cc0c..ddc35e6e 100644 --- a/src/pages/playground/components/upload-img.tsx +++ b/src/pages/playground/components/upload-img.tsx @@ -14,6 +14,8 @@ interface UploadImgProps { disabled?: boolean; children?: React.ReactNode; accept?: string; + icon?: React.ReactNode; + title?: React.ReactNode; handleUpdateImgList: ( imgList: { dataUrl: string; @@ -30,6 +32,8 @@ const UploadImg: React.FC = ({ drag = false, disabled = false, children, + icon, + title, accept = 'image/*', size = 'small' }) => { @@ -135,13 +139,15 @@ const UploadImg: React.FC = ({ > {children ?? ( )} @@ -158,13 +164,15 @@ const UploadImg: React.FC = ({ > {children ?? ( )} diff --git a/src/pages/playground/config/index.ts b/src/pages/playground/config/index.ts index 8e435f68..5fe1295d 100644 --- a/src/pages/playground/config/index.ts +++ b/src/pages/playground/config/index.ts @@ -166,3 +166,11 @@ export const extractErrorMessage = (result: any) => { '' ); }; + +export const scaleImageSize = (size: { width: number; height: number }) => { + const { width, height } = size; + const scale = 64; + const newWidth = Math.floor(width / scale) * scale; + const newHeight = Math.floor(height / scale) * scale; + return { width: newWidth, height: newHeight }; +};