flutter_dashboard/lib/widgets/kodbox_card.dart

196 lines
5.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../services/auth_service.dart';
class KodBoxCard extends StatefulWidget {
const KodBoxCard({super.key});
@override
State<KodBoxCard> createState() => _KodBoxCardState();
}
class _KodBoxCardState extends State<KodBoxCard> {
List<dynamic> _logs = [];
bool _isLoading = false;
String? _error;
Future<void> _fetchLogs() async {
setState(() {
_isLoading = true;
_error = null;
});
try {
final authService = Provider.of<AuthService>(context, listen: false);
final token = authService.credentials['kodbox'];
if (token == null || token.isEmpty) {
throw Exception('未配置 KodBox Token');
}
// 计算时间范围最近7天
final now = DateTime.now();
final sevenDaysAgo = now.subtract(const Duration(days: 7));
final timeTo = (now.millisecondsSinceEpoch / 1000).round();
final timeFrom = (sevenDaysAgo.millisecondsSinceEpoch / 1000).round();
final request = http.MultipartRequest(
'POST',
Uri.parse('https://cloud.jdysya.top/?admin/log/get&accessToken=$token'),
);
request.fields.addAll({
'page': '1',
'pageNum': '50',
'sortField': 'createTime',
'sortType': 'down',
'timeFrom': timeFrom.toString(),
'timeTo': timeTo.toString(),
});
final response = await request.send();
final responseBody = await response.stream.bytesToString();
if (response.statusCode == 200) {
final data = jsonDecode(responseBody);
if (data['code'] == true) {
setState(() {
_logs = data['data'];
_isLoading = false;
});
} else {
throw Exception('请求失败: ${data['info'] ?? '未知错误'}');
}
} else {
throw Exception('请求失败: ${response.statusCode}');
}
} catch (e) {
setState(() {
_error = e.toString();
_isLoading = false;
});
}
}
String _formatTimestamp(String timestamp) {
final date = DateTime.fromMillisecondsSinceEpoch(
(double.parse(timestamp) * 1000).round(),
);
return date.toString().substring(0, 19);
}
Widget _buildLogItem(Map<String, dynamic> log) {
final desc = log['desc'];
final isFileOperation =
desc != null &&
(desc['sourceInfo'] != null || desc['parentInfo'] != null);
return Card(
margin: const EdgeInsets.symmetric(vertical: 4.0),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
CircleAvatar(
radius: 16,
child: Text(log['nickName']?[0].toUpperCase() ?? '?'),
),
const SizedBox(width: 8),
Text(
log['nickName'] ?? log['name'] ?? '未知用户',
style: const TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(width: 8),
Text(log['title'] ?? '未知操作'),
],
),
if (isFileOperation && desc['sourceInfo'] != null) ...[
const SizedBox(height: 8),
Text(
'文件路径: ${desc['sourceInfo']['pathDisplay']}',
style: const TextStyle(color: Colors.blue),
),
],
const SizedBox(height: 8),
Text(
'时间: ${_formatTimestamp(log['createTime'])}',
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
],
),
),
);
}
@override
void initState() {
super.initState();
_fetchLogs();
}
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'KodBox 最近操作',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
IconButton(
icon: const Icon(Icons.refresh),
onPressed: _isLoading ? null : _fetchLogs,
),
],
),
if (_isLoading)
const Center(
child: Padding(
padding: EdgeInsets.all(16.0),
child: CircularProgressIndicator(),
),
)
else if (_error != null)
Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
_error!,
style: const TextStyle(color: Colors.red),
),
),
)
else if (_logs.isEmpty)
const Center(
child: Padding(
padding: EdgeInsets.all(16.0),
child: Text('暂无操作记录'),
),
)
else
Expanded(
child: ListView.builder(
itemCount: _logs.length,
itemBuilder: (context, index) {
return _buildLogItem(_logs[index]);
},
),
),
],
),
),
);
}
}