update it
This commit is contained in:
@@ -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({
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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' }}>
|
||||||
|
|||||||
@@ -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
97
src/utils/avatar.ts
Normal 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'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user