fix: edit image: image field is null
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
import { KeyMap } from '@/config/hotkeys';
|
import { KeyMap } from '@/config/hotkeys';
|
||||||
import {
|
import {
|
||||||
ClearOutlined,
|
ClearOutlined,
|
||||||
CloseOutlined,
|
|
||||||
DownloadOutlined,
|
DownloadOutlined,
|
||||||
ExpandOutlined,
|
ExpandOutlined,
|
||||||
FormatPainterOutlined,
|
FormatPainterOutlined,
|
||||||
@@ -12,8 +11,10 @@ import { Button, Checkbox, Slider, Tooltip } from 'antd';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, {
|
import React, {
|
||||||
|
forwardRef,
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
|
useImperativeHandle,
|
||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
useState
|
useState
|
||||||
@@ -25,6 +26,7 @@ type Point = { x: number; y: number; lineWidth: number };
|
|||||||
type Stroke = Point[];
|
type Stroke = Point[];
|
||||||
|
|
||||||
type CanvasImageEditorProps = {
|
type CanvasImageEditorProps = {
|
||||||
|
ref?: any;
|
||||||
imageSrc: string;
|
imageSrc: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
imguid: string | number;
|
imguid: string | number;
|
||||||
@@ -43,7 +45,9 @@ type CanvasImageEditorProps = {
|
|||||||
|
|
||||||
const COLOR = 'rgba(0, 0, 255, 0.3)';
|
const COLOR = 'rgba(0, 0, 255, 0.3)';
|
||||||
|
|
||||||
const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
const CanvasImageEditor: React.FC<CanvasImageEditorProps> = forwardRef(
|
||||||
|
(
|
||||||
|
{
|
||||||
imageSrc,
|
imageSrc,
|
||||||
disabled: isDisabled,
|
disabled: isDisabled,
|
||||||
imageStatus,
|
imageStatus,
|
||||||
@@ -53,7 +57,9 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
imguid,
|
imguid,
|
||||||
uploadButton,
|
uploadButton,
|
||||||
maskUpload
|
maskUpload
|
||||||
}) => {
|
},
|
||||||
|
ref
|
||||||
|
) => {
|
||||||
const MIN_SCALE = 0.5;
|
const MIN_SCALE = 0.5;
|
||||||
const MAX_SCALE = 8;
|
const MAX_SCALE = 8;
|
||||||
const ZOOM_SPEED = 0.1;
|
const ZOOM_SPEED = 0.1;
|
||||||
@@ -103,7 +109,9 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
return lineWidth / autoScale.current;
|
return lineWidth / autoScale.current;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const setCanvasTransformOrigin = (e: React.MouseEvent<HTMLCanvasElement>) => {
|
const setCanvasTransformOrigin = (
|
||||||
|
e: React.MouseEvent<HTMLCanvasElement>
|
||||||
|
) => {
|
||||||
if (autoScale.current <= MIN_SCALE) {
|
if (autoScale.current <= MIN_SCALE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -177,7 +185,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
|
|
||||||
offscreenCanvas.width = canvas.width;
|
offscreenCanvas.width = canvas.width;
|
||||||
offscreenCanvas.height = canvas.height;
|
offscreenCanvas.height = canvas.height;
|
||||||
}, [canvasRef.current, overlayCanvasRef.current, offscreenCanvasRef.current]);
|
}, []);
|
||||||
|
|
||||||
const setStrokes = (strokes: Stroke[]) => {
|
const setStrokes = (strokes: Stroke[]) => {
|
||||||
strokesRef.current = strokes;
|
strokesRef.current = strokes;
|
||||||
@@ -456,7 +464,12 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
const offscreenCanvas = offscreenCanvasRef.current!;
|
const offscreenCanvas = offscreenCanvasRef.current!;
|
||||||
const offscreenCtx = offscreenCanvas.getContext('2d')!;
|
const offscreenCtx = offscreenCanvas.getContext('2d')!;
|
||||||
offscreenCtx.resetTransform();
|
offscreenCtx.resetTransform();
|
||||||
offscreenCtx.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
offscreenCtx.clearRect(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
offscreenCanvas.width,
|
||||||
|
offscreenCanvas.height
|
||||||
|
);
|
||||||
const { current: scale } = autoScale;
|
const { current: scale } = autoScale;
|
||||||
const { x: translateX, y: translateY } = translatePos.current;
|
const { x: translateX, y: translateY } = translatePos.current;
|
||||||
offscreenCtx!.setTransform(scale, 0, 0, scale, translateX, translateY);
|
offscreenCtx!.setTransform(scale, 0, 0, scale, translateX, translateY);
|
||||||
@@ -465,8 +478,8 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
const onReset = useCallback(() => {
|
const onReset = useCallback(() => {
|
||||||
clearOverlayCanvas();
|
clearOverlayCanvas();
|
||||||
setStrokes([]);
|
setStrokes([]);
|
||||||
currentStroke.current = [];
|
|
||||||
saveImage();
|
saveImage();
|
||||||
|
currentStroke.current = [];
|
||||||
console.log('Resetting strokes', currentStroke.current);
|
console.log('Resetting strokes', currentStroke.current);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -585,15 +598,15 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
|
|
||||||
// fit the image to the container
|
// fit the image to the container
|
||||||
autoScale.current = autoScale.current || 1;
|
autoScale.current = autoScale.current || 1;
|
||||||
updateCanvasSize();
|
|
||||||
|
|
||||||
|
updateCanvasSize();
|
||||||
clearCanvas();
|
clearCanvas();
|
||||||
|
|
||||||
ctx!.drawImage(img, 0, 0, canvas!.width, canvas!.height);
|
ctx!.drawImage(img, 0, 0, canvas!.width, canvas!.height);
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [imageSrc, containerRef.current, canvasRef.current, updateCanvasSize]);
|
}, [imageSrc]);
|
||||||
|
|
||||||
const resetCanvas = useCallback(() => {
|
const resetCanvas = useCallback(() => {
|
||||||
const canvas = canvasRef.current!;
|
const canvas = canvasRef.current!;
|
||||||
@@ -654,34 +667,46 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const initializeImage = useCallback(async () => {
|
const initializeImage = useCallback(async () => {
|
||||||
if (imguid === preImguid.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await drawImage();
|
await drawImage();
|
||||||
onScaleImageSize?.({
|
onScaleImageSize?.({
|
||||||
width: canvasRef.current!.width,
|
width: canvasRef.current!.width,
|
||||||
height: canvasRef.current!.height
|
height: canvasRef.current!.height
|
||||||
});
|
});
|
||||||
|
|
||||||
if (strokeCache.current[imguid]) {
|
console.log('Image status:', imageStatus, invertMask);
|
||||||
strokeCache.current[preImguid.current] = strokesRef.current;
|
|
||||||
strokesRef.current = strokeCache.current[imguid];
|
if (imageStatus.isResetNeeded) {
|
||||||
} else if (preImguid.current !== imguid) {
|
|
||||||
strokeCache.current[preImguid.current] = strokesRef.current;
|
|
||||||
onReset();
|
onReset();
|
||||||
resetCanvas();
|
resetCanvas();
|
||||||
}
|
} else if (
|
||||||
preImguid.current = imguid;
|
strokesRef.current.length &&
|
||||||
|
imageStatus.isOriginal &&
|
||||||
if (strokesRef.current.length && imageStatus.isOriginal) {
|
!invertMask
|
||||||
|
) {
|
||||||
redrawStrokes(strokesRef.current);
|
redrawStrokes(strokesRef.current);
|
||||||
saveImage();
|
saveImage();
|
||||||
|
} else if (
|
||||||
|
strokesRef.current.length &&
|
||||||
|
imageStatus.isOriginal &&
|
||||||
|
invertMask
|
||||||
|
) {
|
||||||
|
invertPainting(true);
|
||||||
|
saveImage();
|
||||||
}
|
}
|
||||||
updateCursorSize();
|
|
||||||
}, [drawImage, onReset, redrawStrokes, imguid]);
|
|
||||||
|
|
||||||
const updateZoom = (scaleChange: number, mouseX: number, mouseY: number) => {
|
updateCursorSize();
|
||||||
|
}, [
|
||||||
|
drawImage,
|
||||||
|
imageStatus.isOriginal,
|
||||||
|
imageStatus.isResetNeeded,
|
||||||
|
invertMask
|
||||||
|
]);
|
||||||
|
|
||||||
|
const updateZoom = (
|
||||||
|
scaleChange: number,
|
||||||
|
mouseX: number,
|
||||||
|
mouseY: number
|
||||||
|
) => {
|
||||||
const newScale = _.round(autoScale.current + scaleChange, 2);
|
const newScale = _.round(autoScale.current + scaleChange, 2);
|
||||||
|
|
||||||
if (newScale < MIN_SCALE || newScale > MAX_SCALE) return;
|
if (newScale < MIN_SCALE || newScale > MAX_SCALE) return;
|
||||||
@@ -789,11 +814,15 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDeleteMask = () => {
|
const handleDeleteMask = () => {
|
||||||
clearUploadMask?.();
|
|
||||||
setInvertMask(false);
|
setInvertMask(false);
|
||||||
redrawStrokes(strokesRef.current);
|
redrawStrokes(strokesRef.current);
|
||||||
|
saveImage();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
clearMask: handleDeleteMask
|
||||||
|
}));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (maskUpload?.length) {
|
if (maskUpload?.length) {
|
||||||
// clear the overlay canvas
|
// clear the overlay canvas
|
||||||
@@ -801,6 +830,12 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
}
|
}
|
||||||
}, [maskUpload]);
|
}, [maskUpload]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (disabled && cursorRef.current) {
|
||||||
|
cursorRef.current!.style.display = 'none';
|
||||||
|
}
|
||||||
|
}, [disabled]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="editor-wrapper">
|
<div className="editor-wrapper">
|
||||||
<div className="flex-between">
|
<div className="flex-between">
|
||||||
@@ -884,23 +919,22 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
<span className="flex-center upload-mask">
|
<span className="flex-center upload-mask">
|
||||||
<span className="font-size-12">
|
<span className="font-size-12">
|
||||||
{intl.formatMessage({ id: 'playground.image.mask.uploaded' })}
|
{intl.formatMessage({ id: 'playground.image.mask.uploaded' })}
|
||||||
...
|
|
||||||
</span>
|
</span>
|
||||||
<Button
|
|
||||||
onClick={handleDeleteMask}
|
|
||||||
size="small"
|
|
||||||
type="text"
|
|
||||||
icon={<CloseOutlined className="close-btn"></CloseOutlined>}
|
|
||||||
></Button>
|
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{imageStatus.isOriginal && (
|
{imageStatus.isOriginal && (
|
||||||
<>
|
<>
|
||||||
|
<Tooltip
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'playground.image.negativeMask.tips'
|
||||||
|
})}
|
||||||
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
onChange={handleOnChangeMask}
|
onChange={handleOnChangeMask}
|
||||||
className="flex-center"
|
className="flex-center"
|
||||||
value={invertMask}
|
checked={invertMask}
|
||||||
|
disabled={isDisabled || !!maskUpload?.length}
|
||||||
>
|
>
|
||||||
<span className="font-size-12">
|
<span className="font-size-12">
|
||||||
{intl.formatMessage({
|
{intl.formatMessage({
|
||||||
@@ -908,6 +942,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
|
</Tooltip>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
id: 'playground.image.saveMask'
|
id: 'playground.image.saveMask'
|
||||||
@@ -924,6 +959,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{!imageStatus.isOriginal && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={intl.formatMessage({ id: 'playground.image.download' })}
|
title={intl.formatMessage({ id: 'playground.image.download' })}
|
||||||
>
|
>
|
||||||
@@ -931,6 +967,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
<DownloadOutlined className="font-size-14" />
|
<DownloadOutlined className="font-size-14" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -970,7 +1007,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
<div
|
<div
|
||||||
ref={cursorRef}
|
ref={cursorRef}
|
||||||
style={{
|
style={{
|
||||||
display: disabled ? 'none' : 'block',
|
display: 'none',
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
width: lineWidth * activeScale,
|
width: lineWidth * activeScale,
|
||||||
height: lineWidth * activeScale,
|
height: lineWidth * activeScale,
|
||||||
@@ -984,6 +1021,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export default React.memo(CanvasImageEditor);
|
export default React.memo(CanvasImageEditor);
|
||||||
|
|||||||
@@ -141,9 +141,12 @@ export default {
|
|||||||
'playground.image.fitview': 'Fit View',
|
'playground.image.fitview': 'Fit View',
|
||||||
'playground.chat.aithought': 'CoT',
|
'playground.chat.aithought': 'CoT',
|
||||||
'playground.image.mask.uploaded': 'Mask Uploaded',
|
'playground.image.mask.uploaded': 'Mask Uploaded',
|
||||||
'playground.image.mask.upload': 'Upload Mask: takes priority in submission.',
|
'playground.image.mask.upload':
|
||||||
|
'Upload Mask: No additional drawing allowed after upload.',
|
||||||
'playground.params.frequency_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.`,
|
'playground.params.frequency_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.`,
|
||||||
'playground.params.presence_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.`,
|
'playground.params.presence_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.`,
|
||||||
'playground.image.origin': 'Original',
|
'playground.image.origin': 'Original',
|
||||||
'playground.image.mask': 'Mask'
|
'playground.image.mask': 'Mask',
|
||||||
|
'playground.image.negativeMask.tips':
|
||||||
|
'After selection, no further masking can be drawn; therefore, you should draw the mask first and then check the option.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -138,9 +138,12 @@ export default {
|
|||||||
'playground.image.fitview': 'Подогнать размер',
|
'playground.image.fitview': 'Подогнать размер',
|
||||||
'playground.chat.aithought': 'Рассуждение (CoT)',
|
'playground.chat.aithought': 'Рассуждение (CoT)',
|
||||||
'playground.image.mask.uploaded': 'Маска загружена',
|
'playground.image.mask.uploaded': 'Маска загружена',
|
||||||
'playground.image.mask.upload':'Загрузить маску: имеет приоритет при отправке',
|
'playground.image.mask.upload':
|
||||||
|
'TODO: Translate key "playground.image.mask.upload"',
|
||||||
'playground.params.frequency_penalty.tips': `Число от -2.0 до 2.0. Положительные значения снижают вероятность повторения токенов, уже часто встречающихся в тексте, уменьшая склонность модели дословно повторять одни и те же фразы.`,
|
'playground.params.frequency_penalty.tips': `Число от -2.0 до 2.0. Положительные значения снижают вероятность повторения токенов, уже часто встречающихся в тексте, уменьшая склонность модели дословно повторять одни и те же фразы.`,
|
||||||
'playground.params.presence_penalty.tips': `Число от -2.0 до 2.0. Положительные значения снижают вероятность повторения любых токенов, присутствующих в тексте, повышая склонность модели к обсуждению новых тем.`,
|
'playground.params.presence_penalty.tips': `Число от -2.0 до 2.0. Положительные значения снижают вероятность повторения любых токенов, присутствующих в тексте, повышая склонность модели к обсуждению новых тем.`,
|
||||||
'playground.image.origin': 'Оригинал',
|
'playground.image.origin': 'Оригинал',
|
||||||
'playground.image.mask': 'Маска'
|
'playground.image.mask': 'Маска',
|
||||||
|
'playground.image.negativeMask.tips':
|
||||||
|
'TODO: Translate key "playground.image.negativeMask.tips"'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -136,9 +136,11 @@ export default {
|
|||||||
'playground.image.fitview': '适应视图',
|
'playground.image.fitview': '适应视图',
|
||||||
'playground.chat.aithought': '思考过程',
|
'playground.chat.aithought': '思考过程',
|
||||||
'playground.image.mask.uploaded': '遮罩已上传',
|
'playground.image.mask.uploaded': '遮罩已上传',
|
||||||
'playground.image.mask.upload': '上传遮罩:在提交时优先使用',
|
'playground.image.mask.upload': '上传遮罩:上传后将不可再绘制',
|
||||||
'playground.params.frequency_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词在文本中已出现的频率对其进行惩罚,从而降低模型逐字重复相同内容的可能性。`,
|
'playground.params.frequency_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词在文本中已出现的频率对其进行惩罚,从而降低模型逐字重复相同内容的可能性。`,
|
||||||
'playground.params.presence_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词是否已在文本中出现过对其进行惩罚,从而增加模型谈论新话题的可能性。`,
|
'playground.params.presence_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词是否已在文本中出现过对其进行惩罚,从而增加模型谈论新话题的可能性。`,
|
||||||
'playground.image.origin': '原图',
|
'playground.image.origin': '原图',
|
||||||
'playground.image.mask': '遮罩'
|
'playground.image.mask': '遮罩',
|
||||||
|
'playground.image.negativeMask.tips':
|
||||||
|
'选择后,将不可再绘制遮罩;因此,你应该先绘制遮罩然后再勾选'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
});
|
});
|
||||||
const doneImage = useRef<boolean>(false);
|
const doneImage = useRef<boolean>(false);
|
||||||
const [activeImgUid, setActiveImgUid] = useState<number>(0);
|
const [activeImgUid, setActiveImgUid] = useState<number>(0);
|
||||||
|
const imageEditorRef = useRef<any>(null);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handleOnValuesChange,
|
handleOnValuesChange,
|
||||||
@@ -110,9 +111,8 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const imageFile = useMemo(() => {
|
const imageFile = useMemo(() => {
|
||||||
if (!image) return null;
|
return base64ToFile(uploadList[0]?.dataUrl, 'image');
|
||||||
return base64ToFile(image, 'image');
|
}, [uploadList]);
|
||||||
}, [image]);
|
|
||||||
|
|
||||||
const maskFile = useMemo(() => {
|
const maskFile = useMemo(() => {
|
||||||
if (!mask) return null;
|
if (!mask) return null;
|
||||||
@@ -123,7 +123,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
if (parameters.size === 'custom') {
|
if (parameters.size === 'custom') {
|
||||||
return {
|
return {
|
||||||
..._.omit(parameters, ['width', 'height', 'preview', 'random_seed']),
|
..._.omit(parameters, ['width', 'height', 'preview', 'random_seed']),
|
||||||
image: imageFile,
|
image: base64ToFile(image, 'image'),
|
||||||
mask: maskFile,
|
mask: maskFile,
|
||||||
size:
|
size:
|
||||||
parameters.width && parameters.height
|
parameters.width && parameters.height
|
||||||
@@ -279,6 +279,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
const handleClearUploadMask = useCallback(() => {
|
const handleClearUploadMask = useCallback(() => {
|
||||||
setMaskUpload([]);
|
setMaskUpload([]);
|
||||||
setMask(null);
|
setMask(null);
|
||||||
|
imageEditorRef.current?.clearMask();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleOnSave = useCallback(
|
const handleOnSave = useCallback(
|
||||||
@@ -299,6 +300,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
if (image) {
|
if (image) {
|
||||||
return (
|
return (
|
||||||
<CanvasImageEditor
|
<CanvasImageEditor
|
||||||
|
ref={imageEditorRef}
|
||||||
imguid={activeImgUid}
|
imguid={activeImgUid}
|
||||||
imageStatus={imageStatus}
|
imageStatus={imageStatus}
|
||||||
imageSrc={image}
|
imageSrc={image}
|
||||||
@@ -361,7 +363,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const handleOnImgClick = useCallback((item: any, isOrigin: boolean) => {
|
const handleOnImgClick = useCallback((item: any, isOrigin: boolean) => {
|
||||||
if (item.progress < 100) {
|
if (item.progress < 100 && !isOrigin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setActiveImgUid(item.uid);
|
setActiveImgUid(item.uid);
|
||||||
@@ -421,8 +423,9 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
preview={false}
|
preview={false}
|
||||||
loading={false}
|
loading={false}
|
||||||
autoSize={false}
|
autoSize={false}
|
||||||
editable={false}
|
editable={true}
|
||||||
autoBgColor={false}
|
autoBgColor={false}
|
||||||
|
onDelete={() => handleClearUploadMask()}
|
||||||
label={
|
label={
|
||||||
<span>{intl.formatMessage({ id: 'playground.image.mask' })}</span>
|
<span>{intl.formatMessage({ id: 'playground.image.mask' })}</span>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ export default function useTextImage(props: any) {
|
|||||||
|
|
||||||
const handleStopConversation = () => {
|
const handleStopConversation = () => {
|
||||||
requestToken.current?.abort?.();
|
requestToken.current?.abort?.();
|
||||||
|
setImageList([]);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,12 @@ const AddWorker: React.FC<ViewModalProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
)}
|
)}
|
||||||
<HighlightCode theme="dark" code={code} lang="bash"></HighlightCode>
|
<HighlightCode
|
||||||
|
theme="dark"
|
||||||
|
code={code}
|
||||||
|
lang="bash"
|
||||||
|
height={130}
|
||||||
|
></HighlightCode>
|
||||||
<h3 className="m-b-0 m-t-10">
|
<h3 className="m-b-0 m-t-10">
|
||||||
3. {intl.formatMessage({ id: 'resources.worker.add.step3' })}
|
3. {intl.formatMessage({ id: 'resources.worker.add.step3' })}
|
||||||
</h3>
|
</h3>
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export const addWorkerGuide: Record<string, any> = {
|
|||||||
return `docker run -d --name gpustack-worker --restart=unless-stopped --gpus all -p 10150:10150 -p 40000-41024:40000-41024 -p 50000-51024:50000-51024 --ipc=host -v gpustack-worker-data:/var/lib/gpustack gpustack/gpustack:${params.tag} --server-url ${params.server} --token ${params.token} --worker-ip ${params.workerip}`;
|
return `docker run -d --name gpustack-worker --restart=unless-stopped --gpus all -p 10150:10150 -p 40000-41024:40000-41024 -p 50000-51024:50000-51024 --ipc=host -v gpustack-worker-data:/var/lib/gpustack gpustack/gpustack:${params.tag} --server-url ${params.server} --token ${params.token} --worker-ip ${params.workerip}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
npu: {
|
npu: {
|
||||||
getToken:
|
getToken:
|
||||||
'Get-Content -Path (Join-Path -Path $env:APPDATA -ChildPath "gpustack\\token") -Raw',
|
'Get-Content -Path (Join-Path -Path $env:APPDATA -ChildPath "gpustack\\token") -Raw',
|
||||||
@@ -53,7 +54,31 @@ export const addWorkerGuide: Record<string, any> = {
|
|||||||
token: string;
|
token: string;
|
||||||
workerip: string;
|
workerip: string;
|
||||||
}) {
|
}) {
|
||||||
return `docker run -d --name gpustack-worker --restart=unless-stopped -e ASCEND_VISIBLE_DEVICES=0 -p 10150:10150 -p 40000-41024:40000-41024 -p 50000-51024:50000-51024 --ipc=host -v gpustack-worker-data:/var/lib/gpustack gpustack/gpustack:${params.tag} --server-url ${params.server} --token ${params.token} --worker-ip ${params.workerip}`;
|
return `docker run -d --name gpustack-worker \\
|
||||||
|
--restart=unless-stopped \\
|
||||||
|
--device /dev/davinci0 \\
|
||||||
|
--device /dev/davinci1 \\
|
||||||
|
--device /dev/davinci2 \\
|
||||||
|
--device /dev/davinci3 \\
|
||||||
|
--device /dev/davinci4 \\
|
||||||
|
--device /dev/davinci5 \\
|
||||||
|
--device /dev/davinci6 \\
|
||||||
|
--device /dev/davinci7 \\
|
||||||
|
--device /dev/davinci_manager \\
|
||||||
|
--device /dev/devmm_svm \\
|
||||||
|
--device /dev/hisi_hdc \\
|
||||||
|
-v /usr/local/dcmi:/usr/local/dcmi \\
|
||||||
|
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \\
|
||||||
|
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \\
|
||||||
|
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \\
|
||||||
|
-v /etc/ascend_install.info:/etc/ascend_install.info \\
|
||||||
|
-p 10150:10150 \\
|
||||||
|
-p 40000-41024:40000-41024 \\
|
||||||
|
-p 50000-51024:50000-51024 \\
|
||||||
|
--ipc=host \\
|
||||||
|
-v gpustack-worker-data:/var/lib/gpustack \\
|
||||||
|
gpustack/gpustack:${params.tag} \\
|
||||||
|
--server-url ${params.server} --token ${params.token} --worker-ip ${params.workerip}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
musa: {
|
musa: {
|
||||||
|
|||||||
Reference in New Issue
Block a user