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
6ac7119e
authored
Jun 12, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: kb UI
parent
daf1148b
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
117 additions
and
93 deletions
+117
-93
README.md
+1
-1
client/src/components/Tag/index.tsx
+3
-3
client/src/constants/theme.ts
+2
-2
client/src/hooks/usePagination.tsx
+3
-1
client/src/pages/api/plugins/kb/data/getDataList.ts
+1
-0
client/src/pages/kb/components/DataCard.tsx
+0
-0
client/src/pages/kb/components/Detail.tsx
+29
-10
client/src/pages/kb/components/Info.tsx
+74
-73
client/src/pages/kb/components/KbList.tsx
+2
-2
client/src/pages/number/index.tsx
+2
-1
No files found.
README.md
View file @
6ac7119e
...
...
@@ -37,8 +37,8 @@ Fast GPT 允许你使用自己的 openai API KEY 来快速的调用 openai 接
## 👀 其他
-
[
FastGpt 常见问题
](
https://kjqvjse66l.feishu.cn/docx/HtrgdT0pkonP4kxGx8qcu6XDnGh
)
-
[
docker 部署教程
](
https://www.bilibili.com/video/BV1jo4y147fT/
)
-
[
公众号接入
](
https://www.bilibili.com/video/BV1xh4y1t7fy/
)
-
[
FastGpt + Laf 最佳实践,将知识库装入公众号,点击去 Laf 公众号体验效果
](
https://b4jky7-fastgpt.oss.laf.run/lafercode.png
)
-
[
FastGpt V3.4 更新集合
](
https://www.bilibili.com/video/BV1Lo4y147Qh/?vd_source=92041a1a395f852f9d89158eaa3f61b4
)
-
[
FastGpt 知识库演示
](
https://www.bilibili.com/video/BV1Wo4y1p7i1/
)
...
...
client/src/components/Tag/index.tsx
View file @
6ac7119e
...
...
@@ -29,11 +29,11 @@ const Tag = ({ children, colorSchema = 'blue', ...props }: Props) => {
},
[
colorSchema
]);
return
(
<
Box
as=
{
'span
'
}
display=
{
'inline-block
'
}
border=
{
'1px solid'
}
px=
{
2
}
lineHeight=
{
0
}
py=
{
'
1
px'
}
lineHeight=
{
1
}
py=
{
'
2
px'
}
borderRadius=
{
'md'
}
fontSize=
{
'xs'
}
{
...
theme
}
...
...
client/src/constants/theme.ts
View file @
6ac7119e
...
...
@@ -249,8 +249,8 @@ export const theme = extendTheme({
'2xl'
:
'2100px'
},
lgColor
:
{
activeBlueGradient
:
'linear-gradient(
120deg
, #d6e8ff 0%, #f0f7ff 100%)'
,
hoverBlueGradient
:
'linear-gradient(
60deg, #f0f7ff 0%, #d6e8
ff 100%)'
,
activeBlueGradient
:
'linear-gradient(
to bottom right
, #d6e8ff 0%, #f0f7ff 100%)'
,
hoverBlueGradient
:
'linear-gradient(
to top left, #d6e8ff 0%, #f0f7
ff 100%)'
,
primary
:
'linear-gradient(to bottom right, #2152d9 0%,#3370ff 40%, #4e83fd 100%)'
,
primary2
:
'linear-gradient(to bottom right, #2152d9 0%,#3370ff 30%,#4e83fd 80%, #85b1ff 100%)'
},
...
...
client/src/hooks/usePagination.tsx
View file @
6ac7119e
...
...
@@ -54,6 +54,7 @@ export const usePagination = <T = any,>({
size=
{
'sm'
}
w=
{
'28px'
}
h=
{
'28px'
}
isLoading=
{
isLoading
}
onClick=
{
()
=>
mutate
(
pageNum
-
1
)
}
/>
<
Flex
mx=
{
2
}
alignItems=
{
'center'
}
>
...
...
@@ -84,13 +85,14 @@ export const usePagination = <T = any,>({
icon=
{
<
ArrowForwardIcon
/>
}
aria
-
label=
{
'left'
}
size=
{
'sm'
}
isLoading=
{
isLoading
}
w=
{
'28px'
}
h=
{
'28px'
}
onClick=
{
()
=>
mutate
(
pageNum
+
1
)
}
/>
</
Flex
>
);
},
[
maxPage
,
mutate
,
pageNum
]);
},
[
isLoading
,
maxPage
,
mutate
,
pageNum
]);
useEffect
(()
=>
{
defaultRequest
&&
mutate
(
1
);
...
...
client/src/pages/api/plugins/kb/data/getDataList.ts
View file @
6ac7119e
...
...
@@ -26,6 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const
{
userId
}
=
await
authUser
({
req
,
authToken
:
true
});
await
connectToDatabase
();
searchText
=
searchText
.
replace
(
/'/g
,
''
);
const
where
:
any
=
[
[
'user_id'
,
userId
],
...
...
client/src/pages/kb/components/DataCard.tsx
View file @
6ac7119e
This diff is collapsed.
Click to expand it.
client/src/pages/kb/components/Detail.tsx
View file @
6ac7119e
import
React
,
{
useRef
}
from
'react'
;
import
React
,
{
useRef
,
useState
}
from
'react'
;
import
{
useRouter
}
from
'next/router'
;
import
{
Card
,
Box
}
from
'@chakra-ui/react'
;
import
{
Box
}
from
'@chakra-ui/react'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
{
KbItemType
}
from
'@/types/plugin'
;
import
{
useScreen
}
from
'@/hooks/useScreen'
;
import
DataCard
from
'./DataCard'
;
import
{
getErrText
}
from
'@/utils/tools'
;
import
Info
,
{
type
ComponentRef
}
from
'./Info'
;
import
Tabs
from
'@/components/Tabs'
;
enum
TabEnum
{
data
=
'data'
,
test
=
'test'
,
info
=
'info'
}
const
Detail
=
({
kbId
}:
{
kbId
:
string
})
=>
{
const
{
toast
}
=
useToast
();
const
router
=
useRouter
();
const
{
isPc
}
=
useScreen
();
const
BasicInfo
=
useRef
<
ComponentRef
>
(
null
);
const
{
setLastKbId
,
kbDetail
,
getKbDetail
,
loadKbList
,
myKbList
}
=
useUserStore
();
const
[
currentTab
,
setCurrentTab
]
=
useState
(
TabEnum
.
data
);
const
form
=
useForm
<
KbItemType
>
({
defaultValues
:
kbDetail
...
...
@@ -42,13 +51,23 @@ const Detail = ({ kbId }: { kbId: string }) => {
});
return
(
<
Box
h=
{
'100%'
}
p=
{
5
}
overflow=
{
'overlay'
}
position=
{
'relative'
}
>
<
Card
p=
{
6
}
>
<
Info
ref=
{
BasicInfo
}
kbId=
{
kbId
}
form=
{
form
}
/>
</
Card
>
<
Card
p=
{
6
}
mt=
{
5
}
>
<
DataCard
kbId=
{
kbId
}
/>
</
Card
>
<
Box
bg=
{
'#fcfcfc'
}
h=
{
'100%'
}
p=
{
5
}
overflow=
{
'overlay'
}
position=
{
'relative'
}
>
<
Box
mb=
{
5
}
>
<
Tabs
m=
{
'auto'
}
w=
{
'260px'
}
size=
{
isPc
?
'md'
:
'sm'
}
list=
{
[
{
id
:
TabEnum
.
data
,
label
:
'数据管理'
},
{
id
:
TabEnum
.
test
,
label
:
'搜索测试'
},
{
id
:
TabEnum
.
info
,
label
:
'基本信息'
}
]
}
activeId=
{
currentTab
}
onChange=
{
(
e
:
any
)
=>
setCurrentTab
(
e
)
}
/>
</
Box
>
{
currentTab
===
TabEnum
.
data
&&
<
DataCard
kbId=
{
kbId
}
/>
}
{
currentTab
===
TabEnum
.
info
&&
<
Info
ref=
{
BasicInfo
}
kbId=
{
kbId
}
form=
{
form
}
/>
}
</
Box
>
);
};
...
...
client/src/pages/kb/components/Info.tsx
View file @
6ac7119e
...
...
@@ -140,88 +140,89 @@ const Info = (
}));
return (
<Box>
<Flex>
<Box fontWeight={'bold'} fontSize={'2xl'} flex={1}>
知识库信息
<Flex flexDirection={'column'} alignItems={'center'}>
<Flex mt={5} w={'100%'} maxW={'350px'} alignItems={'center'}>
<Box flex={'0 0 90px'} w={0}>
知识库头像
</Box>
<Box flex={1}>
<Avatar
m={'auto'}
src={getValues('avatar')}
w={['32px', '40px']}
h={['32px', '40px']}
cursor={'pointer'}
title={'点击切换头像'}
onClick={onOpenSelectFile}
/>
</Box>
{kbDetail._id && (
<>
<Button
isLoading={btnLoading}
mr={3}
onClick={handleSubmit(saveSubmitSuccess, saveSubmitError)}
>
保存
</Button>
<IconButton
isLoading={btnLoading}
icon={<DeleteIcon />}
aria-label={''}
variant={'solid'}
colorScheme={'red'}
onClick={openConfirm(onclickDelKb)}
/>
</>
)}
</Flex>
<F
lex mt={5
} alignItems={'center'}>
<Box flex={'0 0
6
0px'} w={0}>
头像
<F
ormControl mt={8} w={'100%'} maxW={'350px'} display={'flex'
} alignItems={'center'}>
<Box flex={'0 0
9
0px'} w={0}>
知识库名称
</Box>
<Avatar
src={getValues('avatar')}
w={['28px', '36px']}
h={['28px', '36px']}
cursor={'pointer'}
title={'点击切换头像'}
onClick={onOpenSelectFile}
<Input
flex={1}
{...register('name', {
required: '知识库名称不能为空'
})}
/>
</Flex>
<FormControl mt={5}>
<Flex alignItems={'center'} maxW={'350px'}>
<Box flex={'0 0 60px'} w={0}>
名称
</Box>
<Input
{...register('name', {
required: '知识库名称不能为空'
})}
/>
</Flex>
</FormControl>
<Box>
<Flex mt={5} alignItems={'center'} maxW={'350px'} flexWrap={'wrap'}>
<Box flex={'0 0 60px'} w={0}>
标签
<Tooltip label={'仅用于记忆,用空格隔开多个标签'}>
<QuestionOutlineIcon ml={1} />
</Tooltip>
</Box>
<Input
flex={1}
ref={InputRef}
placeholder={'标签,使用空格分割。'}
onChange={(e) => {
setValue('tags', e.target.value);
setRefresh(!refresh);
}}
<Flex mt={8} alignItems={'center'} w={'100%'} maxW={'350px'} flexWrap={'wrap'}>
<Box flex={'0 0 90px'} w={0}>
分类标签
<Tooltip label={'用空格隔开多个标签,便于搜索'}>
<QuestionOutlineIcon ml={1} />
</Tooltip>
</Box>
<Input
flex={1}
maxW={'300px'}
ref={InputRef}
placeholder={'标签,使用空格分割。'}
maxLength={30}
onChange={(e) => {
setValue('tags', e.target.value);
setRefresh(!refresh);
}}
/>
<Box mt={2} w="100%">
{getValues('tags')
.split(' ')
.filter((item) => item)
.map((item, i) => (
<Tag mr={2} mb={2} key={i} whiteSpace={'nowrap'}>
{item}
</Tag>
))}
</Box>
</Flex>
{kbDetail._id && (
<Flex mt={5} w={'100%'} maxW={'350px'} alignItems={'flex-end'}>
<Box flex={'0 0 90px'} w={0}></Box>
<Button
isLoading={btnLoading}
mr={4}
w={'100px'}
onClick={handleSubmit(saveSubmitSuccess, saveSubmitError)}
>
保存
</Button>
<IconButton
isLoading={btnLoading}
icon={<DeleteIcon />}
aria-label={''}
variant={'outline'}
size={'sm'}
colorScheme={'red'}
color={'red.500'}
onClick={openConfirm(onclickDelKb)}
/>
<Box pl={'60px'} mt={2} w="100%">
{getValues('tags')
.split(' ')
.filter((item) => item)
.map((item, i) => (
<Tag mr={2} mb={2} key={i}>
{item}
</Tag>
))}
</Box>
</Flex>
</Box>
)}
<File onSelect={onSelectFile} />
<ConfirmChild />
</
Bo
x>
</
Fle
x>
);
};
...
...
client/src/pages/kb/components/KbList.tsx
View file @
6ac7119e
...
...
@@ -119,12 +119,12 @@ const KbList = ({ kbId }: { kbId: string }) => {
{
item
.
name
}
</
Box
>
{
/* tags */
}
<
Box
c
lassName=
"textEllipsis"
color=
{
'myGray.400'
}
py=
{
1
}
>
<
Box
c
olor=
{
'myGray.400'
}
py=
{
1
}
fontSize=
{
'sm'
}
>
{
!
item
.
tags
?
(
<>
{
item
.
tags
||
'你还没设置标签~'
}
</>
)
:
(
item
.
tags
.
split
(
' '
).
map
((
item
,
i
)
=>
(
<
Tag
key=
{
i
}
mr=
{
2
}
mb=
{
2
}
>
<
Tag
key=
{
i
}
mr=
{
1
}
mb=
{
1
}
>
{
item
}
</
Tag
>
))
...
...
client/src/pages/number/index.tsx
View file @
6ac7119e
...
...
@@ -245,13 +245,14 @@ const NumberSetting = ({ tableType }: { tableType: `${TableEnum}` }) => {
<
Card
mt=
{
4
}
px=
{
[
3
,
6
]
}
py=
{
4
}
>
<
Tabs
m=
{
'auto'
}
w=
{
'200px'
}
list=
{
tableList
.
current
}
activeId=
{
currentTab
}
size=
{
'sm'
}
onChange=
{
(
id
:
any
)
=>
setCurrentTab
(
id
)
}
/>
<
Box
>
<
Box
minH=
{
'300px'
}
>
{
(()
=>
{
const
item
=
tableList
.
current
.
find
((
item
)
=>
item
.
id
===
currentTab
);
...
...
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