part of 'studio_app.dart'; class StudioDashboardPage extends StatelessWidget { const StudioDashboardPage({ super.key, required this.tab, required this.user, required this.activities, }); final StudioTab tab; final StudioUser user; final List activities; @override Widget build(BuildContext context) { return SingleChildScrollView( child: Padding( padding: const EdgeInsets.only(bottom: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Card( child: Padding( padding: const EdgeInsets.all(14), child: Row( children: [ Container( width: 56, height: 56, decoration: BoxDecoration( gradient: LinearGradient( colors: [ Theme.of( context, ).colorScheme.primary.withOpacity(0.25), Theme.of( context, ).colorScheme.tertiary.withOpacity(0.20), ], ), borderRadius: BorderRadius.circular(18), ), child: const Icon( Icons.space_dashboard_rounded, size: 30, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '工作台', style: Theme.of(context).textTheme.titleLarge ?.copyWith(fontWeight: FontWeight.w700), ), const SizedBox(height: 4), Text( '左侧菜单已映射自 studio.html 的核心入口,点击即可打开多标签页。', style: Theme.of(context).textTheme.bodySmall ?.copyWith(color: _mutedColor(context, 0.72)), ), ], ), ), Wrap( spacing: 8, runSpacing: 8, children: [ _MiniBadge(text: user.workspace), _MiniBadge(text: user.languageCode.toUpperCase()), ], ), ], ), ), ), const SizedBox(height: 8), LayoutBuilder( builder: (context, constraints) { final cardWidth = constraints.maxWidth >= 1100 ? (constraints.maxWidth - 32) / 3 : constraints.maxWidth >= 760 ? (constraints.maxWidth - 16) / 2 : constraints.maxWidth; return Wrap( spacing: 12, runSpacing: 12, children: [ SizedBox( width: cardWidth, child: _InfoPanel( title: '会话状态', value: user.displayName, icon: Icons.person_rounded, subtitle: '${user.role} · 已登录', ), ), SizedBox( width: cardWidth, child: _InfoPanel( title: '打开页面', value: '${activities.length} 条记录', icon: Icons.tab_rounded, subtitle: '支持多标签并行工作', ), ), SizedBox( width: cardWidth, child: _InfoPanel( title: '运行方式', value: '桌面端', icon: Icons.desktop_windows_rounded, subtitle: 'Flutter Windows / Web 共用', ), ), ], ); }, ), const SizedBox(height: 10), _ActivityPanel(activities: activities), ], ), ), ); } } class _InfoPanel extends StatelessWidget { const _InfoPanel({ required this.title, required this.value, required this.icon, required this.subtitle, }); final String title; final String value; final IconData icon; final String subtitle; @override Widget build(BuildContext context) { return Card( child: Padding( padding: const EdgeInsets.all(12), child: Row( children: [ Container( width: 40, height: 40, decoration: BoxDecoration( color: Theme.of(context).colorScheme.primary.withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: Icon(icon, size: 20), ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: _mutedColor(context, 0.68), ), ), const SizedBox(height: 4), Text( value, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.w700, ), ), const SizedBox(height: 2), Text( subtitle, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: _mutedColor(context, 0.72), ), ), ], ), ), ], ), ), ); } } class _ActivityPanel extends StatelessWidget { const _ActivityPanel({required this.activities}); final List activities; @override Widget build(BuildContext context) { return Card( child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '最近活动', style: Theme.of( context, ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700), ), const SizedBox(height: 8), ...activities .take(8) .map( (item) => Padding( padding: const EdgeInsets.only(bottom: 8), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Icon(Icons.bolt_rounded, size: 16), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.title, style: Theme.of(context).textTheme.bodyMedium ?.copyWith(fontWeight: FontWeight.w600), ), const SizedBox(height: 2), Text( item.detail, style: Theme.of(context).textTheme.bodySmall ?.copyWith( color: _mutedColor(context, 0.70), ), ), ], ), ), ], ), ), ), ], ), ), ); } }