import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/client_provider.dart'; import '../models/client_status.dart'; import 'log_viewer_screen.dart'; import 'config_editor_screen.dart'; import 'mining_info_screen.dart'; import 'dart:io'; class MainScreen extends StatelessWidget { const MainScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('云算力平台客户端'), centerTitle: true, ), body: Consumer( builder: (context, provider, child) { final clientInfo = provider.clientInfo; if (provider.isLoading && clientInfo == null) { return const Center(child: CircularProgressIndicator()); } if (clientInfo == null) { return const Center(child: Text('无法获取客户端信息')); } return SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 状态指示器 _buildStatusCard(clientInfo), const SizedBox(height: 16), // 基本信息卡片 _buildInfoCard(clientInfo), const SizedBox(height: 16), // 版本更新提示 if (provider.hasUpdate) _buildUpdateCard(context, provider), if (provider.hasUpdate) const SizedBox(height: 16), // GPU信息卡片 _buildGPUCard(clientInfo.gpus), const SizedBox(height: 16), // 操作按钮 _buildActionButtons(context, clientInfo), ], ), ); }, ), ); } Widget _buildStatusCard(ClientInfo clientInfo) { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Row( children: [ Container( width: 20, height: 20, decoration: BoxDecoration( color: clientInfo.status.color, shape: BoxShape.circle, ), ), const SizedBox(width: 12), Text( '当前状态: ${clientInfo.status.displayName}', style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ], ), ), ); } Widget _buildInfoCard(ClientInfo clientInfo) { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '基本信息', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), const Divider(), _buildInfoRow('版本号', clientInfo.version), _buildInfoRow('身份信息', clientInfo.auth), _buildInfoRow('机器码', clientInfo.machineCode), ], ), ), ); } Widget _buildInfoRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 100, child: Text( '$label:', style: const TextStyle(fontWeight: FontWeight.w500), ), ), Expanded( child: Text(value), ), ], ), ); } Widget _buildGPUCard(List gpus) { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'GPU信息', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), const Divider(), if (gpus.isEmpty) const Text('未检测到GPU') else ...gpus.map((gpu) => Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: Text('GPU ${gpu.index}: ${gpu.displayName}'), )), ], ), ), ); } Widget _buildUpdateCard(BuildContext context, ClientProvider provider) { return Card( color: Colors.orange.shade50, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.system_update, color: Colors.orange.shade700), const SizedBox(width: 8), const Text( '发现新版本', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.orange, ), ), ], ), const SizedBox(height: 8), Text('当前版本: ${provider.clientInfo?.version ?? '未知'}'), Text('最新版本: ${provider.remoteVersion ?? '未知'}'), const SizedBox(height: 12), ElevatedButton.icon( onPressed: () => _performUpdate(context, provider), icon: const Icon(Icons.download), label: const Text('立即更新'), style: ElevatedButton.styleFrom( backgroundColor: Colors.orange, foregroundColor: Colors.white, ), ), ], ), ), ); } Future _performUpdate(BuildContext context, ClientProvider provider) async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('确认更新'), content: const Text( '更新将在下载完成后,下次启动时应用。\n' '更新过程中请勿关闭程序。\n\n' '确定要继续吗?', ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('确定'), ), ], ), ); if (confirmed == true) { // 显示进度对话框 showDialog( context: context, barrierDismissible: false, builder: (context) => const AlertDialog( content: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(), SizedBox(height: 16), Text('正在下载更新...'), ], ), ), ); final success = await provider.performUpdate(); if (context.mounted) { Navigator.pop(context); // 关闭进度对话框 showDialog( context: context, builder: (context) => AlertDialog( title: Text(success ? '更新成功' : '更新失败'), content: Text( success ? '更新已下载完成,将在下次启动时应用。\n请重启程序以完成更新。' : '更新下载失败,请检查网络连接或稍后重试。', ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('确定'), ), ], ), ); } } } Widget _buildActionButtons(BuildContext context, ClientInfo clientInfo) { return Wrap( spacing: 12, runSpacing: 12, children: [ ElevatedButton.icon( onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (_) => const LogViewerScreen()), ); }, icon: const Icon(Icons.description), label: const Text('查看日志'), ), ElevatedButton.icon( onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (_) => const ConfigEditorScreen()), ); }, icon: const Icon(Icons.settings), label: const Text('查看/修改配置'), ), ElevatedButton.icon( onPressed: (clientInfo.status == ClientStatus.mining || clientInfo.status == ClientStatus.sustainingMining) && clientInfo.miningInfo != null ? () { Navigator.push( context, MaterialPageRoute( builder: (_) => MiningInfoScreen( miningInfo: clientInfo.miningInfo!, isSustainMining: clientInfo.status == ClientStatus.sustainingMining, ), ), ); } : null, icon: const Icon(Icons.diamond), label: const Text('挖矿信息'), style: ElevatedButton.styleFrom( backgroundColor: ((clientInfo.status == ClientStatus.mining || clientInfo.status == ClientStatus.sustainingMining) && clientInfo.miningInfo != null) ? null : Colors.grey, ), ), ElevatedButton.icon( onPressed: () => _restartClient(context), icon: const Icon(Icons.refresh), label: const Text('重启'), style: ElevatedButton.styleFrom( backgroundColor: Colors.orange, foregroundColor: Colors.white, ), ), ElevatedButton.icon( onPressed: () => _exitApp(context), icon: const Icon(Icons.exit_to_app), label: const Text('退出程序'), style: ElevatedButton.styleFrom( backgroundColor: Colors.red, foregroundColor: Colors.white, ), ), ], ); } void _restartClient(BuildContext context) async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('确认重启'), content: const Text('确定要重启客户端吗?'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('确定'), ), ], ), ); if (confirmed == true) { // 显示加载对话框,禁用所有操作 showDialog( context: context, barrierDismissible: false, builder: (context) => PopScope( canPop: false, // 禁止返回 child: const AlertDialog( content: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(), SizedBox(height: 16), Text('正在重启客户端...'), ], ), ), ), ); final provider = Provider.of(context, listen: false); bool success = false; String errorMessage = ''; try { await provider.restart(); success = true; } catch (e) { errorMessage = e.toString(); } if (context.mounted) { Navigator.pop(context); // 关闭加载对话框 // 显示结果 ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(success ? '客户端重启成功' : '客户端重启失败: $errorMessage'), backgroundColor: success ? Colors.green : Colors.red, duration: const Duration(seconds: 3), ), ); } } } void _exitApp(BuildContext context) async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('确认退出'), content: const Text('确定要退出程序吗?'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('确定'), ), ], ), ); if (confirmed == true) { exit(0); } } }