feat(chat): 优化面具设置

This commit is contained in:
liuyonghe0111 2025-12-23 16:59:10 +08:00
parent bcfcae0793
commit c78e3ed5ff
7 changed files with 30 additions and 44 deletions

View File

@ -18,12 +18,6 @@ import { useModels } from '@/hooks/services/chat';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
const genderMap = {
0: '/icons/male.svg',
1: '/icons/female.svg',
2: '/icons/gender-neutral.svg',
};
const ChatProfilePersona = React.memo(({ onActiveTab }: ProfileProps) => { const ChatProfilePersona = React.memo(({ onActiveTab }: ProfileProps) => {
const t = useTranslations('chat.drawer'); const t = useTranslations('chat.drawer');
const tCommon = useTranslations('common'); const tCommon = useTranslations('common');
@ -32,9 +26,7 @@ const ChatProfilePersona = React.memo(({ onActiveTab }: ProfileProps) => {
const items = [ const items = [
{ {
label: t('profile.gender'), label: t('profile.gender'),
value: ( value: tCommon(`gender_${0}`),
<Image src={genderMap[0 as keyof typeof genderMap]} alt="gender" width={24} height={24} />
),
}, },
{ {
label: t('profile.age'), label: t('profile.age'),
@ -63,7 +55,7 @@ const ChatProfilePersona = React.memo(({ onActiveTab }: ProfileProps) => {
onClick={() => onActiveTab('mask_list')} onClick={() => onActiveTab('mask_list')}
className="bg-surface-element-normal cursor-pointer rounded-m flex items-center justify-between gap-4 px-4 py-3" className="bg-surface-element-normal cursor-pointer rounded-m flex items-center justify-between gap-4 px-4 py-3"
> >
<div className="txt-label-l text-txt-secondary-normal">{t('profile.nickname')}</div> <div className="txt-label-l text-txt-secondary-normal">{t('profile.preset')}</div>
<div className="txt-label-l text-txt-primary-normal"> <div className="txt-label-l text-txt-primary-normal">
{'John Doe'} {'John Doe'}
<IconButton iconfont="icon-arrow-right-border" size="small" variant="ghost" /> <IconButton iconfont="icon-arrow-right-border" size="small" variant="ghost" />

View File

@ -144,7 +144,9 @@ export const useStreamChatStore = create<StreamChatStore>((set, get) => ({
async connect(user) { async connect(user) {
const { client, queryChannels, fetchUserChatSetting } = get(); const { client, queryChannels, fetchUserChatSetting } = get();
set({ user }); set({ user });
if (client) return; if (client) {
return;
}
const { data } = await getUserToken(user); const { data } = await getUserToken(user);
const streamClient = new StreamChat(process.env.NEXT_PUBLIC_STREAM_CHAT_API_KEY || ''); const streamClient = new StreamChat(process.env.NEXT_PUBLIC_STREAM_CHAT_API_KEY || '');
await protect(() => await protect(() =>

View File

@ -1,11 +1,13 @@
export default { export default {
hello: 'Hello',
common: { common: {
search: 'Search', search: 'Search',
cancel: 'Cancel', cancel: 'Cancel',
edit: 'Edit', edit: 'Edit',
select: 'Select', select: 'Select',
default: 'Default', default: 'Default',
gender_0: 'Male',
gender_1: 'Female',
gender_2: 'Other',
}, },
bottomBar: { bottomBar: {
explore: 'Explore', explore: 'Explore',
@ -39,7 +41,7 @@ export default {
background: 'Background', background: 'Background',
model: 'Chat Model', model: 'Chat Model',
profile: { profile: {
nickname: 'Nickname', preset: 'Preset',
gender: 'Gender', gender: 'Gender',
age: 'Age', age: 'Age',
whoAmI: 'Who am I', whoAmI: 'Who am I',

View File

@ -1,11 +1,13 @@
export default { export default {
hello: '你好',
common: { common: {
search: '搜索', search: '搜索',
cancel: '取消', cancel: '取消',
edit: '编辑', edit: '编辑',
select: '选择', select: '选择',
default: '默认', default: '默认',
gender_0: '男性',
gender_1: '女性',
gender_2: '其他',
}, },
bottomBar: { bottomBar: {
explore: '首页', explore: '首页',
@ -39,7 +41,7 @@ export default {
background: '背景', background: '背景',
model: '聊天模型', model: '聊天模型',
profile: { profile: {
nickname: '昵称', preset: '预设',
gender: '性别', gender: '性别',
age: '年龄', age: '年龄',
whoAmI: '我是谁', whoAmI: '我是谁',

View File

@ -77,47 +77,35 @@ function Topbar() {
const rightDomRender = () => { const rightDomRender = () => {
if (!response || isLoading) return null; if (!response || isLoading) return null;
const items = [ return (
{ <div className="flex items-center">
dom: <LocaleSwitch key="locale-switch" />, <LocaleSwitch key="locale-switch" />
}, {user && <Notice key="notice" />}
{ {user && (
hide: !user,
dom: <Notice key="notice" />,
},
{
hide: !user,
dom: (
<Link href="/profile" prefetch key="profile"> <Link href="/profile" prefetch key="profile">
<Avatar className="size-8 cursor-pointer"> <Avatar className="size-8 cursor-pointer">
<AvatarImage <AvatarImage
className="object-cover" className="object-cover"
src={user!.headImage} src={user?.headImage}
alt={user!.nickname} alt={user?.nickname}
width={32} width={32}
height={32} height={32}
/> />
<AvatarFallback>{user!.nickname?.slice(0, 1)}</AvatarFallback> <AvatarFallback>{user?.nickname?.slice(0, 1)}</AvatarFallback>
</Avatar> </Avatar>
</Link> </Link>
), )}
}, {!user && (
{
hide: user,
dom: (
<Link href={loginHref} prefetch key="login"> <Link href={loginHref} prefetch key="login">
<Button size="small">Login in</Button> <Button size="small">Login in</Button>
</Link> </Link>
), )}
}, </div>
].filter((item) => !item.hide); );
return <div className="flex items-center">{items.map((item) => item.dom)}</div>;
}; };
// 移动端根据配置决定是否隐藏 Topbar // 移动端根据配置决定是否隐藏 Topbar
const isMobile = response && !response.sm; if (response?.isMobile && routeConfig.hideOnMobile) {
if (isMobile && routeConfig.hideOnMobile) {
return null; return null;
} }

View File

@ -52,13 +52,13 @@ export default function ConditionalLayout({ children }: ConditionalLayoutProps)
return ( return (
<div className="flex h-screen bg-[url('/common-bg.png')] bg-[length:100%_30%] bg-top bg-no-repeat"> <div className="flex h-screen bg-[url('/common-bg.png')] bg-[length:100%_30%] bg-top bg-no-repeat">
{response?.sm && <Sidebar />} {response?.isPC && <Sidebar />}
<div ref={mainContentRef} className={cn('relative flex flex-1 flex-col')}> <div ref={mainContentRef} className={cn('relative flex flex-1 flex-col')}>
<Topbar /> <Topbar />
<main id="main-content" className="overflow-auto flex-1"> <main id="main-content" className="overflow-auto flex-1">
{children} {children}
</main> </main>
{response && !response.sm && <BottomBar />} {response?.isMobile && <BottomBar />}
</div> </div>
{/* <ChargeDrawer /> */} {/* <ChargeDrawer /> */}
{/* <SubscribeVipDrawer /> */} {/* <SubscribeVipDrawer /> */}

View File

@ -28,7 +28,7 @@ export default function ProfileLayout(props: ProfileLayoutProps) {
{rightDom} {rightDom}
</div> </div>
<div className="flex-1">{children}</div> <div className="flex-1">{children}</div>
{bottomButton && response && !response.sm && ( {bottomButton && response?.isMobile && (
<div className="shrink-0 h-18 flex items-center">{bottomButton}</div> <div className="shrink-0 h-18 flex items-center">{bottomButton}</div>
)} )}
</div> </div>