Files
tuiche/lib/main.dart
2025-08-20 17:47:46 +08:00

690 lines
27 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<void> 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<void> 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<void> startMessagePolling(int ent_type) async {
Get.put(MhMessageController());
MhMessageController messageController = Get.find();
final Set<String> _poppedMessageIds = {}; // 本地已弹窗的消息 ID无论是否已读成功
final Set<String> _readMessageIds = {};
final controller = Get.find<MhMessageController>();
_messageTimer?.cancel();
if (ent_type == APPPackageType.MHT.code) {
if (Get.isRegistered<MhMessageController>()) {
Get.find<MhMessageController>().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<String, dynamic>;
final valList = data['val'] as List<dynamic>;
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<MessageController>()) {
Get.find<MessageController>().getMessageStatus();
}
}
_messageTimer = Timer.periodic(Duration(seconds: 10), (timer) async {
try {
if (ent_type == APPPackageType.MHT.code) {
if (Get.isRegistered<MhMessageController>()) {
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<String, dynamic>;
final valList = data['val'] as List<dynamic>;
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<MessageController>()) {
Get.find<MessageController>().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<void> 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<String, dynamic>? userMap = box.read('user');
if (userMap != null) {
UserModel user = UserModel.fromJson(userMap);
userInfoController.model.user = user;
}
} catch (e) {
print(e);
}
}
//处理绑定未完成的数据
Future<void> 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: '',
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);
}
});
}
}