feat(team): integrate Team components into main application

- Add Team tab to Sidebar with TeamList component
- Update MainViewType to include 'team' view
- Add TeamCollaborationView rendering in App.tsx
- Add selectedTeamId and onSelectTeam props to Sidebar
- Create TeamList component for sidebar team navigation

UI Integration:
- Team tab shows list of teams with status indicators
- Selecting a team displays TeamCollaborationView
- Empty state shows guidance for creating teams

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-15 03:35:10 +08:00
parent c91740c00e
commit cd2a02877c
3 changed files with 170 additions and 12 deletions

View File

@@ -3,26 +3,37 @@ import { Settings } from 'lucide-react';
import { CloneManager } from './CloneManager';
import { HandList } from './HandList';
import { TaskList } from './TaskList';
import { TeamList } from './TeamList';
import { useGatewayStore } from '../store/gatewayStore';
export type MainViewType = 'chat' | 'hands' | 'workflow';
export type MainViewType = 'chat' | 'hands' | 'workflow' | 'team';
interface SidebarProps {
onOpenSettings?: () => void;
onMainViewChange?: (view: MainViewType) => void;
selectedHandId?: string;
onSelectHand?: (handId: string) => void;
selectedTeamId?: string;
onSelectTeam?: (teamId: string) => void;
}
type Tab = 'clones' | 'hands' | 'workflow';
type Tab = 'clones' | 'hands' | 'workflow' | 'team';
const TABS: { key: Tab; label: string; mainView?: MainViewType }[] = [
{ key: 'clones', label: '分身' },
{ key: 'hands', label: 'HANDS', mainView: 'hands' },
{ key: 'workflow', label: 'Workflow', mainView: 'workflow' },
{ key: 'team', label: 'Team', mainView: 'team' },
];
export function Sidebar({ onOpenSettings, onMainViewChange, selectedHandId, onSelectHand }: SidebarProps) {
export function Sidebar({
onOpenSettings,
onMainViewChange,
selectedHandId,
onSelectHand,
selectedTeamId,
onSelectTeam
}: SidebarProps) {
const [activeTab, setActiveTab] = useState<Tab>('clones');
const userName = useGatewayStore((state) => state.quickConfig.userName) || '用户7141';
@@ -37,22 +48,21 @@ export function Sidebar({ onOpenSettings, onMainViewChange, selectedHandId, onSe
const handleSelectHand = (handId: string) => {
onSelectHand?.(handId);
// 切换到 hands 视图
setActiveTab('hands');
onMainViewChange?.('hands');
};
return (
<aside className="w-64 bg-gray-50 border-r border-gray-200 flex flex-col flex-shrink-0">
<aside className="w-64 bg-gray-50 dark:bg-gray-900 border-r border-gray-200 dark:border-gray-700 flex flex-col flex-shrink-0">
{/* 顶部标签 */}
<div className="flex border-b border-gray-200 bg-white">
<div className="flex border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800">
{TABS.map(({ key, label }) => (
<button
key={key}
className={`flex-1 py-3 px-4 text-xs font-medium transition-colors ${
activeTab === key
? 'text-gray-900 border-b-2 border-gray-900'
: 'text-gray-500 hover:text-gray-700'
? 'text-gray-900 dark:text-white border-b-2 border-blue-500'
: 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'
}`}
onClick={() => handleTabClick(key, TABS.find(t => t.key === key)?.mainView)}
>
@@ -71,16 +81,22 @@ export function Sidebar({ onOpenSettings, onMainViewChange, selectedHandId, onSe
/>
)}
{activeTab === 'workflow' && <TaskList />}
{activeTab === 'team' && (
<TeamList
selectedTeamId={selectedTeamId}
onSelectTeam={onSelectTeam}
/>
)}
</div>
{/* 底部用户 */}
<div className="p-3 border-t border-gray-200 bg-gray-50">
<div className="p-3 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900">
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-gradient-to-br from-orange-400 to-red-500 rounded-full flex items-center justify-center text-white text-xs font-bold">
{userName?.charAt(0) || '用'}
</div>
<span className="font-medium text-gray-700">{userName}</span>
<button className="ml-auto text-gray-400 hover:text-gray-600" onClick={onOpenSettings}>
<span className="font-medium text-gray-700 dark:text-gray-300">{userName}</span>
<button className="ml-auto text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" onClick={onOpenSettings}>
<Settings className="w-4 h-4" />
</button>
</div>