Skip to content

Commit

Permalink
优化lobe主题
Browse files Browse the repository at this point in the history
增加头像显示个人信息
增加退出登录按钮
  • Loading branch information
239573049 committed Jun 3, 2024
1 parent 3e9d1fe commit 37443ee
Show file tree
Hide file tree
Showing 10 changed files with 307 additions and 12 deletions.
48 changes: 48 additions & 0 deletions lobe/src/components/@nav/_layout/Desktop/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ActionIcon } from '@lobehub/ui';
import { Tooltip } from 'antd';
import { LucideX } from 'lucide-react';
import { memo, useState } from 'react';
import { Flexbox } from 'react-layout-kit';
import UserPanel from '../../../User/UserPanel';
import UserAvatar from '../../../User/UserAvatar';
import { useActiveUser } from '../../../../hooks/useActiveTabKey';

const Avatar = memo(() => {
const [hideSettingsMoveGuide] = useState(true);
const user = useActiveUser();
const content = (
<UserPanel>
<UserAvatar user={user} clickable />
</UserPanel>
);

return hideSettingsMoveGuide ? (
content
) : (
<Tooltip
color={'blue'}
open
placement={'right'}
prefixCls={'guide'}
title={
<Flexbox align={'center'} gap={8} horizontal>
<ActionIcon
icon={LucideX}
onClick={() => {

}}
role={'close-guide'}
size={'small'}
style={{ color: 'inherit' }}
/>
</Flexbox>
}
>
{content}
</Tooltip>
);
});

Avatar.displayName = 'Avatar';

export default Avatar;
2 changes: 2 additions & 0 deletions lobe/src/components/@nav/_layout/Desktop/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useActiveTabKey } from '../../../../hooks/useActiveTabKey';
import BottomActions from './BottomActions';
import TopActions from './TopActions';
import { useLocation } from 'react-router-dom';
import Avatar from './Avatar';


