12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142 |
- import 'dart:convert';
- import 'dart:math';
- import 'package:fis_common/index.dart';
- import 'package:fis_jsonrpc/rpc.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/services.dart';
- import 'package:get/get.dart';
- import 'package:vitalapp/architecture/storage/text_storage.dart';
- import 'package:vitalapp/architecture/utils/prompt_box.dart';
- import 'package:vitalapp/components/alert_dialog.dart';
- import 'package:vitalapp/components/appbar.dart';
- import 'package:vitalapp/components/button.dart';
- import 'package:vitalapp/components/dialog_input.dart';
- import 'package:vitalapp/components/dialog_select.dart';
- import 'package:vitalapp/components/dynamic_drawer.dart';
- import 'package:vitalapp/consts/styles.dart';
- import 'package:vitalapp/global.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_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_radio.dart';
- import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_radio_score.dart';
- import 'package:vitalapp/store/store.dart';
- class TCMConstitutionModule extends StatefulWidget {
- final String cardKey;
- final Future<bool> Function(String, String, dynamic) callBack;
- final String? patientCode;
- final String? examData;
- final bool? isEdit;
- const TCMConstitutionModule({
- super.key,
- required this.cardKey,
- required this.callBack,
- this.patientCode,
- this.examData,
- this.isEdit = false,
- });
- @override
- State<TCMConstitutionModule> createState() => _ConfigurableFormState();
- }
- class _ConfigurableFormState extends State<TCMConstitutionModule> {
- /// 当前最新的模板的键值对
- Map<String, dynamic> templateRelation = {};
- bool isFirstEnter = true;
- /// 当前模板数据
- List<FormObject> currentTemplate = [];
- /// 当前title的下标
- int currentTitleIndex = 0;
- Map<String, dynamic> formValue = {};
- var scaffoldKey = GlobalKey<ScaffoldState>();
- List<TCMData> resourceInfo = [];
- final _templateManager = Get.find<ITemplateManager>();
- final _cachedRecordManager = Get.find<ICachedRecordManager>();
- Map currentTable = {};
- late MapEntry<String, dynamic> currentResult;
- late List<MapEntry<String, dynamic>> compatibleResult =
- <MapEntry<String, dynamic>>[];
- late List<String> unansweredQuestions = <String>[];
- List<String> storeTypeList = [
- 'Qi_Score',
- 'Yang_Score',
- 'Yin_Score',
- 'Tan_Score',
- 'Shi_Score',
- 'Xue_Score',
- 'Qiyu_Score',
- 'Te_Score',
- 'Ping_Score'
- ];
- Map<String, dynamic> storeTypeMap = {
- "Qi_Score": '气虚质',
- "Yang_Score": '阳虚质',
- "Yin_Score": '阴虚质',
- "Tan_Score": '痰湿质',
- "Shi_Score": '湿热质',
- "Xue_Score": '血瘀质',
- "Qiyu_Score": '气郁质',
- "Te_Score": '特禀质',
- "Ping_Score": '平和质',
- };
- Map<String, dynamic> storeTypeMapDefaultTitle = {
- "Qi_Score": [2, 3, 4, 14],
- "Yang_Score": [11, 12, 13, 29],
- "Yin_Score": [10, 21, 26, 31],
- "Tan_Score": [9, 16, 28, 32],
- "Shi_Score": [23, 25, 27, 30],
- "Xue_Score": [19, 22, 24, 33],
- "Qiyu_Score": [5, 6, 7, 8],
- "Te_Score": [15, 17, 18, 20],
- "Ping_Score": [1, 2, 4, 5, 13],
- };
- Map<String, String> typeMap = {
- 'Peaceful_Quality': "Ping_Score",
- "Yang_Deficiency_Substance": "Yang_Score",
- "Idiosyncratic_Quality": "Te_Score",
- "Qi_Stagnation_Constitution": "Qiyu_Score",
- "Blood_Stasis_Substance": "Xue_Score",
- "Damp-heat_constitution": "Shi_Score",
- "Phlegm-dampness_constitution": "Tan_Score",
- "Yin_Deficiency_Substance": "Yin_Score",
- "Qi_Deficiency_Constitution": "Qi_Score",
- };
- String resultConstitution = "";
- late int? selectedIndex = -1; // 用于跟踪选中的项目索引
- @override
- void initState() {
- selectedIndex = -1;
- super.initState();
- initReadCached();
- getResourceInfo();
- unansweredQuestions.clear();
- // compatibleResult?.clear();
- WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
- if (mounted) {
- initTemplate();
- }
- });
- }
- Future<void> initReadCached() async {
- TextStorage cachedRecord = TextStorage(
- fileName: 'ZYTZ',
- directory: "patient/${widget.patientCode}",
- );
- String? value = await cachedRecord.read();
- if (value == null) {
- formValue = {};
- Store.resident.handleSaveMedicalData(jsonEncode(formValue));
- return;
- }
- Store.resident.handleSaveMedicalData(value);
- formValue = jsonDecode(value);
- }
- Future<bool?> saveCachedRecord() async {
- // deleteDirectory();
- Store.resident.handleSaveMedicalData(jsonEncode(formValue));
- TextStorage cachedRecord = TextStorage(
- fileName: 'ZYTZ',
- directory: "patient/${widget.patientCode}",
- );
- return cachedRecord.save(jsonEncode(formValue));
- }
- Future<bool?> deleteDirectory() async {
- TextStorage cachedRecord = TextStorage(
- fileName: 'ZYTZ',
- directory: "patient/${widget.patientCode}",
- );
- return cachedRecord.deleteDirectory();
- }
- Future<void> getResourceInfo() async {
- TextStorage resourceInfoCacheRecord = TextStorage(
- fileName: "healthGuidance",
- directory: "HealthGuidance/temlpate",
- );
- String? value = await resourceInfoCacheRecord.read();
- if (value != null) {
- var json = jsonDecode(value);
- resourceInfo =
- List<TCMData>.from(json['TCMDesc'].map((x) => TCMData.fromJson(x)));
- }
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- key: scaffoldKey,
- appBar: VAppBar(
- titleText: "中医体质",
- actions: (currentTitleIndex == 0 && !isFirstEnter)
- ? [
- TextButton(
- onPressed: () async {
- final result = await VDialogSelect<String, String>(
- title: "体质类型",
- source: storeTypeList,
- valueGetter: (data) => data,
- labelGetter: (data) => storeTypeMap[data],
- initialValue: formValue["PhysicalConclusion"],
- ).show();
- if (result != null) {
- Random random = Random();
- formValue.clear();
- formValue["PhysicalConclusion"] = result;
- if (result == "Ping_Score") {
- for (var i = 1; i < 34; i++) {
- if (i == 1) {
- int randomNumber = 3 + random.nextInt(3);
- formValue["qusition$i"] = randomNumber.toString();
- } else {
- int randomNumber = 1 + random.nextInt(2);
- formValue["qusition$i"] = randomNumber.toString();
- }
- }
- } else {
- for (var i = 1; i < 34; i++) {
- var questions =
- storeTypeMapDefaultTitle[result] as List<int>;
- if (questions.contains(i)) {
- int randomNumber = 3 + random.nextInt(3);
- formValue["qusition$i"] = randomNumber.toString();
- } else {
- int randomNumber = 1 + random.nextInt(2);
- formValue["qusition$i"] = randomNumber.toString();
- }
- }
- }
- for (var currentFormObject
- in currentTemplate[currentTitleIndex].children!) {
- optionUpdate(currentFormObject,
- formValue[currentFormObject.key]);
- }
- var currentFormObject =
- currentTemplate[currentTitleIndex].children!.first;
- optionUpdate(
- currentFormObject, formValue[currentFormObject.key]);
- }
- setState(() {});
- },
- child: Text(
- "选择体质",
- style: TextStyle(
- color: Colors.white,
- fontSize: 24,
- ),
- ),
- ),
- ]
- : null,
- ),
- resizeToAvoidBottomInset: false,
- body: (!widget.isEdit!) && isFirstEnter
- ? Container(
- decoration: const BoxDecoration(
- image: DecorationImage(
- image:
- AssetImage("assets/images/healthGuidanceBackground.png"),
- fit: BoxFit.cover,
- ),
- ),
- child: Column(
- children: [
- const SizedBox(
- height: 120,
- ),
- Center(
- child: Container(
- decoration: BoxDecoration(
- border: Border.all(color: Colors.black, width: 1)),
- padding: const EdgeInsets.all(10), // 添加内边距
- child: Container(
- decoration: BoxDecoration(
- border: Border.all(color: Colors.black, width: 1)),
- padding: const EdgeInsets.all(10), // 添加内边距
- child: const SizedBox(
- width: 900,
- child: Text(
- '《中医体质分类与判定标准》于2009年4月9日,由中华中医药学会正式发布,该标准旨在为体质辨识及中医体质相关疾病的防治、养生保健、健康管理提供依据,使体质分类科学化、规范化,是我国第一部指导和规范中医体质研究及应用的文件。适用于从事中医体质研究的中医临床医生、科研人员及相关管理人员,并可作为临床实践、判定规范及质量评定的重要参考依据。其中将中国人的体质分为九种,是体质分类的一种规范。具体有平和质、阳虚质、阴虚质、气虚质、痰湿质、湿热质、气郁质、血瘀质、特禀质。',
- style: TextStyle(fontSize: 24),
- ),
- ),
- ),
- ),
- ),
- const SizedBox(
- height: 120,
- ),
- VButton(
- label: "开始检测",
- onTap: () {
- setState(() {
- isFirstEnter = false;
- });
- },
- ),
- ],
- ),
- )
- : Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const SizedBox(
- height: 20,
- ),
- if (currentTitleIndex == 1)
- Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- children: [
- const SizedBox(
- width: 80,
- ),
- Text(
- '当前体质判定为:${storeTypeMap[currentResult.key]} (${jsonDecode(currentResult.value)["Result"]} ${jsonDecode(currentResult.value)["Value"]}分)',
- style: const TextStyle(
- fontSize: 28,
- color: Colors.black,
- ),
- )
- ],
- ),
- if (compatibleResult.isNotEmpty)
- Row(
- children: const [
- SizedBox(
- width: 80,
- ),
- Text(
- '兼夹体质有:',
- style: TextStyle(
- fontSize: 25,
- color: Colors.black,
- ),
- ),
- ],
- ),
- if (compatibleResult.isNotEmpty)
- ListView.builder(
- shrinkWrap: true,
- itemCount: (compatibleResult.length / 3).ceil(),
- itemBuilder: (context, index) {
- return Row(
- children: [
- const SizedBox(width: 120),
- for (int i = index * 5;
- i < (index + 1) * 5;
- i++)
- if (i < compatibleResult.length)
- Column(
- crossAxisAlignment:
- CrossAxisAlignment.start,
- children: [
- Text(
- '${storeTypeMap[compatibleResult[i].key]} (${jsonDecode(compatibleResult[i].value)["Result"]} ${jsonDecode(compatibleResult[i].value)["Value"]}分) ',
- style: const TextStyle(
- fontSize: 20,
- color: Colors.black,
- ),
- softWrap: true,
- ),
- ],
- ),
- if ((index + 1) * 3 < compatibleResult.length)
- Container(height: 20), // 控制换行间距
- ],
- );
- },
- ),
- ],
- ),
- Expanded(
- child: Row(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- // SizedBox(width: widget.isEdit! ? 90 : 50),
- _buildContent(),
- // SizedBox(width: widget.isEdit! ? 90 : 50),
- ],
- ),
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- if (currentTitleIndex == 0)
- VButton(
- onTap: _buildCompute,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Text(
- "计算体质辨识结果",
- style: const TextStyle(
- fontSize: 20,
- ),
- ),
- ],
- ),
- ),
- const SizedBox(
- width: 10,
- ),
- if (currentTitleIndex == 1)
- VButton(
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Text(widget.isEdit! ? "修改" : "返回",
- style: TextStyle(fontSize: 20)),
- ],
- ),
- onTap: () {
- setState(() {
- // if (!widget.isEdit!) formValue.clear();
- currentTitleIndex = 0;
- });
- },
- ),
- const SizedBox(
- width: 10,
- ),
- if (currentTitleIndex == 1)
- VButton(
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Text("提交", style: const TextStyle(fontSize: 20)),
- ],
- ),
- onTap: () async {
- final result = await widget.callBack(
- widget.cardKey,
- templateRelation[widget.cardKey]!,
- jsonEncode(formValue),
- );
- if (result) {
- setState(() {
- if (!widget.isEdit!) formValue.clear();
- currentTitleIndex = 0;
- deleteDirectory();
- });
- }
- Get.back();
- },
- ),
- ],
- ),
- const SizedBox(
- height: 10,
- ),
- ],
- ),
- );
- }
- String getHealthGuidance(String key) {
- String? value =
- resourceInfo.firstWhere((element) => element.key == key).value;
- return value;
- }
- /// 主页面
- Widget _buildContent() {
- return Expanded(
- child: flowCardList(),
- );
- }
- @override
- void dispose() {
- super.dispose();
- }
- Future<void> initTemplate() async {
- Store.app.busy = true;
- await fetchTemplateIndex();
- await fetchTemplate(widget.cardKey);
- await fetchTemplateData();
- Store.app.busy = false;
- }
- /// 读取体检的缓存
- Future<String?> readCachedCheck() async {
- if (widget.patientCode == null) {
- return null;
- }
- String? value = await _cachedRecordManager.readCachedRecord(
- widget.cardKey,
- widget.patientCode!,
- 'FollowUp',
- );
- return value;
- }
- Future<void> fetchTemplateIndex() async {
- try {
- /// 获取模板的键值对
- String? templates;
- templates =
- await _templateManager.readTemplateRelation('templateRelation');
- templateRelation = jsonDecode(templates!);
- setState(() {});
- } catch (error) {
- print('发生错误: $error');
- }
- }
- Future<void> fetchTemplateData() async {
- if (widget.examData?.isNotEmpty ?? false) {
- formValue = jsonDecode(widget.examData!);
- var jsonKey = formValue["PhysicalConclusion"];
- currentResult = MapEntry(jsonKey, formValue[jsonKey]);
- compatibleResult = calculateAllResylts();
- if (widget.isEdit!) {
- currentTitleIndex = 1;
- }
- setState(() {});
- return;
- }
- formValue.forEach(
- (key, value) {
- if (value is List<String>) {
- formValue[key] = List<String>.from(formValue[key]);
- } else if (value is List<Map>) {
- formValue[key] = List<Map>.from(formValue[key]);
- }
- },
- );
- // currentResult = formValue[formValue["PhysicalConclusion"].value];
- // if (widget.isEdit!) {
- // currentTitleIndex = 1;
- // }
- setState(() {});
- }
- Future<void> fetchTemplate(String key) async {
- try {
- if (templateRelation[key] == null) {
- currentTemplate = [];
- setState(() {});
- if (!FPlatform.isWindows) {
- return;
- }
- }
- List<Map<String, dynamic>> list = [];
- String? template;
- if (templateRelation.containsKey(key)) {
- template = await _templateManager.readTemplate(templateRelation[key]!);
- }
- if (template == null) {
- var json = await loadJsonFromAssets('assets/templates/${key}.json');
- list = jsonDecode(json)["Content"].cast<Map<String, dynamic>>();
- } else {
- var templateContent =
- TemplateDTO.fromJson(jsonDecode(template)).templateContent!;
- list = jsonDecode(templateContent).cast<Map<String, dynamic>>();
- }
- for (var i in list) {
- if (i['children'] != null) {
- List<FormObject> 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');
- }
- }
- Future<String> loadJsonFromAssets(String filePath) async {
- String jsonString = await rootBundle.loadString(filePath);
- return jsonString;
- }
- Widget buildSingleItem(Widget item, int span) {
- return Column(
- children: [
- FractionallySizedBox(
- widthFactor: span == 24 ? 1 : 0.5,
- child: item,
- ),
- ],
- );
- }
- Widget buildWidget(FormObject? currentFormObject) {
- Map<String, Widget Function(FormObject)> widgetMap = {
- 'input': _buildInput,
- 'radio': _buildRadio,
- 'radioScore': _buildRadioScore,
- 'healthGuidanceCheckBox': _buildHealthGuidanceCheckBox,
- };
- 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<Widget> items = List.generate(itemCount, (index) {
- FormObject? currentFormObject =
- currentTemplate[currentTitleIndex].children?[index];
- int span = currentFormObject?.span ?? 12;
- //父结构的options不等于空或null
- //子结构的options若是无值则取父类的options值
- if (currentTemplateOptionsIsNotEmpty) {
- if (currentFormObject!.options!.isEmpty)
- currentFormObject.options =
- currentTemplate[currentTitleIndex].options;
- }
- return buildSingleItem(buildWidget(currentFormObject), span);
- });
- final ScrollController scrollController = ScrollController();
- return Scrollbar(
- controller: scrollController,
- // thumbVisibility: false,
- // isAlwaysShown: false,
- child: ListView(
- controller: scrollController,
- padding: EdgeInsets.symmetric(horizontal: 50),
- children: [
- Container(
- alignment: Alignment.topCenter,
- child: Wrap(
- runSpacing: currentTitleIndex == 1 ? 5 : 10, // 纵向元素间距
- alignment: WrapAlignment.start,
- children: items,
- ),
- ),
- if (currentTitleIndex == 1)
- Text(
- getHealthGuidance(currentResult.key),
- style: TextStyle(fontSize: 18),
- ),
- ],
- ),
- );
- }
- /// title标签
- _buildCompute() {
- var questionsAnsweredNumber = formValue.entries
- .where((entry) => entry.key.contains("qusition"))
- .length; //获取已完成答题数量
- unansweredQuestions.clear();
- if (widget.cardKey == 'LNRZYYJKGLFWJL' &&
- currentTitleIndex == 0 &&
- questionsAnsweredNumber >= 33) {
- List<MapEntry<String, dynamic>> result = caculationConclusion();
- String? guidanceResult = hasGuidanceBeenProvided();
- String message = '';
- String title = '';
- bool isExistConflict = false;
- if (result.length == 1) {
- currentResult = result.first;
- formValue["PhysicalConclusion"] = currentResult.key;
- //直接进入中医药保健指导
- setState(() {
- compatibleResult = calculateAllResylts();
- currentTitleIndex = 1;
- });
- } else {
- if (result.length > 1) {
- //弹出选择框
- isExistConflict = result
- .where((entry) =>
- entry.key == "Yang_Score" || entry.key == "Yin_Score")
- .length ==
- 2;
- if (isExistConflict) {
- message = '判定结果既是阴虚又是阳虚的矛盾判定结果,需重新填写问题:10、11、12、13、21、26、29、31';
- title = '体质冲突';
- var list = [10, 11, 12, 13, 21, 26, 29, 31];
- for (var element in list) {
- unansweredQuestions.add('qusition$element');
- }
- } else {
- message = '根据答题情况,计算出多个体质,请选择其中一个';
- title = '体质选择';
- }
- }
- if (result.isEmpty) {
- //无法断体质
- message = '请重新完成体质问询或2周后重新采集填写';
- title = '无法判断体质';
- }
- Get.dialog(
- VAlertDialog(
- title: title,
- width: 700,
- showCancel: false,
- content: Container(
- padding: const EdgeInsets.symmetric(horizontal: 24),
- height: result.length > 1 && !isExistConflict
- ? result.length / 3 * 150
- : 150,
- alignment: Alignment.center,
- child: Column(
- children: [
- Text(
- message,
- style: const TextStyle(fontSize: 24),
- ),
- SizedBox(
- height: 10,
- ),
- if (result.length > 1 && !isExistConflict)
- Expanded(
- child: SelectResult(
- result: result,
- guidanceResult: guidanceResult,
- selectCheckBoxChange: (value) {
- selectedIndex = value;
- currentResult = result[value];
- formValue["PhysicalConclusion"] = currentResult.key;
- },
- ),
- ),
- ],
- ),
- ),
- onConfirm: () {
- if (selectedIndex != -1) {
- compatibleResult = calculateAllResylts();
- currentTitleIndex = 1;
- }
- Get.back();
- setState(() {});
- },
- ),
- barrierDismissible: false,
- barrierColor: Colors.black.withOpacity(.4),
- );
- }
- } else {
- for (var i = 1; i < 34; i++) {
- var isExitsQuestion = formValue.entries
- .where((element) => element.key == 'qusition$i')
- .isNotEmpty;
- if (!isExitsQuestion) {
- unansweredQuestions.add('qusition$i');
- }
- }
- setState(() {});
- PromptBox.toast('题目未答完整,无法计算体质');
- }
- }
- //验证体质
- List<MapEntry<String, dynamic>> caculationConclusion() {
- var formValues = formValue.entries
- .where((entry) =>
- storeTypeList.contains(entry.key) && entry.key != "Ping_Score")
- .toList();
- var pingResult = jsonDecode(formValue["Ping_Score"])["Result"];
- // int score = int.parse(formValue["Ping_Score"]["Value"] ?? 0);
- // var pingResult = getJudgmentResult('Ping_Score', score);
- if (["是", "基本是", "倾向是"].contains(pingResult)) {
- return formValue.entries
- .where((element) => element.key == 'Ping_Score')
- .toList();
- } else {
- dynamic maxValue = formValues
- .map((entry) => jsonDecode(entry.value)["Value"])
- .reduce((a, b) =>
- int.parse(a.toString()) > int.parse(b.toString()) ? a : b);
- if (int.parse(maxValue.toString()) > 8) {
- List<MapEntry<String, dynamic>> keyValuePairs = formValues
- .where((entry) => jsonDecode(entry.value)["Value"] == maxValue)
- .toList();
- return keyValuePairs;
- } else {
- return List.empty();
- }
- }
- }
- String? hasGuidanceBeenProvided() {
- var formValues = formValue.entries
- .where((entry) => entry.key == 'PhysicalConclusion')
- .toList();
- if (formValues.isNotEmpty) {
- return formValues.first.value;
- }
- return "";
- }
- Widget _buildInput(FormObject currentFormObject) {
- String currentInputValue = formValue[currentFormObject.key!] ?? '';
- Future<void> commonInput() async {
- String? result = await VDialogInput(
- title: currentFormObject.label,
- initialValue: formValue[currentFormObject.key],
- ).show();
- if (result?.isNotEmpty ?? false) {
- formValue[currentFormObject.key!] = result;
- currentInputValue = formValue[currentFormObject.key!];
- setState(() {});
- }
- }
- return ExamInput(
- currentInputValue: currentInputValue,
- commonInput: commonInput,
- currentFormObject: currentFormObject,
- );
- }
- ///计算满足的所有体质类型
- List<MapEntry<String, dynamic>> calculateAllResylts() {
- List<MapEntry<String, dynamic>> compatibleResults =
- <MapEntry<String, dynamic>>[];
- for (var key in storeTypeList) {
- var result = jsonDecode(formValue[key])["Result"];
- if (["是", "基本是", "倾向是"].contains(result)) {
- compatibleResults.add(MapEntry(key, formValue[key]));
- }
- }
- compatibleResults = compatibleResults
- .where((element) => element.key != currentResult.key)
- .toList();
- return compatibleResults;
- }
- ///中医药健康指导多选框组件
- Widget _buildHealthGuidanceCheckBox(FormObject currentFormObject) {
- List<Option> options = currentFormObject.options ?? [];
- List<dynamic> currentSelectedCheckBox = formValue["HealthGuidance"] ?? [];
- var currentScoreKey = currentFormObject.groupKeys != null
- ? currentFormObject.groupKeys![0]
- : '';
- if (currentResult.key != currentScoreKey) {
- return Container();
- }
- int score = jsonDecode(formValue[currentScoreKey])["Value"];
- String judgmentResult = jsonDecode(formValue[currentScoreKey])["Result"];
- void selectCheckBoxChange(Option e) {
- if (currentSelectedCheckBox.contains(e.value)) {
- currentSelectedCheckBox.remove(e.value);
- } else {
- currentSelectedCheckBox.add(e.value ?? '');
- }
- formValue["HealthGuidance"] = currentSelectedCheckBox;
- saveCachedRecord();
- setState(() {});
- }
- return ExamHealthGuidanceWidget(
- options: options,
- currentSelectedCheckBox: currentSelectedCheckBox,
- currentFormObject: currentFormObject,
- selectCheckBoxChange: selectCheckBoxChange,
- score: score,
- judgmentResult: judgmentResult,
- );
- }
- ///识别体质
- String getJudgmentResult(String storeKey, int score) {
- if (storeKey == 'Ping_Score') {
- if (score >= 17) {
- bool is8 = true;
- bool is10 = true;
- for (var e in storeTypeList) {
- if (formValue[e] != null && e != 'Ping_Score') {
- var otherScore = jsonDecode(formValue[e])["Value"];
- if (otherScore > 8) {
- if (is8) {
- is8 = false;
- }
- if (otherScore > 10) {
- is10 = false;
- }
- }
- if (!is10) {
- break;
- }
- }
- }
- if (is8) {
- return '是';
- } else if (is10) {
- return '基本是';
- }
- }
- return '否';
- } else {
- if (score >= 11) {
- return '是';
- } else if (9 == score || score == 10) {
- return '倾向是';
- } else {
- return '否';
- }
- }
- }
- /// 单选框组件
- Widget _buildRadio(FormObject currentFormObject) {
- List<Option> options = currentFormObject.options ?? [];
- String currentSelected = formValue[currentFormObject.key!] ?? "";
- void selectRaidoChange(Option e) {
- currentSelected = e.value ?? '';
- setState(() {
- optionUpdate(currentFormObject, currentSelected);
- });
- }
- var decoration = unansweredQuestions.contains(currentFormObject.key!)
- ? BoxDecoration(
- border: Border.all(color: Colors.red, width: 2),
- borderRadius: GlobalStyles.borderRadius,
- )
- : null;
- return Container(
- decoration: decoration,
- child: ExamRadio(
- options: options,
- currentFormObject: currentFormObject,
- selectRaidoChange: selectRaidoChange,
- currentSelected: currentSelected,
- ),
- );
- }
- Future<void> optionUpdate(
- FormObject formObject, String currentSelected) async {
- formValue[formObject.key!] = currentSelected;
- if (widget.cardKey == 'LNRZYYJKGLFWJL') {
- var pingScore = [
- 'qusition1',
- 'qusition2',
- 'qusition4',
- 'qusition5',
- 'qusition13'
- ];
- var isPingScore = pingScore.contains(formObject.key);
- int store =
- calculatePhysicalFitnessScore(formObject.groupKeys?[0], false);
- formValue[formObject.groupKeys?[0]] = jsonEncode({
- "Value": store,
- "Result": getJudgmentResult(formObject.groupKeys?[0], store),
- });
- if (isPingScore) {
- int store = calculatePhysicalFitnessScore('Ping_Score', true);
- formValue['Ping_Score'] = jsonEncode({
- "Value": store,
- "Result": getJudgmentResult('Ping_Score', store),
- });
- }
- }
- saveCachedRecord();
- }
- ///计算得分 currentScoreKey 当前分数的key isPingScore 是否是平和质
- int calculatePhysicalFitnessScore(String currentScoreKey, bool isPingScore) {
- int score = 0;
- var currentTemplateStoreList = currentTemplate[0].children?.where(
- (element) =>
- element.groupKeys != null &&
- element.groupKeys!.contains(currentScoreKey));
- if (!isPingScore) {
- for (var element in currentTemplateStoreList!) {
- if (formValue[element.key!] != null) {
- score += int.parse(formValue[element.key!]!);
- }
- }
- } else {
- int index = 0;
- for (var element in currentTemplateStoreList!) {
- if (index == 0) {
- if (formValue[element.key!] != null) {
- score += int.parse(formValue[element.key!]!);
- }
- } else {
- score += formValue[element.key!] != null
- ? (6 - int.parse(formValue[element.key!]!))
- : 0;
- }
- index++;
- }
- }
- return score;
- }
- Widget _buildRadioScore(FormObject currentFormObject) {
- print(currentFormObject.toJson());
- List<Option> options = currentFormObject.options ?? [];
- String currentSelected =
- formValue[currentFormObject.childrenKey!.first] ?? "";
- String currentScore = formValue[currentFormObject.childrenKey!.last] ?? "";
- void selectRaidoChange(Option e) {
- currentSelected = e.value ?? '';
- formValue[currentFormObject.childrenKey!.first] = currentSelected;
- setState(() {});
- }
- void changeScore(String? score) {
- currentScore = score ?? '';
- formValue[currentFormObject.childrenKey!.last] = currentScore;
- setState(() {});
- }
- return ExamRadioScore(
- options: options,
- currentFormObject: currentFormObject,
- selectRaidoChange: selectRaidoChange,
- currentSelected: currentSelected,
- changeScore: changeScore,
- currentScore: currentScore,
- );
- }
- }
- ///多个体质时选项
- class SelectResult extends StatefulWidget {
- final List<MapEntry<String, dynamic>> result;
- final Function selectCheckBoxChange;
- final String? guidanceResult;
- const SelectResult(
- {super.key,
- required this.result,
- required this.selectCheckBoxChange,
- this.guidanceResult});
- @override
- State<SelectResult> createState() => _SelectResultState();
- }
- class _SelectResultState extends State<SelectResult> {
- Map<String, dynamic> storeTypeMap = {
- "Qi_Score": '气虚质',
- "Yang_Score": '阳虚质',
- "Yin_Score": '阴虚质',
- "Tan_Score": '痰虚质',
- "Shi_Score": '湿热质',
- "Xue_Score": '血瘀质',
- "Qiyu_Score": '气郁质',
- "Te_Score": '特禀质',
- "Ping_Score": '平和质',
- };
- late int? selectedIndex = -1; // 用于跟踪选中的项目索引
- @override
- void initState() {
- super.initState();
- selectedIndex = -1;
- }
- @override
- Widget build(BuildContext context) {
- return GridView.builder(
- gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
- crossAxisCount: 3,
- crossAxisSpacing: 10,
- mainAxisSpacing: 10,
- childAspectRatio: 3,
- ),
- itemCount: widget.result.length,
- itemBuilder: (context, index) {
- if (widget.result[index].key == widget.guidanceResult) {
- widget.selectCheckBoxChange(index);
- selectedIndex = index;
- }
- return Row(
- children: [
- Radio(
- value: index,
- groupValue: selectedIndex,
- onChanged: (value) {
- widget.selectCheckBoxChange(value);
- setState(() {
- selectedIndex = value;
- });
- }),
- Text(
- "${storeTypeMap[widget.result[index].key]} (${jsonDecode(widget.result[index].value)["Result"]} ${jsonDecode(widget.result[index].value)["Value"]}分)",
- style: TextStyle(fontSize: 22),
- ),
- SizedBox(
- width: 5,
- ),
- ],
- );
- });
- }
- @override
- void dispose() {
- super.dispose();
- }
- }
- class TCMData {
- String key;
- String value;
- TCMData({required this.key, required this.value});
- factory TCMData.fromJson(Map<String, dynamic> json) {
- return TCMData(
- key: json['Key'],
- value: json['Value'],
- );
- }
- }
|