@@ -80,11 +80,13 @@ import {
8080 prettyObject ,
8181 // randomNum,
8282 getDirection ,
83+ oneApiImage ,
8384} from '@utils/aidFn'
8485import { fireConfetti } from '@utils/confetti'
8586import Zoom from 'react-medium-image-zoom'
8687import 'react-medium-image-zoom/dist/styles.css'
8788import styles from './index.module.less'
89+ import { image } from 'd3'
8890
8991// const boxList = Array.apply(null, Array(10))
9092
@@ -149,6 +151,8 @@ const Home = () => {
149151 const [ dateTime , setDateTime ] = useState ( '' )
150152 const curController = useRef ( null )
151153
154+ const [ aiImageList , setAiImageList ] = useState ( [ ] )
155+
152156 const mouseEnterRef = useRef ( null )
153157 const [ enterDirection , setEnterDirection ] = useState ( 'left' )
154158 const handleMouseEnter = ( event ) => {
@@ -203,6 +207,14 @@ const Home = () => {
203207 curController . current = controller
204208 fetchAi ( chatText , apiKey , controller )
205209 }
210+ const onSubmitImage = ( ) => {
211+ if ( chatText . trim ( ) === '' ) {
212+ return
213+ }
214+ const controller = new AbortController ( )
215+ curController . current = controller
216+ fetchAiImage ( chatText , apiKey , controller )
217+ }
206218
207219 const onStop = ( ) => {
208220 curController . current . abort ( )
@@ -294,6 +306,60 @@ const Home = () => {
294306 setAiText ( error . message )
295307 } )
296308 }
309+ const fetchAiImage = ( text , key , controller ) => {
310+ aiTextRef . current = ''
311+ setAiText ( aiTextRef . current )
312+ setAiImageList ( [ ] )
313+ const { signal } = controller
314+ setIsStream ( true )
315+ oneApiImage (
316+ [
317+ {
318+ content : text ,
319+ role : 'user' ,
320+ } ,
321+ ] ,
322+ key ,
323+ signal
324+ )
325+ . then ( ( response ) => {
326+ const contentType = response . headers . get ( 'content-type' )
327+ if ( ! response . ok || response . status !== 200 ) {
328+ if ( contentType ?. startsWith ( 'text/html' ) || contentType ?. startsWith ( 'text/plain' ) ) {
329+ const textPlain = response . clone ( ) . text ( )
330+ textPlain . then ( ( plainText ) => {
331+ setAiText ( plainText )
332+ } )
333+ } else if ( contentType ?. startsWith ( 'application/json' ) ) {
334+ const resJson = response . clone ( ) . json ( )
335+ resJson . then ( ( res ) => {
336+ setAiText ( prettyObject ( res ) )
337+ } )
338+ } else {
339+ setAiText ( response . statusText )
340+ }
341+ setIsStream ( false )
342+ } else {
343+ const resJson = response . clone ( ) . json ( )
344+ resJson . then ( ( res ) => {
345+ // setAiText(prettyObject(res))
346+ console . log ( 'res' , res )
347+ if ( res . error ) return
348+ setAiImageList (
349+ res . data . map ( ( item ) => ( {
350+ imageUrl : item . url ,
351+ imagePrompt : item . revised_prompt ,
352+ } ) )
353+ )
354+ } )
355+ setIsStream ( false )
356+ }
357+ } )
358+ . catch ( ( error ) => {
359+ setIsStream ( false )
360+ setAiText ( error . message )
361+ } )
362+ }
297363
298364 const scrollRef = useRef ( null )
299365 const [ customElement , setCustomElement ] = useState ( )
@@ -340,10 +406,63 @@ const Home = () => {
340406 < section className = { styles . avatar } style = { { margin : '10px 0' , fontSize : 24 } } >
341407 < ColorfulText text = { `React version: ${ version } ` } />
342408 </ section >
409+ < section style = { { width : 600 , margin : '30px 0' } } >
410+ < Input defaultValue = { apiKey } placeholder = "api key" onChange = { changeApiKey } style = { { marginBottom : 20 } } />
411+ < Flex align = "center" >
412+ < Input . TextArea
413+ ref = { textareaRef }
414+ defaultValue = { chatText }
415+ placeholder = "来,说点什么呗...Meta + Enter发送"
416+ onChange = { changeChatText }
417+ onKeyDown = { onInputKeyDown }
418+ autoSize
419+ style = { { width : 300 , height : 30 , caretColor : '#ff0000' } }
420+ />
421+ < Button
422+ style = { { margin : '0 10px' } }
423+ icon = { < SendOutlined rotate = { - 60 } /> }
424+ type = "primary"
425+ disabled = { isStream }
426+ onClick = { onSubmit }
427+ >
428+ 发送
429+ </ Button >
430+ < Button
431+ style = { { margin : '0 10px' } }
432+ icon = { < SendOutlined rotate = { - 60 } /> }
433+ type = "primary"
434+ disabled = { isStream }
435+ onClick = { onSubmitImage }
436+ >
437+ 生成图片
438+ </ Button >
439+ < Button icon = { < SendOutlined rotate = { - 60 } /> } type = "primary" disabled = { ! isStream } onClick = { onStop } >
440+ 停止
441+ </ Button >
442+ </ Flex >
443+ </ section >
444+ < section className = "mb-10" >
445+ { isStream && < div > 正在输入...</ div > }
446+ < section style = { { textAlign : 'right' , color : '#666' } } > { dateTime } </ section >
447+ < ReMarkdown markdownText = { aiText } isLoading = { isStream } />
448+ < section className = "aiImage" >
449+ { aiImageList . length > 0 && (
450+ < >
451+ { aiImageList . map ( ( item , index ) => (
452+ < div key = { index } >
453+ < div > { item . imagePrompt } </ div >
454+ < img src = { item . imageUrl } width = "100%" alt = { item . url } />
455+ </ div >
456+ ) ) }
457+ </ >
458+ ) }
459+ </ section >
460+ </ section >
343461 < section style = { { marginBottom : 15 , fontSize : 20 } } >
344462 I love < span className = { styles . circledHighlight } > coding</ span > in{ ' ' }
345463 < AlternatingText alternateText = { [ 'JavaScript' , 'TypeScript' , 'React' , 'Vue' , 'Remix' , 'Node.js' ] } /> .
346464 </ section >
465+
347466 < section style = { { marginBottom : 15 , fontSize : 20 } } >
348467 X岁的你,正处在一个特殊的位置:
349468 < TypeWriter
@@ -815,37 +934,6 @@ const Home = () => {
815934 < section style = { { margin : '20px 0' , fontSize : 40 } } >
816935 < NumberFlowFix />
817936 </ section >
818- < section style = { { width : 600 , margin : '30px 0' } } >
819- < Input defaultValue = { apiKey } placeholder = "api key" onChange = { changeApiKey } style = { { marginBottom : 20 } } />
820- < Flex align = "center" >
821- < Input . TextArea
822- ref = { textareaRef }
823- defaultValue = { chatText }
824- placeholder = "来,说点什么呗...Meta + Enter发送"
825- onChange = { changeChatText }
826- onKeyDown = { onInputKeyDown }
827- autoSize
828- style = { { width : 300 , height : 30 , caretColor : '#ff0000' } }
829- />
830- < Button
831- style = { { margin : '0 10px' } }
832- icon = { < SendOutlined rotate = { - 60 } /> }
833- type = "primary"
834- disabled = { isStream }
835- onClick = { onSubmit }
836- >
837- 发送
838- </ Button >
839- < Button icon = { < SendOutlined rotate = { - 60 } /> } type = "primary" disabled = { ! isStream } onClick = { onStop } >
840- 停止
841- </ Button >
842- </ Flex >
843- </ section >
844- < section >
845- { isStream && < div > 正在输入...</ div > }
846- < section style = { { textAlign : 'right' , color : '#666' } } > { dateTime } </ section >
847- < ReMarkdown markdownText = { aiText } isLoading = { isStream } />
848- </ section >
849937
850938 < section style = { { position : 'relative' , fontSize : 36 } } >
851939 I build
0 commit comments