Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
fd8135f5
authored
Mar 11, 2023
by
Archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: md数学表达式;perf: 字体样式;fix: 发送验证码错误提醒。聊天二次加载
parent
9f965931
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
91 additions
and
82 deletions
+91
-82
src/components/Markdown/codeLight.ts
+0
-4
src/components/Markdown/index.module.scss
+5
-5
src/components/Markdown/index.tsx
+5
-3
src/constants/theme.ts
+9
-11
src/hooks/useSendCode.ts
+7
-12
src/pages/api/user/sendEmail.ts
+0
-1
src/pages/chat/index.tsx
+48
-42
src/pages/model/components/ModelPhoneList.tsx
+6
-2
src/pages/model/components/ModelTable.tsx
+5
-1
src/pages/model/detail.tsx
+2
-1
src/service/mongo.ts
+1
-0
src/styles/reset.scss
+3
-0
No files found.
src/components/Markdown/codeLight.ts
View file @
fd8135f5
...
...
@@ -2,9 +2,7 @@ import React from 'react';
export
const
codeLight
:
{
[
key
:
string
]:
React
.
CSSProperties
}
=
{
'code[class*=language-]'
:
{
color
:
'#d4d4d4'
,
fontSize
:
'13px'
,
textShadow
:
'none'
,
fontFamily
:
'Menlo,Monaco,Consolas,"Andale Mono","Ubuntu Mono","Courier New",monospace'
,
direction
:
'ltr'
,
textAlign
:
'left'
,
whiteSpace
:
'pre'
,
...
...
@@ -21,9 +19,7 @@ export const codeLight: { [key: string]: React.CSSProperties } = {
},
'pre[class*=language-]'
:
{
color
:
'#d4d4d4'
,
fontSize
:
'13px'
,
textShadow
:
'none'
,
fontFamily
:
'Menlo,Monaco,Consolas,"Andale Mono","Ubuntu Mono","Courier New",monospace'
,
direction
:
'ltr'
,
textAlign
:
'left'
,
whiteSpace
:
'pre'
,
...
...
src/components/Markdown/index.module.scss
View file @
fd8135f5
...
...
@@ -341,7 +341,7 @@
background-color
:
#f0f0f0
;
border
:
1px
solid
#cccccc
;
border-radius
:
3px
3px
3px
3px
;
font-size
:
13px
;
font-size
:
max
(
0
.9em
,
14px
)
;
line-height
:
19px
;
overflow
:
auto
;
padding
:
6px
10px
;
...
...
@@ -352,11 +352,12 @@
border
:
medium
none
;
}
.markdown
{
font-size
:
14px
;
line-height
:
1
.6
;
letter-spacing
:
0
.5px
;
text-align
:
justify
;
word-break
:
break-all
;
overflow-y
:
hidden
;
tab-size
:
4
;
word-spacing
:
normal
;
pre
{
display
:
block
;
width
:
100%
;
...
...
@@ -372,7 +373,6 @@
background-color
:
#222
!
important
;
color
:
#fff
;
width
:
100%
;
font-family
:
'Söhne,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,Helvetica Neue,Arial,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji'
;
}
a
{
...
...
src/components/Markdown/index.tsx
View file @
fd8135f5
import
React
,
{
memo
,
useMemo
}
from
'react'
;
import
ReactMarkdown
from
'react-markdown'
;
import
styles
from
'./index.module.scss'
;
import
{
Prism
as
SyntaxHighlighter
}
from
'react-syntax-highlighter'
;
import
{
codeLight
}
from
'./codeLight'
;
import
{
Box
,
Flex
}
from
'@chakra-ui/react'
;
import
{
useCopyData
}
from
'@/utils/tools'
;
import
Icon
from
'@/components/Icon'
;
...
...
@@ -10,8 +8,12 @@ import remarkGfm from 'remark-gfm';
import
remarkMath
from
'remark-math'
;
import
rehypeKatex
from
'rehype-katex'
;
import
'katex/dist/katex.min.css'
;
import
styles
from
'./index.module.scss'
;
import
{
codeLight
}
from
'./codeLight'
;
const
Markdown
=
({
source
,
isChatting
}:
{
source
:
string
;
isChatting
:
boolean
})
=>
{
const
formatSource
=
useMemo
(()
=>
source
.
replace
(
/
\n
/g
,
' \n'
)
,
[
source
]);
const
formatSource
=
useMemo
(()
=>
source
,
[
source
]);
const
{
copyData
}
=
useCopyData
();
return
(
...
...
src/constants/theme.ts
View file @
fd8135f5
...
...
@@ -20,24 +20,27 @@ const Button = defineStyleConfig({
baseStyle
:
{},
sizes
:
{
sm
:
{
fontSize
:
'
sm
'
,
fontSize
:
'
xs
'
,
px
:
3
,
py
:
0
,
fontWeight
:
'normal'
,
height
:
'26px'
height
:
'26px'
,
lineHeight
:
'26px'
},
md
:
{
fontSize
:
'
md
'
,
fontSize
:
'
sm
'
,
px
:
6
,
py
:
0
,
height
:
'34px'
,
lineHeight
:
'34px'
,
fontWeight
:
'normal'
},
lg
:
{
fontSize
:
'
lg
'
,
fontSize
:
'
md
'
,
px
:
8
,
py
:
0
,
height
:
'42px'
,
lineHeight
:
'42px'
,
fontWeight
:
'normal'
}
},
...
...
@@ -58,17 +61,12 @@ export const theme = extendTheme({
global
:
{
'html, body'
:
{
color
:
'blackAlpha.800'
,
fontSize
:
'14px'
,
fontFamily
:
'Söhne,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,Helvetica Neue,Arial,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji'
,
height
:
'100%'
,
overflowY
:
'auto'
maxHeight
:
'100vh'
,
overflowY
:
'hidden'
}
}
},
fonts
:
{
body
:
'system-ui, sans-serif'
},
fontSizes
:
{
xs
:
'0.8rem'
,
sm
:
'0.9rem'
,
...
...
src/hooks/useSendCode.ts
View file @
fd8135f5
import
{
useState
,
useMemo
,
useCallback
}
from
'react'
;
import
{
sendCodeToEmail
}
from
'@/api/user'
;
import
{
EmailTypeEnum
}
from
'@/constants/common'
;
import
{
useToast
}
from
'@chakra-ui/react'
;
let
timer
:
any
;
import
{
useToast
}
from
'./useToast'
;
export
const
useSendCode
=
()
=>
{
const
toast
=
useToast
({
position
:
'top'
,
duration
:
2000
});
const
{
toast
}
=
useToast
();
const
[
codeSending
,
setCodeSending
]
=
useState
(
false
);
const
[
codeCountDown
,
setCodeCountDown
]
=
useState
(
0
);
const
sendCodeText
=
useMemo
(()
=>
{
...
...
@@ -43,13 +40,11 @@ export const useSendCode = () => {
status
:
'success'
,
position
:
'top'
});
}
catch
(
error
)
{
typeof
error
===
'string'
&&
toast
({
title
:
error
,
status
:
'error'
,
position
:
'top'
});
}
catch
(
error
:
any
)
{
toast
({
title
:
error
.
message
||
'发送验证码异常'
,
status
:
'error'
});
}
setCodeSending
(
false
);
},
...
...
src/pages/api/user/sendEmail.ts
View file @
fd8135f5
...
...
@@ -20,7 +20,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
if
(
type
===
EmailTypeEnum
.
register
)
{
const
maxCount
=
process
.
env
.
MAX_USER
?
+
process
.
env
.
MAX_USER
:
Infinity
;
const
userCount
=
await
User
.
count
();
if
(
userCount
>=
maxCount
)
{
throw
new
Error
(
'当前注册用户已满,请等待名额~'
);
}
...
...
src/pages/chat/index.tsx
View file @
fd8135f5
...
...
@@ -22,11 +22,10 @@ const Markdown = dynamic(() => import('@/components/Markdown'));
const
textareaMinH
=
'22px'
;
const
Chat
=
()
=>
{
const
Chat
=
(
{
chatId
,
windowId
}:
{
chatId
:
string
;
windowId
?:
string
}
)
=>
{
const
{
toast
}
=
useToast
();
const
router
=
useRouter
();
const
{
isPc
,
media
}
=
useScreen
();
const
{
chatId
,
windowId
}
=
router
.
query
as
{
chatId
:
string
;
windowId
?:
string
};
const
ChatBox
=
useRef
<
HTMLDivElement
>
(
null
);
const
TextareaDom
=
useRef
<
HTMLTextAreaElement
>
(
null
);
...
...
@@ -40,7 +39,6 @@ const Chat = () => {
// 滚动到底部
const
scrollToBottom
=
useCallback
(()
=>
{
// 滚动到底部
setTimeout
(()
=>
{
ChatBox
.
current
&&
ChatBox
.
current
.
scrollTo
({
...
...
@@ -52,16 +50,14 @@ const Chat = () => {
// 初始化聊天框
useQuery
(
[
chatId
,
windowId
],
[
'initData'
],
()
=>
{
if
(
!
chatId
)
return
null
;
setLoading
(
true
);
return
getInitChatSiteInfo
(
chatId
,
windowId
);
},
{
cacheTime
:
5
*
60
*
1000
,
onSuccess
(
res
)
{
if
(
!
res
)
return
;
// 可能没有 windowId,给它设置一下
router
.
replace
(
`/chat?chatId=
${
chatId
}
&windowId=
${
res
.
windowId
}
`
);
setChatSiteData
(
res
.
chatSite
);
...
...
@@ -72,7 +68,6 @@ const Chat = () => {
}))
);
scrollToBottom
();
setLoading
(
false
);
},
onError
(
e
:
any
)
{
toast
({
...
...
@@ -81,11 +76,30 @@ const Chat = () => {
isClosable
:
true
,
duration
:
5000
});
},
onSettled
()
{
setLoading
(
false
);
}
}
);
// 重置输入内容
const
resetInputVal
=
useCallback
((
val
:
string
)
=>
{
setInputVal
(
val
);
setTimeout
(()
=>
{
/* 回到最小高度 */
if
(
TextareaDom
.
current
)
{
TextareaDom
.
current
.
style
.
height
=
val
===
''
?
textareaMinH
:
`
${
TextareaDom
.
current
.
scrollHeight
}
px`
;
}
},
100
);
},
[]);
// 重载对话
const
resetChat
=
useCallback
(()
=>
{
window
.
open
(
`/chat?chatId=
${
chatId
}
`
,
'_self'
);
},
[
chatId
]);
// gpt3 方法
const
gpt3ChatPrompt
=
useCallback
(
async
(
newChatList
:
ChatSiteItemType
[])
=>
{
...
...
@@ -210,16 +224,8 @@ const Chat = () => {
// 插入内容
setChatList
(
newChatList
);
setInputVal
(
''
);
// 滚动到底部
setTimeout
(()
=>
{
scrollToBottom
();
/* 回到最小高度 */
if
(
TextareaDom
.
current
)
{
TextareaDom
.
current
.
style
.
height
=
textareaMinH
;
}
},
100
);
resetInputVal
(
''
);
scrollToBottom
();
const
fnMap
:
{
[
key
:
string
]:
any
}
=
{
[
OpenAiModelEnum
.
GPT35
]:
chatGPTPrompt
,
...
...
@@ -239,13 +245,13 @@ const Chat = () => {
}
}
catch
(
err
)
{
toast
({
title
:
typeof
err
===
'string'
?
err
:
'聊天
已过期
'
,
title
:
typeof
err
===
'string'
?
err
:
'聊天
出错了~
'
,
status
:
'warning'
,
duration
:
5000
,
isClosable
:
true
});
setInputVal
(
storeInput
);
re
setInputVal
(
storeInput
);
setChatList
(
newChatList
.
slice
(
0
,
newChatList
.
length
-
2
));
}
...
...
@@ -256,6 +262,7 @@ const Chat = () => {
gpt3ChatPrompt
,
inputVal
,
isChatting
,
resetInputVal
,
scrollToBottom
,
toast
]);
...
...
@@ -267,16 +274,10 @@ const Chat = () => {
await
delLastMessage
(
windowId
);
const
val
=
chatList
[
chatList
.
length
-
1
].
value
;
setInputVal
(
val
);
re
setInputVal
(
val
);
setChatList
(
chatList
.
slice
(
0
,
-
1
));
setTimeout
(()
=>
{
if
(
TextareaDom
.
current
)
{
TextareaDom
.
current
.
style
.
height
=
val
.
split
(
'\n'
).
length
*
22
+
'px'
;
}
},
100
);
},
[
chatList
,
windowId
]);
},
[
chatList
,
resetInputVal
,
windowId
]);
return
(
<
Flex
height=
{
'100%'
}
flexDirection=
{
'column'
}
>
...
...
@@ -290,13 +291,9 @@ const Chat = () => {
zIndex=
{
1
}
>
<
Box
flex=
{
1
}
>
{
chatSiteData
?.
name
}
</
Box
>
{
/* 重置按键 */
}
<
Box
cursor=
{
'pointer'
}
onClick=
{
()
=>
router
.
replace
(
`/chat?chatId=${chatId}`
)
}
>
<
Icon
name=
{
'icon-zhongzhi'
}
width=
{
20
}
height=
{
20
}
color=
{
'#718096'
}
></
Icon
>
</
Box
>
{
/* 滚动到底部按键 */
}
{
ChatBox
.
current
&&
ChatBox
.
current
.
scrollHeight
>
2
*
ChatBox
.
current
.
clientHeight
&&
(
<
Box
m
l
=
{
10
}
cursor=
{
'pointer'
}
onClick=
{
scrollToBottom
}
>
<
Box
m
r
=
{
10
}
cursor=
{
'pointer'
}
onClick=
{
scrollToBottom
}
>
<
Icon
name=
{
'icon-xiangxiazhankai-xianxingyuankuang'
}
width=
{
25
}
...
...
@@ -305,6 +302,10 @@ const Chat = () => {
></
Icon
>
</
Box
>
)
}
{
/* 重置按键 */
}
<
Button
size=
{
'sm'
}
colorScheme=
{
'gray'
}
onClick=
{
resetChat
}
>
新对话
</
Button
>
</
Flex
>
{
/* 聊天内容 */
}
<
Box
ref=
{
ChatBox
}
flex=
{
'1 0 0'
}
h=
{
0
}
w=
{
'100%'
}
px=
{
0
}
pb=
{
10
}
overflowY=
{
'auto'
}
>
...
...
@@ -312,7 +313,7 @@ const Chat = () => {
<
Box
key=
{
index
}
py=
{
media
(
9
,
6
)
}
px=
{
media
(
4
,
3
)
}
px=
{
media
(
4
,
2
)
}
backgroundColor=
{
index
%
2
===
0
?
'rgba(247,247,248,1)'
:
'#fff'
}
borderBottom=
{
'1px solid rgba(0,0,0,0.1)'
}
>
...
...
@@ -321,11 +322,11 @@ const Chat = () => {
<
Image
src=
{
item
.
obj
===
'Human'
?
'/icon/human.png'
:
'/icon/logo.png'
}
alt=
"/icon/logo.png"
width=
{
30
}
height=
{
30
}
width=
{
media
(
30
,
20
)
}
height=
{
media
(
30
,
20
)
}
/>
</
Box
>
<
Box
flex=
{
'1 0 0'
}
w=
{
0
}
overflow
X
=
{
'hidden'
}
>
<
Box
flex=
{
'1 0 0'
}
w=
{
0
}
overflow=
{
'hidden'
}
>
{
item
.
obj
===
'AI'
?
(
<
Markdown
source=
{
item
.
value
}
...
...
@@ -350,11 +351,7 @@ const Chat = () => {
<
Box
textAlign=
{
'center'
}
>
<
Box
color=
{
'red'
}
>
对话出现了异常
</
Box
>
<
Flex
py=
{
5
}
justifyContent=
{
'center'
}
>
<
Button
mr=
{
20
}
onClick=
{
()
=>
router
.
replace
(
`/chat?chatId=${chatId}`
)
}
colorScheme=
{
'green'
}
>
<
Button
mr=
{
20
}
onClick=
{
resetChat
}
colorScheme=
{
'green'
}
>
重开对话
</
Button
>
<
Button
onClick=
{
reEdit
}
>
重新编辑最后一句
</
Button
>
...
...
@@ -428,3 +425,12 @@ const Chat = () => {
};
export
default
Chat
;
export
async
function
getServerSideProps
(
context
:
any
)
{
const
chatId
=
context
.
query
?.
chatId
||
''
;
const
windowId
=
context
.
query
?.
windowId
||
''
;
return
{
props
:
{
chatId
,
windowId
}
};
}
src/pages/model/components/ModelPhoneList.tsx
View file @
fd8135f5
import
React
from
'react'
;
import
{
Box
,
Button
,
Flex
,
Heading
,
Tag
}
from
'@chakra-ui/react'
;
import
React
,
{
useEffect
}
from
'react'
;
import
{
Box
,
Button
,
Flex
,
Tag
}
from
'@chakra-ui/react'
;
import
type
{
ModelType
}
from
'@/types/model'
;
import
{
formatModelStatus
}
from
'@/constants/model'
;
import
dayjs
from
'dayjs'
;
...
...
@@ -14,6 +14,10 @@ const ModelPhoneList = ({
})
=>
{
const
router
=
useRouter
();
useEffect
(()
=>
{
router
.
prefetch
(
'/chat'
);
},
[
router
]);
return
(
<
Box
borderRadius=
{
'md'
}
overflow=
{
'hidden'
}
mb=
{
5
}
>
{
models
.
map
((
model
)
=>
(
...
...
src/pages/model/components/ModelTable.tsx
View file @
fd8135f5
import
React
from
'react'
;
import
{
useEffect
}
from
'react'
;
import
{
Button
,
Table
,
...
...
@@ -84,6 +84,10 @@ const ModelTable = ({
}
];
useEffect
(()
=>
{
router
.
prefetch
(
'/chat'
);
},
[
router
]);
return
(
<
Card
py=
{
3
}
>
<
TableContainer
>
...
...
src/pages/model/detail.tsx
View file @
fd8135f5
...
...
@@ -49,7 +49,8 @@ const ModelDetail = () => {
useEffect
(()
=>
{
loadModel
();
},
[
loadModel
,
modelId
]);
router
.
prefetch
(
'/chat'
);
},
[
loadModel
,
modelId
,
router
]);
/* 点击删除 */
const
handleDelModel
=
useCallback
(
async
()
=>
{
...
...
src/service/mongo.ts
View file @
fd8135f5
...
...
@@ -11,6 +11,7 @@ export async function connectToDatabase(): Promise<void> {
global
.
mongodb
=
'connecting'
;
console
.
log
(
'connect mongo'
);
try
{
mongoose
.
set
(
'strictQuery'
,
true
);
global
.
mongodb
=
await
mongoose
.
connect
(
process
.
env
.
MONGODB_URI
as
string
,
{
bufferCommands
:
true
,
dbName
:
'doc_gpt'
,
...
...
src/styles/reset.scss
View file @
fd8135f5
...
...
@@ -50,6 +50,9 @@ svg {
}
@media
(
max-width
:
900px
)
{
html
{
font-size
:
14px
;
}
::-webkit-scrollbar
,
::-webkit-scrollbar
{
width
:
2px
;
...
...
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