const Nav = memo(() => {
Expand All @@ -18,6 +19,7 @@ const Nav = memo(() => {

return (
<SideNav
avatar={<Avatar/>}
bottomActions={<BottomActions />}
topActions={<TopActions tab={sidebarKey} />}
/>
Expand Down
66 changes: 66 additions & 0 deletions lobe/src/components/User/UserAvatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Avatar, type AvatarProps } from '@lobehub/ui';
import { createStyles } from 'antd-style';
import { memo, } from 'react';

const useStyles = createStyles(({ css, token }) => ({
clickable: css`
position: relative;
transition: all 200ms ease-out 0s;
&::before {
content: '';
position: absolute;
transform: skewX(-45deg) translateX(-400%);
overflow: hidden;
box-sizing: border-box;
width: 25%;
height: 100%;
background: rgba(255, 255, 255, 50%);
transition: all 200ms ease-out 0s;
}
&:hover {
box-shadow: 0 0 0 2px ${token.colorPrimary};
&::before {
transform: skewX(-45deg) translateX(400%);
}
}
`,
}));

export interface UserAvatarProps extends AvatarProps {
clickable?: boolean;
user?: any;
}

const UserAvatar = memo<UserAvatarProps>(
({ size = 40, avatar, background, clickable, user, className, style, ...rest }) => {
const { styles, cx } = useStyles();

function getAvatar() {
return user?.avatar || '/vite.svg'
}

return (
<Avatar
avatar={getAvatar()}
background={background}
className={cx(clickable && styles.clickable, className)}
size={size}
style={{ flex: 'none', ...style }}
unoptimized
{...rest}
/>
);
},
);

UserAvatar.displayName = 'UserAvatar';

export default UserAvatar;
55 changes: 55 additions & 0 deletions lobe/src/components/User/UserPanel/PanelContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';
import UserAvatar from '../UserAvatar';
import { Button } from 'antd';
import { Tag } from '@lobehub/ui';
import { Github } from '@lobehub/icons';
import { config } from '../../../config';
import { useActiveUser } from '../../../hooks/useActiveTabKey';
import { renderQuota } from '../../../utils/render';


const PanelContent = memo<{ closePopover: () => void }>(({ }) => {
const user = useActiveUser();


return (
<Flexbox gap={2} style={{ minWidth: 200 }}>
<Flexbox
align={'center'}
horizontal
justify={'space-between'}
style={{ padding: '6px 6px 6px 6px' }}
>
<Flexbox align={'center'} flex={'none'} gap={6} horizontal>
<UserAvatar user={user} size={64} clickable />
<div>
<span>
{user?.userName || "游客"}
</span>
<div>
<span>账号余额:</span>
<Tag color='red'>{renderQuota(user?.residualCredit ?? 0, 2)}</Tag>
</div>
</div>
</Flexbox>
</Flexbox>
<Flexbox
align={'center'}
horizontal
justify={'space-between'}
style={{ padding: '6px 6px 6px 6px' }}
>
<Button block onClick={() => {
localStorage.removeItem('token');
window.location.href = '/login';
}}>
退出登录
</Button>
</Flexbox>
</Flexbox>
);
});

export default PanelContent;
19 changes: 19 additions & 0 deletions lobe/src/components/User/UserPanel/UpgradeBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Badge, ConfigProvider } from 'antd';
import { PropsWithChildren, memo } from 'react';
import { Flexbox } from 'react-layout-kit';

const UpgradeBadge = memo(({ children, showBadge }: PropsWithChildren<{ showBadge?: boolean }>) => {
if (!showBadge) return children;

return (
<Flexbox>
<ConfigProvider theme={{ components: { Badge: { dotSize: 8 } } }}>
<Badge dot offset={[-4, 4]}>
{children}
</Badge>
</ConfigProvider>
</Flexbox>
);
});

export default UpgradeBadge;
39 changes: 39 additions & 0 deletions lobe/src/components/User/UserPanel/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Popover } from 'antd';
import { createStyles } from 'antd-style';
import { PropsWithChildren, memo, useState } from 'react';

import PanelContent from './PanelContent';
import UpgradeBadge from './UpgradeBadge'

const useStyles = createStyles(({ css }) => ({
popover: css`
top: 8px !important;
left: 8px !important;
`,
}));

const UserPanel = memo<PropsWithChildren>(({ children }) => {
const [open, setOpen] = useState(false);
const { styles } = useStyles();

return (
<UpgradeBadge>
<Popover
arrow={false}
content={<PanelContent closePopover={() => setOpen(false)} />}
onOpenChange={setOpen}
open={open}
overlayInnerStyle={{ padding: 0 }}
placement={'topRight'}
rootClassName={styles.popover}
trigger={['click']}
>
{children}
</Popover>
</UpgradeBadge>
);
});

UserPanel.displayName = 'UserPanel';

export default UserPanel;
16 changes: 16 additions & 0 deletions lobe/src/hooks/useActiveTabKey.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@

import { useEffect, useState } from 'react';
import { SidebarTabKey } from '../store/global/initialState';
import { info } from '../services/UserService';
import { ResultDto, User } from '..';

/**
* Returns the active tab key
Expand All @@ -8,3 +11,16 @@ export const useActiveTabKey = () => {
const pathname = window.location.pathname;
return pathname.split('/').find(Boolean)! as SidebarTabKey;
};

export const useActiveUser = () => {
const [user, setUser] = useState<User | null>(null);

useEffect(() => {
info()
.then((data: ResultDto<User>) => {
setUser(data.data)
});
}, []);

return user;
}
44 changes: 44 additions & 0 deletions lobe/src/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
export interface User extends Entity<string> {
userName: string;
email: string;
password: string;
passwordHas: string;
avatar: string | null;
role: string;
isDisabled: boolean;
isDelete: boolean;
deletedAt: string | null;
consumeToken: number;
requestCount: number;
residualCredit: number;
}

export interface Entity<TKey> {
id: TKey;
updatedAt: string | null;
modifier: string | null;
createdAt: string;
creator: string | null;
}

export interface Creatable {
createdAt: string;
creator: string | null;
}

export interface Updatable {
updatedAt: string | null;
modifier: string | null;
}

export interface ResultDto {
message: string;
success: boolean;
data: any | null;
}

export interface ResultDto<T> {
message: string;
success: boolean;
data: T | null;
}
29 changes: 18 additions & 11 deletions lobe/src/pages/redeem-code/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ export default function RedeemCode() {
},
{
key: 2,
label: '复制',
onClick: () => {
copyKey(item.code);
}
},
{
key: 3,
label: '删除',
onClick: () => removeRedeemCode(item.id)
}
Expand All @@ -113,17 +120,17 @@ export default function RedeemCode() {
keyword: '',
});

// function copyKey(key: string) {
// navigator.clipboard.writeText(key).then(() => {
// message.success({
// content: '复制成功',
// })
// }).catch(() => {
// message.error({
// content: '复制失败',
// })
// });
// }
function copyKey(key: string) {
navigator.clipboard.writeText(key).then(() => {
message.success({
content: '复制成功',
})
}).catch(() => {
message.error({
content: '复制失败',
})
});
}

function removeRedeemCode(id: number) {
Remove(id)
Expand Down
1 change: 0 additions & 1 deletion lobe/src/pages/token/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ export default function TokenPage() {
title: '过期时间',
dataIndex: 'expiredTime',
render: (value: any, item: any) => {
// unlimitedExpired
if (item.unlimitedExpired) {
return (<span>不过期</span>)
} else {
Expand Down

0 comments on commit 37443ee

Please sign in to comment.