import 'dart:async'; import 'dart:convert'; import 'package:EasyDartModule/EasyDartModule.dart'; import 'package:EasyDartModule/base/logger/Logger.dart'; import 'package:EasyDartModule/base/websocket/WebSocket.dart'; import 'package:easyweb/utils/appmanger.dart'; import 'package:ef/ef.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:fluwx/fluwx.dart'; import 'package:get_storage/get_storage.dart'; import 'package:localstorage/localstorage.dart'; import 'package:syncfusion_localizations/syncfusion_localizations.dart'; import 'package:vbvs_app/common/color/ServiceConstant.dart'; import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/color/app_uri_status.dart'; import 'package:vbvs_app/common/util/CheckNetwork.dart'; import 'package:vbvs_app/common/util/CommonVariables.dart'; import 'package:vbvs_app/common/util/Dio.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/requestWithLog.dart'; import 'package:vbvs_app/controller/date/CalendarController.dart'; import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart'; import 'package:vbvs_app/controller/device/body_device_controller.dart'; import 'package:vbvs_app/controller/device/device_calibration_controller.dart'; import 'package:vbvs_app/controller/device/device_share_controller.dart'; import 'package:vbvs_app/controller/device/device_share_list_controller.dart'; import 'package:vbvs_app/controller/device/device_type_controller.dart'; import 'package:vbvs_app/controller/home/home_controller.dart'; import 'package:vbvs_app/controller/login/login_controller.dart'; import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; import 'package:vbvs_app/controller/main_bottom/main_page_controller.dart'; import 'package:vbvs_app/controller/message/common_message_setting_controller.dart'; import 'package:vbvs_app/controller/message/message_controller.dart'; import 'package:vbvs_app/controller/message/message_review_controller.dart'; import 'package:vbvs_app/controller/message/message_setting_controller.dart'; import 'package:vbvs_app/controller/mh_controller/address_controller.dart'; import 'package:vbvs_app/controller/mh_controller/address_list_controller.dart'; import 'package:vbvs_app/controller/mh_controller/bedController.dart'; import 'package:vbvs_app/controller/mh_controller/book_info_controller.dart'; import 'package:vbvs_app/controller/mh_controller/device_list_controller.dart'; import 'package:vbvs_app/controller/mh_controller/experience_store_list_page.dart'; import 'package:vbvs_app/controller/mh_controller/find_password_controller.dart'; import 'package:vbvs_app/controller/mh_controller/issue_controller.dart'; import 'package:vbvs_app/controller/mh_controller/issue_preview_controller.dart'; import 'package:vbvs_app/controller/mh_controller/message_controller.dart'; import 'package:vbvs_app/controller/mh_controller/mh_language_controller.dart'; import 'package:vbvs_app/controller/mh_controller/mhdevice_share_controller.dart'; import 'package:vbvs_app/controller/mh_controller/my_experience_list_controller.dart'; import 'package:vbvs_app/controller/mh_controller/people_info_controller.dart'; import 'package:vbvs_app/controller/mh_controller/register_controller.dart'; import 'package:vbvs_app/controller/mh_controller/repair_info_controller.dart'; import 'package:vbvs_app/controller/mh_controller/repair_list_controller.dart'; import 'package:vbvs_app/controller/mh_controller/score_controller.dart'; import 'package:vbvs_app/controller/mh_controller/sleeping_habit_controller.dart'; import 'package:vbvs_app/controller/person/person_controller.dart'; import 'package:vbvs_app/controller/repair/repair_controller.dart'; import 'package:vbvs_app/controller/setting/language/language_controller.dart'; import 'package:vbvs_app/controller/setting/pdf/PrivacyPdfController.dart'; import 'package:vbvs_app/controller/setting/pdf/UserPdfController.dart'; import 'package:vbvs_app/controller/sleep/sleep_report_controller.dart'; import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; import 'package:vbvs_app/controller/time/countdown_controller.dart'; import 'package:vbvs_app/controller/weather/weather_controller.dart'; import 'package:vbvs_app/enum/APPPackageType.dart'; import 'package:vbvs_app/language/AppLanguage.dart'; import 'package:vbvs_app/model/CustomThemeColor.dart'; import 'package:vbvs_app/model/api_response.dart'; import 'package:vbvs_app/model/user_data.dart'; import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart'; import 'package:vbvs_app/pages/mh_page/MattressControl.dart'; import 'package:vbvs_app/pages/mh_page/device/component/mht_device_calibration_controller.dart'; import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart'; import 'package:vbvs_app/pages/mh_page/homepage/controller/mht_home_controller.dart'; import 'package:vbvs_app/pages/mh_page/test/WebviewTestModel.dart'; import 'package:vbvs_app/pages/mh_page/user/controller/bind_tel_controller.dart'; import 'package:vbvs_app/pages/mh_page/user/controller/mht_login_controller.dart'; import 'package:vbvs_app/pages/mh_page/user/controller/mht_register_controller.dart'; import 'package:vbvs_app/pages/mh_page/user/controller/update_password_controller.dart'; import 'package:vbvs_app/routers/mh_routers.dart'; import 'controller/mh_controller/apply_repair_controller.dart'; import 'controller/user_info_controller.dart'; import 'routers/routers.dart'; Future main() async { final ThemeController themeController = Get.put(ThemeController()); WidgetsFlutterBinding.ensureInitialized(); final Locale? deviceLocale = Get.deviceLocale; print('系统语言: ${deviceLocale?.languageCode}'); await loadLanguageSetting(deviceLocale?.languageCode); await initLanguageSetting(); WidgetsFlutterBinding.ensureInitialized(); ApiService.init(); await GetStorage.init(); // 初始化登录 await initLocalStorage(); initEasyDartModule(); await initLogin(); await messageStatus(); startMessagePolling(AppConstants().ent_type); // 检查网络 Checknetwork.checkNetwork(); // 微信开放平台注册 initWX(); // // 初始化 flutter_xupdate android app 更新 // initXUpdate(); initwebService(); WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then((_) { runApp(MyApp()); }); } // languageCode 系统默认语言码 en/zh loadLanguageSetting(String? languageCode) async { int code = AppConstants().ent_type; String? language; if (APPPackageType.MHT.code == code) { await ef.kvdb.openDir("mht"); language = await ef.kvdb.read("mht/language"); } else if (APPPackageType.TH.code == code) { await ef.kvdb.openDir("th"); language = await ef.kvdb.read("th/language"); } else { await ef.kvdb.openDir("th"); language = await ef.kvdb.read("th/language"); } // 如果 kvdb 没有存储 if (language == null || language.isEmpty) { if (languageCode == null || languageCode.isEmpty) { language = 'en_US'; // 系统默认为空时用 en_US } else { language = (languageCode.toLowerCase() == 'zh') ? 'zh_CN' : 'en_US'; } } await AppLanguage().loadLanguage( language, project: (APPPackageType.MHT.code == code) ? APPPackageType.MHT.code : APPPackageType.TH.code, ); } void initwebService() { ef.kvRoot.appmanger = MiniAppManager(assetsfilePath: 'assets/file.json'); ef.kvRoot.appmanger.register(["mhtControl"]); ef.kvRoot.appmanger.init().then((x) { //先加载,后检测更新.. ef.kvRoot.appmanger.start("https://wyf.it.real.he-info.cn:94/apk/webapp/"); }); } initLanguageSetting() async { try { Get.put(MHLanguageController()); Get.put(LanguageController()); int code = AppConstants().ent_type; if (APPPackageType.MHT.code == code) { Get.put(MHTHomeController()); MHLanguageController mhLanguageController = Get.find(); await mhLanguageController.initLanuageList(); } else { LanguageController languageController = Get.find(); await languageController.initLanuageList(); } } catch (e) { print(e); } } // 初始化微信开放平台注册 Future initWX() async { Fluwx fluwx = Fluwx(); fluwx.registerApi( //请填写自己的微信appid appId: "wxeb2688220799e2c5", //太和 // appId: "wx929c548fea6af9c7", //眠花糖 doOnAndroid: true, doOnIOS: true, universalLink: "https://app.he-info.com/theh/", // universalLink: "https://zhmht.swes.com.cn/app/", ); } Timer? _messageTimer; // void startMessagePolling() { // // 避免重复启动 // _messageTimer?.cancel(); // _messageTimer = Timer.periodic(Duration(seconds: 10), (timer) async { // try { // MessageController messageController = Get.find(); // messageController.getMessageStatus(); // // print("轮询消息状态成功"); // } catch (e) { // print("轮询消息状态失败: $e"); // } // }); // } Future startMessagePolling(int ent_type) async { Get.put(MhMessageController()); MhMessageController messageController = Get.find(); final Set _poppedMessageIds = {}; // 本地已弹窗的消息 ID(无论是否已读成功) final Set _readMessageIds = {}; final controller = Get.find(); _messageTimer?.cancel(); if (ent_type == APPPackageType.MHT.code) { if (Get.isRegistered()) { Get.find().getMessageStatus(); await controller.getMessageStatus(); if (controller.model.system_message_read == 1) { await controller.getMessageList("app_system"); final unhandledShareMessages = controller.systemMessageList.where((item) { final data = item['data']; final id = item['_id']?.toString(); return data is Map && (data['type'] == 'share' || data['type'] == 'unShare') && id != null && !_poppedMessageIds.contains(id) && (item['read_time'] == null); }).toList(); if (unhandledShareMessages.isNotEmpty) { for (final message in unhandledShareMessages) { final messageId = message['_id']?.toString(); if (messageId == null || _poppedMessageIds.contains(messageId)) continue; // 新增:如果当前页面是消息页,则跳过弹窗 if (Get.currentRoute == '/messagePage') { continue; } final data = message['data'] as Map; final valList = data['val'] as List; final messageType = data['type']; // Extract device ID final deviceIdEntry = valList.firstWhere( (item) => item['k'] == '设备ID', orElse: () => null, ); final mac = deviceIdEntry?['v'] as String?; _poppedMessageIds.add(messageId); try { await controller.updateMessageReadStatus( Get.context!, message['type'], mid: messageId); } catch (e) { print("标记消息 $messageId 为已读失败: $e"); } String dialogTitle; String msg; if (messageType == 'share') { dialogTitle = '设备分享提醒'.tr; // "Device Sharing Notification" final result = await showMessageConfirmDialog(title: dialogTitle); if (result == 'confirm') { Get.toNamed('/messageDetail', arguments: message); } } else { dialogTitle = '设备解绑提醒'.tr; showUnShareMessageDialog(title: dialogTitle, mac: mac!); } } try { MHTHomeController homeController = Get.find(); //更新设备列表 homeController.getPersonList(); //请求绑定设备列表 // homeController.getSleepReport(); homeController.getDeviceNum(); homeController.getDeviceList(group: 'room').then((apiResponse) { if (apiResponse.code != HttpStatusCodes.ok) { try { WebviewTestController webviewTestController = Get.find(); webviewTestController.web.jsbridge?.dart.alterDevice(); } catch (e) { ef.log("[h5]通知列表更新报错:$e"); } } }); WidgetsBinding.instance.addPostFrameCallback((_) { if (homeController.homeSleepDays.value.isNotEmpty) { homeController.selectedDayIndex.value = homeController.homeSleepDays.value.length - 1; } }); await homeController.getPersonList(); } catch (e) { ef.log("更新失败:$e"); } } } } } else { if (Get.isRegistered()) { Get.find().getMessageStatus(); } } _messageTimer = Timer.periodic(Duration(seconds: 10), (timer) async { try { if (ent_type == APPPackageType.MHT.code) { if (Get.isRegistered()) { await controller.getMessageStatus(); if (controller.model.system_message_read == 1) { await controller.getMessageList("app_system"); final unhandledShareMessages = controller.systemMessageList.where((item) { final data = item['data']; final id = item['_id']?.toString(); return data is Map && (data['type'] == 'share' || data['type'] == 'unShare') && id != null && !_poppedMessageIds.contains(id) && (item['read_time'] == null); }).toList(); if (unhandledShareMessages.isNotEmpty) { for (final message in unhandledShareMessages) { final messageId = message['_id']?.toString(); if (messageId == null || _poppedMessageIds.contains(messageId)) continue; // 新增:如果当前页面是消息页,则跳过弹窗 if (Get.currentRoute == '/messagePage') { continue; } final data = message['data'] as Map; final valList = data['val'] as List; final messageType = data['type']; // Extract device ID final deviceIdEntry = valList.firstWhere( (item) => item['k'] == '设备ID', orElse: () => null, ); final mac = deviceIdEntry?['v'] as String?; _poppedMessageIds.add(messageId); try { await controller.updateMessageReadStatus( Get.context!, message['type'], mid: messageId); } catch (e) { print("标记消息 $messageId 为已读失败: $e"); } String dialogTitle; String msg; if (messageType == 'share') { dialogTitle = '设备分享提醒'.tr; // "Device Sharing Notification" final result = await showMessageConfirmDialog(title: dialogTitle); if (result == 'confirm') { Get.toNamed('/messageDetail', arguments: message); } } else { dialogTitle = '设备解绑提醒'.tr; showUnShareMessageDialog(title: dialogTitle, mac: mac!); } } } } } } else { if (Get.isRegistered()) { Get.find().getMessageStatus(); } } } catch (e) { print("轮询消息状态失败: $e"); } }); } messageStatus() async { Get.put(MessageController()); MessageController messageController = Get.find(); await messageController.getMessageStatus(); } void initEasyDartModule() { try { EasyDartModule.init( loggerConfig: LoggerConfig(host: ServiceConstant.logService, serviceName: "web"), webSocketConfig: WebSocketConfig(ServiceConstant.webSocketService, (data) { // 接收到服务消息 var json = jsonDecode(data); ef.log("[websokcet]:${json}"); if (json['wsId'] != null) { ef.kvRoot.websocketId = json['wsId']; } if (json['code'] != null && json['code'] != 200) { EasyDartModule.logger.error("websocket连接失败--》" + json); } if (json["path"] != null) { var call = CommonVariables.callMap[json["path"]]; if (call != null) { try { if (json['path'] != "/smartbed/connect") { call(json["data"]); } else { call(json); } } catch (e) { print(e); } } else { print("未找到当前路径: ${json["path"]} 回调函数"); } } // print(data); }, onOpen: () { // 连接建立完毕 // EasyDartModule.websocket // .sendData(jsonEncode({"path": "/aa/bb", "type": 1})); print("object"); })); } catch (e) { print(e); } //初始化 } Future initLogin() async { // 初始化控制器 Get.put(UserInfoController()); // Get.put(SettingController()); // 获取设备信息,需要用户点击确认隐私协议与用户协议选择框时才能获取 // Deviceconfig.initPlatformState(); // 获取app版本号 // SettingController settingController = Get.find(); // settingController.model.appVersion = await Deviceconfig.getAppVersion(); final box = GetStorage(); UserInfoController userInfoController = Get.find(); String? token = box.read('token'); if (token != null) { // 根据token去请求 // await userInfoController.autoLogin(token); EasyDartModule.dio.token = token; ApiResponse apiResponse = await userInfoController.getUserInfo(); if (apiResponse.code != 1) { userInfoController.model.login = 0; EasyDartModule.dio.token = null; } else { userInfoController.model.login = 1; } } else { // 如果没有 token,则将用户标记为未登录 userInfoController.model.login = 0; } try { Map? userMap = box.read('user'); if (userMap != null) { UserModel user = UserModel.fromJson(userMap); userInfoController.model.user = user; } } catch (e) { print(e); } } //处理绑定未完成的数据 Future dealBindProcess() async { UserInfoController userInfoController = Get.find(); String serviceAddress = ServiceConstant.service_address; String serviceName = ServiceConstant.server_service; String serviceApi = ServiceConstant.device_list; String queryUrl = "${serviceAddress}${serviceName}${serviceApi}?bindType=1"; userInfoController.device_bind_status = []; try { final res = await requestWithLog( logTitle: "查询设备绑定列表", method: MyHttpMethod.get, queryUrl: queryUrl, ); List data = res.data ?? []; if (data.isNotEmpty) { // 使用 Future.wait 等待所有设备的查询完成 await Future.wait( data.map((element) async { String mac = element['mac']; String type = "device_bind_status_$mac"; String queryUrl = "${serviceAddress}${serviceName}${ServiceConstant.user_setting}?type=${type}"; try { final res = await requestWithLog( logTitle: "查询绑定流程", method: MyHttpMethod.get, queryUrl: queryUrl, ); if (res.data != null && res.data.isNotEmpty) { bool celibration = res.data['celibration']; bool person_info = res.data['person_info']; bool wifi = res.data['wifi']; if (!celibration || !person_info || !wifi) { res.data['device_info'] = element; userInfoController.device_bind_status.add(res.data); } } } catch (e) { print("查询绑定流程失败: $e"); } }), ); } } catch (e) { print("查询设备绑定列表失败: $e"); } } class MyApp extends StatelessWidget { MyApp({super.key}); Widget buildmht(BuildContext context, BoxConstraints cons) { return GetMaterialApp( translations: AppLanguage(), debugShowCheckedModeBanner: false, title: '智慧眠花糖', theme: themeController.currentTheme, localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], locale: AppLanguage().currentLocale, // ✅ 动态读取当前语言 fallbackLocale: const Locale("zh", "CN"), supportedLocales: [ Locale('en', 'US'), Locale('zh', 'CN'), ], initialRoute: "/mianPageBottomChange", onGenerateRoute: mhonGenerateRoute, initialBinding: BindingsBuilder(() => [ // Get.lazyPut(() => UserInfoController()), Get.put(GlobalController()), Get.put(WeatherModelController()), Get.lazyPut(() => ControlCardController()), Get.lazyPut(() => RepairListController()), Get.lazyPut(() => RepairInfoController()), Get.lazyPut(() => UserInfoController()), Get.lazyPut(() => MhMessageController()), Get.lazyPut(() => ScoreController()), Get.lazyPut(() => ExperienceStoreListController()), Get.lazyPut(() => BookExperienceListController()), Get.lazyPut(() => IssuePreviewInfoController()), Get.lazyPut(() => IssueListController()), Get.lazyPut(() => ApplyRepairController()), Get.lazyPut(() => RegisterController()), Get.lazyPut(() => FindPasswordController()), Get.lazyPut(() => SleepingHabitController()), Get.lazyPut(() => PeopleInfoController()), Get.lazyPut(() => MainPageController()), Get.lazyPut(() => AddressListController()), Get.lazyPut(() => AddressController()), // Get.lazyPut(() => MHLanguageController()), Get.lazyPut(() => BlueteethBindController()), Get.lazyPut(() => BookInfoController()), Get.lazyPut(() => PersonController()), Get.lazyPut(() => CountdownController()), Get.lazyPut(() => LoginController()), Get.lazyPut(() => DeviceTypeController()), Get.lazyPut(() => BodyDeviceController()), Get.lazyPut(() => HomeController()), Get.lazyPut(() => MHDeviceShareController()), Get.lazyPut(() => DeviceShareController()), Get.lazyPut(() => DeviceShareListController()), Get.lazyPut(() => DeviceCalibrationController()), Get.lazyPut(() => RepairController()), Get.lazyPut(() => MHTLoginController()), Get.lazyPut(() => MHTRegisterController()), Get.lazyPut(() => WeatherModelController()), Get.lazyPut(() => RegisterController()), Get.lazyPut(() => SleepingHabitController()), Get.lazyPut(() => BedController()), Get.lazyPut(() => UpdatePasswordController()), Get.lazyPut(() => IssueListController()), Get.lazyPut(() => DeviceListController()), Get.lazyPut(() => MHTBlueToothController()), Get.lazyPut(() => MHTDeviceCalibrationController()), Get.lazyPut(() => SleepReportController()), Get.lazyPut(() => CalendarController()), Get.lazyPut(() => UserPdfController()), Get.lazyPut(() => PrivacyPdfController()), Get.lazyPut(() => AuthBindTelController()), ])); } Widget buildth(BuildContext context, BoxConstraints cons) { return GetMaterialApp( translations: AppLanguage(), // locale: const Locale("zh", "CN"), locale: AppLanguage().currentLocale, // ✅ 动态读取当前语言 fallbackLocale: const Locale("zh", "CN"), localizationsDelegates: [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, SfGlobalLocalizations.delegate, ], supportedLocales: [ const Locale('zh', 'CN'), // 中文 const Locale('en', 'US'), // ⚠️ 添加你支持的语言 ], debugShowCheckedModeBanner: false, title: '太和e护', theme: themeController.currentTheme, // home: const MyHomePage(title: '智慧眠花糖 Home Page'), initialRoute: "/mianPageBottomChange", onGenerateRoute: onGenerateRoute, initialBinding: BindingsBuilder(() => [ // Get.lazyPut(() => UserInfoController()), Get.put(GlobalController()), Get.put(WeatherModelController()), Get.lazyPut(() => ApplyRepairController()), Get.lazyPut(() => MainPageController()), Get.lazyPut(() => BlueteethBindController()), Get.lazyPut(() => PersonController()), Get.lazyPut(() => CountdownController()), Get.lazyPut(() => LoginController()), Get.lazyPut(() => DeviceTypeController()), Get.lazyPut(() => BodyDeviceController()), Get.lazyPut(() => HomeController()), Get.lazyPut(() => DeviceShareController()), Get.lazyPut(() => DeviceShareListController()), Get.lazyPut(() => DeviceCalibrationController()), Get.lazyPut(() => RepairController()), Get.lazyPut(() => UserPdfController()), Get.lazyPut(() => PrivacyPdfController()), Get.lazyPut(() => CalendarController()), Get.lazyPut(() => SleepReportController()), Get.lazyPut(() => MessageReviewController()), Get.lazyPut(() => MessageSettingController()), Get.lazyPut(() => CommonMessageSettingController()), Get.lazyPut(() => AuthBindTelController()), ])); } int selectapp = AppConstants().ent_type; @override Widget build(BuildContext context) { var co = MediaQuery.sizeOf(context); FitTool.init(co.height); themeController.changeTheme(CustomThemeColor.dark); return LayoutBuilder(builder: (contxt, cons) { switch (selectapp) { case 1: return buildth(context, cons); case 3: return buildmht(contxt, cons); default: return buildth(context, cons); } }); } }