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
248be389
authored
Jul 26, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: chat ui
parent
2b993b92
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
153 additions
and
54 deletions
+153
-54
client/data/config.json
+9
-1
client/public/locales/en/common.json
+9
-0
client/public/locales/zh/common.json
+9
-0
client/src/api/chat.ts
+2
-4
client/src/components/Icon/index.tsx
+1
-1
client/src/components/Tag/index.tsx
+3
-3
client/src/hooks/useConfirm.tsx
+7
-4
client/src/pages/api/chat/removeHistory.ts
+19
-6
client/src/pages/app/detail/components/AdEdit/components/ChatTest.tsx
+1
-1
client/src/pages/app/detail/components/BasicEdit/index.tsx
+1
-1
client/src/pages/app/list/index.tsx
+5
-5
client/src/pages/chat/components/ChatHistorySlider.tsx
+27
-7
client/src/pages/chat/components/SliderApps.tsx
+2
-2
client/src/pages/chat/index.tsx
+37
-10
client/src/pages/chat/share.tsx
+8
-2
client/src/service/moduleDispatch/chat/oneapi.ts
+2
-2
client/src/store/chat.ts
+8
-1
client/src/store/static.ts
+0
-1
client/src/store/user.ts
+3
-3
No files found.
client/data/config.json
View file @
248be389
...
...
@@ -2,7 +2,7 @@
"FeConfig"
:
{
"show_emptyChat"
:
true
,
"show_register"
:
true
,
"show_appStore"
:
tru
e
,
"show_appStore"
:
fals
e
,
"show_userDetail"
:
true
,
"show_git"
:
true
,
"systemTitle"
:
"FastAI"
,
...
...
@@ -36,6 +36,14 @@
"price"
:
3
},
{
"model"
:
"ERNIE-Bot"
,
"name"
:
"文心一言"
,
"contextMaxToken"
:
3000
,
"quoteMaxToken"
:
1500
,
"maxTemperature"
:
1
,
"price"
:
1.2
},
{
"model"
:
"gpt-4"
,
"name"
:
"FastAI-Plus"
,
"contextMaxToken"
:
8000
,
...
...
client/public/locales/en/common.json
View file @
248be389
{
"Cancel"
:
"No"
,
"Confirm"
:
"Yes"
,
"Warning"
:
"Warning"
,
"app"
:
{
"App Detail"
:
"App Detail"
,
"My Apps"
:
"My Apps"
},
"chat"
:
{
"Confirm to clear history"
:
"Confirm to clear history?"
,
"New Chat"
:
"New Chat"
,
"You need to a chat app"
:
"You need to a chat app"
},
"home"
:
{
"Quickly build AI question and answer library"
:
"Quickly build AI question and answer library"
,
"Start Now"
:
"Start Now"
,
...
...
client/public/locales/zh/common.json
View file @
248be389
{
"Cancel"
:
"取消"
,
"Confirm"
:
"确认"
,
"Warning"
:
"提示"
,
"app"
:
{
"App Detail"
:
"应用详情"
,
"My Apps"
:
"我的应用"
},
"chat"
:
{
"Confirm to clear history"
:
"确认清空该应用的聊天记录?"
,
"New Chat"
:
"新对话"
,
"You need to a chat app"
:
"你需要创建一个应用"
},
"home"
:
{
"Quickly build AI question and answer library"
:
"快速搭建 AI 问答系统"
,
"Start Now"
:
"立即开始"
,
...
...
client/src/api/chat.ts
View file @
248be389
...
...
@@ -23,12 +23,10 @@ export const getChatHistory = (data: RequestPaging & { appId?: string }) =>
* 删除一条历史记录
*/
export
const
delChatHistoryById
=
(
chatId
:
string
)
=>
DELETE
(
`/chat/removeHistory`
,
{
chatId
});
/**
*
get history quotes
*
clear all history by appid
*/
export
const
getHistoryQuote
=
(
params
:
{
chatId
:
string
;
contentId
:
string
})
=>
GET
<
(
QuoteItemType
&
{
_id
:
string
})[]
>
(
`/chat/history/getHistoryQuote`
,
params
);
export
const
clearChatHistoryByAppId
=
(
appId
:
string
)
=>
DELETE
(
`/chat/removeHistory`
,
{
appId
});
/**
* update history quote status
...
...
client/src/components/Icon/index.tsx
View file @
248be389
...
...
@@ -37,7 +37,7 @@ const map = {
minus
:
require
(
'./icons/minus.svg'
).
default
,
chatLight
:
require
(
'./icons/light/chat.svg'
).
default
,
chatFill
:
require
(
'./icons/fill/chat.svg'
).
default
,
clear
Light
:
require
(
'./icons/light/clear.svg'
).
default
,
clear
:
require
(
'./icons/light/clear.svg'
).
default
,
apiLight
:
require
(
'./icons/light/appApi.svg'
).
default
,
overviewLight
:
require
(
'./icons/light/overview.svg'
).
default
,
settingLight
:
require
(
'./icons/light/setting.svg'
).
default
,
...
...
client/src/components/Tag/index.tsx
View file @
248be389
...
...
@@ -15,9 +15,9 @@ const Tag = ({ children, colorSchema = 'blue', ...props }: Props) => {
color
:
'myBlue.700'
},
green
:
{
borderColor
:
'#
54cd19
'
,
bg
:
'#f
2fcf2
'
,
color
:
'#
54cd19
'
borderColor
:
'#
67c13b
'
,
bg
:
'#f
8fff8
'
,
color
:
'#
67c13b
'
},
gray
:
{
borderColor
:
'#979797'
,
...
...
client/src/hooks/useConfirm.tsx
View file @
248be389
...
...
@@ -9,8 +9,11 @@ import {
useDisclosure
,
Button
}
from
'@chakra-ui/react'
;
import
{
useTranslation
}
from
'next-i18next'
;
export
const
useConfirm
=
({
title
=
'Warning'
,
content
}:
{
title
?:
string
;
content
:
string
})
=>
{
const
{
t
}
=
useTranslation
();
export
const
useConfirm
=
({
title
=
'提示'
,
content
}:
{
title
?:
string
;
content
:
string
})
=>
{
const
{
isOpen
,
onOpen
,
onClose
}
=
useDisclosure
();
const
cancelRef
=
useRef
(
null
);
const
confirmCb
=
useRef
<
any
>
();
...
...
@@ -32,7 +35,7 @@ export const useConfirm = ({ title = '提示', content }: { title?: string; cont
<
AlertDialogOverlay
>
<
AlertDialogContent
maxW=
{
'min(90vw,400px)'
}
>
<
AlertDialogHeader
fontSize=
"lg"
fontWeight=
"bold"
>
{
t
itle
}
{
t
(
title
)
}
</
AlertDialogHeader
>
<
AlertDialogBody
>
{
content
}
</
AlertDialogBody
>
...
...
@@ -45,7 +48,7 @@ export const useConfirm = ({ title = '提示', content }: { title?: string; cont
typeof
cancelCb
.
current
===
'function'
&&
cancelCb
.
current
();
}
}
>
取消
{
t
(
'Cancel'
)
}
</
Button
>
<
Button
ml=
{
4
}
...
...
@@ -54,7 +57,7 @@ export const useConfirm = ({ title = '提示', content }: { title?: string; cont
typeof
confirmCb
.
current
===
'function'
&&
confirmCb
.
current
();
}
}
>
确认
{
t
(
'Confirm'
)
}
</
Button
>
</
AlertDialogFooter
>
</
AlertDialogContent
>
...
...
client/src/pages/api/chat/removeHistory.ts
View file @
248be389
...
...
@@ -3,18 +3,31 @@ import { jsonRes } from '@/service/response';
import
{
connectToDatabase
,
Chat
}
from
'@/service/mongo'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
/* 获取历史记录 */
type
Props
=
{
chatId
?:
string
;
appId
?:
string
;
};
/* clear chat history */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
const
{
chatId
}
=
req
.
query
;
const
{
chatId
,
appId
}
=
req
.
query
as
Props
;
const
{
userId
}
=
await
authUser
({
req
,
authToken
:
true
});
await
connectToDatabase
();
await
Chat
.
findOneAndRemove
({
chatId
,
userId
});
if
(
chatId
)
{
await
Chat
.
findOneAndRemove
({
chatId
,
userId
});
}
if
(
appId
)
{
await
Chat
.
deleteMany
({
appId
,
userId
});
}
jsonRes
(
res
);
}
catch
(
err
)
{
...
...
client/src/pages/app/detail/components/AdEdit/components/ChatTest.tsx
View file @
248be389
...
...
@@ -96,7 +96,7 @@ const ChatTest = (
<
IconButton
className=
"chat"
size=
{
'sm'
}
icon=
{
<
MyIcon
name=
{
'clear
Light
'
}
w=
{
'14px'
}
/>
}
icon=
{
<
MyIcon
name=
{
'clear'
}
w=
{
'14px'
}
/>
}
variant=
{
'base'
}
borderRadius=
{
'md'
}
aria
-
label=
{
'delete'
}
...
...
client/src/pages/app/detail/components/BasicEdit/index.tsx
View file @
248be389
...
...
@@ -596,7 +596,7 @@ const ChatTest = ({ appId }: { appId: string }) => {
<
IconButton
className=
"chat"
size=
{
'sm'
}
icon=
{
<
MyIcon
name=
{
'clear
Light
'
}
w=
{
'14px'
}
/>
}
icon=
{
<
MyIcon
name=
{
'clear'
}
w=
{
'14px'
}
/>
}
variant=
{
'base'
}
borderRadius=
{
'md'
}
aria
-
label=
{
'delete'
}
...
...
client/src/pages/app/list/index.tsx
View file @
248be389
...
...
@@ -33,7 +33,7 @@ const MyApps = () => {
const
{
t
}
=
useTranslation
();
const
theme
=
useTheme
();
const
router
=
useRouter
();
const
{
myApps
,
loadMy
Model
s
}
=
useUserStore
();
const
{
myApps
,
loadMy
App
s
}
=
useUserStore
();
const
{
openConfirm
,
ConfirmChild
}
=
useConfirm
({
title
:
'删除提示'
,
content
:
'确认删除该应用所有信息?'
...
...
@@ -53,7 +53,7 @@ const MyApps = () => {
title
:
'删除成功'
,
status
:
'success'
});
loadMy
Model
s
();
loadMy
App
s
();
}
catch
(
err
:
any
)
{
toast
({
title
:
err
?.
message
||
'删除失败'
,
...
...
@@ -61,11 +61,11 @@ const MyApps = () => {
});
}
},
[
toast
,
loadMy
Model
s
]
[
toast
,
loadMy
App
s
]
);
/* 加载模型 */
useQuery
([
'loadModels'
],
loadMy
Model
s
,
{
useQuery
([
'loadModels'
],
loadMy
App
s
,
{
refetchOnMount
:
true
});
...
...
@@ -166,7 +166,7 @@ const MyApps = () => {
))
}
</
Grid
>
<
ConfirmChild
/>
{
isOpenCreateModal
&&
<
CreateModal
onClose=
{
onCloseCreateModal
}
onSuccess=
{
loadMy
Model
s
}
/>
}
{
isOpenCreateModal
&&
<
CreateModal
onClose=
{
onCloseCreateModal
}
onSuccess=
{
loadMy
App
s
}
/>
}
</
PageContainer
>
);
};
...
...
client/src/pages/chat/components/ChatHistorySlider.tsx
View file @
248be389
import
React
,
{
useMemo
,
useState
}
from
'react'
;
import
React
,
{
useMemo
}
from
'react'
;
import
{
Box
,
Button
,
...
...
@@ -16,6 +16,8 @@ import { useRouter } from 'next/router';
import
Avatar
from
'@/components/Avatar'
;
import
MyTooltip
from
'@/components/MyTooltip'
;
import
MyIcon
from
'@/components/Icon'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
{
useConfirm
}
from
'@/hooks/useConfirm'
;
type
HistoryItemType
=
{
id
:
string
;
...
...
@@ -32,6 +34,7 @@ const ChatHistorySlider = ({
activeChatId
,
onChangeChat
,
onDelHistory
,
onClearHistory
,
onSetHistoryTop
,
onSetCustomTitle
}:
{
...
...
@@ -42,17 +45,22 @@ const ChatHistorySlider = ({
activeChatId
:
string
;
onChangeChat
:
(
chatId
?:
string
)
=>
void
;
onDelHistory
:
(
chatId
:
string
)
=>
void
;
onClearHistory
:
()
=>
void
;
onSetHistoryTop
?:
(
e
:
{
chatId
:
string
;
top
:
boolean
})
=>
void
;
onSetCustomTitle
?:
(
e
:
{
chatId
:
string
;
title
:
string
})
=>
void
;
})
=>
{
const
theme
=
useTheme
();
const
router
=
useRouter
();
const
{
t
}
=
useTranslation
();
const
{
isPc
}
=
useGlobalStore
();
// custom title edit
const
{
onOpenModal
,
EditModal
:
EditTitleModal
}
=
useEditInfo
({
title
:
'自定义历史记录标题'
,
placeholder
:
'如果设置为空,会自动跟随聊天记录。'
});
const
{
openConfirm
,
ConfirmChild
}
=
useConfirm
({
content
:
t
(
'chat.Confirm to clear history'
)
});
const
concatHistory
=
useMemo
<
HistoryItemType
[]
>
(
()
=>
(
!
activeChatId
?
[{
id
:
activeChatId
,
title
:
'新对话'
}].
concat
(
history
)
:
history
),
...
...
@@ -70,7 +78,7 @@ const ChatHistorySlider = ({
whiteSpace=
{
'nowrap'
}
>
{
isPc
&&
(
<
MyTooltip
label=
{
appId
?
'应用详情'
:
''
}
offset=
{
[
0
,
0
]
}
>
<
MyTooltip
label=
{
appId
?
t
(
'app.App Detail'
)
:
''
}
offset=
{
[
0
,
0
]
}
>
<
Flex
pt=
{
5
}
pb=
{
2
}
...
...
@@ -92,11 +100,11 @@ const ChatHistorySlider = ({
</
Flex
>
</
MyTooltip
>
)
}
{
/*
新对话
*/
}
<
Bo
x
w=
{
'100%'
}
px=
{
[
2
,
5
]
}
h=
{
'36px'
}
my=
{
5
}
>
{
/*
btn
*/
}
<
Fle
x
w=
{
'100%'
}
px=
{
[
2
,
5
]
}
h=
{
'36px'
}
my=
{
5
}
>
<
Button
variant=
{
'base'
}
w=
{
'100%'
}
flex=
{
1
}
h=
{
'100%'
}
color=
{
'myBlue.700'
}
borderRadius=
{
'xl'
}
...
...
@@ -104,9 +112,20 @@ const ChatHistorySlider = ({
overflow=
{
'hidden'
}
onClick=
{
()
=>
onChangeChat
()
}
>
新对话
{
t
(
'chat.New Chat'
)
}
</
Button
>
</
Box
>
<
IconButton
ml=
{
3
}
h=
{
'100%'
}
variant=
{
'base'
}
aria
-
label=
{
''
}
borderRadius=
{
'xl'
}
onClick=
{
openConfirm
(
onClearHistory
)
}
>
<
MyIcon
name=
{
'clear'
}
w=
{
'16px'
}
/>
</
IconButton
>
</
Flex
>
{
/* chat history */
}
<
Box
flex=
{
'1 0 0'
}
h=
{
0
}
px=
{
[
2
,
5
]
}
overflow=
{
'overlay'
}
>
...
...
@@ -230,6 +249,7 @@ const ChatHistorySlider = ({
</
Flex
>
)
}
<
EditTitleModal
/>
<
ConfirmChild
/>
</
Flex
>
);
};
...
...
client/src/pages/chat/components/SliderApps.tsx
View file @
248be389
...
...
@@ -8,9 +8,9 @@ import Avatar from '@/components/Avatar';
const
SliderApps
=
({
appId
}:
{
appId
:
string
})
=>
{
const
router
=
useRouter
();
const
{
myApps
,
loadMy
Model
s
}
=
useUserStore
();
const
{
myApps
,
loadMy
App
s
}
=
useUserStore
();
useQuery
([
'loadModels'
],
loadMy
Model
s
);
useQuery
([
'loadModels'
],
loadMy
App
s
);
return
(
<>
...
...
client/src/pages/chat/index.tsx
View file @
248be389
...
...
@@ -19,6 +19,7 @@ import { useToast } from '@/hooks/useToast';
import
{
customAlphabet
}
from
'nanoid'
;
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyz1234567890'
,
12
);
import
type
{
ChatHistoryItemType
}
from
'@/types/chat'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
ChatBox
,
{
type
ComponentRef
,
type
StartChatFnProps
}
from
'@/components/ChatBox'
;
import
PageContainer
from
'@/components/PageContainer'
;
...
...
@@ -33,6 +34,7 @@ import { serviceSideProps } from '@/utils/i18n';
const
Chat
=
({
appId
,
chatId
}:
{
appId
:
string
;
chatId
:
string
})
=>
{
const
router
=
useRouter
();
const
theme
=
useTheme
();
const
{
t
}
=
useTranslation
();
const
{
toast
}
=
useToast
();
const
ChatBoxRef
=
useRef
<
ComponentRef
>
(
null
);
...
...
@@ -47,10 +49,11 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
loadHistory
,
updateHistory
,
delHistory
,
clearHistory
,
chatData
,
setChatData
}
=
useChatStore
();
const
{
myApps
,
userInfo
}
=
useUserStore
();
const
{
myApps
,
loadMyApps
,
userInfo
}
=
useUserStore
();
const
{
isPc
}
=
useGlobalStore
();
const
{
Loading
,
setIsLoading
}
=
useLoading
();
...
...
@@ -200,6 +203,26 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
}
});
}
if
(
!
appId
)
{
(
async
()
=>
{
const
apps
=
await
loadMyApps
();
if
(
apps
.
length
===
0
)
{
toast
({
status
:
'error'
,
title
:
t
(
'chat.You need to a chat app'
)
});
router
.
replace
(
'/app/list'
);
}
else
{
router
.
replace
({
query
:
{
appId
:
apps
[
0
].
_id
,
chatId
:
lastChatId
}
});
}
})();
return
;
}
// store id
appId
&&
setLastChatAppId
(
appId
);
...
...
@@ -210,15 +233,11 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
return
null
;
}
if
(
appId
)
{
return
loadChatInfo
({
appId
,
chatId
,
loading
:
appId
!==
chatData
.
appId
});
}
return
null
;
return
loadChatInfo
({
appId
,
chatId
,
loading
:
appId
!==
chatData
.
appId
});
});
useQuery
([
'loadHistory'
,
appId
],
()
=>
(
appId
?
loadHistory
({
appId
})
:
null
));
...
...
@@ -268,6 +287,14 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
}
}
}
onDelHistory=
{
delHistory
}
onClearHistory=
{
()
=>
{
clearHistory
(
appId
);
router
.
replace
({
query
:
{
appId
}
});
}
}
onSetHistoryTop=
{
async
(
e
)
=>
{
try
{
await
putChatHistory
(
e
);
...
...
client/src/pages/chat/share.tsx
View file @
248be389
...
...
@@ -99,8 +99,6 @@ const ShareChat = ({ shareId, chatId }: { shareId: string; chatId: string }) =>
const
loadAppInfo
=
useCallback
(
async
(
shareId
:
string
,
chatId
:
string
)
=>
{
console
.
log
(
shareId
,
chatId
);
if
(
!
shareId
)
return
null
;
const
history
=
shareChatHistory
.
find
((
item
)
=>
item
.
chatId
===
chatId
)
||
defaultHistory
;
...
...
@@ -183,6 +181,14 @@ const ShareChat = ({ shareId, chatId }: { shareId: string; chatId: string }) =>
}
}
}
onDelHistory=
{
delOneShareHistoryByChatId
}
onClearHistory=
{
()
=>
{
delManyShareChatHistoryByShareId
(
shareId
);
router
.
replace
({
query
:
{
shareId
}
});
}
}
/>
)
}
...
...
client/src/service/moduleDispatch/chat/oneapi.ts
View file @
248be389
...
...
@@ -72,16 +72,16 @@ export const dispatchChatCompletion = async (props: Record<string, any>): Promis
maxToken
,
filterMessages
});
// console.log(messages);
// FastGpt temperature range: 1~10
temperature
=
+
(
modelConstantsData
.
maxTemperature
*
(
temperature
/
10
)).
toFixed
(
2
);
temperature
=
Math
.
max
(
temperature
,
0.01
);
const
chatAPI
=
getOpenAIApi
();
const
response
=
await
chatAPI
.
createChatCompletion
(
{
model
,
temperature
:
Number
(
temperature
||
0
)
,
temperature
,
max_tokens
,
messages
,
// frequency_penalty: 0.5, // 越大,重复内容越少
...
...
client/src/store/chat.ts
View file @
248be389
...
...
@@ -4,12 +4,13 @@ import { immer } from 'zustand/middleware/immer';
import
{
ChatHistoryItemType
}
from
'@/types/chat'
;
import
type
{
InitChatResponse
}
from
'@/api/response/chat'
;
import
{
delChatHistoryById
,
getChatHistory
}
from
'@/api/chat'
;
import
{
delChatHistoryById
,
getChatHistory
,
clearChatHistoryByAppId
}
from
'@/api/chat'
;
type
State
=
{
history
:
ChatHistoryItemType
[];
loadHistory
:
(
data
:
{
appId
?:
string
})
=>
Promise
<
null
>
;
delHistory
(
history
:
string
):
Promise
<
void
>
;
clearHistory
(
appId
:
string
):
Promise
<
void
>
;
updateHistory
:
(
history
:
ChatHistoryItemType
)
=>
void
;
chatData
:
InitChatResponse
;
setChatData
:
(
e
:
InitChatResponse
|
((
e
:
InitChatResponse
)
=>
InitChatResponse
))
=>
void
;
...
...
@@ -69,6 +70,12 @@ export const useChatStore = create<State>()(
});
await
delChatHistoryById
(
chatId
);
},
async
clearHistory
(
appId
)
{
set
((
state
)
=>
{
state
.
history
=
[];
});
await
clearChatHistoryByAppId
(
appId
);
},
updateHistory
(
history
)
{
const
index
=
get
().
history
.
findIndex
((
item
)
=>
item
.
chatId
===
history
.
chatId
);
set
((
state
)
=>
{
...
...
client/src/store/static.ts
View file @
248be389
...
...
@@ -29,7 +29,6 @@ export const clientInitData = async (): Promise<InitDateResponse> => {
beianText
=
res
.
systemEnv
?.
beianText
;
googleClientVerKey
=
res
.
systemEnv
?.
googleClientVerKey
;
baiduTongji
=
res
.
systemEnv
?.
baiduTongji
;
console
.
log
(
res
.
feConfigs
);
return
res
;
}
catch
(
error
)
{
...
...
client/src/store/user.ts
View file @
248be389
...
...
@@ -19,7 +19,7 @@ type State = {
updateUserInfo
:
(
user
:
UserUpdateParams
)
=>
void
;
myApps
:
AppListItemType
[];
myCollectionApps
:
AppListItemType
[];
loadMy
Models
:
()
=>
Promise
<
null
>
;
loadMy
Apps
:
()
=>
Promise
<
AppListItemType
[]
>
;
appDetail
:
AppSchema
;
loadAppDetail
:
(
id
:
string
,
init
?:
boolean
)
=>
Promise
<
AppSchema
>
;
updateAppDetail
(
appId
:
string
,
data
:
AppUpdateParams
):
Promise
<
void
>
;
...
...
@@ -63,12 +63,12 @@ export const useUserStore = create<State>()(
},
myApps
:
[],
myCollectionApps
:
[],
async
loadMy
Model
s
()
{
async
loadMy
App
s
()
{
const
res
=
await
getMyModels
();
set
((
state
)
=>
{
state
.
myApps
=
res
;
});
return
null
;
return
res
;
},
appDetail
:
defaultApp
,
async
loadAppDetail
(
id
:
string
,
init
=
false
)
{
...
...
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