Files
MookNote/lib/widgets/note_list_item.dart
DelLevin-Home d28c5e562e 完善2
2026-03-07 23:20:24 +08:00

192 lines
6.3 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 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/app_provider.dart';
import '../models/data_models.dart';
import '../utils/toast_util.dart';
/// 笔记列表项组件 - 极简主义设计
class NoteListItem extends StatelessWidget {
final Note note;
const NoteListItem({super.key, required this.note});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
Navigator.pushNamed(context, '/note-detail', arguments: note);
},
onLongPress: () => _showDeleteDialog(context),
child: Container(
margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: const Color(0xFFE5E5E5)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 内容摘要(去除首尾空格)
Text(
note.summary.trim(),
style: const TextStyle(
fontSize: 14,
color: Color(0xFF1A1A1A),
height: 1.5,
),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
// 图片预览区域显示前2张图片
if (note.images.isNotEmpty) ...[
const SizedBox(height: 10),
SizedBox(
height: 60,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: note.images.length > 2 ? 2 : note.images.length,
itemBuilder: (context, index) {
return Container(
width: 60,
height: 60,
margin: const EdgeInsets.only(right: 8),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFFE5E5E5)),
),
child: Image.file(
File(note.images[index]),
fit: BoxFit.cover,
),
);
},
),
),
],
const SizedBox(height: 10),
// 底部信息:标签 + 时间
Row(
children: [
// 标签
if (note.tags.isNotEmpty) ...[
Expanded(
child: Wrap(
spacing: 4,
runSpacing: 4,
children: note.tags.take(2).map((tag) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: const Color(0xFFF5F5F5),
borderRadius: BorderRadius.circular(2),
),
child: Text(
tag,
style: const TextStyle(
fontSize: 10,
color: Color(0xFF666666),
),
),
);
}).toList(),
),
),
] else
const Spacer(),
// 时间和图片数量
Row(
children: [
// 图片数量(如果有图片)
if (note.images.isNotEmpty) ...[
const Icon(
Icons.image_outlined,
size: 11,
color: Color(0xFF999999),
),
const SizedBox(width: 2),
Text(
'${note.images.length}',
style: const TextStyle(
fontSize: 11,
color: Color(0xFF999999),
),
),
const SizedBox(width: 6),
],
const Icon(
Icons.access_time,
size: 11,
color: Color(0xFF999999),
),
const SizedBox(width: 2),
Text(
_formatDate(note.updatedAt),
style: const TextStyle(
fontSize: 11,
color: Color(0xFF999999),
),
),
],
),
],
),
],
),
),
);
}
/// 格式化日期
String _formatDate(DateTime date) {
final now = DateTime.now();
final difference = now.difference(date);
if (difference.inDays == 0) {
if (difference.inHours == 0) {
if (difference.inMinutes == 0) {
return '刚刚';
}
return '${difference.inMinutes}分钟前';
}
return '${difference.inHours}小时前';
} else if (difference.inDays < 7) {
return '${difference.inDays}天前';
} else {
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
}
}
/// 显示删除确认对话框
void _showDeleteDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
backgroundColor: Colors.white,
elevation: 0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero),
title: const Text('确认删除'),
content: const Text('确定要删除这条笔记吗?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('取消', style: TextStyle(color: Color(0xFF666666))),
),
TextButton(
onPressed: () async {
await context.read<AppProvider>().removeNote(note.id);
Navigator.pop(context);
ToastUtil.show(context, '已删除');
},
child: const Text('删除', style: TextStyle(color: Colors.red)),
),
],
),
);
}
}