# 日期时间选择器优化实现计划 > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** 将摇卦页面的日期时间选择器改为 iOS 滚轮样式,并实现 locale-aware 格式化 **Architecture:** 创建共享的 `DateTimePickerBottomSheet` 组件,封装 `CupertinoDatePicker` 和底部弹层交互,替换现有的 `showDatePicker` + `showTimePicker` 调用 **Tech Stack:** Flutter, Cupertino widgets, intl package --- ## Task 1: 创建 DateTimePickerBottomSheet 组件 **Files:** - Create: `apps/lib/shared/widgets/date_time_picker/date_time_picker_bottom_sheet.dart` **Step 1: 创建文件结构和基础代码** ```dart import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:intl/intl.dart'; class DateTimePickerBottomSheet extends StatefulWidget { const DateTimePickerBottomSheet({ super.key, required this.initialDateTime, this.minDateTime, this.maxDateTime, }); final DateTime initialDateTime; final DateTime? minDateTime; final DateTime? maxDateTime; @override State createState() => _DateTimePickerBottomSheetState(); } class _DateTimePickerBottomSheetState extends State { late DateTime _selectedDateTime; int _selectedTab = 0; // 0=日期, 1=时间 @override void initState() { super.initState(); _selectedDateTime = widget.initialDateTime; } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final locale = Localizations.localeOf(context); return Container( height: 400, decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), ), child: Column( children: [ // 顶部栏 Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton( onPressed: () => Navigator.pop(context), child: Text(l10n.cancel), ), Text( l10n.autoSelectTime, style: Theme.of(context).textTheme.titleMedium, ), TextButton( onPressed: () => Navigator.pop(context, _selectedDateTime), child: Text(l10n.confirm), ), ], ), ), // SegmentedControl 切换日期/时间 Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: CupertinoSlidingSegmentedControl( groupValue: _selectedTab, children: { 0: Text(l10n.dateTab), 1: Text(l10n.timeTab), }, onValueChanged: (value) => setState(() => _selectedTab = value ?? 0), ), ), const SizedBox(height: 16), // CupertinoDatePicker Expanded( child: CupertinoDatePicker( mode: _selectedTab == 0 ? CupertinoDatePickerMode.date : CupertinoDatePickerMode.time, initialDateTime: _selectedDateTime, minimumDate: widget.minDateTime, maximumDate: widget.maxDateTime, onDateTimeChanged: (DateTime newDateTime) { setState(() => _selectedDateTime = newDateTime); }, ), ), ], ), ); } } Future showDateTimePickerBottomSheet({ required BuildContext context, required DateTime initialDateTime, DateTime? minDateTime, DateTime? maxDateTime, }) { return showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (context) => DateTimePickerBottomSheet( initialDateTime: initialDateTime, minDateTime: minDateTime, maxDateTime: maxDateTime, ), ); } ``` **Step 2: 添加 l10n 键值** 在 `apps/lib/l10n/app_zh.arb` 添加: ```json "dateTab": "日期", "timeTab": "时间", "confirm": "确认", "cancel": "取消" ``` 在 `apps/lib/l10n/app_en.arb` 添加: ```json "dateTab": "Date", "timeTab": "Time", "confirm": "Confirm", "cancel": "Cancel" ``` 运行 `flutter gen-l10n` 生成代码 **Step 3: Commit** ```bash git add apps/lib/shared/widgets/date_time_picker/ apps/lib/l10n/ git commit -m "feat(divination): add DateTimePickerBottomSheet with iOS wheel style" ``` --- ## Task 2: 修改 auto_divination_screen.dart 使用新选择器 **Files:** - Modify: `apps/lib/features/divination/presentation/screens/auto_divination_screen.dart:208-230` - Modify: `apps/lib/features/divination/presentation/screens/auto_divination_screen.dart:353` **Step 1: 添加 import** 在文件顶部添加: ```dart import 'package:shared/widgets/date_time_picker/date_time_picker_bottom_sheet.dart'; ``` **Step 2: 修改 _pickTime 方法** 将: ```dart Future _pickTime() async { final date = await showDatePicker( context: context, initialDate: _selectedTime, firstDate: DateTime(2000), lastDate: DateTime(2100), ); if (date == null || !mounted) return; final time = await showTimePicker( context: context, initialTime: TimeOfDay.fromDateTime(_selectedTime), ); if (time == null || !mounted) return; setState(() { _selectedTime = DateTime( date.year, date.month, date.day, time.hour, time.minute, ); }); } ``` 替换为: ```dart Future _pickTime() async { final result = await showDateTimePickerBottomSheet( context: context, initialDateTime: _selectedTime, minDateTime: DateTime(2000), maxDateTime: DateTime(2100), ); if (result == null || !mounted) return; setState(() { _selectedTime = result; }); } ``` **Step 3: 修改日期显示格式** 将: ```dart DateFormat('yyyy年MM月dd日 HH:mm').format(selectedTime) ``` 替换为: ```dart DateFormat.yMd(Localizations.localeOf(context).toString()).add_Hm().format(selectedTime) ``` 需要添加 import: ```dart import 'package:intl/intl.dart'; ``` **Step 4: Commit** ```bash git add apps/lib/features/divination/presentation/screens/auto_divination_screen.dart git commit -m "feat(divination): use DateTimePickerBottomSheet in auto_divination_screen" ``` --- ## Task 3: 修改 manual_divination_screen.dart 使用新选择器 **Files:** - Modify: `apps/lib/features/divination/presentation/screens/manual_divination_screen.dart:142-168` - Modify: `apps/lib/features/divination/presentation/screens/manual_divination_screen.dart:271` **Step 1: 添加 import** ```dart import 'package:shared/widgets/date_time_picker/date_time_picker_bottom_sheet.dart'; import 'package:intl/intl.dart'; ``` **Step 2: 修改 _pickTime 方法和日期显示格式** 同 Task 2 的修改方式 **Step 3: Commit** ```bash git add apps/lib/features/divination/presentation/screens/manual_divination_screen.dart git commit -m "feat(divination): use DateTimePickerBottomSheet in manual_divination_screen" ``` --- ## Task 4: 修改 divination_result_screen.dart 的日期格式 **Files:** - Modify: `apps/lib/features/divination/presentation/screens/divination_result_screen.dart:455-457` **Step 1: 添加 import** ```dart import 'package:intl/intl.dart'; ``` **Step 2: 修改日期格式** 将: ```dart DateFormat( 'yyyy年MM月dd日 HH:mm', ).format(data.params.divinationTime), ``` 替换为: ```dart DateFormat.yMd(Localizations.localeOf(context).toString()).add_Hm().format(data.params.divinationTime), ``` **Step 3: Commit** ```bash git add apps/lib/features/divination/presentation/screens/divination_result_screen.dart git commit -m "refactor(divination): use locale-aware date format in divination_result_screen" ``` --- ## Task 5: 运行验证 **Step 1: 生成 l10n** ```bash cd apps && flutter gen-l10n ``` **Step 2: 运行静态分析** ```bash cd apps && flutter analyze ``` 预期: 无错误 **Step 3: 运行相关测试** ```bash cd apps && flutter test test/features/divination/ ``` --- **Plan complete.** Two execution options: **1. Subagent-Driven (this session)** - I dispatch fresh subagent per task, review between tasks, fast iteration **2. Parallel Session (separate)** - Open new session with executing-plans, batch execution with checkpoints **Which approach?**