zhou zhou
4 小时以前 341b7440f255a7e7213c106361943040ffb27ff8
#ai 页面优化
3个文件已修改
141 ■■■■■ 已修改文件
rsf-admin/src/i18n/en.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/zh.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/layout/AiChatDrawer.jsx 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-admin/src/i18n/en.js
@@ -544,6 +544,9 @@
            noFacts: "No Facts",
            retainLatestRound: "Keep Latest Round",
            clearMemory: "Clear Memory",
            runtimeOverview: "Runtime Overview",
            runtimeExpand: "Show Overview",
            runtimeCollapse: "Hide Overview",
            loadingRuntime: "Loading AI runtime info...",
            emptyHint: "AI responses stream back through SSE here. You can also maintain parameters, prompts, and MCP mounts from the quick links above.",
            userRole: "You",
rsf-admin/src/i18n/zh.js
@@ -560,6 +560,9 @@
            noFacts: "无事实",
            retainLatestRound: "仅保留当前轮",
            clearMemory: "清空记忆",
            runtimeOverview: "运行概览",
            runtimeExpand: "展开概览",
            runtimeCollapse: "收起概览",
            loadingRuntime: "正在加载 AI 运行时信息...",
            emptyHint: "这里会通过 SSE 流式返回 AI 回复。你也可以先去上面的快捷入口维护参数、Prompt 和 MCP 挂载。",
            userRole: "你",
