last_record.dart 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. import 'dart:convert';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/services.dart';
  5. import 'package:get/get.dart';
  6. import 'package:vitalapp/components/dialog_ecg_image.dart';
  7. import 'package:vitalapp/pages/medical/widgets/twelve_ecg_view/widgets/conclusion_dialog.dart';
  8. import 'package:vnote_device_plugin/models/exams/twelve_heart.dart';
  9. class LastRecordTable extends StatelessWidget {
  10. final bool? isExistLocalData;
  11. const LastRecordTable({
  12. super.key,
  13. this.title,
  14. required this.columnNames,
  15. this.columnWidths,
  16. required this.tableData,
  17. this.diagnosisTime,
  18. this.isExistLocalData = false,
  19. this.checkKey,
  20. });
  21. final List<List<String>> tableData;
  22. final List<String> columnNames;
  23. final String? title;
  24. final String? diagnosisTime;
  25. final String? checkKey;
  26. final Map<int, TableColumnWidth>? columnWidths;
  27. @override
  28. Widget build(BuildContext context) {
  29. return Container(child: Expanded(child: _buildTable()));
  30. }
  31. Widget _buildTable() {
  32. final scrollController = ScrollController();
  33. return Column(
  34. children: [
  35. const SizedBox(
  36. height: 10,
  37. ),
  38. Table(
  39. columnWidths: columnWidths,
  40. children: [
  41. TableRow(
  42. decoration: const BoxDecoration(
  43. color: Color.fromRGBO(215, 234, 255, 1),
  44. ),
  45. children: columnNames
  46. .map((columnName) => _buildHeaderCell(columnName))
  47. .toList(),
  48. ),
  49. ],
  50. ),
  51. Expanded(
  52. child: Scrollbar(
  53. controller: scrollController,
  54. thumbVisibility: true,
  55. child: SingleChildScrollView(
  56. controller: scrollController,
  57. child: Table(
  58. columnWidths: columnWidths,
  59. children: _buildRow(tableData),
  60. ),
  61. ),
  62. ),
  63. ),
  64. const SizedBox(
  65. height: 10,
  66. ),
  67. ],
  68. );
  69. }
  70. List<TableRow> _buildRow(List<List<String>> tableData) {
  71. // var controller = Get.find<HealthCheckListController>();
  72. var tableRows = <TableRow>[];
  73. for (var i = 0; i < tableData.length; i++) {
  74. final List<String> rowData = tableData[i];
  75. final label = rowData[0];
  76. List<Widget> children = [];
  77. for (String child in rowData) {
  78. if (rowData.indexOf(child) == 3) {
  79. continue;
  80. }
  81. if (checkKey == "HEITCMC") {
  82. children.add(_buildConstitutionDataCell(child));
  83. }
  84. if (label == '心电测量') {
  85. children.add(_buildImageDataCell(child));
  86. } else if (label == '十二导心电图(30秒)' || label == "十二导心电图(30秒)") {
  87. children.add(_buildImageDataCell(child));
  88. } else if (label == '十二导心电图(5秒)' ||
  89. label == '十二导心电图(5秒)' ||
  90. label == '十二导心电图') {
  91. children.add(_buildImageDataCell(child));
  92. } else if (label == '十二导分析结果') {
  93. children.add(_buildEcg12DataCell(child));
  94. } else {
  95. children.add(_buildDataCell(child));
  96. }
  97. }
  98. tableRows.add(
  99. TableRow(
  100. decoration: i % 2 == 0
  101. ? null
  102. : const BoxDecoration(
  103. color: Color.fromRGBO(233, 244, 255, 1),
  104. ),
  105. children: children,
  106. ),
  107. );
  108. }
  109. return tableRows;
  110. }
  111. TableCell _buildConstitutionDataCell(String title) {
  112. if (title.contains("Value")) {
  113. title = jsonDecode(title)["Value"].toString();
  114. } else if (title.contains("质")) {
  115. title = title.substring(0, 3);
  116. }
  117. Widget contentWidget = _buildSizeOverflow(title);
  118. return TableCell(
  119. child: Container(
  120. padding: const EdgeInsets.symmetric(horizontal: 14),
  121. alignment: Alignment.centerLeft,
  122. height: 37,
  123. child: contentWidget,
  124. ),
  125. );
  126. }
  127. TableCell _buildHeaderCell(String title) {
  128. return TableCell(
  129. child: Container(
  130. padding: const EdgeInsets.symmetric(horizontal: 14),
  131. alignment: Alignment.centerLeft,
  132. height: 37,
  133. child: Text(
  134. title,
  135. style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
  136. ),
  137. ),
  138. );
  139. }
  140. /// 12导心电的结果
  141. TableCell _buildEcg12DataCell(String value) {
  142. if (value.contains("advice")) {
  143. return TableCell(
  144. child: InkWell(
  145. onTap: () async {
  146. TwelveHeartResultEntity resultConclusion =
  147. TwelveHeartResultEntity.fromJson(jsonDecode(value));
  148. await ConclusionDialog.show(twelveHeartResult: resultConclusion);
  149. },
  150. child: Container(
  151. padding: const EdgeInsets.symmetric(horizontal: 14),
  152. alignment: Alignment.centerLeft,
  153. height: 57,
  154. child: const Text(
  155. "点击查看结果",
  156. style: TextStyle(
  157. color: Colors.blue,
  158. ),
  159. ),
  160. ),
  161. ),
  162. );
  163. }
  164. return TableCell(
  165. child: Container(
  166. padding: const EdgeInsets.symmetric(horizontal: 14),
  167. alignment: Alignment.centerLeft,
  168. height: 57,
  169. child: Text(
  170. value,
  171. style: const TextStyle(fontSize: 14),
  172. ),
  173. ),
  174. );
  175. }
  176. String _replaceSemicolon(String input) {
  177. String result = input;
  178. if (result.endsWith(';')) {
  179. result = result.replaceAll(';', '');
  180. } else {
  181. result = result.replaceAll(';', '、');
  182. }
  183. return result;
  184. }
  185. Widget _buildSizeOverflow(String title) {
  186. return LayoutBuilder(
  187. builder: (BuildContext context, BoxConstraints constraints) {
  188. final textPainter = TextPainter(
  189. text: TextSpan(text: title, style: const TextStyle(fontSize: 14)),
  190. maxLines: 2,
  191. textDirection: TextDirection.ltr,
  192. )..layout(maxWidth: constraints.maxWidth);
  193. Widget contentWidget = Text(
  194. title,
  195. style: const TextStyle(
  196. color: Colors.black,
  197. fontSize: 14,
  198. ),
  199. maxLines: 2,
  200. overflow: TextOverflow.ellipsis,
  201. );
  202. if (textPainter.didExceedMaxLines) {
  203. contentWidget = Tooltip(
  204. message: title,
  205. padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
  206. textStyle: const TextStyle(fontSize: 14, color: Colors.white),
  207. triggerMode: TooltipTriggerMode.tap,
  208. child: contentWidget,
  209. );
  210. } else {
  211. // 文本没有超出
  212. print('Text did not overflow');
  213. }
  214. return contentWidget;
  215. },
  216. );
  217. }
  218. TableCell _buildDataCell(String title) {
  219. if (title.contains(";")) {
  220. title = _replaceSemicolon(title);
  221. }
  222. Widget contentWidget = _buildSizeOverflow(title);
  223. return TableCell(
  224. child: Container(
  225. padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 2),
  226. alignment: Alignment.centerLeft,
  227. constraints: BoxConstraints(maxHeight: 48),
  228. child: Row(children: [Expanded(child: contentWidget)]),
  229. ),
  230. );
  231. }
  232. TableCell _buildImageDataCell(String title) {
  233. if (title.length > 50) {
  234. Uint8List imageBytes = (isExistLocalData! && !kIsWeb)
  235. ? base64.decode(title)
  236. : base64.decode(
  237. "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=");
  238. return TableCell(
  239. child: InkWell(
  240. onTap: () {
  241. print(title);
  242. Get.dialog(
  243. EcgImageDialog(
  244. image: (isExistLocalData! && !kIsWeb)
  245. ? Image.memory(
  246. imageBytes,
  247. )
  248. : Image.network(
  249. title,
  250. fit: BoxFit.cover,
  251. ),
  252. ),
  253. );
  254. },
  255. child: Container(
  256. padding: const EdgeInsets.symmetric(horizontal: 8),
  257. alignment: Alignment.center,
  258. height: 40,
  259. child: isExistLocalData!
  260. ? Image.memory(
  261. imageBytes,
  262. fit: BoxFit.fitHeight,
  263. height: 28,
  264. )
  265. : Image.network(
  266. title,
  267. fit: BoxFit.fitHeight,
  268. height: 28,
  269. ),
  270. ),
  271. ),
  272. );
  273. }
  274. return TableCell(
  275. child: Container(
  276. padding: const EdgeInsets.symmetric(horizontal: 14),
  277. alignment: Alignment.centerLeft,
  278. height: 37,
  279. child: Text(
  280. title,
  281. style: const TextStyle(fontSize: 14),
  282. ),
  283. ),
  284. );
  285. }
  286. }