last_record.dart 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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. } else if (label == '心电测量') {
  84. children.add(_buildImageDataCell(child));
  85. } else if (label == '十二导心电图(30秒)' || label == "十二导心电图(30秒)") {
  86. children.add(_buildImageDataCell(child));
  87. } else if (label == '十二导心电图(5秒)' ||
  88. label == '十二导心电图(5秒)' ||
  89. label == '十二导心电图') {
  90. children.add(_buildImageDataCell(child));
  91. } else if (label == '十二导分析结果') {
  92. children.add(_buildEcg12DataCell(child));
  93. } else {
  94. children.add(_buildDataCell(child));
  95. }
  96. }
  97. tableRows.add(
  98. TableRow(
  99. decoration: i % 2 == 0
  100. ? null
  101. : const BoxDecoration(
  102. color: Color.fromRGBO(233, 244, 255, 1),
  103. ),
  104. children: children,
  105. ),
  106. );
  107. }
  108. return tableRows;
  109. }
  110. TableCell _buildConstitutionDataCell(String title) {
  111. if (title.contains("Value")) {
  112. title = jsonDecode(title)["Value"].toString();
  113. } else if (title.contains("质")) {
  114. title = title.substring(0, 3);
  115. }
  116. Widget contentWidget = _buildSizeOverflow(title);
  117. return TableCell(
  118. child: Container(
  119. padding: const EdgeInsets.symmetric(horizontal: 14),
  120. alignment: Alignment.centerLeft,
  121. height: 37,
  122. child: contentWidget,
  123. ),
  124. );
  125. }
  126. TableCell _buildHeaderCell(String title) {
  127. return TableCell(
  128. child: Container(
  129. padding: const EdgeInsets.symmetric(horizontal: 14),
  130. alignment: Alignment.centerLeft,
  131. height: 37,
  132. child: Text(
  133. title,
  134. style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
  135. ),
  136. ),
  137. );
  138. }
  139. /// 12导心电的结果
  140. TableCell _buildEcg12DataCell(String value) {
  141. if (value.contains("advice")) {
  142. return TableCell(
  143. child: InkWell(
  144. onTap: () async {
  145. TwelveHeartResultEntity resultConclusion =
  146. TwelveHeartResultEntity.fromJson(jsonDecode(value));
  147. await ConclusionDialog.show(twelveHeartResult: resultConclusion);
  148. },
  149. child: Container(
  150. padding: const EdgeInsets.symmetric(horizontal: 14),
  151. alignment: Alignment.centerLeft,
  152. height: 57,
  153. child: const Text(
  154. "点击查看结果",
  155. style: TextStyle(
  156. color: Colors.blue,
  157. ),
  158. ),
  159. ),
  160. ),
  161. );
  162. }
  163. return TableCell(
  164. child: Container(
  165. padding: const EdgeInsets.symmetric(horizontal: 14),
  166. alignment: Alignment.centerLeft,
  167. height: 57,
  168. child: Text(
  169. value,
  170. style: const TextStyle(fontSize: 14),
  171. ),
  172. ),
  173. );
  174. }
  175. String _replaceSemicolon(String input) {
  176. String result = input;
  177. if (result.endsWith(';')) {
  178. result = result.replaceAll(';', '');
  179. } else {
  180. result = result.replaceAll(';', '、');
  181. }
  182. return result;
  183. }
  184. Widget _buildSizeOverflow(String title) {
  185. return LayoutBuilder(
  186. builder: (BuildContext context, BoxConstraints constraints) {
  187. final textPainter = TextPainter(
  188. text: TextSpan(text: title, style: const TextStyle(fontSize: 14)),
  189. maxLines: 2,
  190. textDirection: TextDirection.ltr,
  191. )..layout(maxWidth: constraints.maxWidth);
  192. Widget contentWidget = Text(
  193. title,
  194. style: const TextStyle(
  195. color: Colors.black,
  196. fontSize: 14,
  197. ),
  198. maxLines: 2,
  199. overflow: TextOverflow.ellipsis,
  200. );
  201. if (textPainter.didExceedMaxLines) {
  202. contentWidget = Tooltip(
  203. message: title,
  204. padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
  205. textStyle: const TextStyle(fontSize: 14, color: Colors.white),
  206. triggerMode: TooltipTriggerMode.tap,
  207. child: contentWidget,
  208. );
  209. } else {
  210. // 文本没有超出
  211. print('Text did not overflow');
  212. }
  213. return contentWidget;
  214. },
  215. );
  216. }
  217. TableCell _buildDataCell(String title) {
  218. if (title.contains(";")) {
  219. title = _replaceSemicolon(title);
  220. }
  221. Widget contentWidget = _buildSizeOverflow(title);
  222. return TableCell(
  223. child: Container(
  224. padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 2),
  225. alignment: Alignment.centerLeft,
  226. constraints: BoxConstraints(maxHeight: 48),
  227. child: Row(children: [Expanded(child: contentWidget)]),
  228. ),
  229. );
  230. }
  231. TableCell _buildImageDataCell(String title) {
  232. if (title.length > 50) {
  233. Uint8List imageBytes = (isExistLocalData! && !kIsWeb)
  234. ? base64.decode(title)
  235. : base64.decode(
  236. "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=");
  237. return TableCell(
  238. child: InkWell(
  239. onTap: () {
  240. print(title);
  241. Get.dialog(
  242. EcgImageDialog(
  243. image: (isExistLocalData! && !kIsWeb)
  244. ? Image.memory(
  245. imageBytes,
  246. )
  247. : Image.network(
  248. title,
  249. fit: BoxFit.cover,
  250. ),
  251. ),
  252. );
  253. },
  254. child: Container(
  255. padding: const EdgeInsets.symmetric(horizontal: 8),
  256. alignment: Alignment.center,
  257. height: 40,
  258. child: isExistLocalData!
  259. ? Image.memory(
  260. imageBytes,
  261. fit: BoxFit.fitHeight,
  262. height: 28,
  263. )
  264. : Image.network(
  265. title,
  266. fit: BoxFit.fitHeight,
  267. height: 28,
  268. ),
  269. ),
  270. ),
  271. );
  272. }
  273. return TableCell(
  274. child: Container(
  275. padding: const EdgeInsets.symmetric(horizontal: 14),
  276. alignment: Alignment.centerLeft,
  277. height: 37,
  278. child: Text(
  279. title,
  280. style: const TextStyle(fontSize: 14),
  281. ),
  282. ),
  283. );
  284. }
  285. }