import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../constants/app_constants.dart'; class ManuscriptRecord { final String name; final String catename; final String url; final String keywords; final String introduce; final String platform; final DateTime submitTime; ManuscriptRecord({ required this.name, required this.catename, required this.url, required this.keywords, required this.introduce, required this.platform, required this.submitTime, }); Map toJson() { return { 'name': name, 'catename': catename, 'url': url, 'keywords': keywords, 'introduce': introduce, 'platform': platform, 'submitTime': submitTime.toIso8601String(), }; } factory ManuscriptRecord.fromJson(Map json) { return ManuscriptRecord( name: json['name'] ?? '', catename: json['catename'] ?? '', url: json['url'] ?? '', keywords: json['keywords'] ?? '', introduce: json['introduce'] ?? '', platform: json['platform'] ?? '', submitTime: DateTime.parse( json['submitTime'] ?? DateTime.now().toIso8601String(), ), ); } } class TougaoPage extends StatefulWidget { const TougaoPage({super.key}); @override State createState() => _TougaoPageState(); } class _TougaoPageState extends State { List _records = []; bool _isLoading = true; @override void initState() { super.initState(); _loadRecords(); } Future _loadRecords() async { try { final prefs = await SharedPreferences.getInstance(); final recordsJson = prefs.getStringList('manuscript_records') ?? []; setState(() { _records = recordsJson .map((json) => ManuscriptRecord.fromJson(jsonDecode(json))) .toList() ..sort((a, b) => b.submitTime.compareTo(a.submitTime)); _isLoading = false; }); } catch (e) { setState(() => _isLoading = false); } } Future _clearAllRecords() async { final confirm = await showDialog( context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: const Row( children: [ Icon(Icons.warning_amber_rounded, color: AppConstants.errorColor), SizedBox(width: 8), Text('确认清空'), ], ), content: const Text('确定要清空所有投稿记录吗?此操作不可恢复。'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('取消'), ), ElevatedButton( onPressed: () => Navigator.pop(context, true), style: ElevatedButton.styleFrom( backgroundColor: AppConstants.errorColor, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: const Text('确认清空'), ), ], ), ); if (confirm == true) { final prefs = await SharedPreferences.getInstance(); await prefs.remove('manuscript_records'); await _loadRecords(); if (mounted) { ScaffoldMessenger.of( context, ).showSnackBar(const SnackBar(content: Text('已清空所有记录'))); } } } String _formatDate(DateTime date) { return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')} ' '${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}'; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('投稿记录'), actions: [ if (_records.isNotEmpty) IconButton( icon: const Icon(Icons.delete_sweep_outlined), onPressed: _clearAllRecords, tooltip: '清空记录', ), ], ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : _records.isEmpty ? _buildEmptyState() : _buildRecordsList(), ); } Widget _buildEmptyState() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.history_outlined, size: 80, color: Colors.grey[300]), const SizedBox(height: 16), Text( '暂无投稿记录', style: TextStyle(fontSize: 16, color: Colors.grey[600]), ), ], ), ); } Widget _buildRecordsList() { return ListView.builder( padding: const EdgeInsets.all(16), itemCount: _records.length, itemBuilder: (context, index) { final record = _records[index]; return _buildRecordCard(record); }, ); } Widget _buildRecordCard(ManuscriptRecord record) { return Card( elevation: 0, color: Colors.grey[50], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: ExpansionTile( title: Row( children: [ Expanded( child: Text( record.name, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 15, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppConstants.primaryColor.withAlpha(20), borderRadius: BorderRadius.circular(8), ), child: Text( record.catename, style: TextStyle( fontSize: 12, color: AppConstants.primaryColor, fontWeight: FontWeight.w500, ), ), ), ], ), subtitle: Padding( padding: const EdgeInsets.only(top: 4), child: Row( children: [ Icon(Icons.access_time, size: 14, color: Colors.grey[500]), const SizedBox(width: 4), Text( _formatDate(record.submitTime), style: TextStyle(fontSize: 12, color: Colors.grey[500]), ), ], ), ), childrenPadding: const EdgeInsets.fromLTRB(16, 0, 16, 16), children: [ _buildDetailItem('诗人和标题', record.url), _buildDetailItem('关键词', record.keywords), _buildDetailItem('平台', record.platform), _buildDetailItem('诗词介绍', record.introduce, maxLines: 3), ], ), ); } Widget _buildDetailItem(String label, String value, {int maxLines = 1}) { return Padding( padding: const EdgeInsets.only(bottom: 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 13, color: Colors.grey[600], fontWeight: FontWeight.w500, ), ), const SizedBox(height: 4), Text( value, style: const TextStyle(fontSize: 14), maxLines: maxLines, overflow: TextOverflow.ellipsis, ), ], ), ); } }