272 lines
7.7 KiB
Dart
272 lines
7.7 KiB
Dart
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<String, dynamic> toJson() {
|
|
return {
|
|
'name': name,
|
|
'catename': catename,
|
|
'url': url,
|
|
'keywords': keywords,
|
|
'introduce': introduce,
|
|
'platform': platform,
|
|
'submitTime': submitTime.toIso8601String(),
|
|
};
|
|
}
|
|
|
|
factory ManuscriptRecord.fromJson(Map<String, dynamic> 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<TougaoPage> createState() => _TougaoPageState();
|
|
}
|
|
|
|
class _TougaoPageState extends State<TougaoPage> {
|
|
List<ManuscriptRecord> _records = [];
|
|
bool _isLoading = true;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadRecords();
|
|
}
|
|
|
|
Future<void> _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<void> _clearAllRecords() async {
|
|
final confirm = await showDialog<bool>(
|
|
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,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|