264 lines
12 KiB
TypeScript
264 lines
12 KiB
TypeScript
|
|
"use client"
|
||
|
|
|
||
|
|
import { useParams } from "next/navigation";
|
||
|
|
import { useGetAIUserBaseInfo } from "@/hooks/aiUser";
|
||
|
|
import Image from "next/image";
|
||
|
|
|
||
|
|
// 按钮组件
|
||
|
|
interface MobileButtonProps {
|
||
|
|
showIcon?: boolean;
|
||
|
|
icon?: React.ReactNode | null;
|
||
|
|
btnTxt?: string;
|
||
|
|
showTxt?: boolean;
|
||
|
|
size?: "Large" | "Medium" | "Small";
|
||
|
|
variant?: "Contrast" | "Basic" | "Ghost";
|
||
|
|
type?: "Primary" | "Secondary" | "Tertiary" | "Destructive" | "VIP";
|
||
|
|
state?: "Default" | "Disabled" | "Pressed";
|
||
|
|
onClick?: () => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
function MobileButton({
|
||
|
|
showIcon = true,
|
||
|
|
icon = null,
|
||
|
|
btnTxt = "Button",
|
||
|
|
showTxt = true,
|
||
|
|
size = "Large",
|
||
|
|
variant = "Basic",
|
||
|
|
type = "Primary",
|
||
|
|
state = "Default",
|
||
|
|
onClick
|
||
|
|
}: MobileButtonProps) {
|
||
|
|
if (size === "Small" && variant === "Contrast" && type === "Tertiary" && state === "Default") {
|
||
|
|
return (
|
||
|
|
<button
|
||
|
|
onClick={onClick}
|
||
|
|
className="bg-[rgba(0,0,0,0.65)] box-border content-stretch flex gap-1 items-center justify-center overflow-clip px-4 py-1.5 relative rounded-[999px] h-8 hover:bg-[rgba(0,0,0,0.8)] transition-colors"
|
||
|
|
>
|
||
|
|
{showIcon && (
|
||
|
|
icon || (
|
||
|
|
<div className="h-[15.999px] relative shrink-0 w-4">
|
||
|
|
<div className="absolute aspect-[9.25554/12.1612] left-1/4 right-[17.15%] translate-y-[-50%]" style={{ top: "calc(50% + 0.065px)" }}>
|
||
|
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
||
|
|
<path d="M3 2l6 4-6 4V2z" fill="white"/>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)
|
||
|
|
)}
|
||
|
|
{showTxt && (
|
||
|
|
<div className="flex flex-col font-medium justify-center leading-[0] not-italic relative shrink-0 text-[12px] text-center text-nowrap text-white">
|
||
|
|
<p className="leading-[20px] whitespace-pre">{btnTxt}</p>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</button>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<button
|
||
|
|
onClick={onClick}
|
||
|
|
className="bg-[rgba(0,0,0,0.65)] box-border content-stretch flex gap-1 items-center justify-center overflow-clip px-4 py-1.5 relative rounded-[999px] h-8 hover:bg-[rgba(0,0,0,0.8)] transition-colors"
|
||
|
|
>
|
||
|
|
{showIcon && icon}
|
||
|
|
{showTxt && (
|
||
|
|
<span className="font-medium text-[12px] text-white">{btnTxt}</span>
|
||
|
|
)}
|
||
|
|
</button>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
const SharePage = () => {
|
||
|
|
const { userId } = useParams();
|
||
|
|
|
||
|
|
const { data: userInfo } = useGetAIUserBaseInfo({
|
||
|
|
aiId: userId ? Number(userId) : 0
|
||
|
|
});
|
||
|
|
|
||
|
|
const { homeImageUrl } = userInfo || {};
|
||
|
|
|
||
|
|
const handleChatClick = () => {
|
||
|
|
// 跳转到应用或下载页面
|
||
|
|
window.open('https://crushlevel.com/download', '_blank');
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="relative h-screen overflow-hidden max-w-[750px] mx-auto">
|
||
|
|
{/* 背景图片 */}
|
||
|
|
<div
|
||
|
|
className="absolute inset-0 overflow-clip"
|
||
|
|
style={{
|
||
|
|
background: "linear-gradient(180deg, #211A2B 0%, rgba(33, 26, 43, 0.00) 20%, rgba(33, 26, 43, 0.00) 50%, #211A2B 100%)"
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<div className="absolute inset-0">
|
||
|
|
<Image
|
||
|
|
src={homeImageUrl || ''}
|
||
|
|
alt="Background"
|
||
|
|
fill
|
||
|
|
className="object-cover"
|
||
|
|
priority
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div className="absolute inset-0 bg-black/20" />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 内容容器 */}
|
||
|
|
<div className="relative z-10 box-border content-stretch flex flex-col items-start justify-start pb-0 pt-4 px-0 min-h-screen">
|
||
|
|
{/* 头部用户信息 */}
|
||
|
|
<div className="box-border content-stretch flex items-start justify-start overflow-clip px-6 py-0 relative shrink-0 w-full">
|
||
|
|
<div className="basis-0 content-stretch flex gap-2 grow items-center justify-start min-h-px min-w-px relative self-stretch shrink-0">
|
||
|
|
{/* 用户头像 */}
|
||
|
|
<div className="overflow-clip relative rounded-[99px] shrink-0 size-10">
|
||
|
|
{userInfo?.headImg ? (
|
||
|
|
<Image
|
||
|
|
src={userInfo.headImg}
|
||
|
|
alt={userInfo.nickname || 'User'}
|
||
|
|
fill
|
||
|
|
className="object-cover"
|
||
|
|
/>
|
||
|
|
) : (
|
||
|
|
<div className="w-full h-full bg-gradient-to-br from-purple-400 to-pink-400 flex items-center justify-center">
|
||
|
|
<span className="text-white text-lg font-bold">
|
||
|
|
{userInfo?.nickname?.charAt(0) || 'U'}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 用户名和点赞数 */}
|
||
|
|
<div className="content-stretch flex flex-col items-start justify-start leading-[0] not-italic relative shrink-0 text-center text-nowrap text-white">
|
||
|
|
<div className="font-semibold relative shrink-0 text-[20px]">
|
||
|
|
<p className="leading-[24px] text-nowrap whitespace-pre">
|
||
|
|
{userInfo?.nickname || 'Loading...'}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div className="font-medium relative shrink-0 text-[12px]">
|
||
|
|
<p className="leading-[20px] text-nowrap whitespace-pre">
|
||
|
|
0 likes
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 主要内容区域 */}
|
||
|
|
<div className="basis-0 content-stretch flex flex-col grow items-start justify-end min-h-px min-w-px relative shrink-0 w-full">
|
||
|
|
{/* 消息内容 */}
|
||
|
|
<div className="grid-cols-[max-content] grid-rows-[max-content] inline-grid leading-[0] place-items-start relative shrink-0 px-6">
|
||
|
|
|
||
|
|
{/* AI信息卡片 */}
|
||
|
|
<div className="box-border content-stretch flex flex-col gap-1 items-start justify-start px-0 py-2 relative shrink-0 w-full">
|
||
|
|
<div className="backdrop-blur-[32px] backdrop-filter bg-[rgba(251,222,255,0.08)] box-border content-stretch flex flex-col gap-2 items-start justify-start p-[16px] relative rounded-[16px] shrink-0 w-full border border-[rgba(251,222,255,0.2)]">
|
||
|
|
{/* 介绍文本 */}
|
||
|
|
<div className="font-regular leading-[20px] overflow-hidden relative shrink-0 text-[14px] text-white w-full line-clamp-3">
|
||
|
|
<p>
|
||
|
|
<span className="font-semibold">Intro: </span>
|
||
|
|
<span>{userInfo?.introduction || 'This is an AI character with unique personality and charm. Start chatting to discover more about them!'}</span>
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 标签 */}
|
||
|
|
<div className="content-stretch flex gap-2 items-start justify-start relative shrink-0 w-full">
|
||
|
|
{userInfo?.tagName ? (
|
||
|
|
userInfo.tagName.split(',').slice(0, 2).map((tag: string, index: number) => (
|
||
|
|
<div key={index} className="backdrop-blur backdrop-filter box-border content-stretch flex gap-1 h-6 items-center justify-center min-w-6 overflow-clip px-2 py-0.5 relative rounded-[4px] shrink-0 bg-[#d21f77]/45">
|
||
|
|
<div className="font-medium leading-[20px] text-[12px] text-white">
|
||
|
|
{tag.trim()}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
))
|
||
|
|
) : (
|
||
|
|
<>
|
||
|
|
<div className="backdrop-blur backdrop-filter box-border content-stretch flex gap-1 h-6 items-center justify-center min-w-6 overflow-clip px-2 py-0.5 relative rounded-[4px] shrink-0 bg-[#d21f77]/45">
|
||
|
|
<div className="font-medium leading-[20px] text-[12px] text-white">Sensual</div>
|
||
|
|
</div>
|
||
|
|
<div className="backdrop-blur backdrop-filter box-border content-stretch flex gap-1 h-6 items-center justify-center min-w-6 overflow-clip px-2 py-0.5 relative rounded-[4px] shrink-0 bg-[#d21f77]/45">
|
||
|
|
<div className="font-medium leading-[20px] text-[12px] text-white">Romantic</div>
|
||
|
|
</div>
|
||
|
|
</>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* AI生成内容提示 */}
|
||
|
|
<div className="box-border content-stretch flex flex-col gap-1 items-center justify-start px-0 py-2 relative shrink-0 w-full">
|
||
|
|
<div className="backdrop-blur-[32px] backdrop-filter bg-[rgba(251,222,255,0.08)] box-border content-stretch flex gap-2 items-center justify-center px-2 py-1 relative rounded-[4px] shrink-0">
|
||
|
|
<div className="font-regular leading-[20px] text-[12px] text-center text-white">
|
||
|
|
Content generated by AI
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 示例对话消息 */}
|
||
|
|
<div className="box-border content-stretch flex gap-4 items-start justify-start pb-2 pl-0 pr-20 pt-4 relative shrink-0 w-full">
|
||
|
|
<div className="backdrop-blur-[32px] backdrop-filter basis-0 bg-[rgba(0,0,0,0.65)] box-border content-stretch flex gap-2.5 grow items-start justify-start min-h-px min-w-px pb-4 pt-5 px-4 relative rounded-[16px] shrink-0">
|
||
|
|
{/* 语音标签 */}
|
||
|
|
<div className="absolute bg-[#484151] box-border content-stretch flex gap-2 items-center justify-center left-0 overflow-clip px-3 py-1 rounded-br-[8px] rounded-tl-[8px] rounded-tr-[8px] top-[-12px]">
|
||
|
|
<div className="relative shrink-0 size-3">
|
||
|
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
||
|
|
<path d="M3 2l6 4-6 4V2z" fill="white"/>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
<div className="font-medium leading-[20px] text-[12px] text-nowrap text-white">
|
||
|
|
2''
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 消息内容 */}
|
||
|
|
<div className="basis-0 font-regular grow leading-[20px] min-h-px min-w-px text-[14px] text-white">
|
||
|
|
<span className="text-[#958e9e]">(Watching her parents toast you respectfully, I feel very sad.) </span>
|
||
|
|
<span>Are you?</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 底部品牌区域 */}
|
||
|
|
<div className="box-border content-stretch flex gap-1 items-start justify-start overflow-clip px-2 py-4 relative shrink-0 w-full">
|
||
|
|
<div className="basis-0 bg-gradient-to-r from-[#f264a4] to-[#c241e6] box-border content-stretch flex gap-3 grow items-center justify-start min-h-px min-w-px px-4 py-2 relative rounded-[16px] shrink-0">
|
||
|
|
{/* App图标 */}
|
||
|
|
<div className="overflow-clip relative rounded-[12px] shrink-0 size-[24px]">
|
||
|
|
<Image
|
||
|
|
src="/logo.svg"
|
||
|
|
alt="Crushlevel Logo"
|
||
|
|
width={24}
|
||
|
|
height={24}
|
||
|
|
className="object-contain"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 品牌信息 */}
|
||
|
|
<div className="basis-0 content-stretch flex flex-col grow items-start justify-start min-h-px min-w-px relative shrink-0">
|
||
|
|
<div className="h-[14.422px] overflow-clip relative shrink-0">
|
||
|
|
<Image
|
||
|
|
src="/logo.svg"
|
||
|
|
alt="Crushlevel"
|
||
|
|
width={47}
|
||
|
|
height={14}
|
||
|
|
className="object-contain"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div className="font-medium leading-[20px] text-[12px] text-center text-nowrap text-white">
|
||
|
|
Chat. Crush. AI Date
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Chat按钮 */}
|
||
|
|
<MobileButton
|
||
|
|
showIcon={false}
|
||
|
|
btnTxt="Chat"
|
||
|
|
size="Small"
|
||
|
|
variant="Contrast"
|
||
|
|
type="Tertiary"
|
||
|
|
onClick={handleChatClick}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
export default SharePage;
|