hts/apps/blogai/components/header.tsx

365 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import React from 'react'
import { Suspense } from 'react'
import { auth } from '@/auth'
import { clearChats } from '@/app/actions'
import { Sidebar } from '@/components/sidebar'
import { SidebarList } from '@/components/sidebar-list'
import { IconSeparator } from '@/components/ui/icons'
import { SidebarFooter } from '@/components/sidebar-footer'
import { ClearHistory } from '@/components/clear-history'
import { UserMenu, UserData } from '@/components/user-menu'
import { LoginButton } from '@/components/login-button'
import {
Tooltip,
TooltipContent,
TooltipTrigger
} from '@/components/ui/tooltip'
import { Badge } from '@/components/ui/badge'
import { ConnectButton } from '@/components/connect-button'
import { SettingsDropDown } from './settings-drop-down'
import { useLocalStorage } from '@/lib/hooks/use-local-storage'
import { Button } from './ui/button'
import Image from 'next/image';
import logoImage from '@/components/images/logo.png';
import { useRouter } from 'next/navigation'
// import { Button } from './ui/button'
import { Flex, Text } from '@radix-ui/themes';
import Link from 'next/link'
import { useTranslation } from 'react-i18next'
import { message } from 'antd'
import { LogoAI } from '@/components/chat'
import { useState } from "react";
import {
BadgeInfo,
Tags,
CalendarClock,
Building2
} from "lucide-react";
export function Header() {
const router = useRouter();
const { t } = useTranslation();
const [userData, setUserData] = useLocalStorage(
'UserData',
{
auth_token: "",
id: 1,
login_ip: "",
login_time: 0,
role: "",
user_name: "",
version: ""
} as UserData
)
const soonFunc = () => {
message.info(t("soon"))
}
//w-11/12 sm:w-5/6 md:w-3/4 lg:w-2/3 xl:w-3/5 2xl:w-1/2
return (
<header className="sticky top-0 z-50 flex shrink-0 items-center justify-between bg-background px-4 py-[1.5rem] w-[80%] mx-auto">
<a href="/">
<LogoAI className="flex text-center ml-0" />
</a>
<div className="flex items-center justify-between ">
<div className="flex items-center ">
{(!!userData && !!userData.user_name) ? (
<div className='flex text-[#1A1A1A]'>
<UserMenu user={userData} />
</div>
) : (
<div className='flex gap-4 grid-cols-2 text-[#1A1A1A]'>
<Button variant="ghost" className='text-base bg-[#f4f4f5] hover:bg-[#e5e7eb]'>
<Link href="/#subscribe-target"
>
{t('subscribe.subscribe')}
</Link>
</Button>
<LoginButton
variant="ghost"
// variant="link"
showGithubIcon={true}
text={t('login')}
className="-ml-2 text-base bg-[#f4f4f5] hover:bg-[#e5e7eb]"
/>
</div>
)}
</div>
</div>
</header>
)
}
// ✅ 图标显示逻辑现在是这样的:
// data.icon = "🚀" 👉 显示 emoji
// data.icon = "/images/icon.png" 👉 显示图片;
// data.icon = undefined/null 👉 显示默认 "Deploy" 字样。
export function DetailPageHeader({ data }: { data: any }) {
const [loading, setLoading] = useState(false);
const [statusText, setStatusText] = useState(data?.statusText || "加载中...");
const handleClick = async (source: "icon" | "info") => {
setLoading(true);
setStatusText(source === "icon" ? "正在处理图标操作..." : "正在处理信息操作...");
try {
// 从 localStorage 获取用户信息
const userData = JSON.parse(localStorage.getItem("UserData") || "null");
if (!userData || !userData.user_name) {
setStatusText("未登录,正在跳转登录页面...");
window.location.href = "/login";
return;
}
const userName = userData.user_name;
// 从组件 props 里的 data 中取 id
const id = data?.id;
if (!id) {
setStatusText("数据缺失:找不到组件 ID");
return;
}
await fetch("/api/v1/deploy/deploy", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id,
user_name: userName,
}),
});
await new Promise((resolve) => setTimeout(resolve, 1000));
setStatusText(`操作成功:来自${source === "icon" ? "图标" : "信息区域"}`);
} catch (err) {
console.error("请求出错:", err);
setStatusText("操作失败");
} finally {
setLoading(false);
}
};
// 处理图标路径
const isImagePath =
typeof data?.icon === "string" &&
(data.icon.startsWith("http") || data.icon.startsWith("/"));
const resolvedIconSrc =
isImagePath && !data.icon.startsWith("http")
? process.env.NEXT_PUBLIC_CLIENT_IMAGE_URL + data.icon
: data.icon;
return (
<div className="sticky top-0 z-30 bg-white">
<div className="mt-4 mb-1 px-6 lg:px-8 w-11/12 lg:w-2/3 xl:w-3/5 mx-auto">
<div className="flex items-start space-x-6">
{/* 左图标(可点) */}
<button
className="group flex items-center justify-center w-24 h-24 md:w-32 md:h-32 border transition"
onClick={() => handleClick("icon")}
disabled={loading}
>
{isImagePath ? (
<img
src={resolvedIconSrc}
alt="icon"
className="
w-full h-full object-contain
transition-all duration-200
group-hover:border-2 group-hover:border-blue-500
group-active:border-2 group-active:border-green-500
group-hover:scale-105 group-active:scale-95
"
/>
) : (
data?.icon || "Deploy"
)}
</button>
{/* 右信息区域(带图标) */}
<div className="text-sm leading-7 space-y-1.5">
<div className="flex items-center gap-2">
<BadgeInfo size={16} /> {data?.name || "未命名组件"}
</div>
<div className="flex items-center gap-2">
<Tags size={16} /> {data?.category || "未知"}
</div>
<div className="flex items-center gap-2">
<CalendarClock size={16} /> {data?.updated_at || "未提供"}
</div>
<div className="flex items-center gap-2">
<Building2 size={16} /> {data?.company || "未知公司"}
</div>
</div>
</div>
{/* 状态条 */}
<div className="w-full mt-4 bg-gray-200 h-6">
<div
className="bg-blue-500 h-full text-white text-center text-sm flex items-center justify-center transition-all duration-300"
style={{ width: data?.progress || "60%" }}
>
{loading ? "操作中..." : statusText}
</div>
</div>
</div>
</div>
);
}
// export function Header() {
// const router = useRouter();
// const { t } = useTranslation();
// const [userData, setUserData] = useLocalStorage(
// 'UserData',
// {
// auth_token: "",
// id: 1,
// login_ip: "",
// login_time: 0,
// role: "",
// user_name: "",
// version: ""
// } as UserData
// )
// const soonFunc = () => {
// message.info(t("soon"))
// }
// return (
// <header className="sticky top-0 z-50 flex w-full shrink-0 items-center justify-between bg-background px-4 py-[1.5rem]">
// {/* <MobileLinks className="lg:hidden" />
// <DesktopLinks className="hidden lg:flex" /> */}
// <div className="lg:hidden" ></div>
// <div className="hidden lg:flex" >
// {/* <Button variant="ghost" className='text-base font-bold hover:bg-[#e5e7eb]' onClick={soonFunc}>
// {t("header.course")}
// </Button>
// <Button variant="ghost" className='text-base font-bold hover:bg-[#e5e7eb]' onClick={soonFunc}>
// {t("header.models")}
// </Button>
// <Button variant="ghost" className='text-base font-bold hover:bg-[#e5e7eb]' onClick={soonFunc}>
// {t("header.resources")}
// </Button> */}
// </div>
// {/* <Image src={logoImage} height={40} alt="show" className="cursor-pointer" onClick={() => {
// router.push("/")
// // toast.success('coming soon')
// }} /> */}
// <LogoAI
// className='flex text-center m-auto'
// />
// <div className="flex items-center justify-between ">
// <div className="flex items-center ">
// {/* <IconSeparator className="size-6 text-muted-foreground/50" /> */}
// {(!!userData && !!userData.user_name) ? (
// <div className='flex text-[#1A1A1A]'>
// {/* <Button variant="ghost" className='text-base bg-[#f4f4f5] hover:bg-[#e5e7eb]'
// onClick={() => {
// router.push("/subscribe")
// }}
// > {t("subscribe.subscribe")}</Button> */}
// <UserMenu user={userData} />
// </div>
// ) : (
// <div className='flex gap-4 grid-cols-2 text-[#1A1A1A]'>
// <Button variant="ghost" className='text-base bg-[#f4f4f5] hover:bg-[#e5e7eb]'>
// <Link href="/#subscribe-target"
// >
// {t('subscribe.subscribe')}
// </Link>
// </Button>
// <LoginButton
// variant="ghost"
// // variant="link"
// showGithubIcon={true}
// text={t('login')}
// className="-ml-2 text-base bg-[#f4f4f5] hover:bg-[#e5e7eb]"
// />
// </div>
// )}
// </div>
// </div>
// </header>
// )
// }
export function NavBack() {
const router = useRouter();
const { t } = useTranslation();
// const query = router.query; // 假设页面 URL 是 /mypage?id=123
console.log("query", router)
return (
<nav className="fixed top-[1rem] container flex items-center justify-between " >
<Link href="/">
{t("home")}
</Link>
</nav>
)
}
export function TimeP({
date,
}: {
date: string
}) {
const router = useRouter();
const { t } = useTranslation();
return (
<p className=" text-left text-[1rem] text-[#808080]">{date} {t("JellyAI")}</p>
)
}