import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:vitalapp/architecture/utils/prompt_box.dart'; import 'package:vitalapp/components/alert_dialog.dart'; import 'package:vitalapp/database/entities/defines.dart'; import 'package:vitalapp/database/entities/patient.dart'; import 'package:vitalapp/global.dart'; import 'package:vitalapp/managers/interfaces/data_sync.dart'; class _SyncUploadDialogController extends GetxController { final syscManager = Get.find(); /// 数据列表 final dataList = RxList(); /// 已上传数量 final uploadedCount = RxInt(0); /// 数据总量 int get totalCount => dataList.length; /// 当前处理索引 int get handleIndex => uploadedCount.value; /// 当前处理数据 PatientEntity? get handleData { if (dataList.isEmpty) { return null; } if (handleIndex == dataList.length) { return dataList.last; } return dataList[handleIndex]; } @override void onReady() { super.onReady(); _run(); } Future _run() async { final loaded = await _loadData(); // 无数据也要等待页面显示一会 await Future.delayed(const Duration(seconds: 1)); if (!loaded) { PromptBox.toast("未查询到待上传记录"); Get.back(result: false); return; } for (var i = 0; i < totalCount; i++) { if (!kIsOnline) { PromptBox.toast("请检查网络连接"); Get.back(result: false); return; } final success = await _handleSingle(); if (success) { } else { PromptBox.toast("上传 ${handleData?.name} 失败"); await Future.delayed(const Duration(milliseconds: 500)); } uploadedCount.value = uploadedCount.value + 1; // 等进度更新展示一下 await Future.delayed(const Duration(milliseconds: 500)); } if (uploadedCount > 0) { await Future.delayed(const Duration(milliseconds: 500)); PromptBox.toast("批量同步结束"); } Get.back(result: true); } Future _handleSingle() async { final data = dataList[handleIndex]; final result = await syscManager.syncPatientAllData(data.code); return result; } Future _loadData() async { final list = await syscManager.getPatientWaitUploadAllList(); if (list.isEmpty) { await Future.delayed(const Duration(milliseconds: 500)); PromptBox.toast("暂无离线数据需要同步"); Get.back(result: false); return false; } dataList.value = list; return true; } } class SyncUploadDialog extends GetView<_SyncUploadDialogController> { const SyncUploadDialog({super.key}); static Future show() async { final result = await Get.dialog( const SyncUploadDialog(), barrierDismissible: false, ); return result; } @override Widget build(BuildContext context) { return VAlertDialog( content: _buildBody(context), onCanceled: () { return false; }, ); } Widget _buildBody(BuildContext context) { return GetBuilder<_SyncUploadDialogController>( init: _SyncUploadDialogController(), builder: (context) { return Obx(() { // if (!controller.isRunning) { // return const SizedBox(); // } final data = controller.handleData; return Container( height: 280, alignment: Alignment.center, child: data != null ? _SyncProgress( uploadedCount: controller.uploadedCount.value, totalCount: controller.totalCount, patientName: data.name, ) : const SizedBox( width: 28, height: 28, child: CircularProgressIndicator(), ), ); }); }, ); } } class _SyncProgress extends StatelessWidget { static final textStyle = TextStyle(fontSize: 20, color: Colors.grey.shade700); static const textSpace = SizedBox(width: 12); final int uploadedCount; final int totalCount; final String patientName; const _SyncProgress({ required this.uploadedCount, required this.totalCount, required this.patientName, }); @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox( width: 28, height: 28, child: CircularProgressIndicator(), ), const SizedBox(height: 36), Row( mainAxisSize: MainAxisSize.min, children: [ Text( "正在上传", style: textStyle, ), textSpace, Text( patientName, style: const TextStyle(fontSize: 20, color: Colors.black), ), textSpace, Text( "的离线数据", style: textStyle, ), ], ), const SizedBox(height: 20), Row( mainAxisSize: MainAxisSize.min, children: [ Text( "已上传居民", style: TextStyle(fontSize: 18, color: Colors.grey.shade700), ), textSpace, Text( uploadedCount.toString(), style: const TextStyle( fontSize: 20, color: Colors.green, fontWeight: FontWeight.bold, ), ), Text(" /", style: textStyle), Text( "$totalCount", style: const TextStyle(fontSize: 20, color: Colors.black), ), textSpace, Text("人", style: textStyle), ], ), const SizedBox(height: 20), ], ); } }