- 设计 token 重映射为 DeepSeek 调色板(深浅双主题),正文改无衬线字体栈,全面去霓虹化 - 移除顶部 Header,控件迁入左栏(Logo/连接/通道/会话/tabs/底部操作区),左右栏支持拖拽调宽并持久化,折叠为图标 rail - 对话区对齐 DeepSeek 聊天风:hero/docked 状态机、736px 居中列、用户右对齐柔和气泡、助手无气泡平铺、composer 卡片与反差发送键;子智能体点击导航完整保留 - 全功能区同步换肤:侧栏列表、右栏面板、ConfigPage、弹窗、选择器等 - fix: 修复 virtual-core 3.17.x 陈旧行高导致消息行重叠(宽度变化/滚动停止后强制 resizeItem 重测) - fix: 修复 ConfigPage/Modal 引用不存在的 fadeIn/scaleIn keyframes 致入场动画失效
69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
import { Wifi, WifiOff, Loader2 } from 'lucide-react';
|
|
import type { ConnectionStatus } from '../types/protocol';
|
|
|
|
interface ConnectionStatusProps {
|
|
status: ConnectionStatus;
|
|
/** rail 紧凑模式:仅显示图标 */
|
|
compact?: boolean;
|
|
}
|
|
|
|
export function ConnectionStatus({ status, compact = false }: ConnectionStatusProps) {
|
|
const getStatusConfig = () => {
|
|
switch (status) {
|
|
case 'connecting':
|
|
return {
|
|
icon: <Loader2 className={`animate-spin ${compact ? 'h-4 w-4' : 'h-3 w-3'}`} />,
|
|
text: '连接中',
|
|
className:
|
|
'text-[var(--accent-amber)] bg-[var(--accent-amber)]/10 border-[var(--accent-amber)]/30',
|
|
};
|
|
case 'connected':
|
|
return {
|
|
icon: <Wifi className={compact ? 'h-4 w-4' : 'h-3 w-3'} />,
|
|
text: '已连接',
|
|
className:
|
|
'text-[var(--accent-green)] bg-[var(--accent-green)]/10 border-[var(--accent-green)]/30',
|
|
};
|
|
case 'disconnected':
|
|
return {
|
|
icon: <WifiOff className={compact ? 'h-4 w-4' : 'h-3 w-3'} />,
|
|
text: '已断开',
|
|
className:
|
|
'text-[var(--text-muted)] bg-[var(--overlay-dim)] border-[var(--border-color)]',
|
|
};
|
|
case 'error':
|
|
return {
|
|
icon: <WifiOff className={compact ? 'h-4 w-4' : 'h-3 w-3'} />,
|
|
text: '连接错误',
|
|
className:
|
|
'text-[rgb(242,90,90)] bg-[rgb(242,90,90)]/10 border-[rgb(242,90,90)]/30',
|
|
};
|
|
}
|
|
};
|
|
|
|
const config = getStatusConfig();
|
|
|
|
if (!config) return null;
|
|
|
|
if (compact) {
|
|
return (
|
|
<div
|
|
className={`flex h-8 w-8 items-center justify-center rounded-lg border ${config.className}`}
|
|
title={config.text}
|
|
aria-label={config.text}
|
|
>
|
|
{config.icon}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className={`inline-flex w-fit items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs ${config.className}`}
|
|
>
|
|
{config.icon}
|
|
<span>{config.text}</span>
|
|
</div>
|
|
);
|
|
}
|