'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, useRef, } from "react"; import { Trash2 } from "lucide-react"; import { useEffect } 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 (
{(!!userData && !!userData.user_name) ? (
) : (
)}
) } // ✅ 图标显示逻辑现在是这样的: // 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 [progress, setProgress] = useState(data?.progress || "0%"); // const [showDelete, setShowDelete] = useState(true); // 默认可以删除 // // 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 = "/auth/sign-in/"; // // return; // // } // // const userName = userData.user_name; // // // 从组件 props 里的 data 中取 id // // const id = data?.id; // // if (!id) { // // setStatusText("数据缺失:找不到组件 ID"); // // return; // // } // // // 发起部署请求 // // const res = await fetch("/api/v1/deploy/deploy", { // // method: "POST", // // headers: { "Content-Type": "application/json" }, // // body: JSON.stringify({ // // id, // // user_name: userName, // // }), // // }); // // if (!res.ok) { // // throw new Error(`HTTP 请求失败:${res.status}`); // // } // // const json = await res.json(); // // if (json?.header?.code === 0) { // // setStatusText(`${json.header.message || "操作成功"}`); // // } else { // // setStatusText(`${json.header.message || "操作失败(后端返回错误)"}`); // // } // // } catch (err) { // // console.error("请求出错:", err); // // setStatusText("操作失败,请检查网络或服务状态"); // // } finally { // // setLoading(false); // // } // // }; // const handleClick = async (source: "icon" | "info") => { // setLoading(true); // setStatusText(source === "icon" ? "正在处理图标操作..." : "正在处理信息操作..."); // try { // const userData = JSON.parse(localStorage.getItem("UserData") || "null"); // if (!userData || !userData.user_name) { // setStatusText("未登录,正在跳转登录页面..."); // window.location.href = "/auth/sign-in/"; // return; // } // const userName = userData.user_name; // const id = data?.id; // if (!id) { // setStatusText("数据缺失:找不到组件 ID"); // return; // } // // 发起部署请求 // const res = await fetch("/api/v1/deploy/deploy", { // method: "POST", // headers: { "Content-Type": "application/json" }, // body: JSON.stringify({ // id, // user_name: userName, // }), // }); // if (!res.ok) throw new Error(`HTTP 请求失败:${res.status}`); // const json = await res.json(); // if (json?.header?.code === 0) { // setStatusText("部署已启动,正在监听进度..."); // // ✅ 检查 env 变量是否读取成功 // console.log("🧪 WS BASE =", process.env.NEXT_PUBLIC_CLIENT_BASE_WS); // // 发起 WebSocket 连接监听部署进度 // const wsBase = process.env.NEXT_PUBLIC_CLIENT_BASE_WS; // const socket = new WebSocket(`${wsBase}/status/${userName}/${id}`); // socket.onopen = () => { // console.log("WebSocket 已连接"); // }; // socket.onmessage = (event) => { // console.log("收到进度信息:", event.data); // // setStatusText(event.data); // 你也可以用 setProgress() 更新进度条 // const msg = event.data; // setStatusText(msg); // // ✅ 自动解析形如“进度: 65%,阶段: 正在部署”的格式 // const match = msg.match(/进度[::]?\s*(\d+)%/); // if (match && match[1]) { // const percent = match[1] + "%"; // setProgress(percent); // } // }; // socket.onerror = (error) => { // console.error("WebSocket 出错:", error); // setStatusText("WebSocket 出错"); // }; // socket.onclose = () => { // console.log("🔌 WebSocket 连接已关闭"); // }; // } else { // setStatusText(`${json.header.message || "操作失败(后端返回错误)"}`); // } // } catch (err) { // console.error("请求出错:", err); // setStatusText("操作失败,请检查网络或服务状态"); // } finally { // setLoading(false); // } // }; // const handleDelete = () => { // if (loading) return; // const confirmed = window.confirm("确定要删除模型吗?"); // if (confirmed) { // setLoading(true); // // 模拟删除流程(实际调用 API 或其他逻辑) // // await deleteComponent(data.id); // console.log("模型已删除"); // setLoading(false); // } // }; // useEffect(() => { // const fetchDeployStatus = async () => { // try { // const result = await fetch("/api/v1/deploy/status", { // method: "POST", // headers: { "Content-Type": "application/json" }, // body: JSON.stringify({ id: data?.id }), // }).then((res) => res.json()); // console.log("==================>result:", result); // if (!result || result.header?.code !== 1006) { // setStatusText(result?.header?.message || "操作失败(后端返回错误)"); // setShowDelete(false); // 非 1006 隐藏删除按钮 // return; // } // // 如果成功返回 // setStatusText(result.header.message || "部署成功"); // if (result.header?.code === 1006) { // setShowDelete(false); // code === 1006 不可删除,隐藏按钮 // setStatusText(""); // setProgress("0%"); // } else { // setShowDelete(true); // 其他状态可删除 // setStatusText(result.header.message || "部署中"); // setProgress(result.data?.progress || "0%"); // } // // 如果还想设置进度的话,这里也可以 setProgress(result.data.progress || '0%') // } catch (err) { // console.error("请求部署状态失败:", err); // setStatusText("请求失败"); // setShowDelete(false); // } // }; // fetchDeployStatus(); // }, [data?.id]); // id 变化时重新获取 // // 处理图标路径 // 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 ( //
//
//
// {/* 左图标(可点) */} // // {/* 信息 + 删除按钮:左右分布 */} //
// {/* 信息区域 */} //
//
// {data?.name || "未命名组件"} //
//
// {data?.category || "未知"} //
//
// {data?.updated_at || "未提供"} //
//
// {data?.company || "未知公司"} //
//
// {/* 条件显示删除按钮 */} // {showDelete && ( // // )} //
//
// {/* 状态条 */} // {(data?.progress !== "0%" || statusText) && ( //
//
// {loading ? "操作中..." : statusText} //
//
// )} //
//
// ); // } export function DetailPageHeader({ data }: { data: any }) { const [loading, setLoading] = useState(false); const [statusText, setStatusText] = useState(data?.statusText || "加载中..."); const [progress, setProgress] = useState(data?.progress || "0%"); const [progressBarColor, setProgressBarColor] = useState("bg-blue-500"); // ✅ 默认蓝色 const [showProgressBar, setShowProgressBar] = useState(false); const [showDelete, setShowDelete] = useState(false); const [hasWSConnected, setHasWSConnected] = useState(false); const [statusLoaded, setStatusLoaded] = useState(false); const [canDeploy, setCanDeploy] = useState(true); const socketRef = useRef(null); const initWebSocket = (userName: string, id: number) => { if (socketRef.current) socketRef.current.close(); const wsBase = process.env.NEXT_PUBLIC_CLIENT_BASE_WS; const socket = new WebSocket(`${wsBase}/status/${userName}/${id}`); socketRef.current = socket; socket.onopen = () => console.log("WebSocket 已连接"); socket.onmessage = (event) => { const msg = event.data; console.log("收到进度信息:", msg); setStatusText(msg); const match = msg.match(/进度[::]?\s*(\d+)%/); if (match && match[1]) { setProgress(match[1] + "%"); if (match[1] === "100") { console.log("部署完成 ✅,重新拉取状态!"); fetchDeployStatus(); // ✅ 直接重新请求后端最新状态 } } setProgressBarColor("bg-blue-500"); // 保持默认颜色 }; socket.onerror = (err) => { console.error("WebSocket 出错:", err); setStatusText("WebSocket 出错"); }; socket.onclose = () => { console.log("🔌 WebSocket 已关闭"); setHasWSConnected(false); socketRef.current = null; }; setHasWSConnected(true); }; const handleClick = async (source: "icon" | "info") => { setLoading(true); setStatusText(source === "icon" ? "正在处理图标操作..." : "正在处理信息操作..."); setShowProgressBar(true) try { const userData = JSON.parse(localStorage.getItem("UserData") || "null"); if (!userData?.user_name) { setStatusText("未登录,跳转中..."); window.location.href = "/auth/sign-in/"; return; } const userName = userData.user_name; const id = data?.id; if (!id) { setStatusText("缺少组件 ID"); return; } const res = await fetch("/api/v1/deploy/deploy", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id, user_name: userName }), }); const json = await res.json(); if (json?.header?.code === 0) { setStatusText("部署已启动,监听中..."); setProgressBarColor("bg-blue-500"); initWebSocket(userName, id); } else { setStatusText(json.header.message || "操作失败(后端)"); } } catch (err) { console.error("请求出错:", err); setStatusText("请求失败"); } finally { setLoading(false); } }; const handleDelete = async () => { if (loading) return; const confirmed = window.confirm("确定要删除该部署吗?"); if (!confirmed) return; setLoading(true); setStatusText("正在删除部署..."); setProgressBarColor("bg-gray-400"); try { const userData = JSON.parse(localStorage.getItem("UserData") || "null"); const userName = userData?.user_name; const id = data?.id; if (!userName || !id) { setStatusText("缺少 user_name 或 id"); return; } const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 60_000); // ⏰ 60秒超时 const res = await fetch("/api/v1/deploy/delete", { method: "POST", headers: { "Content-Type": "application/json" }, signal: controller.signal, body: JSON.stringify({ user_name: userName, n_id: id }), }); clearTimeout(timeoutId); // ✅ 成功返回前清除 timeout if (!res.ok) { throw new Error(`HTTP 请求失败: ${res.status}`); } const json = await res.json(); if (json?.header?.code === 0) { setStatusText("删除成功"); setProgress("0%"); setShowDelete(false); // 删除成功后隐藏按钮 await fetchDeployStatus(); // ✅ 删除后刷新真实状态 } else { setStatusText(json?.header?.message || "删除失败(后端返回错误)"); } } catch (err) { if ((err as any).name === "AbortError") { setStatusText("请求超时(超过10秒)"); } else { console.error("删除请求出错:", err); setStatusText("删除失败,请检查网络"); } } finally { setLoading(false); } }; const fetchDeployStatus = async () => { try { const result = await fetch("/api/v1/deploy/status", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id: data?.id }), }).then((res) => res.json()); console.log("====> deploy status result:", result); setStatusLoaded(true); if (!result) { setStatusText("接口响应为空"); setShowDelete(false); return; } const code = result?.header?.code; const status = result?.data?.data?.status; const userData = JSON.parse(localStorage.getItem("UserData") || "null"); const userName = userData?.user_name; const id = data?.id; console.log("🟡 状态码 code =", code, "状态 status =", status); if (code === 1006) { setStatusText("尚未部署"); setShowDelete(false); setProgress("0%"); setShowProgressBar(false); setCanDeploy(true); // ✅ 允许部署 return; } if (status === "deploying" && userName && id && !hasWSConnected) { setStatusText("检测到正在部署,连接中..."); initWebSocket(userName, id); setShowProgressBar(true); setCanDeploy(false); // ✅ 正在部署中,禁止点击 } if (status === "running" || status === "stopped") { console.log("✅ 允许删除(status =", status, ")"); setShowDelete(true); setProgress("100%"); setShowProgressBar(true); setCanDeploy(false); // ✅ 已部署/已停止,不允许再次 deploy if (status === "running") { setStatusText("运行中"); setProgressBarColor("bg-green-500"); } else if (status === "stopped") { setStatusText("已停止"); setProgressBarColor("bg-gray-400"); } } else { console.log("❌ 不允许删除(status =", status, ")"); setShowDelete(false); setProgressBarColor("bg-blue-500"); } } catch (err) { console.error("获取状态失败:", err); setStatusText("状态拉取失败"); setShowDelete(false); } }; useEffect(() => { fetchDeployStatus(); }, [data?.id]); // useEffect(() => { // const fetchDeployStatus = async () => { // try { // const result = await fetch("/api/v1/deploy/status", { // method: "POST", // headers: { "Content-Type": "application/json" }, // body: JSON.stringify({ id: data?.id }), // }).then((res) => res.json()); // console.log("====> deploy status result:", result); // setStatusLoaded(true); // if (!result) { // setStatusText("接口响应为空"); // setShowDelete(false); // return; // } // const code = result?.header?.code; // const status = result?.data?.data?.status; // const userData = JSON.parse(localStorage.getItem("UserData") || "null"); // const userName = userData?.user_name; // const id = data?.id; // console.log("🟡 状态码 code =", code, "状态 status =", status); // if (code === 1006) { // setStatusText("尚未部署"); // setShowDelete(false); // setProgress("0%"); // setShowProgressBar(false) // return; // } // if (status === "deploying" && userName && id && !hasWSConnected) { // setStatusText("检测到正在部署,连接中..."); // initWebSocket(userName, id); // setShowProgressBar(true) // } // if (status === "running" || status === "stopped") { // console.log("✅ 允许删除(status =", status, ")"); // setShowDelete(true); // setProgress("100%"); // setShowProgressBar(true) // if (status === "running") { // setStatusText("运行中"); // setProgressBarColor("bg-green-500"); // } else if (status === "stopped") { // setStatusText("已停止"); // setProgressBarColor("bg-gray-400"); // } // } else { // console.log("❌ 不允许删除(status =", status, ")"); // setShowDelete(false); // setProgressBarColor("bg-blue-500"); // 回到默认蓝色 // } // } catch (err) { // console.error("获取状态失败:", err); // setStatusText("状态拉取失败"); // setShowDelete(false); // } // }; // fetchDeployStatus(); // }, [data?.id]); useEffect(() => { return () => { if (socketRef.current) { socketRef.current.close(); } }; }, []); 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 (
{data?.name || "未命名组件"}
{data?.category || "未知"}
{data?.updated_at || "未提供"}
{data?.company || "未知公司"}
{statusLoaded && showDelete && ( )}
{showProgressBar && (progress !== "0%" || statusText) && (
{loading ? "操作中..." : statusText}
)}
); } // 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 ( //
// {/* // */} //
//
// {/* // // */} //
// {/* show { // router.push("/") // // toast.success('coming soon') // }} /> */} // //
//
// {/* */} // {(!!userData && !!userData.user_name) ? ( //
// {/* */} // //
// ) : ( //
// // //
// )} //
//
//
// ) // } export function NavBack() { const router = useRouter(); const { t } = useTranslation(); // const query = router.query; // 假设页面 URL 是 /mypage?id=123 console.log("query", router) return ( ) } export function TimeP({ date, }: { date: string }) { const router = useRouter(); const { t } = useTranslation(); return (

{date} {t("JellyAI")}

) }