221 lines
7.6 KiB
Dart
221 lines
7.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:star_lock/app_settings/app_colors.dart';
|
|
import 'package:star_lock/main/lockDetail/doorLockLog/date_time_extensions.dart';
|
|
|
|
class WeekCalendarView extends StatefulWidget {
|
|
// 用于判断某一天是否有数据(激活状态)
|
|
final bool Function(DateTime date)? hasData;
|
|
final void Function(DateTime date)? onDateSelected; // 新增:选中日期回调
|
|
final void Function(DateTime start, DateTime end)? onWeekChanged;
|
|
|
|
const WeekCalendarView({
|
|
Key? key,
|
|
this.hasData,
|
|
this.onDateSelected,
|
|
this.onWeekChanged,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
_WeekCalendarViewState createState() => _WeekCalendarViewState();
|
|
}
|
|
|
|
class _WeekCalendarViewState extends State<WeekCalendarView> {
|
|
final PageController _pageController = PageController(initialPage: 500);
|
|
int _currentPage = 500;
|
|
|
|
// 当前选中的日期(以 DateTime 格式存储)
|
|
late DateTime _selectedDate;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_selectedDate = DateTime.now().withoutTime; // 默认选中今天
|
|
}
|
|
|
|
// 获取指定 page 对应的一周日期
|
|
List<DateTime> _getWeekDatesForPage(int page) {
|
|
final now = DateTime.now();
|
|
final baseSunday =
|
|
DateTime(now.year, now.month, now.day - (now.weekday % 7));
|
|
final daysOffset = (page - 500) * 7;
|
|
final targetSunday = baseSunday.add(Duration(days: daysOffset));
|
|
return List.generate(
|
|
7,
|
|
(i) => DateTime(
|
|
targetSunday.year, targetSunday.month, targetSunday.day + i));
|
|
}
|
|
|
|
// 判断是否为今天
|
|
bool _isToday(DateTime date) {
|
|
final now = DateTime.now();
|
|
return date.year == now.year &&
|
|
date.month == now.month &&
|
|
date.day == now.day;
|
|
}
|
|
|
|
// 判断是否为选中日期
|
|
bool _isSelected(DateTime date) {
|
|
return date.year == _selectedDate.year &&
|
|
date.month == _selectedDate.month &&
|
|
date.day == _selectedDate.day;
|
|
}
|
|
|
|
// 判断是否有数据(激活状态)
|
|
bool _hasData(DateTime date) {
|
|
return widget.hasData?.call(date.withoutTime) ?? false;
|
|
}
|
|
|
|
void _onDateSelected(DateTime date) {
|
|
setState(() {
|
|
_selectedDate = date.withoutTime;
|
|
});
|
|
// 触发回调,通知父组件
|
|
widget.onDateSelected?.call(date);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// 当前周范围提示
|
|
_buildWeekRangeLabel(_currentPage),
|
|
|
|
SizedBox(height: 10.h),
|
|
|
|
SizedBox(
|
|
height: 100.h,
|
|
child: PageView.builder(
|
|
controller: _pageController,
|
|
itemCount: 1000,
|
|
itemBuilder: (context, page) {
|
|
final weekDates = _getWeekDatesForPage(page);
|
|
return Row(
|
|
children: weekDates.asMap().entries.map((entry) {
|
|
final int index = entry.key;
|
|
final DateTime date = entry.value;
|
|
final bool isSelected = _isSelected(date);
|
|
final bool hasData = _hasData(date);
|
|
final bool isToday = _isToday(date);
|
|
|
|
// 确定文字颜色
|
|
Color textColor;
|
|
if (isSelected) {
|
|
textColor = Colors.white; // 选中时文字为白色
|
|
} else if (hasData) {
|
|
textColor = Colors.black; // 有数据:黑色
|
|
} else if (isToday) {
|
|
textColor = Colors.black; // 今天:黑色
|
|
} else {
|
|
textColor = Colors.grey; // 默认:灰色
|
|
}
|
|
|
|
// 确定背景颜色
|
|
Color? bgColor;
|
|
if (isSelected) {
|
|
bgColor = AppColors.mainColor; // 选中用主题色
|
|
}
|
|
// 其他状态无背景
|
|
|
|
return GestureDetector(
|
|
onTap: () => _onDateSelected(date),
|
|
child: Container(
|
|
padding: EdgeInsets.all(4.w),
|
|
width: 75.w,
|
|
height: 75.w,
|
|
decoration: BoxDecoration(
|
|
color: bgColor,
|
|
borderRadius: BorderRadius.circular(50.r),
|
|
),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Text(
|
|
[
|
|
'简写周日',
|
|
'简写周一',
|
|
'简写周二',
|
|
'简写周三',
|
|
'简写周四',
|
|
'简写周五',
|
|
'简写周六'
|
|
][index]
|
|
.tr,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: textColor,
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
Text(
|
|
date.day.toString(),
|
|
style: TextStyle(
|
|
fontSize: 26.sp,
|
|
color: textColor,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
if (isToday && !isSelected) // 今天但未选中
|
|
SizedBox(height: 2.h),
|
|
if (isToday && !isSelected)
|
|
Container(
|
|
width: 6.w,
|
|
height: 6.w,
|
|
decoration: BoxDecoration(
|
|
color: AppColors.mainColor,
|
|
shape: BoxShape.circle,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}).toList(),
|
|
);
|
|
},
|
|
onPageChanged: (page) {
|
|
setState(() {
|
|
_currentPage = page;
|
|
});
|
|
// ✅ 获取当前页对应的周的起止日期
|
|
final dates = _getWeekDatesForPage(page);
|
|
final startOfWeek = dates.first;
|
|
final endOfWeek = dates.last;
|
|
|
|
// ✅ 触发回调,可用于请求接口
|
|
widget.onWeekChanged?.call(startOfWeek, endOfWeek);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildWeekRangeLabel(int page) {
|
|
final dates = _getWeekDatesForPage(page);
|
|
final start = dates[0];
|
|
final end = dates[6];
|
|
|
|
String label;
|
|
|
|
if (start.year == end.year) {
|
|
// 同一年:显示为 "2025年8月18日 - 8月24日"
|
|
label =
|
|
'${start.year}${'年'.tr}${start.month}${'月'.tr}${start.day}${'日'.tr} - ${end.month}${'月'.tr}${end.day}${'日'.tr}';
|
|
} else {
|
|
// 跨年:显示为 "2024年12月31日 - 2025年1月6日"
|
|
label =
|
|
'${start.year}${'年'.tr}${start.month}${'月'.tr}${start.day}${'日'.tr} - ${end.year}${'年'.tr}${end.month}${'月'.tr}${end.day}${'日'.tr}';
|
|
}
|
|
|
|
return Text(
|
|
label,
|
|
style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.w600),
|
|
);
|
|
}
|
|
}
|