Files
tuiche/lib/pages/mh_page/homepage/new_Home_page.dart
2025-06-09 19:11:25 +08:00

907 lines
48 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/component/tool/ClickableContainer.dart';
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
import 'package:vbvs_app/controller/device/body_device_controller.dart';
import 'package:vbvs_app/controller/main_bottom/global_controller.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';
class NewHomePage extends StatefulWidget {
const NewHomePage({super.key});
@override
State<NewHomePage> createState() => _NewHomePageState();
}
class _NewHomePageState extends State<NewHomePage> {
UserInfoController userInfoController = Get.find();
BodyDeviceController deviceController = Get.find();
double borderRadius = 16.rpx;
var formFieldController = FormFieldController<String>(null);
GlobalController gloablController = Get.find();
WeatherModelController weatherModelController = Get.find();
// get userInfoController => Get.find<UserInfoController>();
var sleepDays = [].obs;
var sleep_mac = "".obs;
Map scoreColor = {
"-1": "#d3d3d3",
"1": "#4e8408",
"2": "#7bbb33",
"3": "#e15b8d",
"4": "#ff0000",
};
Map scoreName = {
"-1": "暂无",
"1": "优秀",
"2": "良好",
"3": "合格",
"4": "注意",
};
@override
void initState() {
super.initState();
}
getWeekName(int i) {
String v = "";
switch (i) {
case 1:
v = "周一";
break;
case 2:
v = "周二";
break;
case 3:
v = "周三";
break;
case 4:
v = "周四";
break;
case 5:
v = "周五";
break;
case 6:
v = "周六";
break;
case 7:
v = "周日";
break;
}
return v;
}
@override
Widget build(BuildContext context) {
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 userInfo(userInfoController.model.login);
}),
const Spacer(), // 左右分隔
FloatingSvgIcon(
assetPath: 'assets/img/icon/xiaoe.svg',
width: 60.rpx,
height: 60.rpx,
onTap: () {
print("点击了小鹅图标");
},
),
SizedBox(width: 40.rpx),
],
),
)),
body: SafeArea(
child: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height * 1.123,
// decoration: BoxDecoration(
// color: AppColors.bg_color,
// image: DecorationImage(
// image: AssetImage("assets/images/background.png"),
// fit: BoxFit.cover,
// ),
// ),
decoration: BoxDecoration(),
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: [
// Text('上海 22° 多云',
// style: TextStyle(
// fontSize: 26.rpx,
// color: Colors.white)),
// Icon(Icons.cloud,
// size: 30.rpx, color: Colors.white),
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(() {
return Container(
padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx),
child: Column(
children: [
if (gloablController.model.deviceList.length > 0)
Container(
child: Column(
children: [
Container(
width: MediaQuery.sizeOf(context).width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.circular(borderRadius),
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding:
EdgeInsetsDirectional.fromSTEB(
30.rpx,
16.rpx,
16.rpx,
8.rpx),
child: Container(
width: MediaQuery.sizeOf(context)
.width,
height: MediaQuery.sizeOf(context)
.height *
0.065,
decoration: BoxDecoration(
color:
FlutterFlowTheme.of(context)
.secondaryBackground,
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
ValueListenableBuilder(
valueListenable:
formFieldController,
builder: (c, a, s) =>
FlutterFlowDropDown<
String>(
controller:
formFieldController,
options: gloablController
.model.JunheDevices
.map<String>((d) =>
"${d["mac"]}")
.toList(),
optionLabels:
gloablController.model
.JunheDevices
.map<String>((d) {
var s = d["name"] ??
d["mac"];
if (s == null) {
return "";
} else {
return "$s";
}
}).toList(),
onChanged: (val) {
// print("$val");
// if (val == null) {
// sleepDays.value = [];
// } else {
// getSleeps(
// formFieldController
// .value);
// }
// // sleep_mac.value = val!;
},
width: 360.rpx,
height: 72.rpx,
maxHeight: 200.rpx,
textStyle: TextStyle(
fontSize: 28.rpx,
overflow: TextOverflow
.ellipsis),
hintText: '',
icon: Icon(
Icons
.keyboard_arrow_down_rounded,
color:
FlutterFlowTheme.of(
context)
.secondaryText,
size: 48.rpx,
),
fillColor: stringToColor(
"#F3F5F6"),
elevation: 2,
borderColor:
stringToColor(
"#F3F5F6"),
borderWidth: 2,
borderRadius: 18,
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(
// "/sleepWebview",
// arguments: [
// formFieldController
// .value
// ]);
// }
},
child: Row(
mainAxisSize:
MainAxisSize.max,
children: [
Text(
'睡眠报告',
style: FlutterFlowTheme
.of(context)
.bodyMedium
.override(
fontFamily:
'Readex Pro',
letterSpacing:
0,
fontSize:
30.rpx),
),
SizedBox(
width: 12.rpx,
),
SvgPicture.asset(
"assets/images/table.svg",
width: 28.rpx,
height: 28.rpx),
SizedBox(
width: 20.rpx,
),
],
),
),
],
),
),
),
Container(
padding: EdgeInsets.only(
top: 0.rpx,
bottom: 20.rpx,
left: 16.rpx,
right: 16.rpx),
width: double.infinity,
decoration: BoxDecoration(),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
...List.generate(
sleepDays.value.length,
(index) {
var day = sleepDays[index];
return Expanded(
child: Container(
padding: EdgeInsets.only(
top: 10.rpx,
bottom: 20.rpx),
width: 100,
// decoration: BoxDecoration(
// color: index == 2
// ? stringToColor("#F3F5F6")
// : Colors.white,
// borderRadius:
// BorderRadius.circular(
// borderRadius),
// ),
child: Column(
mainAxisSize:
MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.center,
children: [
Text(
day['week'],
style: FlutterFlowTheme
.of(context)
.bodyMedium
.override(
fontFamily:
'Readex Pro',
fontSize:
30.rpx,
letterSpacing:
0,
),
),
Text(
day['date'],
style: FlutterFlowTheme
.of(context)
.bodyMedium
.override(
fontFamily:
'Readex Pro',
letterSpacing:
0,
fontSize:
24.rpx,
),
),
SizedBox(
height: 6.rpx,
),
Column(
children: [
Row(
mainAxisSize:
MainAxisSize
.max,
mainAxisAlignment:
MainAxisAlignment
.center,
children: [
Text(
'${day['score'] ?? "-"}',
style: FlutterFlowTheme.of(
context)
.bodyMedium
.override(
fontFamily:
'Readex Pro',
fontSize:
48.rpx,
letterSpacing:
0,
),
),
if (day['score'] !=
null)
SizedBox(
width:
2.rpx,
),
if (day['score'] !=
null)
Text(
'',
style: FlutterFlowTheme.of(
context)
.bodyMedium
.override(
fontFamily:
'Readex Pro',
letterSpacing:
0,
fontSize:
26.rpx,
),
),
],
),
Container(
width: 120.rpx,
height: 52.rpx,
decoration:
BoxDecoration(
color: stringToColor(
day['scoreColor'] ??
"#f3f5f6"),
borderRadius:
BorderRadius
.circular(
26.rpx),
shape: BoxShape
.rectangle,
),
alignment:
Alignment
.center,
child: Text(
'${day['scoreType'] ?? "暂无"}',
style: FlutterFlowTheme.of(
context)
.bodyMedium
.override(
fontFamily:
'Readex Pro',
color: day['scoreType'] !=
null
? Colors.white
: stringToColor("#ced1d7"),
letterSpacing:
0,
fontSize:
28.rpx,
),
),
)
],
)
],
),
),
);
})
],
),
),
],
),
),
...List.generate(
gloablController
.model.deviceList.length, (index) {
var device = gloablController
.model.deviceList[index];
String rname = device['roomName'];
if (index != 0) {
String lrname = gloablController.model
.deviceList[index - 1]["roomName"];
if (lrname == rname) {
rname = "";
}
}
return Column(children: [
Padding(
padding:
EdgeInsetsDirectional.fromSTEB(
20.rpx, 20.rpx, 0, 0),
child: Container(
decoration: BoxDecoration(),
alignment:
AlignmentDirectional(-1, 0),
child: rname.isNotEmpty
? Text(
"$rname",
style: FlutterFlowTheme.of(
context)
.bodyMedium
.override(
fontFamily:
'Readex Pro',
color: Colors.white,
fontSize: 32.rpx,
letterSpacing: 0,
),
)
: SizedBox(
height: 10.rpx,
),
),
),
// getDeviceList(context, device)
]);
}),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 40.rpx, 0, 100.rpx),
child: Container(
width: MediaQuery.sizeOf(context).width,
height: 84.rpx,
decoration: BoxDecoration(),
child: FFButtonWidget(
onPressed: () {
// print('Button pressed ...');
// Get.toNamed("/homeDeviceType");
},
text: '添加新设备'.tr,
icon: Icon(
Icons.add,
size: 60.rpx,
),
options: FFButtonOptions(
height: 80.rpx,
padding:
EdgeInsetsDirectional.fromSTEB(
48.rpx, 0, 48.rpx, 0),
iconPadding:
EdgeInsetsDirectional.fromSTEB(
0, 0, 0, 0),
color: stringToColor("#182B7C"),
textStyle:
FlutterFlowTheme.of(context)
.titleSmall
.override(
fontFamily:
'Readex Pro',
color: Colors.white,
letterSpacing: 0,
fontSize: 30.rpx),
elevation: 3,
borderSide: BorderSide(
color: Colors.transparent,
width: 1,
),
borderRadius: BorderRadius.circular(
borderRadius),
),
),
),
),
],
),
),
if (gloablController.model.deviceList.length == 0)
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 0, 0, 80.rpx),
child: ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.all(0),
onTap: () {
if (userInfoController.model.login ==
null ||
userInfoController.model.login == 0) {
TopSlideNotification.show(context,
text: "请先登录".tr,
textColor:
themeController.currentColor.sc9);
Get.toNamed("/loginPage");
}
},
child: Container(
width: MediaQuery.sizeOf(context).width,
height: 302.rpx,
padding: EdgeInsets.only(
top: 90.rpx, bottom: 80.rpx),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(borderRadius),
border: Border.all(
color: stringToColor("#85F5FF"), // 边框颜色
width: 1.rpx, // 边框宽度
),
),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
SvgPicture.asset(
'assets/images/icon/add.svg',
width: 42.rpx,
height: 42.rpx,
),
SizedBox(
height: 32.rpx,
),
Text(
'添加一台新设备'.tr,
style: TextStyle(
color: stringToColor("#85F5FF"),
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
],
),
),
),
),
],
),
);
})
],
),
),
)
// Padding(
// padding: EdgeInsets.symmetric(horizontal: 30.rpx),
// child: Column(
// children: [
// Padding(
// padding: EdgeInsets.fromLTRB(17.rpx, 30.rpx, 0, 0),
// child: Row(
// children: [
// Text('上海 22° 多云',
// style: TextStyle(
// fontSize: 26.rpx, color: Colors.white)),
// Icon(Icons.cloud,
// size: 30.rpx, color: Colors.white),
// ],
// ),
// ),
// ],
// ))
),
),
));
}
//1 :登录 0未登录
Widget userInfo(int? login) {
return Row(
children: (login == 1)
? [
SizedBox(width: 40.rpx),
CircleAvatar(
radius: 27.rpx, // 可根据需求调整
backgroundImage: login == 1
? (userInfoController.model.user!.avatar == null ||
userInfoController.model.user!.avatar!.isEmpty
? const AssetImage(
"assets/images/default_avatar.png",
)
: NetworkImage(
userInfoController.model.user!.avatar!,
))
: const AssetImage(
"assets/images/default_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, // 可根据需求调整
backgroundImage: login == 1
? (userInfoController.model.user!.avatar == null ||
userInfoController.model.user!.avatar!.isEmpty
? const AssetImage(
"assets/images/default_avatar.png",
)
: NetworkImage(
userInfoController.model.user!.avatar!,
))
: const AssetImage(
"assets/images/default_avatar.png",
),
),
SizedBox(width: 23.rpx), // 左侧头像和文本之间的间距
Text(
'未命名'.tr,
style: TextStyle(fontSize: 30.rpx, color: Colors.white),
)
],
);
}
}
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<ScoreItem> scoreList;
final ValueChanged<String?>? 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<String>(
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,
),
),
],
),
);
},
),
)
],
),
);
}
}