- 添加Flutter项目基础文件与配置,包括.gitignore和analysis_options.yaml - 配置Android相关文件及Gradle构建脚本支持 - 新增设备状态与网络状态数据模型及相关枚举 - 实现网络检测及网速测试服务 - 创建监控状态管理Provider,实现设备状态管理和自动刷新机制 - 编写主界面HomeScreen,包括设备列表、网速仪表盘及基础交互 - 添加资源文件支持应用图标和启动画面 - 配置项目元数据文件,支持Flutter迁移及版本控制 - 新增项目README,提供入门指引和相关资源链接
260 lines
7.7 KiB
Dart
260 lines
7.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
import '../providers/providers.dart';
|
|
import '../widgets/widgets.dart';
|
|
|
|
/// 主页面
|
|
class HomeScreen extends StatefulWidget {
|
|
const HomeScreen({super.key});
|
|
|
|
@override
|
|
State<HomeScreen> createState() => _HomeScreenState();
|
|
}
|
|
|
|
class _HomeScreenState extends State<HomeScreen> {
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
// 初始化数据
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
final provider = context.read<MonitorProvider>();
|
|
provider.initDefaultDevices();
|
|
provider.refreshAll();
|
|
provider.startAutoRefresh(intervalSeconds: 30);
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: _buildAppBar(),
|
|
body: _buildBody(),
|
|
floatingActionButton: _buildFAB(),
|
|
);
|
|
}
|
|
|
|
PreferredSizeWidget _buildAppBar() {
|
|
return AppBar(
|
|
title: const Text('家庭网络监控'),
|
|
centerTitle: true,
|
|
actions: [
|
|
Consumer<MonitorProvider>(
|
|
builder: (context, provider, _) {
|
|
return IconButton(
|
|
icon: provider.isLoading
|
|
? const SizedBox(
|
|
width: 20,
|
|
height: 20,
|
|
child: CircularProgressIndicator(strokeWidth: 2),
|
|
)
|
|
: const Icon(Icons.refresh),
|
|
onPressed: provider.isLoading ? null : () => provider.refreshAll(),
|
|
tooltip: '刷新',
|
|
);
|
|
},
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.settings),
|
|
onPressed: () {
|
|
_showSettingsDialog();
|
|
},
|
|
tooltip: '设置',
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildBody() {
|
|
return Consumer<MonitorProvider>(
|
|
builder: (context, provider, _) {
|
|
return RefreshIndicator(
|
|
onRefresh: () => provider.refreshAll(),
|
|
child: SingleChildScrollView(
|
|
physics: const AlwaysScrollableScrollPhysics(),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// 网速仪表盘
|
|
SpeedGauge(
|
|
networkStatus: provider.networkStatus,
|
|
isLoading: provider.isTestingSpeed,
|
|
),
|
|
|
|
// 概览卡片
|
|
_buildOverviewCards(provider),
|
|
|
|
// 设备列表标题
|
|
Padding(
|
|
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
'监控设备',
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
),
|
|
TextButton.icon(
|
|
onPressed: () => _showAddDeviceDialog(),
|
|
icon: const Icon(Icons.add, size: 18),
|
|
label: const Text('添加'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
// 设备列表
|
|
_buildDeviceList(provider),
|
|
|
|
const SizedBox(height: 80),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
Widget _buildOverviewCards(MonitorProvider provider) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: StatusCard(
|
|
title: '在线设备',
|
|
value: '${provider.onlineDevicesCount}',
|
|
icon: Icons.check_circle,
|
|
iconColor: Colors.green,
|
|
subtitle: '共 ${provider.devices.length} 台设备',
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: StatusCard(
|
|
title: '离线设备',
|
|
value: '${provider.offlineDevicesCount}',
|
|
icon: Icons.error,
|
|
iconColor: provider.offlineDevicesCount > 0
|
|
? Colors.red
|
|
: Colors.grey,
|
|
subtitle: provider.offlineDevicesCount > 0
|
|
? '需要检查'
|
|
: '全部正常',
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildDeviceList(MonitorProvider provider) {
|
|
if (provider.devices.isEmpty) {
|
|
return const Center(
|
|
child: Padding(
|
|
padding: EdgeInsets.all(32),
|
|
child: Column(
|
|
children: [
|
|
Icon(Icons.devices, size: 64, color: Colors.grey),
|
|
SizedBox(height: 16),
|
|
Text('暂无监控设备'),
|
|
SizedBox(height: 8),
|
|
Text('点击右上角添加设备', style: TextStyle(color: Colors.grey)),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return ListView.builder(
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemCount: provider.devices.length,
|
|
itemBuilder: (context, index) {
|
|
final device = provider.devices[index];
|
|
return DeviceTile(
|
|
device: device,
|
|
onRefresh: () => provider.checkSingleDevice(device.id),
|
|
onTap: () => _showDeviceDetail(device),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
Widget _buildFAB() {
|
|
return Consumer<MonitorProvider>(
|
|
builder: (context, provider, _) {
|
|
return FloatingActionButton.extended(
|
|
onPressed: provider.isTestingSpeed ? null : () => provider.runSpeedTest(),
|
|
icon: provider.isTestingSpeed
|
|
? const SizedBox(
|
|
width: 20,
|
|
height: 20,
|
|
child: CircularProgressIndicator(
|
|
strokeWidth: 2,
|
|
color: Colors.white,
|
|
),
|
|
)
|
|
: const Icon(Icons.speed),
|
|
label: Text(provider.isTestingSpeed ? '测速中...' : '测速'),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
void _showSettingsDialog() {
|
|
final provider = context.read<MonitorProvider>();
|
|
int interval = provider.refreshInterval;
|
|
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text('设置'),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
ListTile(
|
|
title: const Text('自动刷新间隔'),
|
|
subtitle: Text('$interval 秒'),
|
|
trailing: DropdownButton<int>(
|
|
value: interval,
|
|
items: const [
|
|
DropdownMenuItem(value: 10, child: Text('10秒')),
|
|
DropdownMenuItem(value: 30, child: Text('30秒')),
|
|
DropdownMenuItem(value: 60, child: Text('1分钟')),
|
|
DropdownMenuItem(value: 300, child: Text('5分钟')),
|
|
],
|
|
onChanged: (value) {
|
|
if (value != null) {
|
|
provider.setRefreshInterval(value);
|
|
Navigator.pop(context);
|
|
}
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text('关闭'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showAddDeviceDialog() {
|
|
// TODO: 实现添加设备对话框
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('添加设备功能开发中...')),
|
|
);
|
|
}
|
|
|
|
void _showDeviceDetail(device) {
|
|
// TODO: 实现设备详情页
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('设备: ${device.name}')),
|
|
);
|
|
}
|
|
}
|