controller.dart 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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/defines.dart';
  6. import 'package:vitalapp/architecture/network_connectivity.dart';
  7. import 'package:vitalapp/architecture/utils/prompt_box.dart';
  8. import 'package:vitalapp/components/alert_dialog.dart';
  9. import 'package:vitalapp/global.dart';
  10. import 'package:vitalapp/managers/interfaces/device.dart';
  11. import 'package:vitalapp/managers/interfaces/models/device.dart';
  12. import 'package:vitalapp/managers/interfaces/models/patient_model_dto.dart';
  13. import 'package:vitalapp/managers/interfaces/patient.dart';
  14. import 'package:vitalapp/managers/interfaces/permission.dart';
  15. import 'package:vitalapp/pages/controllers/blue_location_mixin.dart';
  16. import 'package:vitalapp/pages/controllers/crowd_labels.dart';
  17. import 'package:vitalapp/pages/facial_recognition/index.dart';
  18. import 'package:vitalapp/pages/home/controller.dart';
  19. import 'package:fis_common/logger/logger.dart';
  20. import 'package:vitalapp/pages/id_card_scan/index.dart';
  21. import 'package:vitalapp/pages/patient/bluetooth_card_reader/index.dart';
  22. import 'package:vitalapp/pages/patient/card_reader/index.dart';
  23. import 'package:vitalapp/pages/patient/create/widgets/face_result_dialog.dart';
  24. import 'package:vitalapp/store/store.dart';
  25. import 'package:vnote_device_plugin/consts/types.dart';
  26. import 'state.dart';
  27. class PatientListController extends FControllerBase
  28. with BluetoothAndLocationMixin {
  29. final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
  30. final state = PatientListState();
  31. final _homeController = Get.find<HomeController>();
  32. final _patientManager = Get.find<IPatientManager>();
  33. final _deviceManager = Get.find<IDeviceManager>();
  34. final crowdLabelsController = CrowdLabelsController();
  35. void patientListGotoDetail(PatientDTO dto) async {
  36. await _patientManager.switchCurrentPatient(dto);
  37. _homeController.switchNavByName("/patient/detail");
  38. logger.i('list切换居民 当前居民是:${dto.patientName} 居民code:${dto.code}');
  39. }
  40. Future<DeviceModel?> getDevice(String type) async {
  41. List<DeviceModel> devices = await _deviceManager.getDeviceList();
  42. return devices.firstWhereOrNull((element) => element.type == type);
  43. }
  44. // TODO 人脸录入 点击人脸识别
  45. void onFaceIdLoginClicked() async {
  46. var verifyResult = await _verifyCameraPermissions();
  47. if (!verifyResult) {
  48. return;
  49. }
  50. final FaceRecognitionResult? result = await Get.to<FaceRecognitionResult>(
  51. () => const FacialRecognitionPage(
  52. mode: FacialRecognitionMode.faceRecognition,
  53. ),
  54. );
  55. if (result != null && result.success) {
  56. final patient = result.patientInfo;
  57. final hasConfirmed = await FaceResultDialog.show(patient, true);
  58. if (hasConfirmed) {
  59. await _checkinPatient(patient);
  60. }
  61. } else {
  62. print("识别取消");
  63. }
  64. }
  65. /// 切换当前登记居民
  66. Future<void> _checkinPatient(PatientBaseDTO patient) async {
  67. final patientDTO = PatientDTO(
  68. code: patient.cardNo,
  69. cardNo: patient.cardNo,
  70. patientName: patient.patientName,
  71. nationality: patient.nationality,
  72. patientGender: patient.patientGender,
  73. birthday: patient.birthday,
  74. patientAddress: patient.patientAddress,
  75. );
  76. await onIdcardInfoIsCreateRecord(patientDTO.code!);
  77. Get.find<HomeController>().switchNavByName("/patient/detail");
  78. }
  79. /// (读卡器读卡)若已建档则跳档案详情页面,若未建档则跳创建档案页面
  80. void onReadCardClickedToDetail() async {
  81. final DeviceModel? device = await getDevice(DeviceTypes.IC_READER);
  82. CardReaderResult? result;
  83. if (device != null) {
  84. final envPassed = await checkDeviceConnectEnv();
  85. if (envPassed) {
  86. result = await Get.dialog<CardReaderResult>(
  87. const BluetoothCardReaderDialog(),
  88. barrierDismissible: false,
  89. );
  90. }
  91. } else {
  92. result = await Get.dialog<CardReaderResult>(
  93. const CardReaderDialog(),
  94. barrierDismissible: false,
  95. );
  96. }
  97. if (result != null && result.success) {
  98. PromptBox.toast("读取成功");
  99. PatientBaseDTO patientInfo = PatientBaseDTO();
  100. patientInfo.cardNo = result.cardNo; // 回填身份证号
  101. patientInfo.patientName = result.name; // 回填姓名
  102. patientInfo.patientGender = result.gender; // 回填性别
  103. patientInfo.nationality = result.nation; // 回填民族
  104. patientInfo.birthday = result.birthday; // 回填出生日期
  105. patientInfo.patientAddress = result.address; // 回填户籍地址
  106. onIdcardInfoIsCreateRecord(patientInfo.cardNo!, patientInfo);
  107. } else {
  108. print("读卡取消");
  109. }
  110. }
  111. /// 手动录入 跳转新建档案页面
  112. void onManualInputPatient() {
  113. Get.find<HomeController>().switchNavByName(
  114. "/patient/create",
  115. );
  116. }
  117. /// 扫码和刷卡公用的方法,获取到的身份证信息
  118. Future<void> onIdcardInfoIsCreateRecord(
  119. String cardNo, [
  120. PatientBaseDTO? patientInfo,
  121. ]) async {
  122. PatientDTO? patientInfoDto = await _patientManager.getDetail(cardNo);
  123. if (patientInfoDto != null) {
  124. await _patientManager.switchCurrentPatient(patientInfoDto);
  125. logger.i(
  126. 'create居民 当前居民是:${patientInfoDto.patientName} 居民code:${patientInfoDto.code}');
  127. }
  128. switchOrCreatePatient(patientInfoDto, patientInfo);
  129. }
  130. /// (拍摄扫描身份证)若已建档则跳档案详情页面,若未建档则跳创建档案页面
  131. void onIdCardScanClickedToDetail() async {
  132. var verifyResult = await _verifyCameraPermissions();
  133. if (!verifyResult) {
  134. return;
  135. }
  136. final IdCardScanResult? result = await Get.to<IdCardScanResult>(
  137. () => const IdCardScanPage(),
  138. );
  139. if (result != null && result.success) {
  140. PromptBox.toast("身份证信息识别成功");
  141. PatientBaseDTO patientInfo = result.patientBaseDTO;
  142. onIdcardInfoIsCreateRecord(patientInfo.cardNo!, patientInfo);
  143. } else {
  144. print("识别取消");
  145. }
  146. }
  147. /// 切换居民还是新建居民
  148. Future<void> switchOrCreatePatient(
  149. PatientDTO? patientInfoDto, [
  150. PatientBaseDTO? patientInfo,
  151. ]) async {
  152. if (patientInfo != null) {
  153. if (patientInfoDto != null) {
  154. final hasConfirmed = await FaceResultDialog.show(patientInfo, true);
  155. if (!hasConfirmed) {
  156. return;
  157. }
  158. Get.find<HomeController>().switchNavByName("/patient/detail");
  159. } else {
  160. final hasConfirmed = await FaceResultDialog.show(patientInfo, false);
  161. if (!hasConfirmed) {
  162. return;
  163. }
  164. Get.find<HomeController>().switchNavByName(
  165. "/patient/create",
  166. patientInfo.toJson(),
  167. );
  168. }
  169. }
  170. }
  171. void changeFilterFounder(int value) {
  172. state.selectBoxFilterFounder = value;
  173. }
  174. Future<bool> _verifyCameraPermissions() async {
  175. IPermissionManager permissionManager = Get.find<IPermissionManager>();
  176. var isCameraPermissions =
  177. await permissionManager.requestCameraPermissions();
  178. if (!isCameraPermissions) {
  179. await Get.dialog(
  180. VAlertDialog(
  181. title: "提示",
  182. width: 420,
  183. content: Container(
  184. height: 32,
  185. padding: const EdgeInsets.symmetric(horizontal: 24),
  186. alignment: Alignment.center,
  187. child: const Text(
  188. "未授予相机权限,前去设置",
  189. style: TextStyle(fontSize: 20),
  190. ),
  191. ),
  192. showCancel: false,
  193. onConfirm: () async {
  194. Get.back();
  195. await permissionManager.openAppSettingsAsync();
  196. },
  197. ),
  198. barrierDismissible: false,
  199. barrierColor: Colors.black.withOpacity(.4),
  200. );
  201. }
  202. return isCameraPermissions;
  203. }
  204. @override
  205. void onReady() {
  206. netChecker.onlineChangedEvent.addListener(_onlineChanged);
  207. if (Store.user.roleName == "机构负责人") {
  208. state.selectBoxFilterFounder = 1;
  209. }
  210. reloadList();
  211. super.onReady();
  212. }
  213. void _onlineChanged(_, e) {
  214. state.isOnline = e;
  215. }
  216. /// 重新加载列表
  217. Future<void> reloadList({bool isFilter = false}) async {
  218. busy = true;
  219. state.pageIndex = 0;
  220. state.dataList = [];
  221. state.offlineCodes = [];
  222. if (kIsOnline) {
  223. if (!kIsWeb) {
  224. var offlineList = await _patientManager.getPagedOfflineList(
  225. state.searchString,
  226. state.startTime.value,
  227. state.endTime.value?.add(const Duration(days: 1)),
  228. );
  229. if (offlineList != null) {
  230. state.appendDataList(offlineList);
  231. state.offlineCodes = offlineList.map((e) => e.code!).toList();
  232. }
  233. }
  234. }
  235. await loadNextPageList(isFilter: isFilter);
  236. if (kIsOnline) {
  237. _loadStatistic();
  238. }
  239. }
  240. /// 加载下一页列表
  241. Future<void> loadNextPageList({bool isFilter = false}) async {
  242. busy = true;
  243. final request = PatientPageRequest(
  244. pageIndex: state.pageIndex + 1,
  245. pageSize: state.pageSize,
  246. keyword: state.searchString,
  247. startTime: state.startTime.value,
  248. endTime: state.endTime.value?.add(const Duration(days: 1)),
  249. crowdLabels: crowdLabelsController.state.selectedCodes,
  250. createdBySelf: state.selectBoxFilterFounder == 0,
  251. );
  252. final pagedList = await _patientManager.getPagedList(request);
  253. if (pagedList != null) {
  254. state.totalCount = pagedList.dataCount;
  255. if (pagedList.pageData != null) {
  256. state.pageIndex = state.pageIndex + 1;
  257. final arr = <PatientModelDTO>[];
  258. for (var element in pagedList.pageData!) {
  259. if (!state.offlineCodes.contains(element.code)) {
  260. var existData =
  261. state.dataList.firstWhereOrNull((e) => e.code == element.code);
  262. if (existData == null) {
  263. arr.add(element);
  264. }
  265. }
  266. }
  267. state.appendDataList(arr);
  268. }
  269. }
  270. busy = false;
  271. }
  272. Future<void> removePatient(String code) async {
  273. setBusy("正在删除...");
  274. final result = await _patientManager.removePatient(code);
  275. cancelBusy();
  276. if (result) {
  277. PromptBox.toast("删除成功");
  278. await Future.delayed(const Duration(milliseconds: 500));
  279. await reloadList();
  280. } else {
  281. PromptBox.toast("删除失败");
  282. }
  283. }
  284. Future<void> _loadStatistic() async {
  285. final result = await _patientManager.getStatistic(
  286. state.selectBoxFilterFounder == 0,
  287. );
  288. state.statisticTodayCount = result.todayCount;
  289. state.statisticTotalCount = result.count;
  290. }
  291. @override
  292. void onClose() {
  293. netChecker.onlineChangedEvent.removeListener(_onlineChanged);
  294. }
  295. }