(({ timeout = 2000 }) => {
+ const signIn = useUserStore((s) => s.openLogin);
+ const { t } = useTranslation('error');
+
+ useTimeout(() => {
+ signIn();
+ }, timeout);
+
+ return {t('loginRequired.desc')}
;
+});
+
+export default RedirectLogin;
diff --git a/src/components/FetchErrorNotification/index.tsx b/src/components/Error/fetchErrorNotification.tsx
similarity index 72%
rename from src/components/FetchErrorNotification/index.tsx
rename to src/components/Error/fetchErrorNotification.tsx
index 1b11a1cfd09bf..95919108f148d 100644
--- a/src/components/FetchErrorNotification/index.tsx
+++ b/src/components/Error/fetchErrorNotification.tsx
@@ -1,3 +1,4 @@
+import { FluentEmoji } from '@lobehub/ui';
import { t } from 'i18next';
import { notification } from '@/components/AntdStaticMethods';
@@ -8,7 +9,8 @@ export const fetchErrorNotification = {
error: ({ status, errorMessage }: { errorMessage: string; status: number }) => {
notification.error({
description: ,
- message: t('fetchError', { ns: 'error' }),
+ icon: ,
+ message: t('fetchError.title', { ns: 'error' }),
type: 'error',
});
},
diff --git a/src/components/Error/loginRequiredNotification.tsx b/src/components/Error/loginRequiredNotification.tsx
new file mode 100644
index 0000000000000..305cd63c70c1e
--- /dev/null
+++ b/src/components/Error/loginRequiredNotification.tsx
@@ -0,0 +1,19 @@
+import { FluentEmoji } from '@lobehub/ui';
+import { t } from 'i18next';
+
+import { notification } from '@/components/AntdStaticMethods';
+
+import RedirectLogin from './RedirectLogin';
+
+export const loginRequired = {
+ redirect: ({ timeout = 2000 }: { timeout?: number } = {}) => {
+ notification.error({
+ description: ,
+ duration: timeout / 1000,
+ icon: ,
+ message: t('loginRequired.title', { ns: 'error' }),
+ showProgress: true,
+ type: 'warning',
+ });
+ },
+};
diff --git a/src/features/User/UserInfo.tsx b/src/features/User/UserInfo.tsx
index 414f87d2411f9..5b7a2bd0d41bc 100644
--- a/src/features/User/UserInfo.tsx
+++ b/src/features/User/UserInfo.tsx
@@ -6,7 +6,7 @@ import { Flexbox, FlexboxProps } from 'react-layout-kit';
import PlanTag from '@/features/User/PlanTag';
import { useUserStore } from '@/store/user';
-import { userProfileSelectors } from '@/store/user/selectors';
+import { authSelectors, userProfileSelectors } from '@/store/user/selectors';
import UserAvatar, { type UserAvatarProps } from './UserAvatar';
@@ -28,7 +28,7 @@ export interface UserInfoProps extends FlexboxProps {
const UserInfo = memo(({ avatarProps, ...rest }) => {
const { styles, theme } = useStyles();
-
+ const isSignedIn = useUserStore(authSelectors.isLogin);
const [nickname, username] = useUserStore((s) => [
userProfileSelectors.nickName(s),
userProfileSelectors.username(s),
@@ -51,7 +51,7 @@ const UserInfo = memo(({ avatarProps, ...rest }) => {
{username}
-
+ {isSignedIn && }
);
});
diff --git a/src/libs/trpc/client/lambda.ts b/src/libs/trpc/client/lambda.ts
index 8edb114608a43..543cee1268f74 100644
--- a/src/libs/trpc/client/lambda.ts
+++ b/src/libs/trpc/client/lambda.ts
@@ -2,7 +2,8 @@ import { createTRPCClient, httpBatchLink } from '@trpc/client';
import { createTRPCReact } from '@trpc/react-query';
import superjson from 'superjson';
-import { fetchErrorNotification } from '@/components/FetchErrorNotification';
+import { fetchErrorNotification } from '@/components/Error/fetchErrorNotification';
+import { loginRequired } from '@/components/Error/loginRequiredNotification';
import { ModelProvider } from '@/libs/agent-runtime';
import type { LambdaRouter } from '@/server/routers/lambda';
@@ -20,7 +21,16 @@ const links = [
const errorData = item.error.json;
const status = errorData.data.httpStatus;
- fetchErrorNotification.error({ errorMessage: errorData.message, status });
+
+ switch (status) {
+ case 401: {
+ loginRequired.redirect();
+ break;
+ }
+ default: {
+ fetchErrorNotification.error({ errorMessage: errorData.message, status });
+ }
+ }
});
return response;
diff --git a/src/locales/default/error.ts b/src/locales/default/error.ts
index bc1d86cf907f4..4d4f06c9ab61a 100644
--- a/src/locales/default/error.ts
+++ b/src/locales/default/error.ts
@@ -12,8 +12,14 @@ export default {
retry: '重新加载',
title: '页面遇到一点问题..',
},
- fetchError: '请求失败',
- fetchErrorDetail: '错误详情',
+ fetchError: {
+ detail: '错误详情',
+ title: '请求失败',
+ },
+ loginRequired: {
+ desc: '即将自动跳转到登录页面',
+ title: '请登录后使用该功能',
+ },
notFound: {
backHome: '返回首页',
check: '请检查你的 URL 是否正确',
diff --git a/src/store/user/slices/auth/action.ts b/src/store/user/slices/auth/action.ts
index f5b6fac1b2ee3..5787730bff963 100644
--- a/src/store/user/slices/auth/action.ts
+++ b/src/store/user/slices/auth/action.ts
@@ -41,7 +41,12 @@ export const createAuthSlice: StateCreator<
},
openLogin: async () => {
if (enableClerk) {
- get().clerkSignIn?.({ fallbackRedirectUrl: location.toString() });
+ const reditectUrl = location.toString();
+ get().clerkSignIn?.({
+ fallbackRedirectUrl: reditectUrl,
+ signUpForceRedirectUrl: reditectUrl,
+ signUpUrl: '/signup',
+ });
return;
}