-
-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #58 from lobehub/fix/role-edit
feat: 错误处理 & 配置优化
- Loading branch information
Showing
55 changed files
with
1,126 additions
and
585 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
'use client'; | ||
|
||
import dynamic from 'next/dynamic'; | ||
|
||
export default dynamic(() => import('@/components/Error')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
'use client'; | ||
|
||
import Error from 'next/error'; | ||
import { useEffect } from 'react'; | ||
|
||
export default function GlobalError({ | ||
error, | ||
}: { | ||
error: Error & { digest?: string }; | ||
reset: () => void; | ||
}) { | ||
useEffect(() => { | ||
console.log('error', error); | ||
}, [error]); | ||
return ( | ||
<html> | ||
<body> | ||
<Error statusCode={undefined as any} /> | ||
</body> | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { createStyles } from 'antd-style'; | ||
import NextImage from 'next/image'; | ||
|
||
import { AVATAR_IMAGE_SIZE, DEFAULT_USER_AVATAR_URL } from '@/constants/common'; | ||
|
||
const useStyle = createStyles( | ||
({ css, token }) => css` | ||
cursor: pointer; | ||
overflow: hidden; | ||
border-radius: 50%; | ||
transition: | ||
scale 400ms ${token.motionEaseOut}, | ||
box-shadow 100ms ${token.motionEaseOut}; | ||
&:hover { | ||
box-shadow: 0 0 0 3px ${token.colorText}; | ||
} | ||
&:active { | ||
scale: 0.8; | ||
} | ||
`, | ||
); | ||
|
||
interface Props { | ||
avatar?: string; | ||
size?: number; | ||
} | ||
|
||
export default (props: Props) => { | ||
const { size = AVATAR_IMAGE_SIZE, avatar } = props; | ||
const { styles } = useStyle(); | ||
return ( | ||
<NextImage | ||
className={styles} | ||
alt={avatar ? 'userAvatar' : 'LobeVidol'} | ||
height={size} | ||
src={!!avatar ? avatar : DEFAULT_USER_AVATAR_URL} | ||
unoptimized | ||
width={size} | ||
/> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
'use client'; | ||
|
||
import { FluentEmoji } from '@lobehub/ui'; | ||
import { Button } from 'antd'; | ||
import Link from 'next/link'; | ||
import { memo, useEffect } from 'react'; | ||
import { Flexbox } from 'react-layout-kit'; | ||
|
||
import { MAX_WIDTH } from '@/constants/common'; | ||
import ResetConfig from '@/features/Actions/ClearSession'; | ||
import ClearChat from '@/features/Actions/ResetConfig'; | ||
|
||
interface ErrorCaptureProps { | ||
error: Error & { digest?: string }; | ||
reset: () => void; | ||
} | ||
|
||
const ErrorCapture = memo<ErrorCaptureProps>(({ reset, error }) => { | ||
useEffect(() => { | ||
// Log the error to an error reporting service | ||
console.error(error); | ||
}, [error]); | ||
|
||
return ( | ||
<Flexbox align={'center'} justify={'center'} style={{ minHeight: '100%', width: '100%' }}> | ||
<h1 | ||
style={{ | ||
filter: 'blur(8px)', | ||
fontSize: `min(${MAX_WIDTH / 6}px, 25vw)`, | ||
fontWeight: 900, | ||
margin: 0, | ||
opacity: 0.12, | ||
position: 'absolute', | ||
zIndex: 0, | ||
}} | ||
> | ||
ERROR | ||
</h1> | ||
<FluentEmoji emoji={'🤧'} size={64} /> | ||
<h2 style={{ fontWeight: 'bold', marginTop: '1em', textAlign: 'center' }}> | ||
页面遇到一点问题... | ||
</h2> | ||
<p style={{ marginBottom: '2em' }}> | ||
项目当前正在施工中,不保证数据稳定性,如果遇到问题可以尝试 | ||
<ClearChat text="清除会话消息" type={'link'} /> | ||
或 <ResetConfig text="重置系统设置" type={'link'} /> | ||
,造成地不便敬请谅解 | ||
</p> | ||
<Flexbox gap={12} horizontal style={{ marginBottom: '1em' }}> | ||
<Button onClick={() => reset()}>重新加载</Button> | ||
<Link href="/"> | ||
<Button type={'primary'}>返回首页</Button> | ||
</Link> | ||
</Flexbox> | ||
</Flexbox> | ||
); | ||
}); | ||
|
||
ErrorCapture.displayName = 'ErrorCapture'; | ||
|
||
export default ErrorCapture; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { Menu as AntdMenu, MenuProps as AntdMenuProps, ConfigProvider } from 'antd'; | ||
import { createStyles } from 'antd-style'; | ||
import { memo } from 'react'; | ||
|
||
const useStyles = createStyles(({ css, token, prefixCls }) => ({ | ||
compact: css` | ||
display: flex; | ||
flex-direction: column; | ||
gap: 0.125rem; | ||
`, | ||
menu: css` | ||
flex: 1; | ||
background: transparent; | ||
border: none !important; | ||
.${prefixCls}-menu-item-divider { | ||
margin-block: 0.125rem; | ||
border-color: ${token.colorFillTertiary}; | ||
&:first-child { | ||
margin-top: 0; | ||
} | ||
&:last-child { | ||
margin-bottom: 0; | ||
} | ||
} | ||
.${prefixCls}-menu-item, .${prefixCls}-menu-submenu-title { | ||
display: flex; | ||
gap: 0.75rem; | ||
align-items: center; | ||
height: unset; | ||
min-height: 2rem; | ||
padding: 0.375rem 0.75rem; | ||
line-height: 2; | ||
.anticon + .${prefixCls}-menu-title-content { | ||
margin-inline-start: 0; | ||
} | ||
} | ||
.${prefixCls}-menu-item-selected { | ||
.${prefixCls}-menu-item-icon svg { | ||
color: ${token.colorText}; | ||
} | ||
} | ||
.${prefixCls}-menu-item-icon svg { | ||
color: ${token.colorTextSecondary}; | ||
} | ||
.${prefixCls}-menu-title-content { | ||
flex: 1; | ||
} | ||
`, | ||
})); | ||
|
||
export interface MenuProps extends AntdMenuProps { | ||
variant?: 'default' | 'compact'; | ||
} | ||
|
||
const Menu = memo<MenuProps>(({ className, selectable = false, variant, ...rest }) => { | ||
const isCompact = variant === 'compact'; | ||
const { cx, styles, theme } = useStyles(); | ||
return ( | ||
<ConfigProvider | ||
theme={{ | ||
components: { | ||
Menu: { | ||
controlHeightLG: 36, | ||
iconMarginInlineEnd: 8, | ||
iconSize: 16, | ||
itemBorderRadius: theme.borderRadius, | ||
itemColor: selectable ? theme.colorTextSecondary : theme.colorText, | ||
itemHoverBg: theme.colorFillTertiary, | ||
itemMarginBlock: isCompact ? 0 : 4, | ||
itemMarginInline: isCompact ? 0 : 4, | ||
itemSelectedBg: theme.colorFillSecondary, | ||
paddingXS: -8, | ||
}, | ||
}, | ||
}} | ||
> | ||
<AntdMenu | ||
className={cx(styles.menu, isCompact && styles.compact, className)} | ||
mode="vertical" | ||
selectable={selectable} | ||
{...rest} | ||
/> | ||
</ConfigProvider> | ||
); | ||
}); | ||
|
||
export default Menu; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { App, Button } from 'antd'; | ||
import { ButtonType } from 'antd/es/button'; | ||
import React from 'react'; | ||
|
||
import { useAgentStore } from '@/store/agent'; | ||
import { useSessionStore } from '@/store/session'; | ||
|
||
interface Props { | ||
text?: string; | ||
type?: ButtonType; | ||
} | ||
export default (props: Props) => { | ||
const { text = '立即清除', type = 'primary' } = props; | ||
const clearAgentStorage = useAgentStore((s) => s.clearAgentStorage); | ||
const clearSessions = useSessionStore((s) => s.clearSessions); | ||
const { message, modal } = App.useApp(); | ||
|
||
const handleClear = () => { | ||
modal.confirm({ | ||
cancelText: '取消', | ||
centered: true, | ||
content: '操作无法撤销,清除后数据将无法恢复,请慎重操作', | ||
okButtonProps: { | ||
danger: true, | ||
}, | ||
okText: '确定', | ||
onOk: () => { | ||
clearSessions(); | ||
clearAgentStorage(); | ||
message.success('清除成功'); | ||
}, | ||
title: '确认清除所有会话消息?', | ||
}); | ||
}; | ||
|
||
return ( | ||
<Button danger onClick={handleClear} type={type}> | ||
{text} | ||
</Button> | ||
); | ||
}; |
Oops, something went wrong.