修复DMXAPI文生成画bug

This commit is contained in:
w 2025-05-25 00:42:37 +08:00 committed by 亢奋猫
parent 2f312d68a0
commit adef817e86
2 changed files with 36 additions and 71 deletions

View File

@ -3,7 +3,7 @@ import FileManager from '@renderer/services/FileManager'
import { Painting } from '@renderer/types' import { Painting } from '@renderer/types'
import { download } from '@renderer/utils/download' import { download } from '@renderer/utils/download'
import { Button, Dropdown, Spin } from 'antd' import { Button, Dropdown, Spin } from 'antd'
import { FC } from 'react' import React, { FC } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import styled from 'styled-components' import styled from 'styled-components'
@ -17,6 +17,7 @@ interface ArtboardProps {
onNextImage: () => void onNextImage: () => void
onCancel: () => void onCancel: () => void
retry?: (painting: Painting) => void retry?: (painting: Painting) => void
imageCover?: React.ReactNode
} }
const Artboard: FC<ArtboardProps> = ({ const Artboard: FC<ArtboardProps> = ({
@ -26,7 +27,8 @@ const Artboard: FC<ArtboardProps> = ({
onPrevImage, onPrevImage,
onNextImage, onNextImage,
onCancel, onCancel,
retry retry,
imageCover
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
@ -108,8 +110,10 @@ const Artboard: FC<ArtboardProps> = ({
</div> </div>
</div> </div>
) : ( ) : (
<div>{t('paintings.image_placeholder')}</div> imageCover ?
)} imageCover:
(<div>{t('paintings.image_placeholder')}</div>)
)}
</ImagePlaceholder> </ImagePlaceholder>
)} )}
{isLoading && ( {isLoading && (

View File

@ -9,9 +9,7 @@ import { useTheme } from '@renderer/context/ThemeProvider'
import { usePaintings } from '@renderer/hooks/usePaintings' import { usePaintings } from '@renderer/hooks/usePaintings'
import { useAllProviders } from '@renderer/hooks/useProvider' import { useAllProviders } from '@renderer/hooks/useProvider'
import { useRuntime } from '@renderer/hooks/useRuntime' import { useRuntime } from '@renderer/hooks/useRuntime'
import { useSettings } from '@renderer/hooks/useSettings'
import FileManager from '@renderer/services/FileManager' import FileManager from '@renderer/services/FileManager'
import { translateText } from '@renderer/services/TranslateService'
import { useAppDispatch } from '@renderer/store' import { useAppDispatch } from '@renderer/store'
import { setGenerating } from '@renderer/store/runtime' import { setGenerating } from '@renderer/store/runtime'
import type { FileType, PaintingsState } from '@renderer/types' import type { FileType, PaintingsState } from '@renderer/types'
@ -176,7 +174,7 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
} }
// API请求函数 // API请求函数
const callApi = async (requestConfig: { endpoint: string; body: any }) => { const callApi = async (requestConfig: { endpoint: string; body: any }, controller: AbortController) => {
const { endpoint, body } = requestConfig const { endpoint, body } = requestConfig
const headers = {} const headers = {}
@ -191,7 +189,8 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
const response = await fetch(endpoint, { const response = await fetch(endpoint, {
method: 'POST', method: 'POST',
headers, headers,
body body,
signal: controller.signal
}) })
if (!response.ok) { if (!response.ok) {
@ -239,6 +238,10 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
} }
const onGenerate = async () => { const onGenerate = async () => {
// 如果已经在生成过程中,直接返回
if (isLoading) {
return
}
try { try {
// 获取提示词 // 获取提示词
const prompt = textareaRef.current?.resizableTextArea?.textArea?.value || '' const prompt = textareaRef.current?.resizableTextArea?.textArea?.value || ''
@ -254,26 +257,28 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
centered: true centered: true
}) })
if (!confirmed) return if (!confirmed) return
await FileManager.deleteFiles(painting.files)
} }
setIsLoading(true)
// 设置请求状态 // 设置请求状态
const controller = new AbortController() const controller = new AbortController()
setAbortController(controller) setAbortController(controller)
setIsLoading(true)
dispatch(setGenerating(true)) dispatch(setGenerating(true))
// 准备请求配置 // 准备请求配置
const requestConfig = prepareRequestConfig(prompt, painting) const requestConfig = prepareRequestConfig(prompt, painting)
// 发送API请求 // 发送API请求
const urls = await callApi(requestConfig) const urls = await callApi(requestConfig, controller)
// 下载图像 // 下载图像
if (urls.length > 0) { if (urls.length > 0) {
const downloadedFiles = await downloadImages(urls) const downloadedFiles = await downloadImages(urls)
const validFiles = downloadedFiles.filter((file): file is FileType => file !== null) const validFiles = downloadedFiles.filter((file): file is FileType => file !== null)
// 删除之前的图片
await FileManager.deleteFiles(painting.files)
// 保存文件并更新状态 // 保存文件并更新状态
await FileManager.addFiles(validFiles) await FileManager.addFiles(validFiles)
updatePaintingState({ files: validFiles, urls }) updatePaintingState({ files: validFiles, urls })
@ -325,51 +330,8 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
setCurrentImageIndex(0) setCurrentImageIndex(0)
} }
const { autoTranslateWithSpace } = useSettings()
const [spaceClickCount, setSpaceClickCount] = useState(0)
const [isTranslating, setIsTranslating] = useState(false)
const spaceClickTimer = useRef<NodeJS.Timeout>(null) const spaceClickTimer = useRef<NodeJS.Timeout>(null)
const translate = async () => {
if (isTranslating) {
return
}
if (!painting.prompt) {
return
}
try {
setIsTranslating(true)
const translatedText = await translateText(painting.prompt, 'english')
updatePaintingState({ prompt: translatedText })
} catch (error) {
console.error('Translation failed:', error)
} finally {
setIsTranslating(false)
}
}
const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (autoTranslateWithSpace && event.key === ' ') {
setSpaceClickCount((prev) => prev + 1)
if (spaceClickTimer.current) {
clearTimeout(spaceClickTimer.current)
}
spaceClickTimer.current = setTimeout(() => {
setSpaceClickCount(0)
}, 200)
if (spaceClickCount === 2) {
setSpaceClickCount(0)
setIsTranslating(true)
translate().then(() => {})
}
}
}
const handleProviderChange = (providerId: string) => { const handleProviderChange = (providerId: string) => {
const routeName = location.pathname.split('/').pop() const routeName = location.pathname.split('/').pop()
if (providerId !== routeName) { if (providerId !== routeName) {
@ -481,21 +443,21 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
</SliderContainer> </SliderContainer>
</LeftContainer> </LeftContainer>
<MainContainer> <MainContainer>
{painting?.urls?.length > 0 || DMXAPIPaintings?.length > 1 ? ( <Artboard
<Artboard painting={painting}
painting={painting} isLoading={isLoading}
isLoading={isLoading} currentImageIndex={currentImageIndex}
currentImageIndex={currentImageIndex} onPrevImage={prevImage}
onPrevImage={prevImage} onNextImage={nextImage}
onNextImage={nextImage} onCancel={onCancel}
onCancel={onCancel} imageCover={
/> painting?.urls?.length > 0 || DMXAPIPaintings?.length > 1 ? null : (
) : ( <EmptyImgBox>
<EmptyImgBox> <EmptyImg></EmptyImg>
<EmptyImg></EmptyImg> </EmptyImgBox>
</EmptyImgBox> )
)} }
/>
<InputContainer> <InputContainer>
<Textarea <Textarea
ref={textareaRef} ref={textareaRef}
@ -504,8 +466,7 @@ const DmxapiPage: FC<{ Options: string[] }> = ({ Options }) => {
value={painting.prompt} value={painting.prompt}
spellCheck={false} spellCheck={false}
onChange={(e) => updatePaintingState({ prompt: e.target.value })} onChange={(e) => updatePaintingState({ prompt: e.target.value })}
placeholder={isTranslating ? t('paintings.translating') : t('paintings.prompt_placeholder')} placeholder={t('paintings.prompt_placeholder')}
onKeyDown={handleKeyDown}
/> />
<Toolbar> <Toolbar>
<ToolbarMenu> <ToolbarMenu>