import 'dart:async'; import 'package:easyweb/utils/appmanger.dart'; import 'package:ef/ef.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:flutterflow_ui/flutterflow_ui.dart'; import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/color/app_uri_status.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/component/NullDataComponentWidget.dart'; import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/controller/user_info_controller.dart'; import 'package:vbvs_app/controller/weather/weather_controller.dart'; import 'package:vbvs_app/pages/mh_page/FloatingSvgIcon.dart'; import 'package:vbvs_app/pages/mh_page/homepage/component/HomeDeviceWidget.dart'; import 'package:vbvs_app/pages/mh_page/homepage/controller/mht_home_controller.dart'; class NewHomePage extends StatefulWidget { const NewHomePage({super.key}); @override State createState() => _NewHomePageState(); } class _NewHomePageState extends State { UserInfoController userInfoController = Get.find(); MHTHomeController deviceController = Get.find(); MHTHomeController homeController = Get.find(); double borderRadius = 16.rpx; var formFieldController = FormFieldController(null); var personInfo = {}.obs; // GlobalController gloablController = Get.find(); WeatherModelController weatherModelController = Get.find(); // var selectedDayIndex = (6).obs; StreamSubscription? _newVersionSubscription; @override void initState() { super.initState(); if (userInfoController.model.login == 1) { //查询人员信息列表 deviceController.getPersonList(); //请求绑定设备列表 // homeController.getSleepReport(); deviceController.getDeviceNum().then((apiResponse) { if (apiResponse.code != HttpStatusCodes.ok) { // TopSlideNotification.show( // Get.context!, // text: apiResponse.msg!, // textColor: themeController.currentColor.sc9, // ); } }); deviceController.getDeviceList(group: 'room').then((apiResponse) { if (apiResponse.code != HttpStatusCodes.ok) { // TopSlideNotification.show( // Get.context!, // text: apiResponse.msg!, // textColor: themeController.currentColor.sc9, // ); } else { //请求睡眠报告 // deviceController.getSleepReport(); } }); } WidgetsBinding.instance.addPostFrameCallback((_) { if (homeController.homeSleepDays.value.isNotEmpty) { homeController.selectedDayIndex.value = homeController.homeSleepDays.value.length - 1; } }); try { _newVersionSubscription = ef.kvRoot.appmanger.onAppUpdate.stream.listen((MiniAppPkg pkg) { showDialog( context: context, builder: (context) { return AlertDialog( title: Text("发现新版本".tr), content: Text("新版本号:${pkg.version}"), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: Text("知道了".tr), ), ], ); }, ); }); } catch (e) { print(e); } } getWeekName(int i) { String v = ""; switch (i) { case 1: v = "周一".tr; break; case 2: v = "周二".tr; break; case 3: v = "周三".tr; break; case 4: v = "周四".tr; break; case 5: v = "周五".tr; break; case 6: v = "周六".tr; break; case 7: v = "周日".tr; break; } return v; } @override Widget build(BuildContext context) { deviceController.getDeviceList(group: 'room').then((apiResponse) { if (apiResponse.code != HttpStatusCodes.ok) { // TopSlideNotification.show( // context, // text: apiResponse.msg!, // textColor: themeController.currentColor.sc9, // ); } else { //请求睡眠报告 // deviceController.getSleepReport(); } }); if (userInfoController.model.login == 1) { //查询人员信息列表 deviceController.getPersonList(); //请求绑定设备列表 // homeController.getSleepReport(); deviceController.getDeviceNum().then((apiResponse) { // if (apiResponse.code != HttpStatusCodes.ok) { // TopSlideNotification.show( // Get.context!, // text: apiResponse.msg!, // textColor: themeController.currentColor.sc9, // ); // } }); deviceController.getDeviceList(group: 'room').then((apiResponse) { if (apiResponse.code != HttpStatusCodes.ok) { // TopSlideNotification.show( // Get.context!, // text: apiResponse.msg!, // textColor: themeController.currentColor.sc9, // ); } else { //请求睡眠报告 // deviceController.getSleepReport(); } }); } WidgetsBinding.instance.addPostFrameCallback((_) { if (homeController.homeSleepDays.value.isNotEmpty) { homeController.selectedDayIndex.value = homeController.homeSleepDays.value.length - 1; } }); int login = userInfoController.model.login!; return GestureDetector( // onTap: () => FocusScope.of(context).unfocus(),, child: Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/new_background.png'), // 本地图片 fit: BoxFit.fill, // 填满整个 Container ), ), child: Scaffold( backgroundColor: Colors.transparent, appBar: AppBar( iconTheme: IconThemeData(color: themeController.currentColor.sc3), backgroundColor: Colors.transparent, automaticallyImplyLeading: false, titleSpacing: 0, title: Container( height: 180.rpx, child: Row( children: [ // 左侧头像 Obx(() { return InkWell( onTap: () { if (userInfoController.model.login == 0) { Get.toNamed("/loginPage"); } }, child: userInfo(userInfoController.model.login), ); }), const Spacer(), // 左右分隔 FloatingSvgIcon( assetPath: 'assets/img/icon/xiaoyi.svg', width: 60.rpx, height: 60.rpx, onTap: () { // print("点击了小鹅图标"); if (userInfoController.model.login == 0) { Get.toNamed("/loginPage"); } Get.toNamed("/xiaoEPage", arguments: "https://xiaoe.he-info.cn/?mac=b43a45c3ddf4"); }, ), SizedBox(width: 40.rpx), ], ), ), ), body: SafeArea( child: Container( width: MediaQuery.sizeOf(context).width, height: MediaQuery.sizeOf(context).height * 1.123, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.max, children: [ //天气 Container( padding: EdgeInsets.fromLTRB(26.rpx, 10.rpx, 26.rpx, 40.rpx), width: double.infinity, child: Padding( padding: EdgeInsets.symmetric(horizontal: 0.rpx), child: Column( children: [ Padding( padding: EdgeInsets.fromLTRB(17.rpx, 30.rpx, 0, 0), child: Row( children: [ Obx(() { return Row( children: [ Text( "${weatherModelController.model.cityName ?? '未知数据'.tr}", style: TextStyle( color: Colors.white, fontSize: AppConstants() .normal_text_fontSize, ), ), Text( "${(weatherModelController.model.current_temperature != null && weatherModelController.model.current_temperature! > 0) ? weatherModelController.model.current_temperature : '未知数据'.tr}" + "°C", style: TextStyle( color: Colors.white, fontSize: AppConstants() .normal_text_fontSize, ), ), Text( "${(weatherModelController.model.weather_info?.isNotEmpty ?? false) ? weatherModelController.model.weather_info : '未知数据'.tr}", style: TextStyle( color: Colors.white, fontSize: AppConstants() .normal_text_fontSize, ), ), if (weatherModelController .model.weatherIconurl != null && weatherModelController .model.weatherIconurl!.isNotEmpty) Container( width: 35.rpx, height: 26.rpx, clipBehavior: Clip.antiAlias, decoration: BoxDecoration( shape: BoxShape.circle), child: Image.network( weatherModelController .model.weatherIconurl!, fit: BoxFit.cover, ), ), ].divide(SizedBox( width: 20.rpx, )), ); }), ], ), ), ], ), ), ), //未登录 Obx(() { if (userInfoController.model.login! == null || userInfoController.model.login! == 0) { return Padding( padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 0.rpx, 30.rpx, 100.rpx), child: ClickableContainer( onTap: () { // 点击逻辑 Get.toNamed("/mHTDeviceTypePage"); }, backgroundColor: Colors.transparent, highlightColor: themeController.currentColor .sc21, // 这里可以自定义高亮色,透明就用 Colors.transparent borderRadius: borderRadius, padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 0, 0.rpx, 0), child: Container( height: 92.rpx, alignment: Alignment.center, decoration: BoxDecoration( border: Border.all( color: stringToColor("#85F5FF"), // 边框颜色 width: 1.rpx, // 边框宽度 ), borderRadius: BorderRadius.circular(borderRadius), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ // Icon( // Icons.add, // size: 60.rpx, // color: stringToColor("#85F5FF"), // ), SvgPicture.asset( 'assets/images/icon/add.svg', width: 42.rpx, height: 42.rpx, ), SizedBox(width: 20.rpx), Text( '添加新设备'.tr, style: TextStyle( fontFamily: 'Readex Pro', color: stringToColor("#85F5FF"), letterSpacing: 0, fontSize: 26.rpx, ), ), ], ), ), ), ); } return Container(); }), //已登录 Obx(() { if (userInfoController.model.login! != null && userInfoController.model.login! == 1) { final list = deviceController.personnelList.value; // 当数据第一次到达时自动赋值 if (list.isNotEmpty && formFieldController.value == null) { WidgetsBinding.instance.addPostFrameCallback((_) { formFieldController.value = list[0]["mac"]; personInfo.value = list[0]; homeController.selectPerson.value = list[0]; homeController.selectDevcie.value = list[0]["mac"]; deviceController.getHomeSleeps( formFieldController.value, context); homeController.updateAll(); }); } return SingleChildScrollView( child: Column( children: [ if (homeController.personnelList.value.length != 0) Padding( padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 40.rpx, 30.rpx, 10.rpx), child: Container( width: MediaQuery.sizeOf(context).width, height: MediaQuery.sizeOf(context).height * 0.184, constraints: BoxConstraints( minHeight: 354.rpx, ), decoration: BoxDecoration( color: stringToColor("#003058"), borderRadius: BorderRadius.circular(20.rpx), ), child: Column( mainAxisSize: MainAxisSize.max, children: [ Padding( padding: EdgeInsetsDirectional.fromSTEB( 20.rpx, 20.rpx, 16.rpx, 25.rpx), child: Container( width: MediaQuery.sizeOf(context).width, child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ScrollbarTheme( data: ScrollbarThemeData( thumbColor: MaterialStateProperty.all( Colors.transparent), trackColor: MaterialStateProperty.all( Colors.transparent), trackBorderColor: MaterialStateProperty.all( Colors.transparent), ), child: ValueListenableBuilder( valueListenable: formFieldController, builder: (c, a, s) => FlutterFlowDropDown< String>( controller: formFieldController, options: deviceController .personnelList.value .map((d) => "${d["mac"]}") .toList(), optionLabels: deviceController .personnelList.value .map((d) { var s = d["name"] ?? d["mac"]; if (s == null) { return ""; } else { return "$s"; } }).toList(), onChanged: (val) { final list = deviceController .personnelList .value; final selectedPerson = list.firstWhere( (element) => element['mac'] == val, orElse: () => null, // 防止找不到时报错 ); homeController .selectPerson .value = selectedPerson; personInfo.value = selectedPerson; homeController .selectedDayIndex = (6).obs; print("$val"); if (val == null) { homeController .homeSleepDays .value = []; } else { homeController .selectDevcie .value = formFieldController .value!; deviceController .getHomeSleeps( formFieldController .value, context); homeController .updateAll(); } }, width: 300.rpx, height: 81.rpx, maxHeight: 300.rpx, textStyle: TextStyle( fontSize: 28.rpx, overflow: TextOverflow.ellipsis, color: Colors.white, ), hintText: '', icon: Icon( Icons .keyboard_arrow_down_rounded, color: stringToColor( "#FFFFFF"), size: 30.rpx, ), fillColor: stringToColor( "##011D33"), elevation: 2, borderColor: Colors.transparent, borderWidth: 2, borderRadius: 100.rpx, margin: EdgeInsetsDirectional .fromSTEB( 32.rpx, 8.rpx, 32.rpx, 8.rpx), hidesUnderline: true, isOverButton: false, isSearchable: false, isMultiSelect: false, ), ), ), InkWell( onTap: () { if (formFieldController .value != null) { Get.toNamed( "/newSleepReportPage", arguments: { 'mac': formFieldController .value!, 'type': 1, "person": personInfo.value, 'backgroundImg': 'assets/images/new_background.png', 'date': DateTime.now() .millisecondsSinceEpoch, 'person_show': false, }, ); } }, child: Row( mainAxisSize: MainAxisSize.max, children: [ SizedBox( width: 12.rpx, ), SvgPicture.asset( "assets/images/table.svg", width: 28.rpx, height: 28.rpx, color: stringToColor( "#FFFFFF"), ), SizedBox( width: 20.rpx, ), ], ), ), ], ), ), ), if (homeController .homeSleepDays.value.length == 0) Expanded(child: NullDataWidget()), if (homeController .homeSleepDays.value.length != 0) Container( padding: EdgeInsets.only( top: 0.rpx, bottom: 20.rpx, left: 16.rpx, right: 16.rpx, ), width: double.infinity, decoration: BoxDecoration(), child: Obx(() => Row( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.start, children: [ ...List.generate( homeController .homeSleepDays .value .length, (index) { var day = homeController .homeSleepDays[index]; bool isSelected = homeController .selectedDayIndex .value == index; return Expanded( child: GestureDetector( onTap: () { homeController .selectedDayIndex .value = index; int? timeMillis = parseToInt( day['time']); Get.toNamed( "/newSleepReportPage", arguments: { 'date': timeMillis, 'mac': formFieldController .value!, 'type': 1, "person": personInfo .value, 'backgroundImg': 'assets/images/new_background.png', 'date': timeMillis, // 'backgroundColor':stringToColor("#003058"), 'person_show': false, }, ); }, child: Container( padding: EdgeInsets.only( top: 10.rpx, bottom: 20.rpx, ), width: 90.rpx, decoration: BoxDecoration( color: isSelected ? stringToColor( "#011D33") : Colors .transparent, borderRadius: BorderRadius .circular( 8.rpx), ), child: Column( mainAxisSize: MainAxisSize .max, mainAxisAlignment: MainAxisAlignment .start, crossAxisAlignment: CrossAxisAlignment .center, children: [ Text( day['week'], style: TextStyle( fontFamily: 'Readex Pro', fontSize: 30.rpx, letterSpacing: 0, color: stringToColor( "#FFFFFF"), ), ), SizedBox( height: 12.rpx), Text( day['date'], // "哈哈", style: TextStyle( fontFamily: 'Readex Pro', letterSpacing: 0, fontSize: 22.rpx, color: stringToColor( "#929699"), ), ), SizedBox( height: 39.rpx), buildScoreOrIcon( day['score']), ], ), ), ), ); }) ], )), ), ], ), ), ), if (homeController.bindDeviceNum.value != 0) Padding( padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 40.rpx, 30.rpx, 100.rpx), child: Column( children: homeController.deviceList.entries .map((entry) => HomeDeviceWidget( roomName: entry.key, deviceStatusList: entry.value, )) .toList() .divide(SizedBox(height: 30.rpx)), ), ), if (homeController.bindDeviceNum.value == 0) Padding( padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 0.rpx, 30.rpx, 100.rpx), child: ClickableContainer( onTap: () { // 点击逻辑 Get.toNamed("/mHTDeviceTypePage"); }, backgroundColor: Colors.transparent, highlightColor: themeController.currentColor .sc21, // 这里可以自定义高亮色,透明就用 Colors.transparent borderRadius: borderRadius, padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 0, 0.rpx, 0), child: Container( height: 92.rpx, alignment: Alignment.center, decoration: BoxDecoration( border: Border.all( color: stringToColor("#85F5FF"), // 边框颜色 width: 1.rpx, // 边框宽度 ), borderRadius: BorderRadius.circular(borderRadius), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ // Icon( // Icons.add, // size: 60.rpx, // color: stringToColor("#85F5FF"), // ), SvgPicture.asset( 'assets/images/icon/add.svg', width: 42.rpx, height: 42.rpx, ), SizedBox(width: 20.rpx), Text( '添加新设备'.tr, style: TextStyle( fontFamily: 'Readex Pro', color: stringToColor("#85F5FF"), letterSpacing: 0, fontSize: 26.rpx, ), ), ], ), ), ), ), if (homeController.bindDeviceNum.value != 0) Padding( padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 0.rpx, 30.rpx, 100.rpx), child: ClickableContainer( onTap: () { // 点击逻辑 Get.toNamed("/mHTDeviceTypePage"); }, backgroundColor: Colors.transparent, highlightColor: themeController.currentColor .sc21, // 这里可以自定义高亮色,透明就用 Colors.transparent borderRadius: borderRadius, padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 0, 0.rpx, 0), child: Container( height: 92.rpx, alignment: Alignment.center, decoration: BoxDecoration( border: Border.all( color: stringToColor("#85F5FF"), // 边框颜色 width: 1.rpx, // 边框宽度 ), borderRadius: BorderRadius.circular(borderRadius), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ // Icon( // Icons.add, // size: 60.rpx, // color: stringToColor("#85F5FF"), // ), SvgPicture.asset( 'assets/images/icon/add.svg', width: 42.rpx, height: 42.rpx, ), SizedBox(width: 20.rpx), Text( '添加新设备'.tr, style: TextStyle( fontFamily: 'Readex Pro', color: stringToColor("#85F5FF"), letterSpacing: 0, fontSize: 26.rpx, ), ), ], ), ), ), ), ], ), ); } return Container(); }), ], ), ), ), ), ), )); } //1 :登录 0:未登录 Widget userInfo(int? login) { return Row( children: (login == 1) ? [ SizedBox(width: 40.rpx), CircleAvatar( radius: 27.rpx, // 可根据需求调整 backgroundColor: Colors.transparent, backgroundImage: login == 1 ? (userInfoController.model.user!.avatar == null || userInfoController.model.user!.avatar!.isEmpty ? const AssetImage( "assets/images/mine_avatar.png", ) : NetworkImage( userInfoController.model.user!.avatar!, )) : const AssetImage( "assets/images/mine_avatar.png", ), ), SizedBox(width: 23.rpx), // 左侧头像和文本之间的间距 Text( '${userInfoController.model.user?.nick_name?.isNotEmpty == true ? userInfoController.model.user!.nick_name : '未命名'.tr}', style: TextStyle(fontSize: 30.rpx, color: Colors.white), ) ] : [ SizedBox(width: 40.rpx), CircleAvatar( radius: 27.rpx, // 可根据需求调整 backgroundColor: Colors.transparent, backgroundImage: login == 1 ? (userInfoController.model.user!.avatar == null || userInfoController.model.user!.avatar!.isEmpty ? const AssetImage( "assets/images/mine_avatar.png", ) : NetworkImage( userInfoController.model.user!.avatar!, )) : const AssetImage( "assets/images/mine_avatar.png", ), ), SizedBox(width: 23.rpx), // 左侧头像和文本之间的间距 Text( '未命名'.tr, style: TextStyle(fontSize: 30.rpx, color: Colors.white), ) ], ); } Widget buildScoreOrIcon(dynamic score) { return SizedBox( width: 50.rpx, height: 50.rpx, child: Center( child: (score != null) ? FittedBox( child: Text( '${score['socre']}', style: TextStyle( fontFamily: 'Readex Pro', fontSize: 40.rpx, letterSpacing: 0, color: Colors.white, ), ), ) : SvgPicture.asset( 'assets/img/icon/close.svg', width: 25.rpx, height: 25.rpx, color: themeController.currentColor.sc3, ), ), ); } int? parseToInt(dynamic value) { if (value == null) return null; if (value is int) return value; if (value is String) return int.tryParse(value); return null; } } class ScoreItem { final String weekday; // 如“周四” final String dateStr; // 如“07/03” final int score; final bool isToday; ScoreItem({ required this.weekday, required this.dateStr, required this.score, this.isToday = false, }); } class ScoreCard extends StatelessWidget { final String selectedUser; final List scoreList; final ValueChanged? onUserChanged; final VoidCallback? onChartPressed; const ScoreCard({ super.key, required this.selectedUser, required this.scoreList, this.onUserChanged, this.onChartPressed, }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: const Color(0xff0F2B44), borderRadius: BorderRadius.circular(16), ), padding: const EdgeInsets.all(12), child: Column( children: [ // 顶部用户选择 + 图标按钮 Row( children: [ DropdownButtonHideUnderline( child: DropdownButton( value: selectedUser, borderRadius: BorderRadius.circular(12), dropdownColor: const Color(0xff0F2B44), iconEnabledColor: Colors.white, style: const TextStyle(color: Colors.white), items: ['Eason Chan', 'Jay Chou', 'G.E.M.'] .map((user) => DropdownMenuItem( value: user, child: Text(user), )) .toList(), onChanged: onUserChanged, ), ), const Spacer(), IconButton( onPressed: onChartPressed, icon: const Icon(Icons.bar_chart, color: Colors.white), ), ], ), const SizedBox(height: 12), // 日期+分数 横向滚动展示 SizedBox( height: 70, child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: scoreList.length, separatorBuilder: (_, __) => const SizedBox(width: 12), itemBuilder: (context, index) { final item = scoreList[index]; final isToday = item.isToday; return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: isToday ? Colors.white.withOpacity(0.1) : Colors.transparent, borderRadius: BorderRadius.circular(12), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(item.weekday, style: const TextStyle( color: Colors.white70, fontSize: 12)), Text(item.dateStr, style: const TextStyle( color: Colors.white54, fontSize: 10)), const SizedBox(height: 4), Text( item.score.toString(), style: TextStyle( color: Colors.white, fontWeight: isToday ? FontWeight.bold : FontWeight.normal, fontSize: 16, ), ), ], ), ); }, ), ) ], ), ); } }