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 createState() => _KodBoxCardState(); } class _KodBoxCardState extends State { List _logs = []; bool _isLoading = false; String? _error; Future _fetchLogs() async { setState(() { _isLoading = true; _error = null; }); try { final authService = Provider.of(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 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]); }, ), ), ], ), ), ); } }