update it

This commit is contained in:
maojindao55
2025-04-01 08:56:49 +08:00
parent 6929aa8a47
commit 3eeaa9c514
5 changed files with 113 additions and 99 deletions

View File

@@ -29,7 +29,9 @@ export const onRequestGet: PagesFunction<Env> = async (context) => {
); );
} }
//处理avatar_url //处理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( return new Response(
JSON.stringify({ JSON.stringify({

View File

@@ -73,7 +73,9 @@ export const onRequestPost: PagesFunction<Env> = async (context) => {
WHERE id = ? WHERE id = ?
`).bind(data.user.userId).first(); `).bind(data.user.userId).first();
//处理avatar_url //处理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( return new Response(
JSON.stringify({ JSON.stringify({
success: true, success: true,

View File

@@ -22,94 +22,8 @@ import { MembersManagement } from '@/pages/chat/components/MembersManagement';
import Sidebar from './Sidebar'; import Sidebar from './Sidebar';
import { AdBanner, AdBannerMobile } from './AdSection'; import { AdBanner, AdBannerMobile } from './AdSection';
import { useUserStore } from '@/store/userStore'; import { useUserStore } from '@/store/userStore';
// 使用本地头像数据,避免外部依赖 import { getAvatarData } from '@/utils/avatar';
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],
};
};
// 单个完整头像
const SingleAvatar = ({ user }: { user: User | AICharacter }) => {
// 如果有头像就使用头像,否则使用默认的文字头像
if ('avatar' in user && user.avatar) {
return (
<div className="w-full h-full">
<img src={user.avatar} alt={user.name} className="w-full h-full object-cover" />
</div>
);
}
const avatarData = getAvatarData(user.name);
return (
<div
className="w-full h-full flex items-center justify-center text-xs text-white font-medium"
style={{ backgroundColor: avatarData.backgroundColor }}
>
{avatarData.text}
</div>
);
};
// 左右分半头像
const HalfAvatar = ({ user, isFirst }: { user: User, isFirst: boolean }) => {
if ('avatar' in user && user.avatar) {
return (
<div
className="w-1/2 h-full"
style={{
borderRight: isFirst ? '1px solid white' : 'none'
}}
>
<img src={user.avatar} alt={user.name} className="w-full h-full object-cover" />
</div>
);
}
const avatarData = getAvatarData(user.name);
return (
<div
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'
}}
>
{avatarData.text}
</div>
);
};
// 四分之一头像
const QuarterAvatar = ({ user, index }: { user: User, index: number }) => {
if ('avatar' in user && user.avatar) {
return (
<div
className="aspect-square"
style={{
borderRight: index % 2 === 0 ? '1px solid white' : 'none',
borderBottom: index < 2 ? '1px solid white' : 'none'
}}
>
<img src={user.avatar} alt={user.name} className="w-full h-full object-cover" />
</div>
);
}
const avatarData = getAvatarData(user.name);
return (
<div
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'
}}
>
{avatarData.text}
</div>
);
};
// 修改 KaTeXStyle 组件 // 修改 KaTeXStyle 组件
const KaTeXStyle = () => ( const KaTeXStyle = () => (
@@ -212,7 +126,7 @@ const ChatUI = () => {
userStore.setUserInfo(userInfo.data); userStore.setUserInfo(userInfo.data);
setUsers([ 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 ...groupAiCharacters
]); ]);
} catch (error) { } catch (error) {
@@ -531,7 +445,7 @@ const ChatUI = () => {
<Tooltip> <Tooltip>
<TooltipTrigger> <TooltipTrigger>
<Avatar className="w-7 h-7 border-2 border-white"> <Avatar className="w-7 h-7 border-2 border-white">
{'avatar' in user && user.avatar ? ( {'avatar' in user && user.avatar && user.avatar !== null ? (
<AvatarImage src={user.avatar} /> <AvatarImage src={user.avatar} />
) : ( ) : (
<AvatarFallback style={{ backgroundColor: avatarData.backgroundColor, color: 'white' }}> <AvatarFallback style={{ backgroundColor: avatarData.backgroundColor, color: 'white' }}>

View File

@@ -3,17 +3,13 @@ import { cn } from "@/lib/utils";
import { Edit2Icon, LogOutIcon, CheckIcon, XIcon } from 'lucide-react'; import { Edit2Icon, LogOutIcon, CheckIcon, XIcon } from 'lucide-react';
import { request } from '@/utils/request'; import { request } from '@/utils/request';
import { useUserStore } from '@/store/userStore'; import { useUserStore } from '@/store/userStore';
import { getAvatarData } from '@/utils/avatar';
interface UserSectionProps { interface UserSectionProps {
isOpen: boolean; isOpen: boolean;
} }
// 添加用户信息接口
interface UserInfo {
nickname: string;
avatar_url?: string;
}
export const UserSection: React.FC<UserSectionProps> = ({ isOpen }) => { export const UserSection: React.FC<UserSectionProps> = ({ isOpen }) => {
const [isHovering, setIsHovering] = useState(false); const [isHovering, setIsHovering] = useState(false);
@@ -107,7 +103,8 @@ export const UserSection: React.FC<UserSectionProps> = ({ isOpen }) => {
onChange={handleAvatarUpload} onChange={handleAvatarUpload}
/> />
<div <div
className="w-10 h-10 rounded-full bg-gradient-to-br from-orange-400 to-rose-400 flex items-center justify-center shadow-sm overflow-hidden" className="w-10 h-10 rounded-full flex items-center justify-center shadow-sm overflow-hidden"
style={{ backgroundColor: getAvatarData(userStore.userInfo?.nickname || '我').backgroundColor }}
onClick={() => !uploadingAvatar && fileInputRef.current?.click()} onClick={() => !uploadingAvatar && fileInputRef.current?.click()}
> >
{uploadingAvatar ? ( {uploadingAvatar ? (
@@ -121,8 +118,10 @@ export const UserSection: React.FC<UserSectionProps> = ({ isOpen }) => {
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
) : ( ) : (
<span className="text-base font-medium text-white"> <span
{userStore.userInfo?.nickname?.[0] || '我'} className="text-base font-medium text-white"
>
{getAvatarData(userStore.userInfo?.nickname || '我').text}
</span> </span>
)} )}
</div> </div>

97
src/utils/avatar.ts Normal file
View File

@@ -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'
}
};
};