view.dart 11 KB

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