view.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. import 'package:fis_jsonrpc/rpc.dart';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_easyloading/flutter_easyloading.dart';
  5. import 'package:get/get.dart';
  6. import 'package:vitalapp/architecture/app_parameters.dart';
  7. import 'package:vitalapp/architecture/utils/datetime.dart';
  8. import 'package:vitalapp/architecture/utils/prompt_box.dart';
  9. import 'package:vitalapp/architecture/values/features.dart';
  10. import 'package:vitalapp/components/cell.dart';
  11. import 'package:vitalapp/components/dialog_date.dart';
  12. import 'package:vitalapp/components/dialog_input.dart';
  13. import 'package:vitalapp/components/dialog_label_select.dart';
  14. import 'package:vitalapp/components/dialog_select.dart';
  15. import 'package:vitalapp/consts/nations.dart';
  16. import 'package:vitalapp/consts/rpc_enum_labels.dart';
  17. import 'package:vitalapp/helper/id_card_helper.dart';
  18. import 'package:vitalapp/managers/interfaces/label.dart';
  19. import 'package:vitalapp/pages/patient_info/widgets/health_infos.dart';
  20. import 'package:vitalapp/store/store.dart';
  21. import 'controller.dart';
  22. import 'widgets/detail_infos.dart';
  23. class PatientInfomationPage extends GetView<PatientInfomationController> {
  24. final bool isNeedSyncAddressCheck;
  25. final bool isCanEditId;
  26. final bool isRequiredName;
  27. final bool isRequiredCard;
  28. PatientInfomationPage({
  29. this.isNeedSyncAddressCheck = false,
  30. this.isCanEditId = false,
  31. this.isRequiredName = false,
  32. this.isRequiredCard = false,
  33. });
  34. @override
  35. Widget build(BuildContext context) {
  36. return VListFormCellGroup(
  37. children: [
  38. VListFormCellGroup(
  39. formTitle: "基本信息",
  40. children: _buildBaseInfo(context),
  41. ),
  42. DetailInfomations(),
  43. HealthInfomations(),
  44. ],
  45. );
  46. }
  47. List<Widget> _buildBaseInfo(BuildContext context) {
  48. final state = controller.state;
  49. return [
  50. Obx(
  51. () => VListFormCell(
  52. label: "姓名",
  53. content: controller.state.name,
  54. isRequired: isRequiredName,
  55. onTap: () async {
  56. final result = await VDialogInput(
  57. title: "姓名",
  58. initialValue: controller.state.name,
  59. placeholder: "请填写姓名",
  60. ).show();
  61. if (result != null) {
  62. controller.state.name = result;
  63. }
  64. },
  65. endIcon: _buildEndIcon(),
  66. ),
  67. ),
  68. Obx(
  69. () => VListFormCell(
  70. label: "证件号",
  71. content: controller.state.cardNo,
  72. isRequired: isRequiredCard,
  73. onTap: () async {
  74. if (isCanEditId) {
  75. print("点击修改证件号");
  76. final result = await VDialogInput(
  77. title: "证件号",
  78. initialValue: controller.state.cardNo,
  79. placeholder: "请填写证件号",
  80. onConfirmVerification: (v) {
  81. bool isValid = IdCardHelper.validateIDCard(v);
  82. if (!isValid) {
  83. PromptBox.showToast("请填写正确的证件号",
  84. toastPosition: EasyLoadingToastPosition.top);
  85. }
  86. return isValid;
  87. },
  88. showCancel: true,
  89. ).show();
  90. if (result != null && result is String) {
  91. final passed =
  92. await controller.onCardNoChanged(result.toUpperCase());
  93. if (passed) {
  94. await controller
  95. .checkOfflinePatientExists(result.toUpperCase());
  96. }
  97. }
  98. }
  99. },
  100. endIcon: _buildEndIcon(isEdit: isCanEditId),
  101. ),
  102. ),
  103. if (Store.user.hasFeature(FeatureKeys.CrowdClassification)) ...[
  104. Obx(
  105. () => VListFormCell(
  106. label: "人群分类",
  107. content: controller.state.labels.join("、"),
  108. onTap: () async {
  109. var allLabels = await Get.find<ILabelManager>().getAllLabels();
  110. final result = await Get.dialog(
  111. VDialogLabelSelect(
  112. selectedLabels: controller.state.labels,
  113. allLabels: allLabels,
  114. ),
  115. );
  116. var selectedLabels = result as List<String>;
  117. controller.state.labels = selectedLabels;
  118. },
  119. endIcon: _buildEndIcon(),
  120. ),
  121. ),
  122. ],
  123. Obx(
  124. () => VListFormCell(
  125. label: "联系电话",
  126. content: controller.state.phoneNo,
  127. onTap: () async {
  128. final result = await VDialogInput(
  129. title: "联系电话",
  130. initialValue: controller.state.phoneNo,
  131. placeholder: "请填写联系电话",
  132. showCancel: true,
  133. onConfirmVerification: (v) {
  134. var isValid = (v.length == 11 && IdCardHelper.isNumeric(v));
  135. if (!isValid) {
  136. PromptBox.showToast("请填写正确的联系电话",
  137. toastPosition: EasyLoadingToastPosition.top);
  138. }
  139. return isValid;
  140. },
  141. ).show();
  142. if (result != null) {
  143. controller.state.phoneNo = result;
  144. }
  145. },
  146. endIcon: _buildEndIcon(),
  147. ),
  148. ),
  149. Obx(
  150. () => VListFormCell(
  151. label: "联系人姓名",
  152. content: controller.state.emergencyName,
  153. onTap: () async {
  154. final result = await VDialogInput(
  155. title: "联系人姓名",
  156. initialValue: controller.state.emergencyName,
  157. placeholder: "请填写联系人姓名",
  158. ).show();
  159. if (result != null) {
  160. controller.state.emergencyName = result;
  161. }
  162. },
  163. endIcon: _buildEndIcon(),
  164. ),
  165. ),
  166. Obx(
  167. () => VListFormCell(
  168. label: "联系人电话",
  169. content: controller.state.emergencyPhone,
  170. onTap: () async {
  171. final result = await VDialogInput(
  172. title: "联系人电话",
  173. initialValue: controller.state.emergencyPhone,
  174. placeholder: "请填写联系人电话",
  175. showCancel: true,
  176. onConfirmVerification: (v) {
  177. var isValid = (v.length == 11 && IdCardHelper.isNumeric(v));
  178. if (!isValid) {
  179. PromptBox.showToast("请填写正确的联系人电话",
  180. toastPosition: EasyLoadingToastPosition.top);
  181. }
  182. return isValid;
  183. },
  184. ).show();
  185. if (result != null) {
  186. controller.state.emergencyPhone = result;
  187. }
  188. },
  189. endIcon: _buildEndIcon(),
  190. ),
  191. ),
  192. Obx(
  193. () => VListFormCell(
  194. label: "性别",
  195. content: RpcEnumLabels.gender[state.gender],
  196. onTap: () async {
  197. final result = await VDialogSelect<GenderEnum, GenderEnum>(
  198. title: "选择性别",
  199. source: const [
  200. GenderEnum.Male,
  201. GenderEnum.Female,
  202. GenderEnum.Unknown,
  203. GenderEnum.Unspecified
  204. ],
  205. valueGetter: (data) => data,
  206. labelGetter: (data) => RpcEnumLabels.gender[data] ?? "",
  207. initialValue: state.gender,
  208. ).show();
  209. if (result != null) {
  210. controller.state.gender = result;
  211. }
  212. },
  213. endIcon: _buildEndIcon(),
  214. ),
  215. ),
  216. Obx(
  217. () => VListFormCell(
  218. label: "民族",
  219. content: state.nation,
  220. onTap: () async {
  221. final result = await VDialogSelect<String, String>(
  222. title: "选择民族",
  223. source: Nations.china,
  224. valueGetter: (data) => data,
  225. labelGetter: (data) => data,
  226. initialValue: state.nation.contains("族")
  227. ? state.nation
  228. : "${state.nation}族",
  229. ).show();
  230. if (result != null) {
  231. controller.state.nation = result;
  232. }
  233. },
  234. endIcon: _buildEndIcon(),
  235. ),
  236. ),
  237. Obx(
  238. () => VListFormCell(
  239. label: "出生日期",
  240. content: controller.state.birthday != null
  241. ? DataTimeUtils.formatDateString(controller.state.birthday!)
  242. : "",
  243. onTap: () async {
  244. bool _isLocalStation = AppParameters.data.isLocalStation;
  245. DateTime? result;
  246. if (kIsWeb || _isLocalStation) {
  247. result = await showDatePicker(
  248. context: context,
  249. initialDate: controller.state.birthday ?? DateTime.now(),
  250. firstDate: DateTime(1900),
  251. lastDate: DateTime.now(),
  252. );
  253. } else {
  254. result = await VDialogDate(
  255. title: "设置出生日期",
  256. initialValue: controller.state.birthday,
  257. maxValue: DateTime.now(),
  258. ).show();
  259. }
  260. if (result != null) {
  261. controller.state.birthday = result;
  262. }
  263. },
  264. endIcon: _buildEndIcon(),
  265. ),
  266. ),
  267. Obx(
  268. () => VListFormCell(
  269. label: "年龄",
  270. content: controller.state.age,
  271. endIcon: _buildEndIcon(isEdit: false),
  272. onTap: () {},
  273. ),
  274. ),
  275. if (isNeedSyncAddressCheck)
  276. Obx(
  277. () => VListFormCell(
  278. label: "同步户籍地址到现住地址",
  279. labelWidth: 250,
  280. contentWidget: Container(
  281. child: Switch(
  282. onChanged: (value) {
  283. controller.onSyncAddressCheckChanged(value);
  284. },
  285. value: controller.state.isSyncAddresses,
  286. ),
  287. ),
  288. ),
  289. ),
  290. Obx(
  291. () => VListFormCell(
  292. label: "户籍地址",
  293. content: controller.state.permanentResidenceAddress,
  294. onTap: () async {
  295. final result = await VDialogInput(
  296. title: "户籍地址",
  297. initialValue: controller.state.permanentResidenceAddress,
  298. placeholder: "请填写户籍地址",
  299. ).show();
  300. if (result != null) {
  301. controller.state.permanentResidenceAddress = result;
  302. }
  303. },
  304. endIcon: _buildEndIcon(),
  305. ),
  306. ),
  307. Obx(
  308. () => VListFormCell(
  309. label: "现住地址",
  310. content: controller.state.address,
  311. onTap: () async {
  312. final result = await VDialogInput(
  313. title: "现住地址",
  314. initialValue: controller.state.address,
  315. placeholder: "请填写现住地址",
  316. ).show();
  317. if (result != null) {
  318. controller.state.address = result;
  319. }
  320. },
  321. endIcon: _buildEndIcon(),
  322. ),
  323. ),
  324. Obx(
  325. () => VListFormCell(
  326. label: "建档单位",
  327. content: controller.state.createdOrgName,
  328. endIcon: _buildEndIcon(isEdit: false),
  329. onTap: () {},
  330. ),
  331. ),
  332. Obx(
  333. () => VListFormCell(
  334. label: "建档人",
  335. content: controller.state.createdDoctorName,
  336. endIcon: _buildEndIcon(isEdit: false),
  337. onTap: () {},
  338. ),
  339. ),
  340. Obx(
  341. () => VListFormCell(
  342. label: "建档时间",
  343. content: controller.state.createTime,
  344. endIcon: _buildEndIcon(isEdit: false),
  345. onTap: () {},
  346. ),
  347. ),
  348. ];
  349. }
  350. Widget _buildEndIcon({bool isEdit = true}) {
  351. return Container(
  352. margin: EdgeInsets.only(left: isEdit ? 15 : 35),
  353. child: isEdit ? Icon(Icons.edit_outlined) : SizedBox(),
  354. );
  355. }
  356. }