From 3eeaa9c514ecfb006a3275287bd53f9d42fa39d3 Mon Sep 17 00:00:00 2001 From: maojindao55 Date: Tue, 1 Apr 2025 08:56:49 +0800 Subject: [PATCH] update it --- functions/api/user/info.ts | 4 +- functions/api/user/update.ts | 4 +- src/pages/chat/components/ChatUI.tsx | 92 +-------------------- src/pages/chat/components/UserSection.tsx | 15 ++-- src/utils/avatar.ts | 97 +++++++++++++++++++++++ 5 files changed, 113 insertions(+), 99 deletions(-) create mode 100644 src/utils/avatar.ts diff --git a/functions/api/user/info.ts b/functions/api/user/info.ts index 93723a6..4b4697c 100644 --- a/functions/api/user/info.ts +++ b/functions/api/user/info.ts @@ -29,7 +29,9 @@ export const onRequestGet: PagesFunction = async (context) => { ); } //处理avatar_url - userInfo.avatar_url = `${env.NEXT_PUBLIC_CF_IMAGES_DELIVERY_URL}/${userInfo.avatar_url}/public`; + if (userInfo.avatar_url) { + userInfo.avatar_url = `${env.NEXT_PUBLIC_CF_IMAGES_DELIVERY_URL}/${userInfo.avatar_url}/public`; + } return new Response( JSON.stringify({ diff --git a/functions/api/user/update.ts b/functions/api/user/update.ts index 9f8447d..dd5f999 100644 --- a/functions/api/user/update.ts +++ b/functions/api/user/update.ts @@ -73,7 +73,9 @@ export const onRequestPost: PagesFunction = async (context) => { WHERE id = ? `).bind(data.user.userId).first(); //处理avatar_url - userInfo.avatar_url = `${env.NEXT_PUBLIC_CF_IMAGES_DELIVERY_URL}/${userInfo.avatar_url}/public`; + if (userInfo.avatar_url) { + userInfo.avatar_url = `${env.NEXT_PUBLIC_CF_IMAGES_DELIVERY_URL}/${userInfo.avatar_url}/public`; + } return new Response( JSON.stringify({ success: true, diff --git a/src/pages/chat/components/ChatUI.tsx b/src/pages/chat/components/ChatUI.tsx index 7e3fb55..bbf8d5b 100644 --- a/src/pages/chat/components/ChatUI.tsx +++ b/src/pages/chat/components/ChatUI.tsx @@ -22,94 +22,8 @@ import { MembersManagement } from '@/pages/chat/components/MembersManagement'; import Sidebar from './Sidebar'; import { AdBanner, AdBannerMobile } from './AdSection'; import { useUserStore } from '@/store/userStore'; -// 使用本地头像数据,避免外部依赖 -const getAvatarData = (name: string) => { - const colors = ['#1abc9c', '#3498db', '#9b59b6', '#f1c40f', '#e67e22']; - const index = (name.charCodeAt(0) + (name.charCodeAt(1) || 0 )) % colors.length; - return { - backgroundColor: colors[index], - text: name[0], - }; -}; +import { getAvatarData } from '@/utils/avatar'; -// 单个完整头像 -const SingleAvatar = ({ user }: { user: User | AICharacter }) => { - // 如果有头像就使用头像,否则使用默认的文字头像 - if ('avatar' in user && user.avatar) { - return ( -
- {user.name} -
- ); - } - const avatarData = getAvatarData(user.name); - return ( -
- {avatarData.text} -
- ); -}; - -// 左右分半头像 -const HalfAvatar = ({ user, isFirst }: { user: User, isFirst: boolean }) => { - if ('avatar' in user && user.avatar) { - return ( -
- {user.name} -
- ); - } - const avatarData = getAvatarData(user.name); - return ( -
- {avatarData.text} -
- ); -}; - -// 四分之一头像 -const QuarterAvatar = ({ user, index }: { user: User, index: number }) => { - if ('avatar' in user && user.avatar) { - return ( -
- {user.name} -
- ); - } - const avatarData = getAvatarData(user.name); - return ( -
- {avatarData.text} -
- ); -}; // 修改 KaTeXStyle 组件 const KaTeXStyle = () => ( @@ -212,7 +126,7 @@ const ChatUI = () => { userStore.setUserInfo(userInfo.data); setUsers([ - { id: 1, name: userInfo.data.nickname, avatar: userInfo.data.avatar_url }, + { id: 1, name: userInfo.data.nickname, avatar: userInfo.data.avatar_url? userInfo.data.avatar_url : null }, ...groupAiCharacters ]); } catch (error) { @@ -531,7 +445,7 @@ const ChatUI = () => { - {'avatar' in user && user.avatar ? ( + {'avatar' in user && user.avatar && user.avatar !== null ? ( ) : ( diff --git a/src/pages/chat/components/UserSection.tsx b/src/pages/chat/components/UserSection.tsx index 08f6cd2..e452103 100644 --- a/src/pages/chat/components/UserSection.tsx +++ b/src/pages/chat/components/UserSection.tsx @@ -3,17 +3,13 @@ import { cn } from "@/lib/utils"; import { Edit2Icon, LogOutIcon, CheckIcon, XIcon } from 'lucide-react'; import { request } from '@/utils/request'; import { useUserStore } from '@/store/userStore'; +import { getAvatarData } from '@/utils/avatar'; interface UserSectionProps { isOpen: boolean; } -// 添加用户信息接口 -interface UserInfo { - nickname: string; - avatar_url?: string; -} export const UserSection: React.FC = ({ isOpen }) => { const [isHovering, setIsHovering] = useState(false); @@ -107,7 +103,8 @@ export const UserSection: React.FC = ({ isOpen }) => { onChange={handleAvatarUpload} />
!uploadingAvatar && fileInputRef.current?.click()} > {uploadingAvatar ? ( @@ -121,8 +118,10 @@ export const UserSection: React.FC = ({ isOpen }) => { className="w-full h-full object-cover" /> ) : ( - - {userStore.userInfo?.nickname?.[0] || '我'} + + {getAvatarData(userStore.userInfo?.nickname || '我').text} )}
diff --git a/src/utils/avatar.ts b/src/utils/avatar.ts new file mode 100644 index 0000000..c0ab36a --- /dev/null +++ b/src/utils/avatar.ts @@ -0,0 +1,97 @@ +import React from 'react'; + +interface User { + id: number | string; + name: string; + avatar?: string; +} + +interface AICharacter { + id: string; + name: string; + personality: string; + model: string; + avatar?: string; + custom_prompt?: string; + tags?: string[]; +} + +export const getAvatarData = (name: string) => { + const colors = ['#1abc9c', '#3498db', '#9b59b6', '#f1c40f', '#e67e22']; + const index = (name.charCodeAt(0) + (name.charCodeAt(1) || 0)) % colors.length; + return { + backgroundColor: colors[index], + text: name[0], + }; +}; + +// 获取单个头像的样式和内容 +export const getSingleAvatarData = (user: User | AICharacter) => { + if ('avatar' in user && user.avatar) { + return { + type: 'image', + src: user.avatar, + alt: user.name, + className: 'w-full h-full object-cover' + }; + } + const avatarData = getAvatarData(user.name); + return { + type: 'text', + text: avatarData.text, + className: 'w-full h-full flex items-center justify-center text-xs text-white font-medium', + style: { backgroundColor: avatarData.backgroundColor } + }; +}; + +// 获取半头像的样式和内容 +export const getHalfAvatarData = (user: User, isFirst: boolean) => { + if ('avatar' in user && user.avatar) { + return { + type: 'image', + src: user.avatar, + alt: user.name, + className: 'w-full h-full object-cover', + containerStyle: { + borderRight: isFirst ? '1px solid white' : 'none' + } + }; + } + const avatarData = getAvatarData(user.name); + return { + type: 'text', + text: avatarData.text, + className: 'w-1/2 h-full flex items-center justify-center text-xs text-white font-medium', + style: { + backgroundColor: avatarData.backgroundColor, + borderRight: isFirst ? '1px solid white' : 'none' + } + }; +}; + +// 获取四分之一头像的样式和内容 +export const getQuarterAvatarData = (user: User, index: number) => { + if ('avatar' in user && user.avatar) { + return { + type: 'image', + src: user.avatar, + alt: user.name, + className: 'w-full h-full object-cover', + containerStyle: { + borderRight: index % 2 === 0 ? '1px solid white' : 'none', + borderBottom: index < 2 ? '1px solid white' : 'none' + } + }; + } + const avatarData = getAvatarData(user.name); + return { + type: 'text', + text: avatarData.text, + className: 'aspect-square flex items-center justify-center text-[8px] text-white font-medium', + style: { + backgroundColor: avatarData.backgroundColor, + borderRight: index % 2 === 0 ? '1px solid white' : 'none', + borderBottom: index < 2 ? '1px solid white' : 'none' + } + }; +}; \ No newline at end of file