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
b4604860
authored
Sep 11, 2023
by
Archer
Committed by
GitHub
Sep 11, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: move dataset (#277)
parent
ae2887e9
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
413 additions
and
49 deletions
+413
-49
client/public/locales/en/common.json
+5
-0
client/public/locales/zh/common.json
+5
-0
client/src/api/plugins/kb.ts
+3
-2
client/src/api/request/kb.d.ts
+1
-0
client/src/components/Icon/icons/light/move.svg
+2
-0
client/src/components/Icon/icons/light/rightArrow.svg
+2
-1
client/src/components/Icon/index.tsx
+2
-1
client/src/components/MyMenu/index.tsx
+5
-2
client/src/hooks/useEditInfo.tsx
+2
-1
client/src/pages/api/plugins/kb/list.ts
+4
-2
client/src/pages/api/plugins/kb/update.ts
+5
-2
client/src/pages/app/detail/components/KBSelectModal.tsx
+8
-2
client/src/pages/components/Hero.tsx
+36
-7
client/src/pages/kb/detail/components/FileCard.tsx
+1
-1
client/src/pages/kb/list/component/MoveModal.tsx
+181
-0
client/src/pages/kb/list/index.tsx
+124
-25
client/src/store/dataset.ts
+27
-3
No files found.
client/public/locales/en/common.json
View file @
b4604860
...
@@ -5,7 +5,9 @@
...
@@ -5,7 +5,9 @@
"Create New"
:
"Create"
,
"Create New"
:
"Create"
,
"Dataset"
:
"Dataset"
,
"Dataset"
:
"Dataset"
,
"Folder"
:
"Folder"
,
"Folder"
:
"Folder"
,
"Move"
:
"Move"
,
"Name"
:
"Name"
,
"Name"
:
"Name"
,
"Rename"
:
"Rename"
,
"Running"
:
"Running"
,
"Running"
:
"Running"
,
"Select value is empty"
:
"Select value is empty"
,
"Select value is empty"
:
"Select value is empty"
,
"UnKnow"
:
"UnKnow"
,
"UnKnow"
:
"UnKnow"
,
...
@@ -163,6 +165,7 @@
...
@@ -163,6 +165,7 @@
},
},
"kb"
:
{
"kb"
:
{
"Chunk Length"
:
"Chunk Length"
,
"Chunk Length"
:
"Chunk Length"
,
"Confirm move the folder"
:
"Confirm Move"
,
"Confirm to delete the file"
:
"Are you sure to delete the file and all its data?"
,
"Confirm to delete the file"
:
"Are you sure to delete the file and all its data?"
,
"Create Folder"
:
"Create Folder"
,
"Create Folder"
:
"Create Folder"
,
"Delete Dataset Error"
:
"Delete dataset failed"
,
"Delete Dataset Error"
:
"Delete dataset failed"
,
...
@@ -171,7 +174,9 @@
...
@@ -171,7 +174,9 @@
"Filename"
:
"Filename"
,
"Filename"
:
"Filename"
,
"Files"
:
"{{total}} Files"
,
"Files"
:
"{{total}} Files"
,
"Folder Name"
:
"Input folder name"
,
"Folder Name"
:
"Input folder name"
,
"Move Failed"
:
"Move Failed"
,
"My Dataset"
:
"My Dataset"
,
"My Dataset"
:
"My Dataset"
,
"No Folder"
:
"No Folder"
,
"Other Data"
:
"Other Data"
,
"Other Data"
:
"Other Data"
,
"Select Dataset"
:
"Select Dataset"
,
"Select Dataset"
:
"Select Dataset"
,
"Select Folder"
:
"Enter folder"
,
"Select Folder"
:
"Enter folder"
,
...
...
client/public/locales/zh/common.json
View file @
b4604860
...
@@ -5,7 +5,9 @@
...
@@ -5,7 +5,9 @@
"Create New"
:
"新建"
,
"Create New"
:
"新建"
,
"Dataset"
:
"知识库"
,
"Dataset"
:
"知识库"
,
"Folder"
:
"文件夹"
,
"Folder"
:
"文件夹"
,
"Move"
:
"移动"
,
"Name"
:
"名称"
,
"Name"
:
"名称"
,
"Rename"
:
"重命名"
,
"Running"
:
"运行中"
,
"Running"
:
"运行中"
,
"Select value is empty"
:
"选择的内容为空"
,
"Select value is empty"
:
"选择的内容为空"
,
"UnKnow"
:
"未知"
,
"UnKnow"
:
"未知"
,
...
@@ -163,6 +165,7 @@
...
@@ -163,6 +165,7 @@
},
},
"kb"
:
{
"kb"
:
{
"Chunk Length"
:
"数据总量"
,
"Chunk Length"
:
"数据总量"
,
"Confirm move the folder"
:
"确认移动到该目录"
,
"Confirm to delete the file"
:
"确认删除该文件及其所有数据?"
,
"Confirm to delete the file"
:
"确认删除该文件及其所有数据?"
,
"Create Folder"
:
"创建文件夹"
,
"Create Folder"
:
"创建文件夹"
,
"Delete Dataset Error"
:
"删除知识库异常"
,
"Delete Dataset Error"
:
"删除知识库异常"
,
...
@@ -171,7 +174,9 @@
...
@@ -171,7 +174,9 @@
"Filename"
:
"文件名"
,
"Filename"
:
"文件名"
,
"Files"
:
"文件: {{total}}个"
,
"Files"
:
"文件: {{total}}个"
,
"Folder Name"
:
"输入文件夹名称"
,
"Folder Name"
:
"输入文件夹名称"
,
"Move Failed"
:
"移动出现错误~"
,
"My Dataset"
:
"我的知识库"
,
"My Dataset"
:
"我的知识库"
,
"No Folder"
:
"没有子目录了~"
,
"Other Data"
:
"其他数据"
,
"Other Data"
:
"其他数据"
,
"Select Dataset"
:
"选择该知识库"
,
"Select Dataset"
:
"选择该知识库"
,
"Select Folder"
:
"进入文件夹"
,
"Select Folder"
:
"进入文件夹"
,
...
...
client/src/api/plugins/kb.ts
View file @
b4604860
...
@@ -19,10 +19,11 @@ import {
...
@@ -19,10 +19,11 @@ import {
import
{
Props
as
UpdateDataProps
}
from
'@/pages/api/openapi/kb/updateData'
;
import
{
Props
as
UpdateDataProps
}
from
'@/pages/api/openapi/kb/updateData'
;
import
type
{
KbUpdateParams
,
CreateKbParams
,
GetKbDataListProps
}
from
'../request/kb'
;
import
type
{
KbUpdateParams
,
CreateKbParams
,
GetKbDataListProps
}
from
'../request/kb'
;
import
{
QuoteItemType
}
from
'@/types/chat'
;
import
{
QuoteItemType
}
from
'@/types/chat'
;
import
{
KbTypeEnum
}
from
'@/constants/kb'
;
/* knowledge base */
/* knowledge base */
export
const
getKbList
=
(
parentId
?:
string
)
=>
export
const
getKbList
=
(
data
:
{
parentId
?:
string
;
type
?:
`
${
KbTypeEnum
}
`
}
)
=>
GET
<
KbListItemType
[]
>
(
`/plugins/kb/list`
,
{
parentId
}
);
GET
<
KbListItemType
[]
>
(
`/plugins/kb/list`
,
data
);
export
const
getAllDataset
=
()
=>
GET
<
KbListItemType
[]
>
(
`/plugins/kb/allDataset`
);
export
const
getAllDataset
=
()
=>
GET
<
KbListItemType
[]
>
(
`/plugins/kb/allDataset`
);
export
const
getKbPaths
=
(
parentId
?:
string
)
=>
export
const
getKbPaths
=
(
parentId
?:
string
)
=>
...
...
client/src/api/request/kb.d.ts
View file @
b4604860
...
@@ -3,6 +3,7 @@ import type { RequestPaging } from '@/types';
...
@@ -3,6 +3,7 @@ import type { RequestPaging } from '@/types';
export
type
KbUpdateParams
=
{
export
type
KbUpdateParams
=
{
id
:
string
;
id
:
string
;
parentId
?:
string
;
tags
?:
string
;
tags
?:
string
;
name
?:
string
;
name
?:
string
;
avatar
?:
string
;
avatar
?:
string
;
...
...
client/src/components/Icon/icons/light/move.svg
0 → 100644
View file @
b4604860
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
t=
"1694403033666"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"4053"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"64"
height=
"64"
><path
d=
"M1016.32 494.08l-143.872-143.36c-9.728-9.728-26.112-9.728-35.84 0-9.728 9.728-9.728 26.112 0 35.84L936.96 486.4h-399.36V87.04l99.84 100.352c9.728 9.728 26.112 9.728 35.84 0 9.728-9.728 9.728-26.112 0-35.84l-143.36-143.872c-9.728-9.728-26.112-9.728-35.84 0l-143.36 143.872c-9.728 9.728-9.728 26.112 0 35.84 9.728 9.728 26.112 9.728 35.84 0L486.4 87.04v399.36H87.04l100.352-99.84c9.728-9.728 9.728-26.112 0-35.84-9.728-9.728-26.112-9.728-35.84 0l-143.872 143.36c-9.728 9.728-9.728 26.112 0 35.84l143.872 143.36c9.728 9.728 26.112 9.728 35.84 0 9.728-9.728 9.728-26.112 0-35.84L87.04 537.6h399.36v399.36l-99.84-100.352c-9.728-9.728-26.112-9.728-35.84 0-9.728 9.728-9.728 26.112 0 35.84l143.36 143.872c9.728 9.728 26.112 9.728 35.84 0l143.36-143.872c9.728-9.728 9.728-26.112 0-35.84-9.728-9.728-26.112-9.728-35.84 0L537.6 936.96v-399.36h399.36l-100.352 99.84c-9.728 9.728-9.728 26.112 0 35.84 9.728 9.728 26.112 9.728 35.84 0l143.872-143.36c10.24-9.728 10.24-26.112 0-35.84z"
p-id=
"4054"
></path></svg>
\ No newline at end of file
client/src/components/Icon/icons/light/rightArrow.svg
View file @
b4604860
<svg
width=
"24"
height=
"24"
viewBox=
"0 0 24 24"
>
<svg
viewBox=
"0 0 24 24"
>
<path
d=
"M8.3 5.7a1 1 0 011.4-1.4l7.71 7.7-7.7 7.7a1 1 0 11-1.42-1.4l6.3-6.3-6.3-6.3z"
fill-rule=
"nonzero"
></path>
<path
d=
"M8.3 5.7a1 1 0 011.4-1.4l7.71 7.7-7.7 7.7a1 1 0 11-1.42-1.4l6.3-6.3-6.3-6.3z"
fill-rule=
"nonzero"
></path>
</svg>
</svg>
\ No newline at end of file
client/src/components/Icon/index.tsx
View file @
b4604860
...
@@ -83,7 +83,8 @@ const map = {
...
@@ -83,7 +83,8 @@ const map = {
retryLight
:
require
(
'./icons/light/retry.svg'
).
default
,
retryLight
:
require
(
'./icons/light/retry.svg'
).
default
,
rightArrowLight
:
require
(
'./icons/light/rightArrow.svg'
).
default
,
rightArrowLight
:
require
(
'./icons/light/rightArrow.svg'
).
default
,
searchLight
:
require
(
'./icons/light/search.svg'
).
default
,
searchLight
:
require
(
'./icons/light/search.svg'
).
default
,
plusFill
:
require
(
'./icons/fill/plus.svg'
).
default
plusFill
:
require
(
'./icons/fill/plus.svg'
).
default
,
moveLight
:
require
(
'./icons/light/move.svg'
).
default
};
};
export
type
IconName
=
keyof
typeof
map
;
export
type
IconName
=
keyof
typeof
map
;
...
...
client/src/components/MyMenu/index.tsx
View file @
b4604860
...
@@ -8,7 +8,7 @@ interface Props {
...
@@ -8,7 +8,7 @@ interface Props {
menuList
:
{
menuList
:
{
isActive
?:
boolean
;
isActive
?:
boolean
;
child
:
React
.
ReactNode
;
child
:
React
.
ReactNode
;
onClick
:
()
=>
void
;
onClick
:
()
=>
any
;
}[];
}[];
}
}
...
@@ -37,7 +37,10 @@ const MyMenu = ({ width, offset = [0, 10], Button, menuList }: Props) => {
...
@@ -37,7 +37,10 @@ const MyMenu = ({ width, offset = [0, 10], Button, menuList }: Props) => {
<
MenuItem
<
MenuItem
key=
{
i
}
key=
{
i
}
{
...
menuItemStyles
}
{
...
menuItemStyles
}
onClick=
{
item
.
onClick
}
onClick=
{
(
e
)
=>
{
e
.
stopPropagation
();
item
.
onClick
&&
item
.
onClick
();
}
}
color=
{
item
.
isActive
?
'hover.blue'
:
''
}
color=
{
item
.
isActive
?
'hover.blue'
:
''
}
>
>
{
item
.
child
}
{
item
.
child
}
...
...
client/src/hooks/useEditInfo.tsx
View file @
b4604860
import
React
,
{
useCallback
,
useRef
,
useState
}
from
'react'
;
import
React
,
{
useCallback
,
useRef
}
from
'react'
;
import
{
ModalFooter
,
ModalBody
,
Input
,
useDisclosure
,
Button
}
from
'@chakra-ui/react'
;
import
{
ModalFooter
,
ModalBody
,
Input
,
useDisclosure
,
Button
}
from
'@chakra-ui/react'
;
import
MyModal
from
'@/components/MyModal'
;
import
MyModal
from
'@/components/MyModal'
;
...
@@ -39,6 +39,7 @@ export const useEditInfo = ({
...
@@ -39,6 +39,7 @@ export const useEditInfo = ({
try
{
try
{
const
val
=
inputRef
.
current
.
value
;
const
val
=
inputRef
.
current
.
value
;
await
onSuccessCb
.
current
?.(
val
);
await
onSuccessCb
.
current
?.(
val
);
onClose
();
onClose
();
}
catch
(
err
)
{
}
catch
(
err
)
{
onErrorCb
.
current
?.(
err
);
onErrorCb
.
current
?.(
err
);
...
...
client/src/pages/api/plugins/kb/list.ts
View file @
b4604860
...
@@ -4,10 +4,11 @@ import { connectToDatabase, KB } from '@/service/mongo';
...
@@ -4,10 +4,11 @@ import { connectToDatabase, KB } from '@/service/mongo';
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
getVectorModel
}
from
'@/service/utils/data'
;
import
{
getVectorModel
}
from
'@/service/utils/data'
;
import
{
KbListItemType
}
from
'@/types/plugin'
;
import
{
KbListItemType
}
from
'@/types/plugin'
;
import
{
KbTypeEnum
}
from
'@/constants/kb'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
try
{
const
{
parentId
}
=
req
.
query
as
{
parentId
:
string
};
const
{
parentId
,
type
}
=
req
.
query
as
{
parentId
?:
string
;
type
?:
`
${
KbTypeEnum
}
`
};
// 凭证校验
// 凭证校验
const
{
userId
}
=
await
authUser
({
req
,
authToken
:
true
});
const
{
userId
}
=
await
authUser
({
req
,
authToken
:
true
});
...
@@ -15,7 +16,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...
@@ -15,7 +16,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const
kbList
=
await
KB
.
find
({
const
kbList
=
await
KB
.
find
({
userId
,
userId
,
parentId
:
parentId
||
null
...(
parentId
!==
undefined
&&
{
parentId
:
parentId
||
null
}),
...(
type
&&
{
type
})
}).
sort
({
updateTime
:
-
1
});
}).
sort
({
updateTime
:
-
1
});
const
data
=
await
Promise
.
all
(
const
data
=
await
Promise
.
all
(
...
...
client/src/pages/api/plugins/kb/update.ts
View file @
b4604860
...
@@ -6,9 +6,9 @@ import type { KbUpdateParams } from '@/api/request/kb';
...
@@ -6,9 +6,9 @@ import type { KbUpdateParams } from '@/api/request/kb';
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
try
{
const
{
id
,
name
,
avatar
,
tags
=
''
}
=
req
.
body
as
KbUpdateParams
;
const
{
id
,
parentId
,
name
,
avatar
,
tags
}
=
req
.
body
as
KbUpdateParams
;
if
(
!
id
||
!
name
)
{
if
(
!
id
)
{
throw
new
Error
(
'缺少参数'
);
throw
new
Error
(
'缺少参数'
);
}
}
...
@@ -23,9 +23,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...
@@ -23,9 +23,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
userId
userId
},
},
{
{
...(
parentId
!==
undefined
&&
{
parentId
:
parentId
||
null
}),
...(
name
&&
{
name
}),
...(
name
&&
{
name
}),
...(
avatar
&&
{
avatar
}),
...(
avatar
&&
{
avatar
}),
...(
typeof
tags
===
'string'
&&
{
tags
:
tags
.
split
(
' '
).
filter
((
item
)
=>
item
)
tags
:
tags
.
split
(
' '
).
filter
((
item
)
=>
item
)
})
}
}
);
);
...
...
client/src/pages/app/detail/components/KBSelectModal.tsx
View file @
b4604860
...
@@ -83,7 +83,13 @@ export const KBSelectModal = ({
...
@@ -83,7 +83,13 @@ export const KBSelectModal = ({
<
Flex
flexDirection=
{
'column'
}
h=
{
[
'90vh'
,
'auto'
]
}
>
<
Flex
flexDirection=
{
'column'
}
h=
{
[
'90vh'
,
'auto'
]
}
>
<
ModalHeader
>
<
ModalHeader
>
{
!!
parentId
?
(
{
!!
parentId
?
(
<
Flex
flex=
{
1
}
>
<
Flex
flex=
{
1
}
userSelect=
{
'none'
}
fontSize=
{
[
'sm'
,
'lg'
]
}
fontWeight=
{
'normal'
}
color=
{
'myGray.900'
}
>
{
paths
.
map
((
item
,
i
)
=>
(
{
paths
.
map
((
item
,
i
)
=>
(
<
Flex
key=
{
item
.
parentId
}
mr=
{
2
}
alignItems=
{
'center'
}
>
<
Flex
key=
{
item
.
parentId
}
mr=
{
2
}
alignItems=
{
'center'
}
>
<
Box
<
Box
...
@@ -106,7 +112,7 @@ export const KBSelectModal = ({
...
@@ -106,7 +112,7 @@ export const KBSelectModal = ({
{
item
.
parentName
}
{
item
.
parentName
}
</
Box
>
</
Box
>
{
i
!==
paths
.
length
-
1
&&
(
{
i
!==
paths
.
length
-
1
&&
(
<
MyIcon
name=
{
'rightArrowLight'
}
color=
{
'myGray.500'
}
/>
<
MyIcon
name=
{
'rightArrowLight'
}
color=
{
'myGray.500'
}
w=
{
[
'18px'
,
'24px'
]
}
/>
)
}
)
}
</
Flex
>
</
Flex
>
))
}
))
}
...
...
client/src/pages/components/Hero.tsx
View file @
b4604860
import
{
Box
,
Flex
,
Button
,
Image
}
from
'@chakra-ui/react'
;
import
{
Box
,
Flex
,
Button
,
Image
}
from
'@chakra-ui/react'
;
import
React
from
'react'
;
import
React
,
{
useState
}
from
'react'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
{
feConfigs
}
from
'@/store/static'
;
import
{
feConfigs
}
from
'@/store/static'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
MyIcon
from
'@/components/Icon'
;
import
MyIcon
from
'@/components/Icon'
;
import
{
useRouter
}
from
'next/router'
;
import
{
useRouter
}
from
'next/router'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
const
Hero
=
()
=>
{
const
Hero
=
()
=>
{
const
router
=
useRouter
();
const
router
=
useRouter
();
const
{
toast
}
=
useToast
();
const
{
t
}
=
useTranslation
();
const
{
t
}
=
useTranslation
();
const
{
isPc
,
gitStar
}
=
useGlobalStore
();
const
{
isPc
,
gitStar
}
=
useGlobalStore
();
const
[
showVideo
,
setShowVide
]
=
useState
(
false
);
return
(
return
(
<
Flex
flexDirection=
{
'column'
}
pt=
{
[
'24px'
,
'50px'
]
}
alignItems=
{
'center'
}
userSelect=
{
'none'
}
>
<
Flex
flexDirection=
{
'column'
}
pt=
{
[
'24px'
,
'50px'
]
}
alignItems=
{
'center'
}
userSelect=
{
'none'
}
>
...
@@ -62,6 +61,7 @@ const Hero = () => {
...
@@ -62,6 +61,7 @@ const Hero = () => {
mx=
{
[
'-10%'
,
'auto'
]
}
mx=
{
[
'-10%'
,
'auto'
]
}
maxW=
{
[
'120%'
,
'1000px'
]
}
maxW=
{
[
'120%'
,
'1000px'
]
}
alt=
""
alt=
""
draggable=
{
false
}
/>
/>
<
MyIcon
<
MyIcon
name=
{
'playFill'
}
name=
{
'playFill'
}
...
@@ -72,14 +72,43 @@ const Hero = () => {
...
@@ -72,14 +72,43 @@ const Hero = () => {
top=
{
'50%'
}
top=
{
'50%'
}
color=
{
'#363c42b8'
}
color=
{
'#363c42b8'
}
transform=
{
[
'translate(-50%,5px)'
,
'translate(-50%,40px)'
]
}
transform=
{
[
'translate(-50%,5px)'
,
'translate(-50%,40px)'
]
}
onClick=
{
()
=>
{
onClick=
{
()
=>
setShowVide
(
true
)
}
toast
({
/>
title
:
'录制中~'
</
Box
>
});
{
showVideo
&&
(
<
Flex
position=
{
'fixed'
}
zIndex=
{
99
}
top=
{
0
}
left=
{
0
}
right=
{
0
}
bottom=
{
0
}
alignItems=
{
'center'
}
justifyContent=
{
'center'
}
bg=
{
'rgba(255,255,255,0.4)'
}
onClick=
{
()
=>
setShowVide
(
false
)
}
>
<
Box
w=
{
[
'100vw'
,
'50%'
]
}
borderRadius=
{
'lg'
}
overflow=
{
'hidden'
}
onClick=
{
(
e
)
=>
e
.
preventDefault
()
}
>
<
video
style=
{
{
margin
:
'auto'
}
}
}
}
onClick=
{
(
e
)
=>
{
e
.
stopPropagation
();
}
}
src=
{
'https://otnvvf-imgs.oss.laf.run/fastgpt.mp4'
}
controls
autoPlay
/>
/>
</
Box
>
</
Box
>
</
Flex
>
</
Flex
>
)
}
</
Flex
>
);
);
};
};
...
...
client/src/pages/kb/detail/components/FileCard.tsx
View file @
b4604860
...
@@ -145,7 +145,7 @@ const FileCard = ({ kbId }: { kbId: string }) => {
...
@@ -145,7 +145,7 @@ const FileCard = ({ kbId }: { kbId: string }) => {
cursor=
{
'pointer'
}
cursor=
{
'pointer'
}
title=
{
'点击查看数据详情'
}
title=
{
'点击查看数据详情'
}
onClick=
{
()
=>
onClick=
{
()
=>
router
.
push
({
router
.
replace
({
query
:
{
query
:
{
kbId
,
kbId
,
fileId
:
file
.
id
,
fileId
:
file
.
id
,
...
...
client/src/pages/kb/list/component/MoveModal.tsx
0 → 100644
View file @
b4604860
import
React
,
{
useMemo
,
useState
}
from
'react'
;
import
{
Card
,
Flex
,
Box
,
Button
,
ModalBody
,
ModalHeader
,
ModalFooter
,
useTheme
,
Grid
}
from
'@chakra-ui/react'
;
import
{
getKbPaths
}
from
'@/api/plugins/kb'
;
import
Avatar
from
'@/components/Avatar'
;
import
MyTooltip
from
'@/components/MyTooltip'
;
import
MyModal
from
'@/components/MyModal'
;
import
MyIcon
from
'@/components/Icon'
;
import
{
KbTypeEnum
}
from
'@/constants/kb'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
getKbList
,
putKbById
}
from
'@/api/plugins/kb'
;
import
{
useRequest
}
from
'@/hooks/useRequest'
;
const
MoveModal
=
({
onClose
,
onSuccess
,
moveDataId
}:
{
onClose
:
()
=>
void
;
onSuccess
:
()
=>
void
;
moveDataId
:
string
;
})
=>
{
const
{
t
}
=
useTranslation
();
const
theme
=
useTheme
();
const
[
parentId
,
setParentId
]
=
useState
<
string
>
(
''
);
const
{
data
}
=
useQuery
([
'getKbList'
,
parentId
],
()
=>
{
return
Promise
.
all
([
getKbList
({
parentId
,
type
:
'folder'
}),
getKbPaths
(
parentId
)]);
});
const
paths
=
useMemo
(
()
=>
[
{
parentId
:
''
,
parentName
:
t
(
'kb.My Dataset'
)
},
...(
data
?.[
1
]
||
[])
],
[
data
,
t
]
);
const
folderList
=
useMemo
(
()
=>
(
data
?.[
0
]
||
[]).
filter
((
item
)
=>
item
.
_id
!==
moveDataId
),
[
moveDataId
,
data
]
);
const
{
mutate
,
isLoading
}
=
useRequest
({
mutationFn
:
()
=>
putKbById
({
id
:
moveDataId
,
parentId
}),
onSuccess
,
errorToast
:
t
(
'kb.Move Failed'
)
});
return
(
<
MyModal
isOpen=
{
true
}
maxW=
{
[
'90vw'
,
'800px'
]
}
w=
{
'800px'
}
onClose=
{
onClose
}
>
<
Flex
flexDirection=
{
'column'
}
h=
{
[
'90vh'
,
'auto'
]
}
>
<
ModalHeader
>
{
!!
parentId
?
(
<
Flex
flex=
{
1
}
userSelect=
{
'none'
}
fontSize=
{
[
'sm'
,
'lg'
]
}
fontWeight=
{
'normal'
}
>
{
paths
.
map
((
item
,
i
)
=>
(
<
Flex
key=
{
item
.
parentId
}
mr=
{
2
}
alignItems=
{
'center'
}
>
<
Box
borderRadius=
{
'md'
}
{
...
(
i
===
paths
.
length
-
1
?
{
cursor
:
'
default
'
}
:
{
cursor
:
'
pointer
',
_hover
:
{
color
:
'
myBlue
.
600'
},
onClick
:
()
=
>
{
setParentId
(
item
.
parentId
);
}
})}
>
{
item
.
parentName
}
</
Box
>
{
i
!==
paths
.
length
-
1
&&
(
<
MyIcon
name=
{
'rightArrowLight'
}
color=
{
'myGray.500'
}
w=
{
[
'18px'
,
'24px'
]
}
/>
)
}
</
Flex
>
))
}
</
Flex
>
)
:
(
<
Box
>
我的知识库
</
Box
>
)
}
</
ModalHeader
>
<
ModalBody
flex=
{
[
'1 0 0'
,
'0 0 auto'
]
}
maxH=
{
'80vh'
}
overflowY=
{
'auto'
}
display=
{
'grid'
}
userSelect=
{
'none'
}
>
<
Grid
gridTemplateColumns=
{
[
'repeat(1,1fr)'
,
'repeat(2,1fr)'
,
'repeat(3,1fr)'
]
}
gridGap=
{
3
}
>
{
folderList
.
map
((
item
)
=>
(()
=>
{
return
(
<
MyTooltip
key=
{
item
.
_id
}
label=
{
item
.
type
===
KbTypeEnum
.
dataset
?
t
(
'kb.Select Dataset'
)
:
t
(
'kb.Select Folder'
)
}
>
<
Card
p=
{
3
}
border=
{
theme
.
borders
.
base
}
boxShadow=
{
'sm'
}
h=
{
'80px'
}
cursor=
{
'pointer'
}
_hover=
{
{
boxShadow
:
'md'
}
}
onClick=
{
()
=>
{
setParentId
(
item
.
_id
);
}
}
>
<
Flex
alignItems=
{
'center'
}
h=
{
'38px'
}
>
<
Avatar
src=
{
item
.
avatar
}
w=
{
[
'24px'
,
'28px'
]
}
></
Avatar
>
<
Box
className=
"textEllipsis"
ml=
{
3
}
fontWeight=
{
'bold'
}
fontSize=
{
[
'md'
,
'lg'
,
'xl'
]
}
>
{
item
.
name
}
</
Box
>
</
Flex
>
<
Flex
justifyContent=
{
'flex-end'
}
alignItems=
{
'center'
}
fontSize=
{
'sm'
}
>
{
item
.
type
===
KbTypeEnum
.
folder
?
(
<
Box
color=
{
'myGray.500'
}
>
{
t
(
'Folder'
)
}
</
Box
>
)
:
(
<>
<
MyIcon
mr=
{
1
}
name=
"kbTest"
w=
{
'12px'
}
/>
<
Box
color=
{
'myGray.500'
}
>
{
item
.
vectorModel
.
name
}
</
Box
>
</>
)
}
</
Flex
>
</
Card
>
</
MyTooltip
>
);
})()
)
}
</
Grid
>
{
folderList
.
length
===
0
&&
(
<
Flex
mt=
{
5
}
flexDirection=
{
'column'
}
alignItems=
{
'center'
}
>
<
MyIcon
name=
"empty"
w=
{
'48px'
}
h=
{
'48px'
}
color=
{
'transparent'
}
/>
<
Box
mt=
{
2
}
color=
{
'myGray.500'
}
>
{
t
(
'kb.No Folder'
)
}
</
Box
>
</
Flex
>
)
}
</
ModalBody
>
<
ModalFooter
>
<
Button
isLoading=
{
isLoading
}
onClick=
{
mutate
}
>
{
t
(
'kb.Confirm move the folder'
)
}
</
Button
>
</
ModalFooter
>
</
Flex
>
</
MyModal
>
);
};
export
default
MoveModal
;
client/src/pages/kb/list/index.tsx
View file @
b4604860
import
React
,
{
use
Callback
,
use
Memo
,
useRef
,
useState
}
from
'react'
;
import
React
,
{
useMemo
,
useRef
,
useState
}
from
'react'
;
import
{
import
{
Box
,
Box
,
Flex
,
Flex
,
...
@@ -6,7 +6,6 @@ import {
...
@@ -6,7 +6,6 @@ import {
useTheme
,
useTheme
,
useDisclosure
,
useDisclosure
,
Card
,
Card
,
IconButton
,
MenuButton
,
MenuButton
,
Image
Image
}
from
'@chakra-ui/react'
;
}
from
'@chakra-ui/react'
;
...
@@ -16,8 +15,7 @@ import PageContainer from '@/components/PageContainer';
...
@@ -16,8 +15,7 @@ import PageContainer from '@/components/PageContainer';
import
{
useConfirm
}
from
'@/hooks/useConfirm'
;
import
{
useConfirm
}
from
'@/hooks/useConfirm'
;
import
{
AddIcon
}
from
'@chakra-ui/icons'
;
import
{
AddIcon
}
from
'@chakra-ui/icons'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
delKbById
,
getKbPaths
,
putKbById
}
from
'@/api/plugins/kb'
;
import
{
delKbById
,
getKbPaths
}
from
'@/api/plugins/kb'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
Avatar
from
'@/components/Avatar'
;
import
Avatar
from
'@/components/Avatar'
;
import
MyIcon
from
'@/components/Icon'
;
import
MyIcon
from
'@/components/Icon'
;
...
@@ -28,16 +26,17 @@ import Tag from '@/components/Tag';
...
@@ -28,16 +26,17 @@ import Tag from '@/components/Tag';
import
MyMenu
from
'@/components/MyMenu'
;
import
MyMenu
from
'@/components/MyMenu'
;
import
{
useRequest
}
from
'@/hooks/useRequest'
;
import
{
useRequest
}
from
'@/hooks/useRequest'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useEditInfo
}
from
'@/hooks/useEditInfo'
;
const
CreateModal
=
dynamic
(()
=>
import
(
'./component/CreateModal'
),
{
ssr
:
false
});
const
CreateModal
=
dynamic
(()
=>
import
(
'./component/CreateModal'
),
{
ssr
:
false
});
const
EditFolderModal
=
dynamic
(()
=>
import
(
'./component/EditFolderModal'
),
{
ssr
:
false
});
const
EditFolderModal
=
dynamic
(()
=>
import
(
'./component/EditFolderModal'
),
{
ssr
:
false
});
const
MoveModal
=
dynamic
(()
=>
import
(
'./component/MoveModal'
),
{
ssr
:
false
});
const
Kb
=
()
=>
{
const
Kb
=
()
=>
{
const
{
t
}
=
useTranslation
();
const
{
t
}
=
useTranslation
();
const
theme
=
useTheme
();
const
theme
=
useTheme
();
const
router
=
useRouter
();
const
router
=
useRouter
();
const
{
parentId
}
=
router
.
query
as
{
parentId
:
string
};
const
{
parentId
}
=
router
.
query
as
{
parentId
:
string
};
const
{
toast
}
=
useToast
();
const
{
setLoading
}
=
useGlobalStore
();
const
{
setLoading
}
=
useGlobalStore
();
const
DeleteTipsMap
=
useRef
({
const
DeleteTipsMap
=
useRef
({
...
@@ -49,7 +48,13 @@ const Kb = () => {
...
@@ -49,7 +48,13 @@ const Kb = () => {
title
:
t
(
'common.Delete Warning'
),
title
:
t
(
'common.Delete Warning'
),
content
:
''
content
:
''
});
});
const
{
myKbList
,
loadKbList
,
setKbList
}
=
useDatasetStore
();
const
{
myKbList
,
loadKbList
,
setKbList
,
updateDataset
}
=
useDatasetStore
();
const
{
onOpenModal
:
onOpenTitleModal
,
EditModal
:
EditTitleModal
}
=
useEditInfo
({
title
:
t
(
'Rename'
)
});
const
[
moveDataId
,
setMoveDataId
]
=
useState
<
string
>
();
const
[
dragStartId
,
setDragStartId
]
=
useState
<
string
>
();
const
[
dragTargetId
,
setDragTargetId
]
=
useState
<
string
>
();
const
{
const
{
isOpen
:
isOpenCreateModal
,
isOpen
:
isOpenCreateModal
,
...
@@ -102,8 +107,8 @@ const Kb = () => {
...
@@ -102,8 +107,8 @@ const Kb = () => {
{
paths
.
map
((
item
,
i
)
=>
(
{
paths
.
map
((
item
,
i
)
=>
(
<
Flex
key=
{
item
.
parentId
}
mr=
{
2
}
alignItems=
{
'center'
}
>
<
Flex
key=
{
item
.
parentId
}
mr=
{
2
}
alignItems=
{
'center'
}
>
<
Box
<
Box
fontSize=
{
'lg'
}
fontSize=
{
[
'sm'
,
'lg'
]
}
px=
{
2
}
px=
{
[
0
,
2
]
}
py=
{
1
}
py=
{
1
}
borderRadius=
{
'md'
}
borderRadius=
{
'md'
}
{
...
(
i
===
paths
.
length
-
1
{
...
(
i
===
paths
.
length
-
1
...
@@ -126,7 +131,9 @@ const Kb = () => {
...
@@ -126,7 +131,9 @@ const Kb = () => {
>
>
{
item
.
parentName
}
{
item
.
parentName
}
</
Box
>
</
Box
>
{
i
!==
paths
.
length
-
1
&&
<
MyIcon
name=
{
'rightArrowLight'
}
color=
{
'myGray.500'
}
/>
}
{
i
!==
paths
.
length
-
1
&&
(
<
MyIcon
name=
{
'rightArrowLight'
}
color=
{
'myGray.500'
}
w=
{
[
'18px'
,
'24px'
]
}
/>
)
}
</
Flex
>
</
Flex
>
))
}
))
}
</
Flex
>
</
Flex
>
...
@@ -184,6 +191,7 @@ const Kb = () => {
...
@@ -184,6 +191,7 @@ const Kb = () => {
p=
{
5
}
p=
{
5
}
gridTemplateColumns=
{
[
'1fr'
,
'repeat(3,1fr)'
,
'repeat(4,1fr)'
,
'repeat(5,1fr)'
]
}
gridTemplateColumns=
{
[
'1fr'
,
'repeat(3,1fr)'
,
'repeat(4,1fr)'
,
'repeat(5,1fr)'
]
}
gridGap=
{
5
}
gridGap=
{
5
}
userSelect=
{
'none'
}
>
>
{
myKbList
.
map
((
kb
)
=>
(
{
myKbList
.
map
((
kb
)
=>
(
<
Card
<
Card
...
@@ -196,8 +204,36 @@ const Kb = () => {
...
@@ -196,8 +204,36 @@ const Kb = () => {
h=
{
'130px'
}
h=
{
'130px'
}
border=
{
theme
.
borders
.
md
}
border=
{
theme
.
borders
.
md
}
boxShadow=
{
'none'
}
boxShadow=
{
'none'
}
userSelect=
{
'none'
}
position=
{
'relative'
}
position=
{
'relative'
}
data
-
drag
-
id=
{
kb
.
type
===
KbTypeEnum
.
folder
?
kb
.
_id
:
undefined
}
borderColor=
{
dragTargetId
===
kb
.
_id
?
'myBlue.600'
:
''
}
draggable
onDragStart=
{
(
e
)
=>
{
setDragStartId
(
kb
.
_id
);
}
}
onDragOver=
{
(
e
)
=>
{
e
.
preventDefault
();
const
targetId
=
e
.
currentTarget
.
getAttribute
(
'data-drag-id'
);
if
(
!
targetId
)
return
;
KbTypeEnum
.
folder
&&
setDragTargetId
(
targetId
);
}
}
onDragLeave=
{
(
e
)
=>
{
e
.
preventDefault
();
setDragTargetId
(
undefined
);
}
}
onDrop=
{
async
(
e
)
=>
{
e
.
preventDefault
();
if
(
!
dragTargetId
||
!
dragStartId
||
dragTargetId
===
dragStartId
)
return
;
// update parentId
try
{
await
putKbById
({
id
:
dragStartId
,
parentId
:
dragTargetId
});
refetch
();
}
catch
(
error
)
{}
setDragTargetId
(
undefined
);
}
}
_hover=
{
{
_hover=
{
{
boxShadow
:
'1px 1px 10px rgba(0,0,0,0.2)'
,
boxShadow
:
'1px 1px 10px rgba(0,0,0,0.2)'
,
borderColor
:
'transparent'
,
borderColor
:
'transparent'
,
...
@@ -223,33 +259,85 @@ const Kb = () => {
...
@@ -223,33 +259,85 @@ const Kb = () => {
}
}
}
}
}
}
>
>
<
Flex
alignItems=
{
'center'
}
h=
{
'38px'
}
>
<
MyMenu
<
Avatar
src=
{
kb
.
avatar
}
borderRadius=
{
'lg'
}
w=
{
'28px'
}
/>
offset=
{
[
-
30
,
10
]
}
<
Box
ml=
{
3
}
>
{
kb
.
name
}
</
Box
>
width=
{
120
}
Button=
{
<
IconButton
<
MenuButton
className=
"delete"
position=
{
'absolute'
}
position=
{
'absolute'
}
top=
{
4
}
top=
{
3
}
right=
{
4
}
right=
{
3
}
size=
{
'sm'
}
w=
{
'22px'
}
icon=
{
<
MyIcon
name=
{
'delete'
}
w=
{
'14px'
}
/>
}
h=
{
'22px'
}
variant=
{
'base'
}
borderRadius=
{
'md'
}
borderRadius=
{
'md'
}
aria
-
label=
{
'delete'
}
display=
{
[
''
,
'none'
]
}
_hover=
{
{
_hover=
{
{
bg
:
'red.100'
color
:
'myBlue.600'
,
'& .icon'
:
{
bg
:
'myGray.100'
}
}
}
}
}
onClick=
{
(
e
)
=>
{
onClick=
{
(
e
)
=>
{
e
.
stopPropagation
();
e
.
stopPropagation
();
}
}
>
<
MyIcon
className=
"icon"
name=
{
'more'
}
h=
{
'16px'
}
w=
{
'16px'
}
px=
{
1
}
py=
{
1
}
borderRadius=
{
'md'
}
cursor=
{
'pointer'
}
/>
</
MenuButton
>
}
menuList=
{
[
{
child
:
(
<
Flex
alignItems=
{
'center'
}
>
<
MyIcon
name=
{
'edit'
}
w=
{
'14px'
}
mr=
{
2
}
/>
{
t
(
'Rename'
)
}
</
Flex
>
),
onClick
:
()
=>
onOpenTitleModal
({
defaultVal
:
kb
.
name
,
onSuccess
:
(
val
)
=>
{
if
(
val
===
kb
.
name
||
!
val
)
return
;
updateDataset
({
id
:
kb
.
_id
,
name
:
val
});
}
})
},
{
child
:
(
<
Flex
alignItems=
{
'center'
}
>
<
MyIcon
name=
{
'moveLight'
}
w=
{
'14px'
}
mr=
{
2
}
/>
{
t
(
'Move'
)
}
</
Flex
>
),
onClick
:
()
=>
setMoveDataId
(
kb
.
_id
)
},
{
child
:
(
<
Flex
alignItems=
{
'center'
}
>
<
MyIcon
name=
{
'delete'
}
w=
{
'14px'
}
mr=
{
2
}
/>
{
t
(
'common.Delete'
)
}
</
Flex
>
),
onClick
:
()
=>
{
openConfirm
(
openConfirm
(
()
=>
onclickDelKb
(
kb
.
_id
),
()
=>
onclickDelKb
(
kb
.
_id
),
undefined
,
undefined
,
DeleteTipsMap
.
current
[
kb
.
type
]
DeleteTipsMap
.
current
[
kb
.
type
]
)();
)();
}
}
}
}
]
}
/>
/>
<
Flex
alignItems=
{
'center'
}
h=
{
'38px'
}
>
<
Avatar
src=
{
kb
.
avatar
}
borderRadius=
{
'lg'
}
w=
{
'28px'
}
/>
<
Box
ml=
{
3
}
>
{
kb
.
name
}
</
Box
>
</
Flex
>
</
Flex
>
<
Box
flex=
{
'1 0 0'
}
overflow=
{
'hidden'
}
pt=
{
2
}
>
<
Box
flex=
{
'1 0 0'
}
overflow=
{
'hidden'
}
pt=
{
2
}
>
<
Flex
>
<
Flex
>
...
@@ -282,6 +370,7 @@ const Kb = () => {
...
@@ -282,6 +370,7 @@ const Kb = () => {
</
Flex
>
</
Flex
>
)
}
)
}
<
ConfirmModal
/>
<
ConfirmModal
/>
<
EditTitleModal
/>
{
isOpenCreateModal
&&
<
CreateModal
onClose=
{
onCloseCreateModal
}
parentId=
{
parentId
}
/>
}
{
isOpenCreateModal
&&
<
CreateModal
onClose=
{
onCloseCreateModal
}
parentId=
{
parentId
}
/>
}
{
!!
editFolderData
&&
(
{
!!
editFolderData
&&
(
<
EditFolderModal
<
EditFolderModal
...
@@ -291,6 +380,16 @@ const Kb = () => {
...
@@ -291,6 +380,16 @@ const Kb = () => {
{
...
editFolderData
}
{
...
editFolderData
}
/>
/>
)
}
)
}
{
!!
moveDataId
&&
(
<
MoveModal
moveDataId=
{
moveDataId
}
onClose=
{
()
=>
setMoveDataId
(
''
)
}
onSuccess=
{
()
=>
{
refetch
();
setMoveDataId
(
''
);
}
}
/>
)
}
</
PageContainer
>
</
PageContainer
>
);
);
};
};
...
...
client/src/store/dataset.ts
View file @
b4604860
...
@@ -3,8 +3,9 @@ import { devtools, persist } from 'zustand/middleware';
...
@@ -3,8 +3,9 @@ import { devtools, persist } from 'zustand/middleware';
import
{
immer
}
from
'zustand/middleware/immer'
;
import
{
immer
}
from
'zustand/middleware/immer'
;
import
{
type
KbTestItemType
}
from
'@/types/plugin'
;
import
{
type
KbTestItemType
}
from
'@/types/plugin'
;
import
type
{
KbItemType
,
KbListItemType
}
from
'@/types/plugin'
;
import
type
{
KbItemType
,
KbListItemType
}
from
'@/types/plugin'
;
import
{
getKbList
,
getKbById
,
getAllDataset
}
from
'@/api/plugins/kb'
;
import
{
getKbList
,
getKbById
,
getAllDataset
,
putKbById
}
from
'@/api/plugins/kb'
;
import
{
defaultKbDetail
}
from
'@/constants/kb'
;
import
{
defaultKbDetail
}
from
'@/constants/kb'
;
import
{
KbUpdateParams
}
from
'@/api/request/kb'
;
type
State
=
{
type
State
=
{
datasets
:
KbListItemType
[];
datasets
:
KbListItemType
[];
...
@@ -14,6 +15,7 @@ type State = {
...
@@ -14,6 +15,7 @@ type State = {
setKbList
(
val
:
KbListItemType
[]):
void
;
setKbList
(
val
:
KbListItemType
[]):
void
;
kbDetail
:
KbItemType
;
kbDetail
:
KbItemType
;
getKbDetail
:
(
id
:
string
,
init
?:
boolean
)
=>
Promise
<
KbItemType
>
;
getKbDetail
:
(
id
:
string
,
init
?:
boolean
)
=>
Promise
<
KbItemType
>
;
updateDataset
:
(
data
:
KbUpdateParams
)
=>
Promise
<
any
>
;
kbTestList
:
KbTestItemType
[];
kbTestList
:
KbTestItemType
[];
pushKbTestItem
:
(
data
:
KbTestItemType
)
=>
void
;
pushKbTestItem
:
(
data
:
KbTestItemType
)
=>
void
;
...
@@ -34,8 +36,8 @@ export const useDatasetStore = create<State>()(
...
@@ -34,8 +36,8 @@ export const useDatasetStore = create<State>()(
return
res
;
return
res
;
},
},
myKbList
:
[],
myKbList
:
[],
async
loadKbList
(
parentId
)
{
async
loadKbList
(
parentId
=
''
)
{
const
res
=
await
getKbList
(
parentId
);
const
res
=
await
getKbList
(
{
parentId
}
);
set
((
state
)
=>
{
set
((
state
)
=>
{
state
.
myKbList
=
res
;
state
.
myKbList
=
res
;
});
});
...
@@ -58,6 +60,28 @@ export const useDatasetStore = create<State>()(
...
@@ -58,6 +60,28 @@ export const useDatasetStore = create<State>()(
return
data
;
return
data
;
},
},
async
updateDataset
(
data
)
{
if
(
get
().
kbDetail
.
_id
===
data
.
id
)
{
set
((
state
)
=>
{
state
.
kbDetail
=
{
...
state
.
kbDetail
,
...
data
};
});
}
set
((
state
)
=>
{
state
.
myKbList
=
state
.
myKbList
=
state
.
myKbList
.
map
((
item
)
=>
item
.
_id
===
data
.
id
?
{
...
item
,
...
data
,
tags
:
data
.
tags
?.
split
(
' '
)
||
[]
}
:
item
);
});
await
putKbById
(
data
);
},
kbTestList
:
[],
kbTestList
:
[],
pushKbTestItem
(
data
)
{
pushKbTestItem
(
data
)
{
set
((
state
)
=>
{
set
((
state
)
=>
{
...
...
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