app-starlock/lib/main/lockDetail/doorLockLog/week_calendar_view.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),
);
}
}