import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:vnote_device_plugin/models/exams/nibp.dart'; import 'package:vitalapp/components/alert_dialog.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_card.dart'; import 'package:vitalapp/pages/medical/models/item.dart'; import 'package:vitalapp/pages/medical/widgets/switch_button.dart'; /// 小弹窗输入 class VDialogBloodPressure extends StatelessWidget { /// 标题 final String? title; /// 描述 final String? description; /// 输入占位符 final String? placeholder; /// 初始值 final List? initialValue; const VDialogBloodPressure({ super.key, this.title, this.description, this.placeholder, this.initialValue, }); Future show() => VAlertDialog.showDialog(this); @override Widget build(BuildContext context) { final controller1 = TextEditingController(text: initialValue?.first); final controller2 = TextEditingController(text: initialValue?.last); return VAlertDialog( title: title, width: 440, contentPadding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24), content: _buildContent(context, controller1, controller2), showCancel: true, onConfirm: () { Get.back(result: json.encode([controller1.text, controller2.text])); }, ); } Widget _buildContent( BuildContext context, TextEditingController controller1, TextEditingController controller2, ) { final children = []; if (description != null) { children.add( Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: Text( description!, style: const TextStyle(color: Colors.black87, fontSize: 18), ), ), ); children.add(const SizedBox(height: 8)); } else { children.add(const SizedBox(height: 12)); } children.add(_buildInputWidget(context, controller1, controller2)); return SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: children, ), ); } Widget _buildInputWidget( BuildContext context, TextEditingController controller1, TextEditingController controller2, ) { const fontSize = 20.0; return Row( children: [ _buildItem(context, controller1, '高压'), const Text( '/', style: TextStyle(fontSize: fontSize), ), _buildItem(context, controller2, '低压'), ], ); } Widget _buildItem( BuildContext context, TextEditingController controller, String hintText, ) { const fontSize = 20.0; const height = 56.0; return Expanded( child: SizedBox( height: height, child: TextField( controller: controller, readOnly: false, autofocus: true, keyboardType: const TextInputType.numberWithOptions( decimal: true), // 允许输入数字和小数点 inputFormatters: [ FilteringTextInputFormatter.allow( RegExp(r'^\d+\.?\d{0,2}'), ), // 只允许输入数字和小数点,俩位小数 ], style: const TextStyle(fontSize: fontSize), decoration: InputDecoration( border: const UnderlineInputBorder( borderRadius: BorderRadius.zero, borderSide: BorderSide(), ), enabledBorder: const UnderlineInputBorder( borderRadius: BorderRadius.zero, borderSide: BorderSide( color: Colors.black54, ), ), focusedBorder: UnderlineInputBorder( borderRadius: BorderRadius.zero, borderSide: BorderSide( color: Theme.of(context).primaryColor.withOpacity(.4), ), ), filled: true, fillColor: Colors.white, contentPadding: const EdgeInsets.symmetric( vertical: (height - fontSize * 1.2) / 2, horizontal: 8, ), hintStyle: const TextStyle(fontSize: fontSize), labelStyle: const TextStyle(fontSize: fontSize), hintText: hintText, isCollapsed: true, ), onSubmitted: (value) { print(value); Get.back(result: value); }, ), ), ); } } /// TODO 优化血压组件,存储需要重新设计 // ignore: must_be_immutable class ExamBloodPressure extends StatefulWidget { ExamBloodPressure({ super.key, required this.currentValue, required this.bloodPressure, }); Map currentValue; Function(Map) bloodPressure; @override State createState() => _ExamBloodPressureState(); } class _ExamBloodPressureState extends State { PressureStatus pressureStatus = PressureStatus.left; NibpExamValue? value; NibpExamValue? leftNibpExamValue; NibpExamValue? rightNibpExamValue; String? right; String? left; @override void initState() { if (widget.currentValue['left'] != null) { leftNibpExamValue = NibpExamValue( systolicPressure: int.parse( jsonDecode(widget.currentValue['left']).first.toString()), diastolicPressure: int.parse( jsonDecode(widget.currentValue['left']).last.toString()), pulse: 0); } if (widget.currentValue['right'] != null) { rightNibpExamValue = NibpExamValue( systolicPressure: int.parse( jsonDecode(widget.currentValue['right']).first.toString()), diastolicPressure: int.parse( jsonDecode(widget.currentValue['right']).last.toString()), pulse: 0); } super.initState(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Stack( children: [ ExamCard( // clickCard: () {}, content: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ InkWell( child: _SideBar( title: '左侧血压', value: _buildResult(leftNibpExamValue), unit: 'mmHg', ), onTap: () async { String? result = await VDialogBloodPressure( title: '左侧血压', initialValue: [ leftNibpExamValue?.systolicPressure.toString() ?? '', leftNibpExamValue?.diastolicPressure.toString() ?? '', ], ).show(); if (result != null) { widget.bloodPressure({ 'left': result, 'right': right, }); leftNibpExamValue = NibpExamValue( diastolicPressure: int.parse(jsonDecode(result).last), systolicPressure: int.parse(jsonDecode(result).first), pulse: 0, ); } setState(() {}); }, ), const Divider(indent: 3), InkWell( child: _SideBar( title: '右侧血压', value: _buildResult(rightNibpExamValue), unit: 'mmHg', ), onTap: () async { String? result = await VDialogBloodPressure( title: '右侧血压', initialValue: [ rightNibpExamValue?.systolicPressure.toString() ?? '', rightNibpExamValue?.diastolicPressure.toString() ?? '', ], ).show(); if (result != null) { widget.bloodPressure({ 'left': left, 'right': result, }); rightNibpExamValue = NibpExamValue( diastolicPressure: int.parse(jsonDecode(result).last), systolicPressure: int.parse(jsonDecode(result).first), pulse: 0, ); } setState(() {}); }, ), ], ), ), ], ); } Widget _buildButtonGroup() { return AnimatedToggle( values: const ['左侧', '右侧'], onToggleCallback: (value) { setState(() { pressureStatus = value; }); }, statusValue: pressureStatus, buttonColor: Theme.of(context).primaryColor, backgroundColor: const Color(0xFFB5C1CC), textColor: const Color(0xFFFFFFFF), ); } Widget _buildResult(NibpExamValue? nibpExamValue) { const textStyle = TextStyle(fontSize: 26, color: Colors.black); return Row( children: [ Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Align( alignment: Alignment.centerLeft, child: Text( nibpExamValue?.systolicPressure.toString() ?? '', style: textStyle, ), ), Align( alignment: Alignment.centerRight, child: Text( nibpExamValue?.diastolicPressure.toString() ?? '', style: textStyle, ), ), ], ), ], ); } Widget _buildResultWidget() { const textStyle = TextStyle(fontSize: 48, color: Colors.black); return Row( children: [ Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Align( alignment: Alignment.centerLeft, child: Text( value!.systolicPressure.toString(), style: textStyle, ), ), Align( alignment: Alignment.centerRight, child: Text( value!.diastolicPressure.toString(), style: textStyle, ), ), ], ), _buildButtonGroup(), ], ); } } class _SideBar extends StatelessWidget { final String title; final Widget value; final String unit; const _SideBar({ required this.title, required this.value, required this.unit, }); @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( // padding: const EdgeInsets.symmetric(horizontal: 30), child: Text( title, style: const TextStyle( fontSize: 26, ), ), ), Container( alignment: Alignment.bottomRight, padding: const EdgeInsets.only( right: 30, ), child: Row( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: [ value, ], ), ), ], ); } } // /// 血压组件 // class ExamBloodPressure extends StatelessWidget { // const ExamBloodPressure({ // super.key, // required this.currentFormObject, // required this.currentBloodPressureValue, // required this.commonBloodPressure, // }); // final FormObject currentFormObject; // final List currentBloodPressureValue; // final Function commonBloodPressure; // String get getBloodPressure { // if (currentBloodPressureValue.first.isNotEmpty || // currentBloodPressureValue.last.isNotEmpty) { // return '${currentBloodPressureValue.first} / ${currentBloodPressureValue.last}'; // } else { // return ''; // } // } // @override // Widget build(BuildContext context) { // return ExamCard( // title: currentFormObject.label ?? '', // clickCard: () => commonBloodPressure.call(), // content: Container( // alignment: Alignment.bottomRight, // padding: const EdgeInsets.only(bottom: 20, right: 30, left: 40), // constraints: const BoxConstraints(minHeight: 50), // child: FittedBox( // child: Row( // mainAxisAlignment: MainAxisAlignment.end, // crossAxisAlignment: CrossAxisAlignment.end, // children: [ // RichText( // text: TextSpan( // text: getBloodPressure, // style: const TextStyle( // fontSize: 60, // color: Colors.black, // ), // children: [ // TextSpan( // text: currentFormObject.append ?? '', // style: const TextStyle(fontSize: 25), // ) // ], // ), // ), // ], // ), // ), // ), // ); // } // }