view.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. import 'package:fis_jsonrpc/rpc.dart';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:get/get.dart';
  5. import 'package:intl/intl.dart';
  6. import 'package:vitalapp/components/appbar.dart';
  7. import 'package:vitalapp/consts/styles.dart';
  8. import 'package:vitalapp/database/entities/defines.dart';
  9. import 'package:vitalapp/global.dart';
  10. import 'package:vitalapp/pages/check/follow_up/widgets/follow_up_from.dart';
  11. import 'package:vitalapp/pages/check/follow_up_record/controller.dart';
  12. import 'package:vitalapp/pages/check/widgets/configurable_card.dart';
  13. import 'package:vitalapp/pages/medical/controller.dart';
  14. import 'package:vitalapp/pages/patient/list/widgets/status.dart';
  15. import 'package:vitalapp/pages/widgets/record_common_item.dart';
  16. class FollowUpRecordPage extends GetView<FollowUpRecordController> {
  17. const FollowUpRecordPage({
  18. Key? key,
  19. required this.followUpType,
  20. }) : super(key: key);
  21. final String followUpType;
  22. @override
  23. Widget build(BuildContext context) {
  24. return GetBuilder(
  25. init: FollowUpRecordController(
  26. followUpType: followUpType,
  27. ),
  28. id: "FollowUpRecord",
  29. builder: (_) {
  30. return Scaffold(
  31. backgroundColor: const Color.fromRGBO(238, 238, 238, 1),
  32. appBar: VAppBar(
  33. titleWidget: Text(controller.getFollowUpValueByKey(followUpType)),
  34. actions: [
  35. IconButton(
  36. onPressed: () {
  37. _changePage(followUpType);
  38. },
  39. icon: Icon(
  40. Icons.add,
  41. size: 48,
  42. ),
  43. ),
  44. SizedBox(
  45. width: 8,
  46. )
  47. ],
  48. ),
  49. body: Stack(
  50. children: [
  51. Row(
  52. mainAxisAlignment: MainAxisAlignment.start,
  53. crossAxisAlignment: CrossAxisAlignment.start,
  54. children: [
  55. _buildDiagram(),
  56. _buildListView(),
  57. ],
  58. )
  59. ],
  60. ),
  61. );
  62. });
  63. }
  64. void _changePage(String key) async {
  65. /// TODO BAKA 急需求 后面改掉
  66. await Get.put(MedicalController());
  67. controller.followUpController.state.followUpTime = DateTime.now();
  68. controller.followUpController.state.nextFollowUpTime = null;
  69. controller.followUpController.state.followUpMode =
  70. FollowUpModeEnum.Outpatient;
  71. controller.followUpController.state.followUpPhoto = '';
  72. await Get.to(
  73. ConfigurableCard(
  74. cardKey: key,
  75. callBack: (key, templateCode, data) async {
  76. final result = await controller.followUpController
  77. .createFollowUp(key, templateCode, data);
  78. return result;
  79. },
  80. followUpWidget: FollowUpFrom(
  81. cardKey: key,
  82. ),
  83. ),
  84. transition: Transition.rightToLeft,
  85. );
  86. await controller.getFollowUpRecordList();
  87. await Get.find<MedicalController>().initRecordDataState();
  88. await Get.delete<MedicalController>();
  89. }
  90. Widget _buildDiagram() {
  91. return Expanded(
  92. flex: 1,
  93. child: Padding(
  94. padding: const EdgeInsets.all(16.0).copyWith(right: 0),
  95. child: Container(
  96. // color: Colors.white,
  97. padding: const EdgeInsets.all(16),
  98. decoration: BoxDecoration(
  99. color: Colors.white,
  100. border: Border.all(
  101. color: Colors.white,
  102. ),
  103. borderRadius: GlobalStyles.borderRadius,
  104. ),
  105. child: Image.asset(
  106. 'assets/images/exam/normalMeasurementChart.png',
  107. height: double.infinity,
  108. fit: BoxFit.fitWidth,
  109. ),
  110. ),
  111. ),
  112. );
  113. }
  114. Widget _buildListView() {
  115. return Expanded(
  116. flex: 2,
  117. child: Padding(
  118. padding: const EdgeInsets.all(16),
  119. child: RefreshIndicator(
  120. child: Obx(
  121. () {
  122. final list = controller.state.followUpDTOList;
  123. final children = <Widget>[];
  124. for (var i = 0; i < list.length; i++) {
  125. final dto = list[i];
  126. final offlineSyncArr = controller.offlineSyncTemp[i];
  127. final records = dto.followUpRecordDatas;
  128. if (records == null) {
  129. continue;
  130. }
  131. for (var j = 0; j < records.length; j++) {
  132. final data = records[j];
  133. OfflineDataSyncState? offlineSyncState;
  134. offlineSyncState = kIsWeb ? null : offlineSyncArr[j];
  135. children.add(
  136. _followUpRecordCard(
  137. index: j,
  138. dto: dto,
  139. dataDto: data,
  140. syncState: offlineSyncState,
  141. ),
  142. );
  143. }
  144. }
  145. return list.isEmpty
  146. ? Container(
  147. margin: const EdgeInsets.only(top: 80),
  148. child: Column(
  149. children: [
  150. Center(
  151. child: Image.asset(
  152. "assets/images/no_data.png",
  153. width: 300,
  154. height: 300,
  155. fit: BoxFit.cover,
  156. ),
  157. ),
  158. const Text(
  159. "暂无数据,先看看别的吧",
  160. style: TextStyle(fontSize: 18),
  161. ),
  162. ],
  163. ),
  164. )
  165. : GridView(
  166. gridDelegate:
  167. const SliverGridDelegateWithFixedCrossAxisCount(
  168. crossAxisCount: 1,
  169. mainAxisSpacing: 16,
  170. crossAxisSpacing: 20,
  171. childAspectRatio: 900 / 180,
  172. ),
  173. children: children,
  174. );
  175. },
  176. ),
  177. onRefresh: () async {}),
  178. ),
  179. );
  180. }
  181. }
  182. // ignore: camel_case_types
  183. class _followUpRecordCard extends StatelessWidget {
  184. final FollowUpRecordDTO dto;
  185. final FollowUpRecordDataDTO dataDto;
  186. final int index;
  187. final OfflineDataSyncState? syncState; // TODO temp
  188. _followUpRecordCard({
  189. required this.dto,
  190. required this.dataDto,
  191. required this.index,
  192. this.syncState,
  193. });
  194. final controller = Get.find<FollowUpRecordController>();
  195. @override
  196. Widget build(BuildContext context) {
  197. final body = Stack(
  198. children: [
  199. Row(
  200. children: [
  201. Expanded(
  202. flex: 10,
  203. child: Container(
  204. padding: const EdgeInsets.symmetric(
  205. horizontal: 30,
  206. vertical: 12,
  207. ),
  208. child: Column(
  209. crossAxisAlignment: CrossAxisAlignment.start,
  210. children: [
  211. const SizedBox(
  212. height: 8,
  213. ),
  214. LayoutBuilder(builder: (context, c) {
  215. final width = c.maxWidth - 100;
  216. return SizedBox(
  217. width: width,
  218. child: _buildBaseInfoRow(),
  219. );
  220. }),
  221. const SizedBox(
  222. height: 20,
  223. ),
  224. Wrap(
  225. alignment: WrapAlignment.start,
  226. spacing: 20,
  227. runSpacing: 8,
  228. children: [
  229. SizedBox(
  230. width: 300,
  231. child: RecordCommonItem(
  232. itemName: '姓名',
  233. itemValue: dto.patientName ?? "",
  234. fontSize: 18,
  235. ),
  236. ),
  237. RecordCommonItem(
  238. itemName: '随访类型',
  239. itemValue:
  240. controller.getFollowUpMode(dataDto.followUpMode),
  241. fontSize: 18,
  242. ),
  243. ],
  244. ),
  245. const SizedBox(
  246. height: 20,
  247. ),
  248. Wrap(
  249. alignment: WrapAlignment.start,
  250. spacing: 20,
  251. runSpacing: 8,
  252. children: [
  253. SizedBox(
  254. width: 300,
  255. child: RecordCommonItem(
  256. itemName: '随访医生',
  257. itemValue: dataDto.followUpDoctor ?? "",
  258. fontSize: 18,
  259. ),
  260. ),
  261. RecordCommonItem(
  262. itemName: '随访时间',
  263. itemValue: dataDto.followUpTime != null
  264. ? DateFormat("yyyy-MM-dd")
  265. .format(dataDto.followUpTime!.toLocal())
  266. : "",
  267. fontSize: 18,
  268. ),
  269. ],
  270. )
  271. ],
  272. ),
  273. ),
  274. ),
  275. Expanded(
  276. child: IconButton(
  277. onPressed: () {
  278. controller.toCheckPage(dataDto, isCreateFromOldDto: true);
  279. },
  280. icon: Icon(
  281. Icons.add,
  282. size: 56,
  283. color: Colors.grey.shade400,
  284. ),
  285. ),
  286. )
  287. ],
  288. ),
  289. Positioned(
  290. top: 16,
  291. right: 0,
  292. child: _FollowUpRecordSignStatusTag(
  293. dataDto: dataDto,
  294. ),
  295. ),
  296. // if(dataDto)
  297. Positioned(
  298. top: 16,
  299. right: 100,
  300. child: _OfflineSyncTag(syncState: syncState),
  301. ),
  302. // Positioned(
  303. // bottom: 16,
  304. // right: 12,
  305. // child: IconButton(
  306. // icon: Icon(
  307. // Icons.edit,
  308. // size: 26,
  309. // color: Theme.of(context).primaryColor,
  310. // ),
  311. // onPressed: () {
  312. // controller.toCheckPage(dataDto); //跳转到随访页面
  313. // },
  314. // ),
  315. // ),
  316. ],
  317. );
  318. return Material(
  319. borderRadius: GlobalStyles.borderRadius,
  320. child: Ink(
  321. decoration: BoxDecoration(
  322. color: Colors.white,
  323. borderRadius: GlobalStyles.borderRadius,
  324. ),
  325. child: InkWell(
  326. borderRadius: GlobalStyles.borderRadius,
  327. onTap: () {
  328. // controller.toFollowUpDetailPage(index, dto);
  329. controller.toCheckPage(dataDto); //跳转到随访页面
  330. },
  331. child: body,
  332. ),
  333. ),
  334. );
  335. }
  336. Widget _buildBaseInfoRow() {
  337. return SizedBox(
  338. child: RecordCommonItem(
  339. itemName: '随访病症',
  340. itemValue: controller.getFollowUpValueByKey(dataDto.key ?? ""),
  341. fontSize: 20,
  342. ),
  343. );
  344. }
  345. }
  346. // ignore: camel_case_types
  347. class _FollowUpRecordSignStatusTag extends StatelessWidget {
  348. final FollowUpRecordDataDTO dataDto;
  349. _FollowUpRecordSignStatusTag({required this.dataDto});
  350. final controller = Get.find<FollowUpRecordController>();
  351. @override
  352. Widget build(BuildContext context) {
  353. return Container(
  354. alignment: Alignment.centerRight,
  355. width: 120,
  356. child: StatusLabel(
  357. title: controller.followUpStateTransition(dataDto.followUpState),
  358. color: controller.followUpStateColors(dataDto.followUpState),
  359. ),
  360. );
  361. }
  362. }
  363. class _OfflineSyncTag extends StatelessWidget {
  364. final OfflineDataSyncState? syncState;
  365. const _OfflineSyncTag({required this.syncState});
  366. @override
  367. Widget build(BuildContext context) {
  368. if (syncState == null || syncState == OfflineDataSyncState.success) {
  369. return const SizedBox();
  370. }
  371. return Container(
  372. height: 30,
  373. alignment: Alignment.center,
  374. padding: const EdgeInsets.symmetric(horizontal: 16),
  375. decoration: BoxDecoration(
  376. borderRadius: BorderRadius.circular(16),
  377. color: Colors.red,
  378. ),
  379. child: Text(
  380. syncState!.getDescription(),
  381. style: const TextStyle(color: Colors.white, fontSize: 14),
  382. ),
  383. );
  384. }
  385. }