import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/controller/date/CalendarController.dart'; import 'SleepdateWidget.dart'; class SleepCalendarWidget extends StatefulWidget { final int? timestamp; final ValueChanged? onDateSelected; final int? type; // 新增参数,默认日历类型为日 final Color highlightColor; // ✅ 新增 const SleepCalendarWidget({ super.key, this.timestamp, this.onDateSelected, this.type = 1, this.highlightColor = Colors.black, // ✅ 默认值 }); @override State createState() => _SleepCalendarWidgetState(); } class _SleepCalendarWidgetState extends State { CalendarController calendarController = Get.find(); @override void initState() { super.initState(); final initialDate = widget.timestamp != null ? DateTime.fromMillisecondsSinceEpoch(widget.timestamp!) : DateTime.now(); calendarController.displayedMonth.value = initialDate; calendarController.selectedDate.value = initialDate; } @override Widget build(BuildContext context) { List> showLabel = [ {"level": 1, "name": "优秀", "color": Color(0xFF4CAF50)}, {"level": 2, "name": "良好", "color": Color(0xFF8BC34A)}, {"level": 3, "name": "合格", "color": Color(0xFFFFC107)}, {"level": 4, "name": "注意", "color": Color(0xFFF44336)}, {"level": 5, "name": "无报告", "color": Color(0xFF9E9E9E)}, ]; return Container( width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(20.rpx), topRight: Radius.circular(20.rpx), ), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ _buildHeader(), _buildCalendarBody(showLabel), ], ), ); } Widget _buildHeader() { return Container( width: double.infinity, constraints: BoxConstraints(minHeight: 90.rpx), decoration: BoxDecoration( color: const Color(0xFF313541), borderRadius: BorderRadius.only( topLeft: Radius.circular(20.rpx), topRight: Radius.circular(20.rpx), ), ), child: Padding( padding: EdgeInsets.symmetric(horizontal: 65.rpx), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, padding: EdgeInsets.all(8.rpx), onTap: () => calendarController.previousMonth(), child: Icon( Icons.arrow_back_ios_new, color: const Color(0xFF6D6F73), size: 24.rpx, ), ), Obx(() => Text( '${calendarController.displayedMonth.value.year}年${calendarController.displayedMonth.value.month}月', style: TextStyle( color: Colors.white, fontSize: 30.rpx, ), )), ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, padding: EdgeInsets.all(8.rpx), onTap: () => calendarController.nextMonth(), child: Icon( Icons.arrow_forward_ios, color: const Color(0xFF6D6F73), size: 24.rpx, ), ), ], ), ), ); } Widget _buildCalendarBody(List> showLabel) { return Container( width: double.infinity, constraints: BoxConstraints(minHeight: 720.rpx), decoration: const BoxDecoration(color: Color(0xFF242835)), child: Padding( // padding: EdgeInsetsDirectional.fromSTEB(65.rpx, 13.rpx, 65.rpx, 38.rpx), padding: EdgeInsetsDirectional.fromSTEB(65.rpx, 0.rpx, 65.rpx, 0.rpx), child: Obx(() { final daysInMonth = calendarController.getDaysInMonth(); final calendarRows = calendarController.getCalendarRows(daysInMonth); final selectedDate = calendarController.selectedDate.value; return Column( mainAxisSize: MainAxisSize.max, children: [ // 仅当为日历模式显示周标题 _buildWeekdayHeader(), // 日历日期格子,支持日和周的高亮逻辑 _buildCalendarGrid(calendarRows, selectedDate), // TODO: 你可以扩展 month 类型的展示 SizedBox(height: 55.rpx), _buildLegend(showLabel), ], ); }), ), ); } Widget _buildWeekdayHeader() { return Container( constraints: BoxConstraints(minHeight: 90.rpx), child: Row( children: ["一", "二", "三", "四", "五", "六", "日"].map((day) { return Expanded( child: Center( child: Text( day, style: TextStyle( color: stringToColor("#FFFFFF"), fontSize: AppConstants().normal_text_fontSize, ), ), ), ); }).toList(), ), ); } Widget _buildCalendarGrid( List> calendarRows, DateTime? selectedDate) { final isMonthSelected = widget.type == 3; Widget content = Column( children: calendarRows.map((week) { final isWeekSelected = widget.type == 2 && selectedDate != null && week.any((d) => d.year == selectedDate.year && d.month == selectedDate.month && d.day == selectedDate.day); final row = Row( children: week.map((date) { if (date.year == 0) { return const Expanded(child: SizedBox.shrink()); } final isSelected = widget.type == 1 && selectedDate != null && date.year == selectedDate.year && date.month == selectedDate.month && date.day == selectedDate.day; return Expanded( child: SleepdateWidget( highlightColor: widget.highlightColor, // ✅ 传入高亮颜色 date: date, isSelected: isSelected, onTap: () { calendarController.selectDate(date); widget.onDateSelected?.call(date); Get.back(); }, ), ); }).toList(), ); if (isWeekSelected) { return Container( decoration: BoxDecoration( color: widget.highlightColor, borderRadius: BorderRadius.circular(AppConstants().button_container_radius), ), padding: EdgeInsets.symmetric(vertical: 6.rpx), margin: EdgeInsets.symmetric(vertical: 6.rpx), child: row, ); } else { return row; } }).toList(), ); // 如果是月份模式,包一层黑色背景容器 if (isMonthSelected && selectedDate != null) { final displayedMonth = calendarController.displayedMonth.value; final isSameMonth = displayedMonth.year == selectedDate.year && displayedMonth.month == selectedDate.month; if (isSameMonth) { // ✅ 当前显示的月 == 当前选中的月 → 加高亮外框 return Container( decoration: BoxDecoration( color: widget.highlightColor, // 背景淡色 borderRadius: BorderRadius.circular(AppConstants().normal_container_radius), // border: Border.all( // color: widget.highlightColor, // width: 2.rpx, // ), ), // padding: EdgeInsets.symmetric(vertical: 0.rpx, horizontal: 0.rpx), // margin: EdgeInsets.symmetric(vertical: 0.rpx), child: content, ); } else { return content; } } else { return content; } } Widget _buildLegend(List> showLabel) { return Wrap( spacing: 20.rpx, runSpacing: 20.rpx, children: showLabel.map((item) { return Container( padding: EdgeInsets.all(5.rpx), child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 20.rpx, height: 20.rpx, decoration: BoxDecoration( color: item["color"], borderRadius: BorderRadius.circular(10.rpx), ), ), SizedBox(width: 8.rpx), Text( item["name"], style: TextStyle( color: Colors.white, fontSize: 24.rpx, ), ), ], ), ); }).toList(), ); } }