import 'package:flutter/material.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'; // 假设你自己扩展的 .rpx import 'SleepdateWidget.dart'; // 导入你自定义的 SleepdateWidget class SleepCalendarWidget extends StatefulWidget { final int? timestamp; // 可选时间戳 const SleepCalendarWidget({super.key, this.timestamp}); @override State createState() => _SleepCalendarWidgetState(); } class _SleepCalendarWidgetState extends State { late DateTime _currentDate; @override void initState() { super.initState(); _currentDate = widget.timestamp != null ? DateTime.fromMillisecondsSinceEpoch(widget.timestamp!) : DateTime.now(); } List getDaysInMonth(DateTime date) { // 获取当前月份的第一天 DateTime firstDayOfMonth = DateTime(date.year, date.month, 1); // 获取当前月份的最后一天 DateTime lastDayOfMonth = DateTime(date.year, date.month + 1, 0); List days = []; // 获取该月的所有日期 for (int i = 0; i < lastDayOfMonth.day; i++) { days.add(firstDayOfMonth.add(Duration(days: i))); } return days; } List> getCalendarRows(List daysInMonth) { // 获取该月所有日期后,处理为 7 列的格式 List> calendarRows = []; int firstWeekday = daysInMonth.first.weekday; // 获取该月第一天是周几 int emptyDays = (firstWeekday == 7 ? 0 : firstWeekday) - 1; // 调整为空白天数 List row = []; for (int i = 0; i < emptyDays; i++) { row.add(DateTime(0)); // 填充空白日期 } for (var day in daysInMonth) { row.add(day); if (row.length == 7) { // 如果当前行满了 7 个日期,则添加到 calendarRows 中,并重置 row calendarRows.add(List.from(row)); row.clear(); } } if (row.isNotEmpty) { // 如果最后一行的日期不足 7 个,则补充空白日期 while (row.length < 7) { row.add(DateTime(0)); // 填充空白日期 } calendarRows.add(List.from(row)); // 添加最后一行 } return calendarRows; } @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), // 灰色 }, ]; List sleepData = []; // 获取当前月的所有日期 List daysInMonth = getDaysInMonth(_currentDate); // 获取按行排列的日期 List> calendarRows = getCalendarRows(daysInMonth); return Container( width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.only( bottomLeft: Radius.circular(0), bottomRight: Radius.circular(0), topLeft: Radius.circular(20.rpx), topRight: Radius.circular(20.rpx), ), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: double.infinity, // height: MediaQuery.sizeOf(context).height * 0.055, constraints: BoxConstraints( minHeight: 90.rpx, ), decoration: BoxDecoration( color: const Color(0xFF313541), borderRadius: BorderRadius.only( bottomLeft: Radius.circular(0), bottomRight: Radius.circular(0), topLeft: Radius.circular(20.rpx), topRight: Radius.circular(20.rpx), ), ), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 65.rpx, 0.rpx, 65.rpx, 0.rpx, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Icon( Icons.arrow_back_ios_new, color: const Color(0xFF6D6F73), size: 24.rpx, ), Text( '${_currentDate.year}年${_currentDate.month}月', style: TextStyle( color: Colors.white, fontSize: 30.rpx, letterSpacing: 0.0, ), ), Icon( Icons.arrow_forward_ios, color: const Color(0xFF6D6F73), size: 24.rpx, ), ], ), ), ), 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, ), child: Column( mainAxisSize: MainAxisSize.max, children: [ // Weekdays Header Container( constraints: BoxConstraints(minHeight: 90.rpx), child: Row( children: [ for (var day in ["一", "二", "三", "四", "五", "六", "日"]) Expanded( child: Center( child: Text( day, style: TextStyle( color: stringToColor("#FFFFFF"), fontSize: AppConstants().normal_text_fontSize, ), ), ), ), ], ), ), // 日历显示部分 Column( children: calendarRows.map((week) { return Row( mainAxisAlignment: MainAxisAlignment.start, // 保证每一行左对齐 children: week.map((date) { return Expanded( child: Padding( padding: EdgeInsets.all(4.rpx), child: date.year != 0 // 如果是空白日期就不显示 ? SleepdateWidget(date: date) : SizedBox.shrink(), ), ); }).toList(), ); }).toList(), ), SizedBox( height: 55.rpx, ), Wrap( direction: Axis.horizontal, // 默认是水平排列的,可以去掉这行 spacing: 20.rpx, // 水平间距 runSpacing: 20.rpx, // 垂直间距 children: showLabel.map((item) { return Container( padding: EdgeInsets.all(5.rpx), // 可选,添加一点间距 child: Row( mainAxisSize: MainAxisSize.min, // 确保 Row 不会占满整个宽度 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(), ), ], ), ), ), ], ), ); } }