'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 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); // 删除成功后隐藏按钮
} 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);
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);
}
};
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 (
//
// )
// }
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")}
)
}