@@ -80,11 +80,13 @@ import {
80
80
prettyObject ,
81
81
// randomNum,
82
82
getDirection ,
83
+ oneApiImage ,
83
84
} from '@utils/aidFn'
84
85
import { fireConfetti } from '@utils/confetti'
85
86
import Zoom from 'react-medium-image-zoom'
86
87
import 'react-medium-image-zoom/dist/styles.css'
87
88
import styles from './index.module.less'
89
+ import { image } from 'd3'
88
90
89
91
// const boxList = Array.apply(null, Array(10))
90
92
@@ -149,6 +151,8 @@ const Home = () => {
149
151
const [ dateTime , setDateTime ] = useState ( '' )
150
152
const curController = useRef ( null )
151
153
154
+ const [ aiImageList , setAiImageList ] = useState ( [ ] )
155
+
152
156
const mouseEnterRef = useRef ( null )
153
157
const [ enterDirection , setEnterDirection ] = useState ( 'left' )
154
158
const handleMouseEnter = ( event ) => {
@@ -203,6 +207,14 @@ const Home = () => {
203
207
curController . current = controller
204
208
fetchAi ( chatText , apiKey , controller )
205
209
}
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
+ }
206
218
207
219
const onStop = ( ) => {
208
220
curController . current . abort ( )
@@ -294,6 +306,60 @@ const Home = () => {
294
306
setAiText ( error . message )
295
307
} )
296
308
}
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
+ }
297
363
298
364
const scrollRef = useRef ( null )
299
365
const [ customElement , setCustomElement ] = useState ( )
@@ -340,10 +406,63 @@ const Home = () => {
340
406
< section className = { styles . avatar } style = { { margin : '10px 0' , fontSize : 24 } } >
341
407
< ColorfulText text = { `React version: ${ version } ` } />
342
408
</ 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 >
343
461
< section style = { { marginBottom : 15 , fontSize : 20 } } >
344
462
I love < span className = { styles . circledHighlight } > coding</ span > in{ ' ' }
345
463
< AlternatingText alternateText = { [ 'JavaScript' , 'TypeScript' , 'React' , 'Vue' , 'Remix' , 'Node.js' ] } /> .
346
464
</ section >
465
+
347
466
< section style = { { marginBottom : 15 , fontSize : 20 } } >
348
467
X岁的你,正处在一个特殊的位置:
349
468
< TypeWriter
@@ -815,37 +934,6 @@ const Home = () => {
815
934
< section style = { { margin : '20px 0' , fontSize : 40 } } >
816
935
< NumberFlowFix />
817
936
</ 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 >
849
937
850
938
< section style = { { position : 'relative' , fontSize : 36 } } >
851
939
I build
0 commit comments