import 'dart:convert'; import 'package:fis_jsonrpc/rpc.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:vitalapp/components/button.dart'; import 'package:vitalapp/components/dialog_input.dart'; import 'package:vitalapp/components/dialog_number.dart'; import 'package:vitalapp/components/dynamic_drawer.dart'; import 'package:vitalapp/managers/interfaces/cachedRecord.dart'; import 'package:vitalapp/managers/interfaces/template.dart'; import 'package:vitalapp/pages/check/models/form.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_blood_pressure.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_blood_sugar.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_body_temperature.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_body_weight.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_boold_oxygen.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_check_box.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_health_guidance_check_box.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_input.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_number_input.dart'; import 'dart:math' as math; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_radio.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_radio_score.dart'; import 'package:vitalapp/pages/check/widgets/device_controller.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_table.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_toxic_substance.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_urinalys.dart'; import 'package:vitalapp/pages/check/widgets/exam_table/homecare_bed_history_from.dart'; import 'package:vitalapp/pages/check/widgets/exam_table/hospitalization_history_from.dart'; import 'package:vitalapp/pages/check/widgets/exam_table/inoculate_history_from.dart'; import 'package:vitalapp/pages/check/widgets/exam_table/main_medication_status_from.dart'; import 'package:vitalapp/pages/check/widgets/title_clip_path.dart'; class ConfigurableCard extends StatefulWidget { final String cardKey; final Future Function(String, String, dynamic) callBack; final Widget? followUpWidget; final String? patientCode; final String? examData; const ConfigurableCard({ super.key, required this.cardKey, required this.callBack, this.followUpWidget, this.patientCode, this.examData, }); @override State createState() => _ConfigurableFormState(); } class _ConfigurableFormState extends State { /// 当前最新的模板的键值对 Map templateRelation = {}; /// 当前模板数据 List currentTemplate = []; /// 当前title的下标 int currentTitleIndex = 0; Map formValue = {}; var scaffoldKey = GlobalKey(); final _templateManager = Get.find(); final _cachedRecordManager = Get.find(); final arrowHeight = math.tan(120 / 180) * 19; List deviceList = ['Temp', 'GLU', 'NIBP', 'SpO2', 'BMI']; Map deviceCached = {}; Map currentTable = {}; List storeTypeList = [ 'Qi_Score', 'Yang_Score', 'Yin_Score', 'Tan_Score', 'Shi_Score', 'Xue_Score', 'Qiyu_Score', 'Te_Score', 'Ping_Score' ]; @override void initState() { Get.put(DeviceController()); super.initState(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { if (mounted) { initTemplate(); } }); } @override void dispose() { super.dispose(); } Future initTemplate() async { Get.find().busy = true; await fetchTemplateIndex(); await fetchTemplate(widget.cardKey); await fetchTemplateData(); // GlobalCacheHelper.setItem(GlobalCacheHelper.keys.followUpEditTemp, "");//TODO Get.find().busy = false; // if (!['GXY', 'TNB'].contains(widget.cardKey)) { // fetchTemplateData(); // } } /// 读取健康检测的缓存 Future readCachedRecord(String currentDevice) async { if (widget.patientCode == null) { return null; } String? value = await _cachedRecordManager.readCachedRecord( currentDevice, widget.patientCode!, 'ZLZS', ); return value; } /// 读取体检的缓存 Future readCachedCheck() async { if (widget.patientCode == null) { return null; } String? value = await _cachedRecordManager.readCachedRecord( widget.cardKey, widget.patientCode!, 'exam', ); return value; } Future readCached() async { for (var element in deviceList) { String? value = await readCachedRecord(element); if (value?.isNotEmpty ?? false) { deviceCached.addAll(jsonDecode(value!)); } } } Future fetchTemplateIndex() async { try { /// 获取模板的键值对 String? templates; templates = await _templateManager.readTemplateRelation('templateRelation'); templateRelation = jsonDecode(templates!); setState(() {}); } catch (error) { print('发生错误: $error'); } } Future fetchTemplateData() async { // / 这逻辑需要优化 if (widget.examData?.isNotEmpty ?? false) { formValue = jsonDecode(widget.examData!); return; } String? value = await readCachedCheck(); await readCached(); if (deviceCached.isNotEmpty) { formValue = deviceCached; setState(() {}); return; } if (value?.isNotEmpty ?? false) { formValue = jsonDecode(value!); } formValue.forEach( (key, value) { if (value is List) { formValue[key] = List.from(formValue[key]); } else if (value is List) { formValue[key] = List.from(formValue[key]); } }, ); setState(() {}); } Future fetchTemplate(String key) async { try { if (templateRelation[key] == null) { currentTemplate = []; setState(() {}); return; } var template = await _templateManager.readTemplate(templateRelation[key]!); String templateContent = TemplateDTO.fromJson(jsonDecode(template!)).templateContent!; List> list = jsonDecode(templateContent).cast>(); for (var i in list) { if (i['children'] != null) { List currentChildren = []; for (var j in i['children']) { currentChildren.add(FormObject.fromJson(j)); } i['children'] = currentChildren; } var item = FormObject.fromJson(i); currentTemplate.add(item); } if (widget.cardKey == 'LNRZYYJKGLFWJL') { for (var element in storeTypeList) { formValue[element] = calculatePhysicalFitnessScore(element, element == 'Ping_Score'); } } setState(() {}); } catch (error) { print('发生错误: $error'); } } @override Widget build(BuildContext context) { return Scaffold( key: scaffoldKey, endDrawer: VDynamicDrawerWrapper(scaffoldKey: scaffoldKey), resizeToAvoidBottomInset: false, body: Column( children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox( width: 16, ), Container( margin: const EdgeInsets.only(top: 8), width: 130, height: 54, child: VButton( onTap: () => {Get.back()}, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: const [ Icon(Icons.arrow_back_ios_new, size: 24), SizedBox( width: 8, ), Text("返回", style: TextStyle(fontSize: 20)), ], ), ), ), Expanded( child: Container( padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 10), child: _buildTitleList(), ), ), Container( margin: const EdgeInsets.only(top: 8, right: 16), width: 130, height: 54, child: VButton( onTap: () async { final result = await widget.callBack( widget.cardKey, templateRelation[widget.cardKey]!, jsonEncode(formValue), ); if (result) { Get.back(); } }, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: const [ Icon(Icons.save, size: 24), SizedBox( width: 8, ), Text("保存", style: TextStyle(fontSize: 20)), ], ), ), ), ], ), Expanded( child: Stack( children: [ Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildDiagram(), _buildContent(), ], ), if (currentTitleIndex != currentTemplate.length - 1) _buildPositionedButton( () async { currentTitleIndex++; setState(() {}); }, right: -30, ), ], ), ) ], ), ); } Widget buildSingleItem(Widget item, int span) { return FractionallySizedBox( widthFactor: span == 24 ? 1 : 0.5, child: item, ); } Widget buildWidget(FormObject? currentFormObject) { Map widgetMap = { 'checkbox': _buildCheckBox, 'numberInput': _buildNumberInput, 'input': _buildInput, 'radio': _buildRadio, 'radioScore': _buildRadioScore, 'bloodPressure': _buildBloodPressure, 'bodyTemperature': _buildBodyTemperature, 'weight': _buildBodyWeight, 'sugar': _buildBodySugar, 'bloodOxygen': _buildBloodOxygen, 'healthGuidanceCheckBox': _buildHealthGuidanceCheckBox, 'medicalHistory': _buildMedicalHistory, 'homecareBedHistor': _buildHomecareBedHistory, 'table': _buildMainMedicationHistory, 'inoculateHistory': _buildInoculateHistory, 'safetyPrecautions': _buildToxicSubstance, 'urinalys': _buildUrinalysis, }; Widget Function(FormObject) builder = widgetMap[currentFormObject?.type] ?? _buildInput; return builder(currentFormObject!); } Widget flowCardList() { int itemCount = 0; bool currentTemplateOptionsIsNotEmpty = false; if (currentTemplate.isNotEmpty) { itemCount = currentTemplate[currentTitleIndex].children?.length ?? 0; currentTemplateOptionsIsNotEmpty = currentTemplate[currentTitleIndex].options?.isNotEmpty ?? false; } List items = List.generate(itemCount, (index) { FormObject? currentFormObject = currentTemplate[currentTitleIndex].children?[index]; int span = currentFormObject?.span ?? 12; //父结构的options不等于空或null if (true) { //子结构的options若是无值则取父类的options值 if (currentTemplateOptionsIsNotEmpty) { currentFormObject!.options = currentTemplate[currentTitleIndex].options; } } return buildSingleItem(buildWidget(currentFormObject), span); }); return Scrollbar( thumbVisibility: true, child: SingleChildScrollView( child: Container( alignment: Alignment.topCenter, padding: const EdgeInsets.all(15), child: Wrap( runSpacing: 20, // 纵向元素间距 alignment: WrapAlignment.start, children: items, ), ), ), ); } /// title标签 Widget _buildTitleList() { return Wrap( runSpacing: 10, // 设置子小部件之间的间距 spacing: -12, alignment: WrapAlignment.start, children: currentTemplate.asMap().entries.map( (e) { /// TODO 这边需要改下 MaterialColor currentColors = Colors.grey; e.value.children?.forEach((element) { if (formValue.containsKey(element.key)) { if (!(widget.cardKey == 'LNRZYYJKGLFWJL' && element.parentKey == 'Ping_Score')) { currentColors = Colors.green; } else if (element.key == 'qusition1') { { currentColors = Colors.green; } } } }); return TitleClipRect( title: e.value.label ?? '', color: currentTitleIndex == e.key ? null : currentColors, arrowHeight: arrowHeight, clickTitle: () { // if (widget.cardKey == 'LNRZYYJKGLFWJL' && // currentTitleIndex == 0 && // formValue.length != 33) { // PromptBox.toast('题目未答全,不可进行指导'); // } else { currentTitleIndex = e.key; setState(() {}); } }, ); }, ).toList(), ); } /// 示意图 Widget _buildDiagram() { if (widget.cardKey == 'ZYYYFMYGHYFJZS') { return const SizedBox(); } return Expanded( flex: 1, child: Stack( children: [ /// TODO BAKA-优化 _buildImageCard(), if (currentTitleIndex != 0) _buildPositionedButton( () async { if (currentTitleIndex == 0) { Get.back(); } else { currentTitleIndex--; setState(() {}); } }, left: -30, ), ], ), ); } Widget _buildImageCard() { // if (currentTemplate[currentTitleIndex].key == 'Temperature') { // return Container( // alignment: Alignment.topCenter, // margin: const EdgeInsets.all(16).copyWith(top: 0), // child: Image.asset( // 'assets/images/healthCheck/temp.png', // height: double.infinity, // fit: BoxFit.fitWidth, // 设置图像的适应方式 // ), // ); // } if (['GXY', 'TNB', 'LNRZYYJKGLFWJL'].contains(widget.cardKey)) { return widget.followUpWidget!; } else { return Container( alignment: Alignment.topCenter, margin: const EdgeInsets.all(16).copyWith(top: 0), child: Image.asset( 'assets/images/exam/normalMeasurementChart.png', height: double.infinity, fit: BoxFit.fitWidth, // 设置图像的适应方式 ), ); } } /// 按钮 Widget _buildPositionedButton(Function onTap, {double? right, double? left}) { return Positioned( right: right, left: left, bottom: 0, top: 0, child: Container( width: 100, height: 100, alignment: Alignment.centerLeft, child: InkWell( onTap: () => onTap.call(), child: Container( width: 100, height: 100, padding: const EdgeInsets.all(20), alignment: right == null ? Alignment.centerRight : Alignment.centerLeft, decoration: BoxDecoration( borderRadius: BorderRadius.circular(50), color: Theme.of(context).primaryColor.withOpacity( .8, ), ), child: Image.asset( right == null ? "assets/images/exam/left-arrow.png" : "assets/images/exam/right-arrow.png", width: 40, height: 40, color: Colors.white, fit: BoxFit.contain, ), ), ), ), ); } /// 主页面 Widget _buildContent() { return Expanded( flex: 2, child: flowCardList(), ); } /// 多选框组件 Widget _buildCheckBox(FormObject currentFormObject) { List