Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sdream-ai-fe
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
侯明涛
sdream-ai-fe
Commits
7733c889
Commit
7733c889
authored
Aug 06, 2024
by
HoMeTown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 修改chat input 为 editor
parent
6384ebb2
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
130 additions
and
16 deletions
+130
-16
src/components/ChatEditor/index.tsx
+116
-0
src/pages/Home/Home.tsx
+13
-15
src/pages/Home/components/WelcomeWord/WelcomeWord.tsx
+1
-1
No files found.
src/components/ChatEditor/index.tsx
0 → 100644
View file @
7733c889
import
React
,
{
useEffect
,
useRef
,
useState
}
from
'react'
import
{
AnimatePresence
,
motion
}
from
'framer-motion'
interface
EditorProps
{
onChange
?:
(
value
:
string
)
=>
void
onFocus
?:
()
=>
void
onSubmit
?:
(
value
:
string
)
=>
void
placeholders
:
string
[]
}
const
Editor
:
React
.
FC
<
EditorProps
>
=
({
onChange
,
onFocus
,
onSubmit
,
placeholders
})
=>
{
const
[
content
,
setContent
]
=
useState
(
''
)
const
editorRef
=
useRef
<
HTMLDivElement
>
(
null
)
const
[
currentPlaceholder
,
setCurrentPlaceholder
]
=
useState
(
0
)
const
intervalRef
=
useRef
<
NodeJS
.
Timeout
|
null
>
(
null
)
const
startAnimation
=
()
=>
{
intervalRef
.
current
=
setInterval
(()
=>
{
setCurrentPlaceholder
(
prev
=>
(
prev
+
1
)
%
placeholders
.
length
)
},
3000
)
}
const
handleVisibilityChange
=
()
=>
{
if
(
document
.
visibilityState
!==
'visible'
&&
intervalRef
.
current
)
{
clearInterval
(
intervalRef
.
current
)
// Clear the interval when the tab is not visible
intervalRef
.
current
=
null
}
else
if
(
document
.
visibilityState
===
'visible'
)
{
startAnimation
()
// Restart the interval when the tab becomes visible
}
}
const
handleInput
=
()
=>
{
if
(
editorRef
.
current
)
{
const
newContent
=
editorRef
.
current
.
textContent
||
''
setContent
(
newContent
)
onChange
?.(
newContent
)
}
}
const
handleKeyDown
=
(
e
:
React
.
KeyboardEvent
)
=>
{
if
(
e
.
key
===
'Enter'
&&
!
e
.
shiftKey
)
{
e
.
preventDefault
()
if
(
content
.
trim
())
{
onSubmit
?.(
content
.
trim
())
setContent
(
''
)
if
(
editorRef
.
current
)
{
editorRef
.
current
.
textContent
=
''
}
}
}
else
if
(
e
.
key
===
'Backspace'
&&
!
content
)
{
e
.
preventDefault
()
// 防止删除最后一个字符后继续删除
}
}
useEffect
(()
=>
{
startAnimation
()
document
.
addEventListener
(
'visibilitychange'
,
handleVisibilityChange
)
if
(
editorRef
.
current
)
{
editorRef
.
current
.
style
.
height
=
'auto'
editorRef
.
current
.
style
.
height
=
`
${
editorRef
.
current
.
scrollHeight
}
px`
}
return
()
=>
{
if
(
intervalRef
.
current
)
{
clearInterval
(
intervalRef
.
current
)
}
document
.
removeEventListener
(
'visibilitychange'
,
handleVisibilityChange
)
}
},
[
content
])
return
(
<
div
className=
"w-full h-auto relative mx-auto bg-white rounded-[36px] overflow-hidden transition duration-200 py-[012px] px-[32px]"
>
<
div
ref=
{
editorRef
}
contentEditable
className=
"w-full min-h-[40px] max-h-[200px] p-2 rounded overflow-y-auto outline-none"
onInput=
{
handleInput
}
onFocus=
{
onFocus
}
onKeyDown=
{
handleKeyDown
}
suppressContentEditableWarning=
{
true
}
style=
{
{
resize
:
'none'
,
}
}
/>
<
div
className=
"absolute inset-0 flex items-center rounded-full pointer-events-none"
>
<
AnimatePresence
mode=
"wait"
>
{
!
content
&&
(
<
motion
.
p
initial=
{
{
y
:
5
,
opacity
:
0
,
}
}
key=
{
`current-placeholder-${currentPlaceholder}`
}
animate=
{
{
y
:
0
,
opacity
:
1
,
}
}
exit=
{
{
y
:
-
15
,
opacity
:
0
,
}
}
transition=
{
{
duration
:
0.3
,
ease
:
'linear'
,
}
}
className=
"dark:text-zinc-500 text-[12px] sm:text-base font-normal text-[#3333334d] pl-4 sm:pl-12 text-left w-[calc(100%-2rem)] truncate"
>
{
placeholders
[
currentPlaceholder
]
}
</
motion
.
p
>
)
}
</
AnimatePresence
>
</
div
>
</
div
>
)
}
export
default
Editor
src/pages/Home/Home.tsx
View file @
7733c889
...
...
@@ -7,7 +7,7 @@ import { Slogan } from './components/Slogan/Slogan'
import
HomeIcon1
from
'@/assets/homeIcon1.png'
import
HomeIcon2
from
'@/assets/homeIcon2.png'
import
{
GradientBackground
}
from
'@/components/GradientBackground'
import
{
PlaceholdersInput
}
from
'@/components/PlaceholdersInput
'
import
ChatEditor
from
'@/components/ChatEditor
'
export
const
Home
:
React
.
FC
=
()
=>
{
const
placeholders
=
[
...
...
@@ -17,14 +17,14 @@ export const Home: React.FC = () => {
'直接开始问吧!'
,
'保险公司偿付能力在哪里可以看?'
,
]
const
handleChange
=
(
e
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
e
.
preventDefault
()
// console.log(e.target.value)
}
const
onSubmit
=
(
e
:
React
.
FormEvent
<
HTMLFormElement
>
)
=>
{
e
.
preventDefault
()
// console.log('submitted')
}
//
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
//
e.preventDefault()
//
// console.log(e.target.value)
//
}
//
const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
//
e.preventDefault()
//
// console.log('submitted')
//
}
return
(
<
div
className=
{
styles
.
homePage
}
>
<
GradientBackground
/>
...
...
@@ -50,15 +50,13 @@ export const Home: React.FC = () => {
/>
</
div
>
<
div
className=
"box-border px-[0] mx-auto iptContainer w-full
h-[122px] max-w-[1000px] flex-shrink-0 sm:px-0 sm:h-[132px]
"
>
<
PlaceholdersInput
<
div
className=
"box-border px-[0] mx-auto iptContainer w-full
max-w-[1000px] flex-shrink-0 sm:px-0
"
>
{
/*
<PlaceholdersInput
placeholders={placeholders}
onChange={handleChange}
onSubmit={onSubmit}
/>
{
/* <div className="w-full h-[72px] bg-white rounded-[36px]">
123
</div> */
}
/> */
}
<
ChatEditor
placeholders=
{
placeholders
}
/>
<
div
className=
"w-full text-center mt-[20px] text-[#3333334d] text-[12px]"
>
内容由AI模型生成,其准确性和完整性无法保证,仅供参考
</
div
>
...
...
src/pages/Home/components/WelcomeWord/WelcomeWord.tsx
View file @
7733c889
...
...
@@ -19,7 +19,7 @@ const BotEye: React.FC = () => {
useEffect
(()
=>
{
const
blinkInterval
=
setInterval
(()
=>
{
blink
()
},
4000
)
// 每2秒眨一次眼
},
4000
)
return
()
=>
clearInterval
(
blinkInterval
)
},
[])
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment