csv_datas_view.dart 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. import 'package:fis_common/index.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:get/get.dart';
  4. import 'package:vitalapp/components/appbar.dart';
  5. import 'package:vitalapp/components/search_input.dart';
  6. import 'package:vitalapp/managers/interfaces/models/csv_data.dart';
  7. class CSVDatasView extends StatefulWidget {
  8. final List<CsvRevord> records;
  9. CSVDatasView(this.records);
  10. @override
  11. State<StatefulWidget> createState() {
  12. return CSVDatasViewState();
  13. }
  14. }
  15. class CSVDatasViewState extends State<CSVDatasView> {
  16. final _searchController = TextEditingController();
  17. List<CsvRevord> _pendingUploadDatas = [];
  18. List<CsvRevord> _errorDatas = [];
  19. List<String> _selectedCsvDataCodes = [];
  20. bool _isShowErrorData = false;
  21. bool _isSelectedAll = true;
  22. @override
  23. void initState() {
  24. //sampleBarcode对应的就是体检系统的条码
  25. _pendingUploadDatas = widget.records
  26. .where((element) =>
  27. element.csvDatas
  28. .firstWhereOrNull((element) => element.key == "sampleBarcode")
  29. ?.value
  30. .isNotNullOrEmpty ??
  31. false)
  32. .toList();
  33. _errorDatas = widget.records
  34. .where((element) =>
  35. element.csvDatas
  36. .firstWhereOrNull((element) => element.key == "sampleBarcode")
  37. ?.value
  38. .isNullOrEmpty ??
  39. false)
  40. .toList();
  41. _selectedAll();
  42. super.initState();
  43. }
  44. @override
  45. Widget build(BuildContext context) {
  46. return Scaffold(
  47. backgroundColor: Colors.white,
  48. appBar: VAppBar(
  49. titleWidget: Text(
  50. "数据上传",
  51. style: const TextStyle(fontSize: 24, color: Colors.white),
  52. ),
  53. actions: [
  54. if (!_isShowErrorData)
  55. TextButton.icon(
  56. onPressed: () async {},
  57. label: Text(
  58. '提交',
  59. style: TextStyle(fontSize: 20, color: Colors.white),
  60. ),
  61. icon: Icon(Icons.save, size: 32, color: Colors.white),
  62. ),
  63. ],
  64. ),
  65. body: _buildBody(),
  66. );
  67. }
  68. Widget _buildBody() {
  69. return Column(
  70. children: [
  71. Container(
  72. height: 40,
  73. child: _buildHead(),
  74. margin: EdgeInsets.symmetric(vertical: 10),
  75. ),
  76. Expanded(
  77. child: ListView(
  78. children: [
  79. if (_isShowErrorData) ...[
  80. ..._errorDatas.map((e) => _buildRecord(e)),
  81. ] else ...[
  82. ..._pendingUploadDatas.map((e) => _buildRecord(e)),
  83. ],
  84. ],
  85. ),
  86. ),
  87. ],
  88. );
  89. }
  90. Widget _buildRecord(CsvRevord e) {
  91. List<CsvData> csvDatas = e.csvDatas;
  92. List<Widget> children = [];
  93. for (var c in csvDatas) {
  94. children.add(_buildItem(c));
  95. }
  96. var code = csvDatas
  97. .firstWhereOrNull((element) => element.key == "sampleBarcode")
  98. ?.value ??
  99. '';
  100. return Container(
  101. padding: EdgeInsets.only(left: 10),
  102. width: MediaQuery.of(context).size.width,
  103. child: Row(
  104. children: [
  105. if (!_isShowErrorData)
  106. Checkbox(
  107. value: _selectedCsvDataCodes.contains(code),
  108. onChanged: (v) {
  109. if (_selectedCsvDataCodes.contains(code)) {
  110. _selectedCsvDataCodes.remove(code);
  111. } else {
  112. _selectedCsvDataCodes.add(code);
  113. }
  114. setState(() {});
  115. },
  116. ),
  117. Expanded(
  118. child: Wrap(
  119. children: children,
  120. ),
  121. ),
  122. ],
  123. ),
  124. decoration: BoxDecoration(
  125. border: Border(
  126. bottom: BorderSide(
  127. color: Colors.grey[300]!, // 边框颜色
  128. width: 1.0, // 边框宽度
  129. ),
  130. )),
  131. );
  132. }
  133. Widget _buildItem(CsvData c) {
  134. if (c.value.isEmpty) {
  135. return SizedBox();
  136. }
  137. String value = c.value;
  138. if (c.unit.isNotNullOrEmpty) {
  139. value += " " + c.unit!;
  140. }
  141. String title = c.des ?? '';
  142. if (title.isNotEmpty) {
  143. title += ":";
  144. }
  145. return Row(
  146. mainAxisSize: MainAxisSize.min,
  147. children: [
  148. Text(
  149. title,
  150. style: TextStyle(fontWeight: FontWeight.bold),
  151. ),
  152. SizedBox(
  153. width: 3,
  154. ),
  155. Text(value),
  156. SizedBox(
  157. width: 15,
  158. ),
  159. ],
  160. );
  161. }
  162. Widget _buildHead() {
  163. return Row(
  164. children: [
  165. SizedBox(width: 10),
  166. if (!_isShowErrorData)
  167. Checkbox(
  168. value: _isSelectedAll,
  169. onChanged: (v) {
  170. _isSelectedAll = !_isSelectedAll;
  171. _selectedCsvDataCodes.clear();
  172. if (_isSelectedAll) {
  173. _selectedAll();
  174. }
  175. setState(() {});
  176. },
  177. ),
  178. _buildSearchInput(),
  179. SizedBox(width: 20),
  180. _buildTips(),
  181. SizedBox(width: 10),
  182. _buildSwichButton(),
  183. if (_isShowErrorData) ...[
  184. SizedBox(width: 10),
  185. Icon(
  186. Icons.warning,
  187. color: Colors.orange,
  188. ),
  189. Text(
  190. "请检查样本条码是否正确!",
  191. style: TextStyle(color: Colors.orange),
  192. ),
  193. ],
  194. ],
  195. );
  196. }
  197. void _selectedAll() {
  198. for (var data in _pendingUploadDatas) {
  199. var code = data.csvDatas
  200. .firstWhereOrNull((element) => element.key == "sampleBarcode")
  201. ?.value ??
  202. '';
  203. _selectedCsvDataCodes.add(code);
  204. }
  205. }
  206. Widget _buildSearchInput() {
  207. return Container(
  208. width: 400,
  209. margin: EdgeInsets.only(left: 20),
  210. child: VSearchInput(
  211. textEditingController: _searchController,
  212. placeholder: "请输入姓名",
  213. onSearch: (v) {
  214. if (_isShowErrorData) {
  215. var errorDatas = widget.records
  216. .where((element) =>
  217. element.csvDatas
  218. .firstWhereOrNull(
  219. (element) => element.key == "sampleBarcode")
  220. ?.value
  221. .isNullOrEmpty ??
  222. false)
  223. .toList();
  224. _errorDatas = errorDatas
  225. .where((element) =>
  226. element.csvDatas
  227. .firstWhereOrNull(
  228. (element) => element.key == "patientName")
  229. ?.value
  230. .contains(v) ??
  231. false)
  232. .toList();
  233. } else {
  234. var pendingUploadDatas = widget.records
  235. .where((element) =>
  236. element.csvDatas
  237. .firstWhereOrNull(
  238. (element) => element.key == "sampleBarcode")
  239. ?.value
  240. .isNotNullOrEmpty ??
  241. false)
  242. .toList();
  243. _pendingUploadDatas = pendingUploadDatas
  244. .where((element) =>
  245. element.csvDatas
  246. .firstWhereOrNull(
  247. (element) => element.key == "patientName")
  248. ?.value
  249. .contains(v) ??
  250. false)
  251. .toList();
  252. if (_isSelectedAll) {
  253. _selectedCsvDataCodes.clear();
  254. for (var data in _pendingUploadDatas) {
  255. var code = data.csvDatas
  256. .firstWhereOrNull(
  257. (element) => element.key == "sampleBarcode")
  258. ?.value ??
  259. '';
  260. _selectedCsvDataCodes.add(code);
  261. }
  262. }
  263. }
  264. setState(() {});
  265. },
  266. ),
  267. );
  268. }
  269. Widget _buildTips() {
  270. var tips =
  271. "共计 ${widget.records.length} 条数据,其中校验通过 ${_pendingUploadDatas.length} 条数据";
  272. if (_errorDatas.length > 0) {
  273. tips += ",校验不通过${_errorDatas.length}条数据";
  274. }
  275. return Text(tips);
  276. }
  277. Widget _buildSwichButton() {
  278. return OutlinedButton(
  279. onPressed: () {
  280. setState(() {
  281. _isShowErrorData = !_isShowErrorData;
  282. });
  283. },
  284. child: Text(
  285. _isShowErrorData ? "切换至校验通过数据" : "切换至校验不通过数据",
  286. ),
  287. );
  288. }
  289. }