Agent 初版设计
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
IconButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Stack,
|
||||
Typography,
|
||||
alpha,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import AutoAwesome from "@mui/icons-material/AutoAwesome";
|
||||
import AddCommentRounded from "@mui/icons-material/AddCommentRounded";
|
||||
import CloseRounded from "@mui/icons-material/CloseRounded";
|
||||
|
||||
type AgentHeaderProps = {
|
||||
isStreaming: boolean;
|
||||
menuAnchorEl: HTMLElement | null;
|
||||
onMenuOpen: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
onMenuClose: () => void;
|
||||
onNewConversation: () => void;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
export const AgentHeader = ({
|
||||
isStreaming,
|
||||
menuAnchorEl,
|
||||
onMenuOpen,
|
||||
onMenuClose,
|
||||
onNewConversation,
|
||||
onClose,
|
||||
}: AgentHeaderProps) => {
|
||||
const theme = useTheme();
|
||||
const isMenuOpen = Boolean(menuAnchorEl);
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
px: 3,
|
||||
py: 2.5,
|
||||
zIndex: 10,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={2}>
|
||||
<motion.div whileHover={{ rotate: 10, scale: 1.08 }} whileTap={{ scale: 0.95 }}>
|
||||
<IconButton
|
||||
onClick={onMenuOpen}
|
||||
aria-label="打开 Agent 菜单"
|
||||
aria-controls={isMenuOpen ? "global-chatbox-header-menu" : undefined}
|
||||
aria-expanded={isMenuOpen ? "true" : undefined}
|
||||
aria-haspopup="menu"
|
||||
sx={{ p: 0, borderRadius: "50%" }}
|
||||
>
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<Avatar
|
||||
sx={{
|
||||
background: `linear-gradient(135deg, ${theme.palette.primary.light}, ${theme.palette.primary.main})`,
|
||||
boxShadow: `0 8px 20px ${alpha(theme.palette.primary.main, 0.4)}`,
|
||||
width: 48,
|
||||
height: 48,
|
||||
}}
|
||||
>
|
||||
<AutoAwesome fontSize="medium" sx={{ color: "#fff" }} />
|
||||
</Avatar>
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: 2,
|
||||
right: 2,
|
||||
width: 12,
|
||||
height: 12,
|
||||
bgcolor: isStreaming ? "warning.main" : "success.main",
|
||||
borderRadius: "50%",
|
||||
border: "2px solid #fff",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</IconButton>
|
||||
</motion.div>
|
||||
<Box>
|
||||
<Typography
|
||||
variant="h6"
|
||||
fontWeight={900}
|
||||
sx={{
|
||||
background: `linear-gradient(90deg, ${theme.palette.primary.dark}, ${theme.palette.secondary.dark})`,
|
||||
backgroundClip: "text",
|
||||
color: "transparent",
|
||||
letterSpacing: -0.5,
|
||||
}}
|
||||
>
|
||||
TJWater Agent
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary" fontWeight={600}>
|
||||
{isStreaming ? "正在分析管网任务" : "管网分析工作台"}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
<Menu
|
||||
id="global-chatbox-header-menu"
|
||||
anchorEl={menuAnchorEl}
|
||||
open={isMenuOpen}
|
||||
onClose={onMenuClose}
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
|
||||
transformOrigin={{ vertical: "top", horizontal: "left" }}
|
||||
slotProps={{
|
||||
paper: {
|
||||
elevation: 8,
|
||||
sx: {
|
||||
mt: 1,
|
||||
minWidth: 180,
|
||||
borderRadius: 3,
|
||||
border: `1px solid ${alpha(theme.palette.divider, 0.12)}`,
|
||||
backdropFilter: "blur(12px)",
|
||||
bgcolor: alpha("#fff", 0.92),
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<MenuItem onClick={onNewConversation}>
|
||||
<ListItemIcon>
|
||||
<AddCommentRounded fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary="新建对话"
|
||||
secondary="清空当前会话"
|
||||
primaryTypographyProps={{ sx: { fontSize: "0.95rem", fontWeight: 700 } }}
|
||||
secondaryTypographyProps={{ sx: { fontSize: "0.8rem" } }}
|
||||
/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
<motion.div whileHover={{ scale: 1.08, rotate: 90 }} whileTap={{ scale: 0.92 }}>
|
||||
<IconButton
|
||||
onClick={onClose}
|
||||
size="small"
|
||||
aria-label="关闭 Agent"
|
||||
sx={{
|
||||
color: "text.primary",
|
||||
bgcolor: alpha("#fff", 0.54),
|
||||
"&:hover": { bgcolor: "#fff" },
|
||||
}}
|
||||
>
|
||||
<CloseRounded />
|
||||
</IconButton>
|
||||
</motion.div>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user