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
e64a2b04
authored
Jul 14, 2026
by
light5980
Committed by
GitHub
Jul 14, 2026
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix:split register methods from team sync mode (#7230)
parent
c8abd09d
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
116 additions
and
37 deletions
+116
-37
packages/global/common/system/types/index.ts
+12
-4
pro
+1
-1
projects/app/src/pageComponents/account/team/MemberTable.tsx
+2
-2
projects/app/src/pageComponents/account/team/OrgManage/index.tsx
+2
-1
projects/app/src/pageComponents/login/LoginForm/LoginForm.tsx
+32
-26
projects/app/src/pageComponents/login/RegisterForm.tsx
+3
-2
projects/app/src/pages/account/info/index.tsx
+2
-1
projects/app/src/web/common/system/utils.ts
+24
-0
projects/app/test/web/common/system/utils.test.ts
+38
-0
No files found.
packages/global/common/system/types/index.ts
View file @
e64a2b04
...
...
@@ -23,6 +23,10 @@ export type ExternalProviderWorkflowVarType = {
url
?:
string
;
};
export
type
FastGPTRegisterMethodType
=
'email'
|
'phone'
;
export
type
FastGPTRegisterMethodCompatType
=
FastGPTRegisterMethodType
|
'sync'
;
export
type
FastGPTTeamModeType
=
'multi'
|
'single'
|
'sync'
;
/* fastgpt main */
export
type
FastGPTConfigFileType
=
{
feConfigs
:
FastGPTFeConfigsType
;
...
...
@@ -42,10 +46,14 @@ export type FastGPTFeConfigsType = {
show_emptyChat
?:
boolean
;
isPlus
?:
boolean
;
hideChatCopyrightSetting
?:
boolean
;
register_method
?:
[
'email'
|
'phone'
|
'sync'
];
login_method
?:
[
'email'
|
'phone'
];
// Attention: login method is different with oauth
find_password_method
?:
[
'email'
|
'phone'
];
bind_notification_method
?:
[
'email'
|
'phone'
];
/**
* 用户自助注册方式。兼容期允许读取旧配置中的 sync,但新配置不再写入 sync。
*/
register_method
?:
FastGPTRegisterMethodCompatType
[];
teamMode
?:
FastGPTTeamModeType
;
login_method
?:
FastGPTRegisterMethodType
[];
// Attention: login method is different with oauth
find_password_method
?:
FastGPTRegisterMethodType
[];
bind_notification_method
?:
FastGPTRegisterMethodType
[];
googleClientVerKey
?:
string
;
/**
* @deprecated MCP SSE 代理地址已迁移到环境变量 SSE_MCP_SERVER_PROXY_ENDPOINT。
...
...
pro
@
11ed3ecf
Subproject commit
5f90c283f1e89ccfb40d17707f9f7603e0a1928e
Subproject commit
11ed3ecf86e55b38e9d829440f9492ec2479dd72
projects/app/src/pageComponents/account/team/MemberTable.tsx
View file @
e64a2b04
...
...
@@ -39,7 +39,7 @@ import { format } from 'date-fns/format';
import
OrgTags
from
'@/components/support/user/team/OrgTags'
;
import
SearchInput
from
'@fastgpt/web/components/common/Input/SearchInput'
;
import
{
useCallback
,
useState
,
useMemo
}
from
'react'
;
import
{
downloadFetch
}
from
'@/web/common/system/utils'
;
import
{
downloadFetch
,
getIsMemberSyncMode
}
from
'@/web/common/system/utils'
;
import
{
type
TeamMemberItemType
}
from
'@fastgpt/global/support/user/team/type'
;
import
{
useToast
}
from
'@fastgpt/web/hooks/useToast'
;
import
MyBox
from
'@fastgpt/web/components/common/MyBox'
;
...
...
@@ -59,7 +59,7 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
const
{
toast
}
=
useToast
();
const
{
userInfo
,
initUserInfo
}
=
useUserStore
();
const
{
feConfigs
}
=
useSystemStore
();
const
isSyncMode
=
feConfigs
?.
register_method
?.
includes
(
'sync'
);
const
isSyncMode
=
getIsMemberSyncMode
(
feConfigs
);
const
{
myTeams
,
onSwitchTeam
}
=
useContextSelector
(
TeamContext
,
(
v
)
=>
v
);
...
...
projects/app/src/pageComponents/account/team/OrgManage/index.tsx
View file @
e64a2b04
...
...
@@ -36,6 +36,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
import
{
delRemoveMember
}
from
'@/web/support/user/team/api'
;
import
SearchInput
from
'@fastgpt/web/components/common/Input/SearchInput'
;
import
useOrg
from
'@/web/support/user/team/org/hooks/useOrg'
;
import
{
getIsMemberSyncMode
}
from
'@/web/common/system/utils'
;
const
OrgInfoModal
=
dynamic
(()
=>
import
(
'./OrgInfoModal'
));
const
OrgMemberManageModal
=
dynamic
(()
=>
import
(
'./OrgMemberManageModal'
));
...
...
@@ -74,7 +75,7 @@ function OrgTable({ Tabs }: { Tabs: React.ReactNode }) {
const
{
t
}
=
useTranslation
();
const
{
userInfo
,
isTeamAdmin
}
=
useUserStore
();
const
{
feConfigs
}
=
useSystemStore
();
const
isSyncMember
=
feConfigs
.
register_method
?.
includes
(
'sync'
);
const
isSyncMember
=
getIsMemberSyncMode
(
feConfigs
);
const
[
editOrg
,
setEditOrg
]
=
useState
<
OrgFormType
>
();
const
[
manageMemberOrg
,
setManageMemberOrg
]
=
useState
<
OrgListItemType
>
();
const
[
movingOrg
,
setMovingOrg
]
=
useState
<
OrgListItemType
>
();
...
...
projects/app/src/pageComponents/login/LoginForm/LoginForm.tsx
View file @
e64a2b04
...
...
@@ -14,6 +14,7 @@ import { useMount } from 'ahooks';
import
type
{
LangEnum
}
from
'@fastgpt/global/common/i18n/type'
;
import
type
{
LoginSuccessResponseType
}
from
'@fastgpt/global/openapi/support/user/account/login/api'
;
import
PolicyTip
from
'./PolicyTip'
;
import
{
getRegisterMethods
}
from
'@/web/common/system/utils'
;
type
LoginSuccessHandler
=
(
res
:
LoginSuccessResponseType
)
=>
void
|
Promise
<
void
>
;
...
...
@@ -32,6 +33,9 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
const
{
feConfigs
}
=
useSystemStore
();
const
query
=
useSearchParams
();
const
router
=
useRouter
();
const
registerMethods
=
getRegisterMethods
(
feConfigs
);
const
hasRegisterMethod
=
registerMethods
.
length
>
0
;
const
hasFindPasswordMethod
=
!!
feConfigs
?.
find_password_method
?.
length
;
const
{
register
,
...
...
@@ -74,7 +78,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
}
);
const
isCommunityVersion
=
!!
(
feConfigs
?.
register_method
&&
!
feConfigs
?.
isPlus
)
;
const
isCommunityVersion
=
hasRegisterMethod
&&
!
feConfigs
?.
isPlus
;
const
placeholder
=
(()
=>
{
if
(
isCommunityVersion
)
{
...
...
@@ -158,29 +162,31 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
{
t
(
'login:Login'
)
}
</
Button
>
<
Flex
mt=
{
6
}
align=
{
'center'
}
justifyContent
=
{
'center'
}
gap=
{
0
}
color=
{
'primary.700'
}
fontWeight=
{
'medium
'
}
h=
{
'16px
'
}
lineHeight
=
{
'16px'
}
>
{
feConfigs
?.
find_password_method
&&
feConfigs
.
find_password_method
.
length
>
0
&&
(
<
Box
cursor=
{
'pointer'
}
_hover=
{
{
textDecoration
:
'underline'
}
}
onClick=
{
()
=>
setPageType
(
'forgetPassword'
)
}
fontSize=
"mini"
>
{
t
(
'login:forget_password'
)
}
</
Box
>
)
}
{
feConfigs
?.
register_method
&&
feConfigs
.
register_method
.
length
>
0
&&
(
<>
{
(
hasFindPasswordMethod
||
hasRegisterMethod
)
&&
(
<
Flex
mt=
{
6
}
align
=
{
'center'
}
justifyContent=
{
'center'
}
gap=
{
0
}
color=
{
'primary.700
'
}
fontWeight=
{
'medium
'
}
h
=
{
'16px'
}
lineHeight=
{
'16px'
}
>
{
hasFindPasswordMethod
&&
(
<
Box
cursor=
{
'pointer'
}
_hover=
{
{
textDecoration
:
'underline'
}
}
onClick=
{
()
=>
setPageType
(
'forgetPassword'
)
}
fontSize=
"mini"
>
{
t
(
'login:forget_password'
)
}
</
Box
>
)
}
{
hasFindPasswordMethod
&&
hasRegisterMethod
&&
(
<
Box
display=
{
[
'block'
,
'block'
]
}
mx=
{
3
}
h=
{
'12px'
}
w=
{
'1px'
}
bg=
{
'myGray.250'
}
></
Box
>
)
}
{
hasRegisterMethod
&&
(
<
Box
cursor=
{
'pointer'
}
_hover=
{
{
textDecoration
:
'underline'
}
}
...
...
@@ -190,9 +196,9 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
>
{
t
(
'login:register'
)
}
</
Box
>
</>
)
}
</
Flex
>
)
}
</
Flex
>
)
}
</
Box
>
</
FormLayout
>
);
...
...
projects/app/src/pageComponents/login/RegisterForm.tsx
View file @
e64a2b04
...
...
@@ -18,6 +18,7 @@ import {
import
{
checkPasswordRule
}
from
'@fastgpt/global/common/string/password'
;
import
type
{
LoginSuccessResponseType
}
from
'@fastgpt/global/openapi/support/user/account/login/api'
;
import
type
{
LangEnum
}
from
'@fastgpt/global/common/i18n/type'
;
import
{
getRegisterMethods
}
from
'@/web/common/system/utils'
;
type
LoginSuccessHandler
=
(
res
:
LoginSuccessResponseType
)
=>
void
|
Promise
<
void
>
;
...
...
@@ -88,8 +89,8 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
}
};
const
placeholder
=
feConfigs
?.
register_method
?
.
map
((
item
)
=>
{
const
placeholder
=
getRegisterMethods
(
feConfigs
)
.
map
((
item
)
=>
{
switch
(
item
)
{
case
'email'
:
return
t
(
'common:support.user.login.Email'
);
...
...
projects/app/src/pages/account/info/index.tsx
View file @
e64a2b04
...
...
@@ -47,6 +47,7 @@ import { useUploadAvatar } from '@fastgpt/web/common/file/hooks/useUploadAvatar'
import
{
getUploadAvatarPresignedUrl
}
from
'@/web/common/file/api'
;
import
{
TeamErrEnum
}
from
'@fastgpt/global/common/error/code/team'
;
import
{
i18nT
}
from
'@fastgpt/global/common/i18n/utils'
;
import
{
getIsMemberSyncMode
}
from
'@/web/common/system/utils'
;
const
RedeemCouponModal
=
dynamic
(()
=>
import
(
'@/pageComponents/account/info/RedeemCouponModal'
),
{
ssr
:
false
...
...
@@ -251,7 +252,7 @@ const MyInfo = ({ onOpenContact }: { onOpenContact: () => void }) => {
minW
:
'52px'
}
as
const
;
const
isSyncMember
=
feConfigs
.
register_method
?.
includes
(
'sync'
);
const
isSyncMember
=
getIsMemberSyncMode
(
feConfigs
);
return
(
<
Box
>
{
/* user info */
}
...
...
projects/app/src/web/common/system/utils.ts
View file @
e64a2b04
...
...
@@ -2,9 +2,33 @@ import {
type
EmbeddingModelItemType
,
type
LLMModelItemType
}
from
'@fastgpt/global/core/ai/model.schema'
;
import
type
{
FastGPTFeConfigsType
,
FastGPTRegisterMethodType
}
from
'@fastgpt/global/common/system/types'
;
import
{
useSystemStore
}
from
'./useSystemStore'
;
import
{
getWebReqUrl
}
from
'@fastgpt/web/common/system/utils'
;
/**
* 获取真实支持的自助注册方式,兼容过滤旧配置中被混入的 sync 团队模式。
*/
export
const
getRegisterMethods
=
(
feConfigs
?:
FastGPTFeConfigsType
):
FastGPTRegisterMethodType
[]
=>
feConfigs
?.
register_method
?.
filter
(
(
method
):
method
is
FastGPTRegisterMethodType
=>
method
===
'email'
||
method
===
'phone'
)
??
[];
/**
* 判断是否为成员同步模式。teamMode 是当前权威字段;旧 register_method: ['sync']
* 仅用于兼容缺少 teamMode 的历史配置,避免新旧字段冲突时前后端模式不一致。
*/
export
const
getIsMemberSyncMode
=
(
feConfigs
?:
FastGPTFeConfigsType
)
=>
{
if
(
feConfigs
?.
teamMode
)
{
return
feConfigs
.
teamMode
===
'sync'
;
}
return
!!
feConfigs
?.
register_method
?.
includes
(
'sync'
);
};
export
const
downloadFetch
=
async
({
url
,
filename
,
...
...
projects/app/test/web/common/system/utils.test.ts
0 → 100644
View file @
e64a2b04
import
{
describe
,
expect
,
it
}
from
'vitest'
;
import
type
{
FastGPTFeConfigsType
}
from
'@fastgpt/global/common/system/types'
;
import
{
getIsMemberSyncMode
,
getRegisterMethods
}
from
'@/web/common/system/utils'
;
const
createFeConfigs
=
(
overrides
:
Partial
<
FastGPTFeConfigsType
>
):
FastGPTFeConfigsType
=>
({
uploadFileMaxAmount
:
10
,
uploadFileMaxSize
:
100
,
...
overrides
});
describe
(
'system fe config utils'
,
()
=>
{
it
(
'filters legacy sync from register methods'
,
()
=>
{
expect
(
getRegisterMethods
(
createFeConfigs
({
register_method
:
[
'sync'
]
}))).
toEqual
([]);
expect
(
getRegisterMethods
(
createFeConfigs
({
register_method
:
[
'email'
,
'sync'
,
'phone'
]
}))
).
toEqual
([
'email'
,
'phone'
]);
});
it
(
'detects member sync mode from new teamMode and legacy register_method'
,
()
=>
{
expect
(
getIsMemberSyncMode
(
createFeConfigs
({
teamMode
:
'sync'
,
register_method
:
[]
}))).
toBe
(
true
);
expect
(
getIsMemberSyncMode
(
createFeConfigs
({
register_method
:
[
'sync'
]
}))).
toBe
(
true
);
expect
(
getIsMemberSyncMode
(
createFeConfigs
({
teamMode
:
'single'
,
register_method
:
[
'sync'
]
}))
).
toBe
(
false
);
expect
(
getIsMemberSyncMode
(
createFeConfigs
({
teamMode
:
'multi'
,
register_method
:
[
'sync'
]
}))
).
toBe
(
false
);
expect
(
getIsMemberSyncMode
(
createFeConfigs
({
teamMode
:
'multi'
,
register_method
:
[
'phone'
]
}))
).
toBe
(
false
);
expect
(
getIsMemberSyncMode
(
createFeConfigs
({
teamMode
:
'single'
,
register_method
:
[]
}))).
toBe
(
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