import 'dart:async'; 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/NullDataComponentWidget.dart'; import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/controller/mh_controller/device_list_controller.dart'; import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart'; class VitalSignsSensorPage extends StatefulWidget { Map data; VitalSignsSensorPage({required this.data}); @override _VitalSignsSensorState createState() => _VitalSignsSensorState(); } class _VitalSignsSensorState extends State { BoxConstraints? bodysize; DeviceListController controller = Get.find(); Timer? _timer; @override void initState() { super.initState(); _fetchDeviceList(); _timer = Timer.periodic(Duration(seconds: 5), (timer) { _fetchDeviceList(); }); } _fetchDeviceList() async { await controller.getVitalList(widget.data['mac'.tr]); } @override void dispose() { _timer?.cancel(); // 页面销毁时取消定时器 super.dispose(); } @override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, cc) { bodysize = cc; return GestureDetector( 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( backgroundColor: Colors.transparent, iconTheme: const IconThemeData(color: Colors.white), automaticallyImplyLeading: false, titleSpacing: 0, title: SizedBox( width: double.infinity, height: 180.rpx, child: Stack( alignment: Alignment.center, children: [ // 中间居中的标题 Text( "体征传感器".tr, textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 30.rpx, ), ), // 左侧图标 Positioned( left: 0.rpx, child: returnIconButtomNew(), ), ], ), ), centerTitle: false, ), body: SafeArea( child: Obx(() { var list = controller.model.vitalList; return list.isEmpty ? const NullDataWidget() : _buildVitalListView(list); }), ), ))); }); } Widget _buildVitalListView(List dataList) { return Container( width: double.infinity, padding: EdgeInsets.symmetric(horizontal: 30.rpx), child: SingleChildScrollView( child: Column( children: [ SizedBox(height: 30.rpx), ...List.generate(dataList.length, (index) { final item = dataList[index]; final title = index == 0 ? '体征传感器A'.tr : '体征传感器B'.tr; // ✅ 只处理 A/B 场景 return VitalWidget(title: title, data: item); }).divide(SizedBox(height: 30.rpx)), SizedBox(height: 30.rpx), ], ), ), ); } } class VitalWidget extends StatelessWidget { final String title; final Map data; const VitalWidget({super.key, required this.title, required this.data}); @override Widget build(BuildContext context) { final String id = data['mac'.tr] ?? '--'; final int? timestamp = data['status']['updateTime']; final String time = (timestamp != null) ? DateFormat('yyyy-MM-dd HH:mm') .format(DateTime.fromMillisecondsSinceEpoch(timestamp)) : '--'; final List icons = data['icons'] ?? []; return ClickableContainer( backgroundColor: Color(0xFF003058), highlightColor: Color(0xFF055466), borderRadius: 20.rpx, padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 30.rpx, 30.rpx, 40.rpx), onTap: () {}, child: Column( mainAxisSize: MainAxisSize.max, children: [ Container( width: double.infinity, // constraints: BoxConstraints( // minHeight: 60.rpx, // ), child: Align( alignment: AlignmentDirectional(-1, 0), child: Text( // '实时监测结果通知'.tr, title, style: TextStyle( fontFamily: 'Inter', fontSize: 30.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc3, ), ), ), ), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Container( width: MediaQuery.sizeOf(context).width * 0.14, constraints: BoxConstraints(minWidth: 106.rpx), child: Text( "设备ID".tr, style: TextStyle( color: stringToColor("#929699"), fontSize: 26.rpx, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), Text( id, style: TextStyle(fontSize: 26.rpx, color: Color(0xFFFFFFFF)), ), ].divide(SizedBox(width: 33.rpx)), ), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Container( width: MediaQuery.sizeOf(context).width * 0.14, constraints: BoxConstraints(minWidth: 106.rpx), child: Text( "更新时间".tr, style: TextStyle( color: stringToColor("#929699"), fontSize: 26.rpx, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), Text( time, style: TextStyle(fontSize: 26.rpx, color: Color(0xFFFFFFFF)), ), ].divide(SizedBox(width: 33.rpx)), ), Row( mainAxisSize: MainAxisSize.max, children: [ Container( width: MediaQuery.sizeOf(context).width * 0.14, constraints: BoxConstraints(minWidth: 106.rpx), child: Text( "设备状态".tr, style: TextStyle( color: stringToColor("#929699"), fontSize: 26.rpx, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), Row( mainAxisSize: MainAxisSize.max, children: [ if (data['status']['signal'] != null && data['status']['signal'] != -1 && data['status']['status'] != null && data['status']['status'] == 1) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, // 或根据你主题定制颜色 padding: EdgeInsets.zero, borderRadius: 0, onTap: () { // 点击事件 showTipDialog( context, Container( child: RichText( text: TextSpan( text: "信号强度".tr, // 文本前缀部分 style: TextStyle( color: Colors.black, fontSize: AppConstants().title_text_fontSize, ), children: [ TextSpan( text: getBedSignal( data['status']['signal']), // 状态部分 style: TextStyle( color: themeController .currentColor.sc2, // 同样颜色,也可改成其他颜色 fontSize: AppConstants().title_text_fontSize, ), ), ], ), ), ), backgroundColor: Color(0xFFFFFFFF), colors: [ Color(0XFF1592AA), Color(0xFF0C83A7), Color(0xFF006FA3) ], ); }, child: Container( width: 30.rpx, height: 24.rpx, child: Image.asset( 'assets/img/signal${_getSignalLevel(data['status']['signal'])}.png'), ), ), if (data['status']['inBed'] != null && data['status']['status'] != null && data['status']['status'] == 1) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), borderRadius: 0, onTap: () { showTipDialog( context, Container( child: RichText( text: TextSpan( text: "是否在床".tr, // 文本前缀部分 style: TextStyle( color: Colors.black, fontSize: AppConstants().title_text_fontSize, ), children: [ TextSpan( text: getBedStatus( data['status']['inBed']), // 状态部分 style: TextStyle( color: themeController .currentColor.sc2, // 同样颜色,也可改成其他颜色 fontSize: AppConstants().title_text_fontSize, ), ), ], ), ), ), backgroundColor: Color(0xFFFFFFFF), colors: [ Color(0XFF1592AA), Color(0xFF0C83A7), Color(0xFF006FA3) ], ); }, child: SizedBox( width: 16.rpx, height: 36.rpx, child: SvgPicture.asset( data['status']['inBed'] == 0 ? 'assets/img/icon/not_bed.svg' : 'assets/img/icon/in_bed.svg', fit: BoxFit.fill, ), ), ), if (data['status']['failure'] != 0 && data['status']['status'] != null && data['status']['status'] == 1) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, // 可自定义点击水波纹颜色 padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), borderRadius: 0, onTap: () { showTipDialog( context, Container( child: RichText( text: TextSpan( text: "设备故障".tr, // 文本前缀部分 style: TextStyle( color: Colors.black, fontSize: AppConstants().title_text_fontSize, ), children: [ // TextSpan( // text:widget // .device['status']['status'] == 1?"在线".tr:"离线".tr, // 状态部分 // style: TextStyle( // color: themeController.currentColor // .sc2, // 同样颜色,也可改成其他颜色 // fontSize: AppConstants() // .title_text_fontSize, // ), // ), ], ), ), ), backgroundColor: Color(0xFFFFFFFF), colors: [ Color(0XFF1592AA), Color(0xFF0C83A7), Color(0xFF006FA3) ], ); }, child: SizedBox( width: 27.rpx, height: 27.rpx, child: SvgPicture.asset( 'assets/img/icon/device_issue.svg', fit: BoxFit.cover, ), ), ), if (data['status']['upgrade'] != 0 && data['status']['status'] != null && data['status']['status'] == 1) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, // 可自定义点击效果颜色 padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), borderRadius: 0, onTap: () { //todo 升级 }, child: SizedBox( width: 34.rpx, height: 24.rpx, child: SvgPicture.asset( 'assets/img/icon/upgrade.svg', fit: BoxFit.cover, // color: themeController.currentColor.sc3, // 若你想加颜色控制可取消注释 ), ), ), if (data['status']['status'] != null && data['status']['status'] == 0) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, // 可替换为点击高亮色 padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), borderRadius: 0, onTap: () { showTipDialog( context, Container( child: RichText( text: TextSpan( text: "网络状态".tr, // 文本前缀部分 style: TextStyle( color: Colors.black, fontSize: AppConstants().title_text_fontSize, ), children: [ TextSpan( text: data['status']['status'] == 1 ? "在线".tr : "离线".tr, // 状态部分 style: TextStyle( color: themeController .currentColor.sc2, // 同样颜色,也可改成其他颜色 fontSize: AppConstants().title_text_fontSize, ), ), ], ), ), ), backgroundColor: Color(0xFFFFFFFF), colors: [ Color(0XFF1592AA), Color(0xFF0C83A7), Color(0xFF006FA3) ], ); }, child: SizedBox( width: 27.rpx, height: 27.rpx, child: SvgPicture.asset( // data['status']['status'] == 1 // ? 'assets/img/icon/device_online.svg' // : 'assets/img/icon/device_offline.svg', 'assets/img/icon/device_issue.svg', fit: BoxFit.cover, ), ), ), ].divide(SizedBox(width: 50.rpx)), ), ].divide(SizedBox(width: 34.rpx)), ), ].divide( SizedBox(height: 20.rpx), )), ); } getBedSignal(signal) { if (signal <= 1) { return "较弱".tr; } if (signal > 1 && signal <= 2) { return "弱".tr; } if (signal > 2 && signal <= 3) { return "一般".tr; } if (signal > 3) { return "强".tr; } return "未知数据".tr; } String getBedStatus(int status) { if (status == 0) { return "离床".tr; } else if (status == 1) { return "在床".tr; } return ""; } int _getSignalLevel(int signal) { if (signal <= 25) { return 1; } else if (signal <= 50) { return 2; } else if (signal <= 75) { return 3; } else { return 4; } } }