diff --git a/ln_jq_app/ios/Podfile.lock b/ln_jq_app/ios/Podfile.lock index 27b161b..20c507a 100644 --- a/ln_jq_app/ios/Podfile.lock +++ b/ln_jq_app/ios/Podfile.lock @@ -12,6 +12,8 @@ PODS: - device_info_plus (0.0.1): - Flutter - Flutter (1.0.0) + - flutter_app_update (0.0.1): + - Flutter - flutter_inappwebview_ios (0.0.1): - Flutter - flutter_inappwebview_ios/Core (= 0.0.1) @@ -50,6 +52,7 @@ DEPENDENCIES: - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - Flutter (from `Flutter`) + - flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`) - flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`) - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_pdfview (from `.symlinks/plugins/flutter_pdfview/ios`) @@ -80,6 +83,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/device_info_plus/ios" Flutter: :path: Flutter + flutter_app_update: + :path: ".symlinks/plugins/flutter_app_update/ios" flutter_inappwebview_ios: :path: ".symlinks/plugins/flutter_inappwebview_ios/ios" flutter_native_splash: @@ -111,6 +116,7 @@ SPEC CHECKSUMS: connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896 Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9 flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf flutter_pdfview: 32bf27bda6fd85b9dd2c09628a824df5081246cf diff --git a/ln_jq_app/lib/pages/home/controller.dart b/ln_jq_app/lib/pages/home/controller.dart index 7c339cb..9588648 100644 --- a/ln_jq_app/lib/pages/home/controller.dart +++ b/ln_jq_app/lib/pages/home/controller.dart @@ -2,8 +2,11 @@ import 'dart:io'; import 'package:aliyun_push_flutter/aliyun_push_flutter.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_app_update/flutter_app_update.dart'; +import 'package:flutter_app_update/result_model.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:getx_scaffold/getx_scaffold.dart'; +import 'package:ln_jq_app/common/model/base_model.dart'; import 'package:ln_jq_app/common/styles/theme.dart'; import 'package:ln_jq_app/pages/b_page/base_widgets/view.dart'; import 'package:ln_jq_app/pages/c_page/base_widgets/view.dart'; @@ -20,107 +23,195 @@ class HomeController extends GetxController with BaseControllerMixin { final _aliyunPush = AliyunPushFlutter(); + @override + bool get listenLifecycleEvent => true; + @override void onInit() { super.onInit(); initAliyunPush(); addPushCallback(); FlutterNativeSplash.remove(); + log('page-init'); + + // 页面初始化后执行版本检查 + checkVersionInfo(); + } + + String downloadUrl = ""; + + /// 检查 App 更新信息,增加版本号比对逻辑 + void checkVersionInfo() async { + try { + final response = await HttpService.to.get('appointment/appConfig/get'); + if (response != null) { + final result = BaseModel.fromJson(response.data); + if (result.code == 0 && result.data != null) { + final data = result.data as Map; + + bool hasUpdate = data['hasUpdate']?.toString().toLowerCase() == "true"; + bool isForce = data['isForce']?.toString().toLowerCase() == "true"; + String versionName = data['versionName'] ?? "新版本"; + String updateContent = data['updateContent'] ?? "优化系统性能,提升用户体验"; + downloadUrl = data['downloadUrl'].toString(); + + // 获取服务器配置的目标构建号 + int serverVersionCode = + int.tryParse(data['versionCode']?.toString() ?? "0") ?? 0; + int serverIosBuildId = int.tryParse(data['iosBuildId']?.toString() ?? "0") ?? 0; + + // 获取本地当前的构建号 + String currentBuildStr = await getBuildNumber(); + int currentBuild = int.tryParse(currentBuildStr) ?? 0; + + bool needUpdate = false; + if (GetPlatform.isAndroid) { + needUpdate = currentBuild < serverVersionCode; + } else if (GetPlatform.isIOS) { + needUpdate = currentBuild < serverIosBuildId; + } + + // 如果服务器标记有更新,且本地版本号确实较低,则弹出更新 + if (hasUpdate && needUpdate) { + _showUpdateDialog("版本:$versionName\n\n更新内容:\n$updateContent", isForce); + } + } + } + } catch (e) { + Logger.d("版本检查失败: $e"); + } + } + + /// 显示更新弹窗 + void _showUpdateDialog(String content, bool isForce) { + DialogX.to.showConfirmDialog( + title: '升级提醒', + confirmText: '立即升级', + content: _buildDialogContent(content), + // 如果是强制更新,取消按钮显示为空,即隐藏 + cancelText: isForce ? "" : '以后再说', + // 设置为 false,禁止点击背景和物理返回键关闭 + barrierDismissible: false, + onConfirm: () { + jumpUpdateApp(); + + // ios如果是强制更新,点击后维持弹窗,防止用户进入 App + if (isForce && GetPlatform.isIOS) { + Future.delayed(const Duration(milliseconds: 500), () { + _showUpdateDialog(content, isForce); + }); + } + }, + ); + } + + Widget _buildDialogContent(String content) { + return PopScope( + canPop: false, // 关键:禁止 pop + child: TextX.bodyMedium(content).padding(bottom: 16.h), + ); + } + + void jumpUpdateApp() { + if (GetPlatform.isIOS) { + // 跳转到 iOS 应用商店网页 + openWebPage("https://apps.apple.com/cn/app/羚牛氢能/6756245815"); + } else if (GetPlatform.isAndroid) { + // Android 执行下载安装流程 + showAndroidDownloadDialog(); + } + } + + void showAndroidDownloadDialog() { + AzhonAppUpdate.listener((ResultModel model) { + if (model.type == ResultType.start) { + DialogX.to.showConfirmDialog( + content: PopScope( + canPop: false, + child: Center( + child: Column( + children: [ + TextX.bodyMedium('升级中...').padding(bottom: 45.h), + CircularProgressIndicator(), + ], + ), + ), + ), + confirmText: '', + cancelText: "", + barrierDismissible: false, + ); + } else if (model.type == ResultType.done) { + Get.back(); + } + }); + + UpdateModel model = UpdateModel(downloadUrl, "xll.apk", "logo", '正在下载最新版本...'); + AzhonAppUpdate.update(model); } // 根据登录状态和登录渠道返回不同的首页 Widget getHomePage() { requestPermission(); - //登录状态跳转 if (StorageService.to.isLoggedIn) { - // 如果已登录,再判断是哪个渠道 if (StorageService.to.loginChannel == LoginChannel.station) { - return B_BaseWidgetsPage(); // 站点首页 + return B_BaseWidgetsPage(); } else if (StorageService.to.loginChannel == LoginChannel.driver) { - return BaseWidgetsPage(); // 司机首页 + return BaseWidgetsPage(); } else { return LoginPage(); } } else { - // 未登录,直接去登录页 return LoginPage(); } } void requestPermission() async { PermissionStatus status = await Permission.notification.status; - if (status.isGranted) { - Logger.d("通知权限已开启"); - return; - } + if (status.isGranted) return; if (status.isDenied) { - // 建议此处增加一个应用内的 Rationale (解释说明) 弹窗 status = await Permission.notification.request(); } if (status.isGranted) { - // 授权成功 Logger.d('通知已开启'); } else if (status.isPermanentlyDenied) { Logger.d('通知权限已被拒绝,请到系统设置中开启'); - } else if (status.isDenied) { - Logger.d('请授予通知权限,以便接收加氢站通知'); } } - ///推送相关 + ///推送相关初始化 (保持原样) Future initAliyunPush() async { - // 1. 配置分离:建议将 Key 提取到外部或配置文件中 final String appKey = Platform.isIOS ? AppTheme.ios_key : AppTheme.android_key; final String appSecret = Platform.isIOS ? AppTheme.ios_appsecret : AppTheme.android_appsecret; try { - // 初始化推送 final result = await _aliyunPush.initPush(appKey: appKey, appSecret: appSecret); - - if (result['code'] != kAliyunPushSuccessCode) { - Logger.d('初始化推送失败: ${result['code']} - ${result['errorMsg']}'); - return; - } - - Logger.d('阿里云推送初始化成功'); - // 分平台配置 + if (result['code'] != kAliyunPushSuccessCode) return; if (Platform.isIOS) { await _setupIOSConfig(); } else if (Platform.isAndroid) { await _setupAndroidConfig(); } } catch (e) { - Logger.d('初始化过程中发生异常: $e'); + Logger.d('初始化异常: $e'); } } - /// iOS 专属配置 Future _setupIOSConfig() async { - final res = await _aliyunPush.showIOSNoticeWhenForeground(true); - if (res['code'] == kAliyunPushSuccessCode) { - Logger.d('iOS 前台通知展示已开启'); - } else { - Logger.d('iOS 前台通知开启失败: ${res['errorMsg']}'); - } + await _aliyunPush.showIOSNoticeWhenForeground(true); } - /// Android 专属配置 Future _setupAndroidConfig() async { await _aliyunPush.setNotificationInGroup(true); - final res = await _aliyunPush.createAndroidChannel( + await _aliyunPush.createAndroidChannel( "xll_push_android", '新消息通知', 4, '用于接收加氢站实时状态提醒', ); - if (res['code'] == kAliyunPushSuccessCode) { - Logger.d('Android 通知通道创建成功'); - } else { - Logger.d('Android 通道创建失败: ${res['code']} - ${res['errorMsg']}'); - } } void addPushCallback() { @@ -139,40 +230,23 @@ class HomeController extends GetxController with BaseControllerMixin { Future _onAndroidNotificationClickedWithNoAction( Map message, - ) async { - Logger.d('onAndroidNotificationClickedWithNoAction ====> $message'); - } + ) async {} - Future _onAndroidNotificationReceivedInApp(Map message) async { - Logger.d('onAndroidNotificationReceivedInApp ====> $message'); - } + Future _onAndroidNotificationReceivedInApp(Map message) async {} - Future _onMessage(Map message) async { - Logger.d('onMessage ====> $message'); - } + Future _onMessage(Map message) async {} - Future _onNotification(Map message) async { - Logger.d('onNotification ====> $message'); - } + Future _onNotification(Map message) async {} Future _onNotificationOpened(Map message) async { - Logger.d('onNotificationOpened ====> $message'); await Get.to(() => const MessagePage()); } - Future _onNotificationRemoved(Map message) async { - Logger.d('onNotificationRemoved ====> $message'); - } + Future _onNotificationRemoved(Map message) async {} - Future _onIOSChannelOpened(Map message) async { - Logger.d('onIOSChannelOpened ====> $message'); - } + Future _onIOSChannelOpened(Map message) async {} - Future _onIOSRegisterDeviceTokenSuccess(Map message) async { - Logger.d('onIOSRegisterDeviceTokenSuccess ====> $message'); - } + Future _onIOSRegisterDeviceTokenSuccess(Map message) async {} - Future _onIOSRegisterDeviceTokenFailed(Map message) async { - Logger.d('onIOSRegisterDeviceTokenFailed====> $message'); - } + Future _onIOSRegisterDeviceTokenFailed(Map message) async {} } diff --git a/ln_jq_app/lib/pages/home/view.dart b/ln_jq_app/lib/pages/home/view.dart index de19787..1edfc6b 100644 --- a/ln_jq_app/lib/pages/home/view.dart +++ b/ln_jq_app/lib/pages/home/view.dart @@ -5,18 +5,13 @@ import 'package:ln_jq_app/pages/home/controller.dart'; class HomePage extends GetView { const HomePage({super.key}); - // 主视图 - Widget _buildView() { - return [Text('主页面')].toColumn(mainAxisSize: MainAxisSize.min).center(); - } - @override Widget build(BuildContext context) { return GetBuilder( init: HomeController(), id: 'home', builder: (_) { - return controller.getHomePage(); + return Scaffold(body: controller.getHomePage()); }, ); } diff --git a/ln_jq_app/lib/pages/login/view.dart b/ln_jq_app/lib/pages/login/view.dart index f2865b8..ce47516 100644 --- a/ln_jq_app/lib/pages/login/view.dart +++ b/ln_jq_app/lib/pages/login/view.dart @@ -204,9 +204,9 @@ class _LoginPageState extends State with SingleTickerProviderStateMix Row( children: [ const Text( - "欢迎使用 ", + "欢迎使用小羚羚 ", style: TextStyle( - fontSize: 24, + fontSize: 22, fontWeight: FontWeight.w500, color: Color.fromRGBO(51, 51, 51, 1), ), diff --git a/ln_jq_app/pubspec.lock b/ln_jq_app/pubspec.lock index d680450..feaf345 100644 --- a/ln_jq_app/pubspec.lock +++ b/ln_jq_app/pubspec.lock @@ -302,6 +302,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_app_update: + dependency: "direct main" + description: + name: flutter_app_update + sha256: "09290240949c4651581cd6fc535e52d019e189e694d6019c56b5a56c2e69ba65" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.2.2" flutter_easyloading: dependency: transitive description: diff --git a/ln_jq_app/pubspec.yaml b/ln_jq_app/pubspec.yaml index 2416bf3..00dd76d 100644 --- a/ln_jq_app/pubspec.yaml +++ b/ln_jq_app/pubspec.yaml @@ -52,7 +52,7 @@ dependencies: geolocator: ^14.0.2 # 获取精确定位 aliyun_push_flutter: ^1.3.6 pull_to_refresh: ^2.0.0 - + flutter_app_update: ^3.2.2 dev_dependencies: