last_record.dart 8.4 KB

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