Files
beaver_project/app-instance/frontend/components/chat-workbench/CurrentSessionProgressSidebar.tsx
steven_li 2c5205b06e feat: 添加MinIO文件系统支持并优化外部连接器功能
- 添加MinIO用户文件系统配置选项(BEAVER_MINIO_ROOT_USER等)
- 更新外部连接器配置结构,包括BASE_URL和认证令牌设置
- 改进connector provider支持更多类型(official, feishu_bot等)
- 实现Mistral模型推理模式支持reasoning_effort参数
- 增强外部连接器策略配置和运行时配置管理
- 添加connector bridge事件验证和安全保护机制
- 优化任务路由逻辑,区分simple_chat和new_task场景
- 更新初始技能工具提示配置,分离authoring admin功能
2026-06-05 11:46:40 +08:00

99 lines
3.3 KiB
TypeScript

'use client';
import React from 'react';
import { Activity, PanelRightOpen, X } from 'lucide-react';
import { TaskTimeline } from '@/components/task-detail';
import { ScrollArea } from '@/components/ui/scroll-area';
import { pickAppText } from '@/lib/i18n/core';
import { useAppI18n } from '@/lib/i18n/provider';
import type { TaskTimelineCard } from '@/types';
function ProgressPanel({
cards,
isLive,
onClose,
}: {
cards: TaskTimelineCard[];
isLive: boolean;
onClose?: () => void;
}) {
const { locale } = useAppI18n();
return (
<div className="flex h-full flex-col bg-[#FBFAF9]">
<div className="flex h-16 shrink-0 items-center justify-between border-b border-[#E6E1DE] px-5">
<div>
<h2 className="text-base font-semibold text-foreground">
{pickAppText(locale, '当前会话的运行进度', 'Current Session Progress')}
</h2>
<p className="flex items-center gap-1.5 text-xs text-muted-foreground">
{isLive ? <Activity className="h-3.5 w-3.5" /> : null}
{isLive
? pickAppText(locale, '任务时间线实时更新', 'Task timeline updates live')
: pickAppText(locale, '与任务详情时间线一致', 'Matches the Task detail timeline')}
</p>
</div>
{onClose ? (
<button
type="button"
onClick={onClose}
className="rounded-full p-2 text-muted-foreground transition-colors hover:bg-[#ECE8E5] hover:text-foreground"
aria-label={pickAppText(locale, '关闭进度面板', 'Close progress panel')}
>
<X className="h-4 w-4" />
</button>
) : null}
</div>
<ScrollArea className="min-h-0 flex-1 px-4 py-4">
<div className="pb-6">
<TaskTimeline cards={cards} isLive={isLive} showHeader={false} />
</div>
</ScrollArea>
</div>
);
}
export function CurrentSessionProgressSidebar({
cards,
isLive,
}: {
cards: TaskTimelineCard[];
isLive: boolean;
}) {
const { locale } = useAppI18n();
const [mobileOpen, setMobileOpen] = React.useState(false);
return (
<>
<aside className="hidden h-full w-[380px] shrink-0 border-l border-[#E6E1DE] xl:flex">
<ProgressPanel cards={cards} isLive={isLive} />
</aside>
<button
type="button"
onClick={() => setMobileOpen(true)}
className="fixed right-3 top-24 z-40 flex h-11 w-11 items-center justify-center rounded-full border border-[#E6E1DE] bg-white text-[#342E2B] shadow-[0_8px_22px_rgba(0,0,0,0.16)] transition-colors hover:bg-[#F7F6F5] xl:hidden"
aria-label={pickAppText(locale, '查看当前会话运行进度', 'View current session progress')}
>
<PanelRightOpen className="h-5 w-5" />
</button>
{mobileOpen ? (
<div className="fixed inset-0 z-50 xl:hidden">
<button
type="button"
className="absolute inset-0 bg-black/30"
onClick={() => setMobileOpen(false)}
aria-label={pickAppText(locale, '关闭进度面板', 'Close progress panel')}
/>
<div className="absolute inset-y-0 right-0 w-[min(92vw,390px)] border-l border-[#E6E1DE] shadow-2xl">
<ProgressPanel cards={cards} isLive={isLive} onClose={() => setMobileOpen(false)} />
</div>
</div>
) : null}
</>
);
}