feat: 增强日历功能并集成 AgentScope 代理服务

This commit is contained in:
qzl
2026-03-11 17:16:11 +08:00
parent e20e7d2a02
commit 85b314cf64
53 changed files with 3642 additions and 297 deletions
@@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:lucide_icons/lucide_icons.dart';
import '../../../../core/di/injection.dart';
import '../../../../core/notifications/local_notification_service.dart';
import '../../../../core/theme/design_tokens.dart';
import '../../data/models/schedule_item_model.dart';
import '../../data/services/mock_calendar_service.dart';
@@ -63,6 +64,7 @@ class _CreateEventSheetState extends State<CreateEventSheet>
DateTime? _endDate;
DateTime? _endTime;
String _selectedColor = '#3B82F6';
int? _reminderMinutes = 15;
bool _saving = false;
List<Attachment> _attachments = const [];
@@ -84,11 +86,13 @@ class _CreateEventSheetState extends State<CreateEventSheet>
_endDate = event.endAt;
_endTime = event.endAt;
_selectedColor = event.metadata?.color ?? '#3B82F6';
_reminderMinutes = event.metadata?.reminderMinutes ?? 15;
_attachments = List<Attachment>.from(
event.metadata?.attachments ?? const [],
);
} else {
final now = widget.initialDate ?? DateTime.now();
final now =
widget.initialDate ?? _roundToNearestMinute(DateTime.now(), 5);
_startDate = now;
_startTime = now;
_endDate = now;
@@ -108,6 +112,11 @@ class _CreateEventSheetState extends State<CreateEventSheet>
super.dispose();
}
DateTime _roundToNearestMinute(DateTime dt, int interval) {
final minute = (dt.minute / interval).round() * interval;
return DateTime(dt.year, dt.month, dt.day, dt.hour, minute % 60);
}
@override
Widget build(BuildContext context) {
return Container(
@@ -254,6 +263,8 @@ class _CreateEventSheetState extends State<CreateEventSheet>
const SizedBox(height: 20),
_buildTextField('地点', _locationController, '请输入地点'),
const SizedBox(height: 20),
_buildReminderPicker(),
const SizedBox(height: 20),
_buildColorPicker(),
const SizedBox(height: 20),
_buildAttachmentsSection(),
@@ -706,6 +717,68 @@ class _CreateEventSheetState extends State<CreateEventSheet>
);
}
Widget _buildReminderPicker() {
const options = <int?>[null, 0, 5, 10, 15, 30, 60, 120];
String labelOf(int? value) {
if (value == null) {
return '无提醒';
}
if (value == 0) {
return '准时提醒';
}
return '开始前$value分钟';
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'提醒时间',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.slate700,
),
),
const SizedBox(height: 8),
Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(color: AppColors.border),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<int?>(
value: _reminderMinutes,
isExpanded: true,
items: options
.map(
(value) => DropdownMenuItem<int?>(
value: value,
child: Text(
labelOf(value),
style: const TextStyle(
fontSize: 14,
color: AppColors.slate700,
),
),
),
)
.toList(),
onChanged: (value) {
setState(() {
_reminderMinutes = value;
});
},
),
),
),
],
);
}
Future<void> _saveEvent() async {
if (_titleController.text.trim().isEmpty || _saving) return;
setState(() {
@@ -739,6 +812,7 @@ class _CreateEventSheetState extends State<CreateEventSheet>
notes: _notesController.text.trim().isNotEmpty
? _notesController.text.trim()
: null,
reminderMinutes: _reminderMinutes,
attachments: _attachments,
version: widget.editingEvent?.metadata?.version ?? 1,
);
@@ -758,22 +832,21 @@ class _CreateEventSheetState extends State<CreateEventSheet>
try {
final service = sl<CalendarService>();
debugPrint('CalendarService: $service');
debugPrint('Is mock: ${service.runtimeType}');
final notificationService = sl<LocalNotificationService>();
late final ScheduleItemModel saved;
if (_isEditing) {
await service.updateEvent(event);
saved = await service.updateEvent(event);
} else {
await service.addEvent(event);
saved = await service.addEvent(event);
}
await notificationService.upsertEventReminder(saved);
widget.onSaved?.call();
if (mounted) {
Navigator.pop(context);
}
} catch (e, stack) {
debugPrint('Save error: $e');
debugPrint('Stack: $stack');
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(
context,