diff --git a/src/components/App.tsx b/src/components/App.tsx index 4340a24..6c1c13c 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -8,6 +8,7 @@ import Dialog from './Dialog.tsx' import LangSwitcher from './Widgets/LangSwitcher.tsx' import ModeSwitcher from './Widgets/ModeSwitcher.tsx' import ImageSelector from './Widgets/ImageSelector.tsx' +import PromptGenerator from './Widgets/PromptGenerator.tsx' // Hook import { useState, useEffect, useRef } from 'react' import { useDialog } from '../libs/useDialog.tsx' @@ -51,6 +52,8 @@ export function App() { const status = useRef('') // 图片选择器 const imageSelectorRef = useRef(null) + // 提示词输入区 + const promptRef = useRef(null) // 初始化操作 useEffect(() => { // 视情况弹出更新提示 @@ -80,6 +83,7 @@ export function App() { geneMode={geneMode} fileRef={imageSelectorRef} setLoadingImage={setLoadingImage} + promptRef={promptRef} >
+ + ) } diff --git a/src/components/Images.tsx b/src/components/Images.tsx index d1fd2d6..e0a54ef 100644 --- a/src/components/Images.tsx +++ b/src/components/Images.tsx @@ -131,8 +131,7 @@ function Images({ currentImages, setCurrentImages, langMode, dialogAction, statu
这里是赛博画师小叶子
- 在下方输入{langMode === 'zh' ? '中文' : '英文'}提示词并点击生成
- 大部分模型输入自然语言即可
+ 请输入{langMode === 'zh' ? '中文' : '英文'}提示词并点击生成
本站开源于 GitHub ↗
diff --git a/src/components/Prompt.tsx b/src/components/Prompt.tsx index dff0d76..2853365 100644 --- a/src/components/Prompt.tsx +++ b/src/components/Prompt.tsx @@ -41,6 +41,7 @@ interface PromptProps { geneMode: 'textToImage' | 'imageToImage' fileRef: React.RefObject setLoadingImage: React.Dispatch> + promptRef: React.RefObject } class ErrorInfo { @@ -52,11 +53,10 @@ class ErrorInfo { } } -function Prompt({ children, currentImages, setCurrentImages, dialogAction, langMode, status, geneMode, fileRef, setLoadingImage }: PromptProps) { +function Prompt({ children, currentImages, setCurrentImages, dialogAction, langMode, status, geneMode, fileRef, setLoadingImage, promptRef }: PromptProps) { // 引用元素 const submitRef = useRef(null) - const promptRef = useRef(null) const modelRef = useRef(null) // 翻译函数 diff --git a/src/components/Widgets/ImageSelector.tsx b/src/components/Widgets/ImageSelector.tsx index e3d6882..e4cef00 100644 --- a/src/components/Widgets/ImageSelector.tsx +++ b/src/components/Widgets/ImageSelector.tsx @@ -25,11 +25,11 @@ function ImageSelector({ ref, geneMode, dialogAction }: ImageSelectorProps) { if (!event.target.files) return const file = event.target.files[0] // 限制图片大小 - if (file.size > 10 * 1024 * 1024) { + if (file.size > 5 * 1024 * 1024) { dialogAction({ type: 'open', title: '图片过大', - content: '请选择小于 10MB 的图片', + content: '请选择小于 5MB 的图片', }) event.target.value = '' return diff --git a/src/components/Widgets/PromptGenerator.tsx b/src/components/Widgets/PromptGenerator.tsx new file mode 100644 index 0000000..78f0276 --- /dev/null +++ b/src/components/Widgets/PromptGenerator.tsx @@ -0,0 +1,97 @@ +import type { DialogAction } from '../../libs/useDialog' +import { SERVER } from '../../config.json' +import { useRef, useState } from 'react' +import { LoadingOutlined } from '@ant-design/icons' +import { flushSync } from 'react-dom' + +interface PromptGeneratorProps { + status: React.MutableRefObject + dialogAction: React.Dispatch + promptRef: React.RefObject +} + +export default function PromptGenerator({ status, dialogAction, promptRef }: PromptGeneratorProps) { + + const initText: React.JSX.Element = 用图片生成提示词 + const loadText = 生成提示词中 + const textRef = useRef(null) + const [text, setText] = useState(initText) + const lebalRef = useRef(null) + + async function handleFileChange(e: React.ChangeEvent) { + if (!e.target.files) return + try { + // 设置状态 + status.current = '生成提示词' + e.target.disabled = true + lebalRef.current!.style.cursor = 'not-allowed' + lebalRef.current!.style.filter = 'grayscale(0.9)' + lebalRef.current!.style.opacity = '0.9' + flushSync(() => setText(loadText)) + // 检测文件大小 + const file = e.target.files[0] + if (file.size > 2 * 1024 * 1024) { + dialogAction({ + type: 'open', + title: '图片过大', + content: '请选择小于 2MB 的图片', + }) + return + } + // 读取文件 + const uint8array = new Uint8Array(await file.arrayBuffer()) + // 发送请求 + const res = await fetch(`${SERVER}/painter/genprompt`, { + method: 'POST', + body: JSON.stringify({ + image: Array.from(uint8array), + }), + }) + if (!res.ok) throw new Error(`HTTP ${res.status}`) + // 处理返回数据 + const data = await res.json() + const prompt = data.result.description as string + // 设置提示词 + promptRef.current!.value = prompt + } catch (error) { + if (error instanceof Error) { + dialogAction({ + type: 'open', + title: '错误', + content: `提示词生成失败:${error.name} - ${error.message}` + }) + } + } finally { + status.current = '' + e.target.value = '' + e.target.disabled = false + lebalRef.current!.style.cursor = 'pointer' + lebalRef.current!.style.filter = 'grayscale(0)' + lebalRef.current!.style.opacity = '0.3' + setText(initText) + } + } + + return ( + + ) +} \ No newline at end of file diff --git a/src/styles/Widgets.css b/src/styles/Widgets.css index decebd6..a9c7bf9 100644 --- a/src/styles/Widgets.css +++ b/src/styles/Widgets.css @@ -68,3 +68,37 @@ cursor: not-allowed; } + +.prompt-generator-container { + position: fixed; + display: flex; + justify-content: center; + align-items: center; + bottom: 161px; + right: calc(10% + 7px); + width: 108px; + height: 21px; + + font-size: 0.7rem; + font-weight: bold; + color: var(--text); + background-color: var(--back-filearea); + border: 1px solid var(--text); + border-radius: 20px; + cursor: pointer; + transition: all 0.2s ease; + /* 文字省略号 */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + opacity: 0.3; + &:hover { + opacity: 0.9!important; + } +} +@media screen and (min-width: 768px) { + .prompt-generator-container { + bottom: 111px; + } +}