云算力平台windows桌面应用
This commit is contained in:
145
lib/screens/log_viewer_screen.dart
Normal file
145
lib/screens/log_viewer_screen.dart
Normal file
@@ -0,0 +1,145 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../providers/client_provider.dart';
|
||||
import '../services/log_service.dart';
|
||||
import 'dart:async';
|
||||
|
||||
class LogViewerScreen extends StatefulWidget {
|
||||
const LogViewerScreen({super.key});
|
||||
|
||||
@override
|
||||
State<LogViewerScreen> createState() => _LogViewerScreenState();
|
||||
}
|
||||
|
||||
class _LogViewerScreenState extends State<LogViewerScreen> {
|
||||
final LogService _logService = LogService();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
String _logs = '';
|
||||
StreamSubscription<String>? _logSubscription;
|
||||
StreamSubscription<String>? _clientLogSubscription;
|
||||
bool _autoScroll = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadLogs();
|
||||
_startMonitoring();
|
||||
}
|
||||
|
||||
Future<void> _loadLogs() async {
|
||||
final logs = await _logService.getRecentLogs();
|
||||
setState(() {
|
||||
_logs = logs;
|
||||
});
|
||||
if (_autoScroll && _scrollController.hasClients) {
|
||||
_scrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
void _startMonitoring() {
|
||||
// 监控日志文件
|
||||
_logSubscription = _logService.logStream.listen((log) {
|
||||
setState(() {
|
||||
_logs += '\n$log';
|
||||
});
|
||||
if (_autoScroll && _scrollController.hasClients) {
|
||||
_scrollToBottom();
|
||||
}
|
||||
});
|
||||
|
||||
// 监控客户端日志流
|
||||
final clientProvider = Provider.of<ClientProvider>(context, listen: false);
|
||||
_clientLogSubscription = clientProvider.logStream.listen((log) {
|
||||
setState(() {
|
||||
_logs += '\n$log';
|
||||
});
|
||||
if (_autoScroll && _scrollController.hasClients) {
|
||||
_scrollToBottom();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _scrollToBottom() {
|
||||
if (_scrollController.hasClients) {
|
||||
_scrollController.animateTo(
|
||||
_scrollController.position.maxScrollExtent,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOut,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_logSubscription?.cancel();
|
||||
_clientLogSubscription?.cancel();
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('日志查看'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(_autoScroll ? Icons.arrow_downward : Icons.arrow_upward),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_autoScroll = !_autoScroll;
|
||||
});
|
||||
},
|
||||
tooltip: _autoScroll ? '关闭自动滚动' : '开启自动滚动',
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.refresh),
|
||||
onPressed: _loadLogs,
|
||||
tooltip: '刷新日志',
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
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) {
|
||||
await _logService.clearLogs();
|
||||
_loadLogs();
|
||||
}
|
||||
},
|
||||
tooltip: '清理日志',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Container(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SingleChildScrollView(
|
||||
controller: _scrollController,
|
||||
child: SelectableText(
|
||||
_logs.isEmpty ? '暂无日志' : _logs,
|
||||
style: const TextStyle(
|
||||
fontFamily: 'monospace',
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user