rsf-admin/src/layout/AiChatDrawer.jsx
@@ -47,6 +47,8 @@
import { clearAiSessionMemory, getAiRuntime, getAiSessions, pinAiSession, removeAiSession, renameAiSession, retainAiSessionLatestRound, streamAiChat } from "@/api/ai/chat";
const DEFAULT_PROMPT_CODE = "home.default";
const AI_CHAT_DRAWER_Z_INDEX = 1400;
const AI_CHAT_DIALOG_Z_INDEX = AI_CHAT_DRAWER_Z_INDEX + 20;
const THINKING_PHASE_ORDER = {
    ANALYZE: 0,
    TOOL_CALL: 1,
@@ -248,6 +250,7 @@
    const [drawerError, setDrawerError] = useState("");
    const [sessionKeyword, setSessionKeyword] = useState("");
    const [renameDialog, setRenameDialog] = useState({ open: false, sessionId: null, title: "" });
    const [runtimePanelExpanded, setRuntimePanelExpanded] = useState(false);
    const quickLinks = useMemo(() => ([
        { label: translate("menu.aiParam"), path: "/aiParam", icon: <SettingsSuggestOutlinedIcon fontSize="small" /> },
@@ -297,6 +300,7 @@
    useEffect(() => {
        if (open) {
            setRuntimePanelExpanded(false);
            initializeDrawer();
        } else {
            stopStream(false);
@@ -726,7 +730,7 @@
            onClose={onClose}
            ModalProps={{ keepMounted: true }}
            sx={{
                zIndex: 1400,
                zIndex: AI_CHAT_DRAWER_Z_INDEX,
                "& .MuiDrawer-paper": {
                    top: 0,
                    height: "100vh",
@@ -935,63 +939,80 @@
                    <Box flex={1} display="flex" flexDirection="column" minHeight={0}>
                        <Box px={2} py={1.5}>
                            <Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap>
                                <Chip size="small" label={translate("ai.drawer.requestMetric", { value: runtimeSummary.requestId })} />
                                <Chip size="small" label={translate("ai.drawer.sessionMetric", { id: sessionId || "--" })} />
                                <Chip size="small" label={translate("ai.drawer.promptMetric", { value: runtimeSummary.promptName })} />
                                <Chip size="small" label={translate("ai.drawer.modelMetric", { value: runtimeSummary.model })} />
                                <Chip size="small" label={translate("ai.drawer.mcpMetric", { value: runtimeSummary.mountedMcpCount })} />
                                <Chip size="small" label={translate("ai.drawer.historyMetric", { value: persistedMessages.length })} />
                                <Chip size="small" label={translate("ai.drawer.recentMetric", { value: runtimeSummary.recentMessageCount })} />
                                <Chip size="small" color={runtimeSummary.hasSummary ? "success" : "default"} label={translate(runtimeSummary.hasSummary ? "ai.drawer.hasSummary" : "ai.drawer.noSummary")} />
                                <Chip size="small" color={runtimeSummary.hasFacts ? "info" : "default"} label={translate(runtimeSummary.hasFacts ? "ai.drawer.hasFacts" : "ai.drawer.noFacts")} />
                            <Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}>
                                <Typography variant="subtitle2">
                                    {translate("ai.drawer.runtimeOverview")}
                                </Typography>
                                <Button
                                    size="small"
                                    onClick={() => setRuntimePanelExpanded((prev) => !prev)}
                                    endIcon={runtimePanelExpanded
                                        ? <ExpandLessOutlinedIcon fontSize="small" />
                                        : <ExpandMoreOutlinedIcon fontSize="small" />}
                                    sx={{ minWidth: "auto", px: 1 }}
                                >
                                    {translate(runtimePanelExpanded ? "ai.drawer.runtimeCollapse" : "ai.drawer.runtimeExpand")}
                                </Button>
                            </Stack>
                            <Stack direction="row" spacing={1} mt={1.5} flexWrap="wrap" useFlexGap>
                                {quickLinks.map((item) => (
                            <Collapse in={runtimePanelExpanded} timeout="auto" unmountOnExit>
                                <Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap sx={{ mt: 1.5 }}>
                                    <Chip size="small" label={translate("ai.drawer.requestMetric", { value: runtimeSummary.requestId })} />
                                    <Chip size="small" label={translate("ai.drawer.sessionMetric", { id: sessionId || "--" })} />
                                    <Chip size="small" label={translate("ai.drawer.promptMetric", { value: runtimeSummary.promptName })} />
                                    <Chip size="small" label={translate("ai.drawer.modelMetric", { value: runtimeSummary.model })} />
                                    <Chip size="small" label={translate("ai.drawer.mcpMetric", { value: runtimeSummary.mountedMcpCount })} />
                                    <Chip size="small" label={translate("ai.drawer.historyMetric", { value: persistedMessages.length })} />
                                    <Chip size="small" label={translate("ai.drawer.recentMetric", { value: runtimeSummary.recentMessageCount })} />
                                    <Chip size="small" color={runtimeSummary.hasSummary ? "success" : "default"} label={translate(runtimeSummary.hasSummary ? "ai.drawer.hasSummary" : "ai.drawer.noSummary")} />
                                    <Chip size="small" color={runtimeSummary.hasFacts ? "info" : "default"} label={translate(runtimeSummary.hasFacts ? "ai.drawer.hasFacts" : "ai.drawer.noFacts")} />
                                </Stack>
                                <Stack direction="row" spacing={1} mt={1.5} flexWrap="wrap" useFlexGap>
                                    {quickLinks.map((item) => (
                                        <Button
                                            key={item.path}
                                            size="small"
                                            variant="outlined"
                                            startIcon={item.icon}
                                            onClick={() => navigate(item.path)}
                                        >
                                            {item.label}
                                        </Button>
                                    ))}
                                    <Button
                                        key={item.path}
                                        size="small"
                                        variant="outlined"
                                        startIcon={item.icon}
                                        onClick={() => navigate(item.path)}
                                        startIcon={<HistoryOutlinedIcon />}
                                        onClick={handleRetainLatestRound}
                                        disabled={!sessionId || streaming}
                                    >
                                        {item.label}
                                        {translate("ai.drawer.retainLatestRound")}
                                    </Button>
                                ))}
                                <Button
                                    size="small"
                                    variant="outlined"
                                    startIcon={<HistoryOutlinedIcon />}
                                    onClick={handleRetainLatestRound}
                                    disabled={!sessionId || streaming}
                                >
                                    {translate("ai.drawer.retainLatestRound")}
                                </Button>
                                <Button
                                    size="small"
                                    variant="outlined"
                                    color="warning"
                                    startIcon={<AutoDeleteOutlinedIcon />}
                                    onClick={handleClearMemory}
                                    disabled={!sessionId || streaming}
                                >
                                    {translate("ai.drawer.clearMemory")}
                                </Button>
                            </Stack>
                            {!!runtime?.memorySummary && (
                                <Alert severity="info" sx={{ mt: 1.5 }}>
                                    <Typography variant="body2" sx={{ whiteSpace: "pre-wrap" }}>
                                        {runtime.memorySummary}
                                    </Typography>
                                </Alert>
                            )}
                            {!!runtime?.memoryFacts && (
                                <Alert severity="success" sx={{ mt: 1.5 }}>
                                    <Typography variant="body2" sx={{ whiteSpace: "pre-wrap" }}>
                                        {runtime.memoryFacts}
                                    </Typography>
                                </Alert>
                            )}
                                    <Button
                                        size="small"
                                        variant="outlined"
                                        color="warning"
                                        startIcon={<AutoDeleteOutlinedIcon />}
                                        onClick={handleClearMemory}
                                        disabled={!sessionId || streaming}
                                    >
                                        {translate("ai.drawer.clearMemory")}
                                    </Button>
                                </Stack>
                                {!!runtime?.memorySummary && (
                                    <Alert severity="info" sx={{ mt: 1.5 }}>
                                        <Typography variant="body2" sx={{ whiteSpace: "pre-wrap" }}>
                                            {runtime.memorySummary}
                                        </Typography>
                                    </Alert>
                                )}
                                {!!runtime?.memoryFacts && (
                                    <Alert severity="success" sx={{ mt: 1.5 }}>
                                        <Typography variant="body2" sx={{ whiteSpace: "pre-wrap" }}>
                                            {runtime.memoryFacts}
                                        </Typography>
                                    </Alert>
                                )}
                            </Collapse>
                            {loadingRuntime && (
                                <Typography variant="body2" color="text.secondary" mt={1}>
                                    {translate("ai.drawer.loadingRuntime")}
@@ -1205,7 +1226,15 @@
                    </Box>
                </Box>
            </Box>
            <Dialog open={renameDialog.open} onClose={closeRenameDialog} fullWidth maxWidth="xs">
            <Dialog
                open={renameDialog.open}
                onClose={closeRenameDialog}
                fullWidth
                maxWidth="xs"
                sx={{
                    zIndex: AI_CHAT_DIALOG_Z_INDEX,
                }}
            >
                <DialogTitle>{translate("ai.drawer.renameDialogTitle")}</DialogTitle>
                <DialogContent>
                    <TextField