From df9548289c217e5733a9fa69b2d54c3e9c8bb6fe Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Mon, 4 Aug 2025 20:20:29 +0800 Subject: [PATCH] =?UTF-8?q?refactor(version=5Fupdate):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E7=89=88=E6=9C=AC=E6=9B=B4=E6=96=B0=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=B9=B6=E6=B7=BB=E5=8A=A0=E5=86=85=E5=AD=98=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将版本更新服务重构为使用静态变量缓存应用信息,减少重复获取 添加 UserChannel.fromName 方法支持从字符串创建枚举 移除重复的 UserChannel 定义并统一使用 channel_app_model 优化游客登录状态检查逻辑,直接使用缓存值 --- lib/data/models/channel_app_model.dart | 24 +++ lib/data/services/version_update_service.dart | 178 +++++++++--------- .../login/controllers/login_controller.dart | 62 +++--- lib/modules/settings/views/settings_view.dart | 7 - 4 files changed, 135 insertions(+), 136 deletions(-) diff --git a/lib/data/models/channel_app_model.dart b/lib/data/models/channel_app_model.dart index 7fc3dcabf..dac792f28 100644 --- a/lib/data/models/channel_app_model.dart +++ b/lib/data/models/channel_app_model.dart @@ -177,6 +177,30 @@ enum UserChannel { ); } + // 从字符串名称创建枚举 + static UserChannel fromName(String name) { + switch (name.toUpperCase()) { + case 'CHINA_HUAWEI': + return UserChannel.CHINA_HUAWEI; + case 'CHINA_XIAOMI': + return UserChannel.CHINA_XIAOMI; + case 'CHINA_OPPO': + return UserChannel.CHINA_OPPO; + case 'CHINA_VIVO': + return UserChannel.CHINA_VIVO; + case 'CHINA_HONOR': + return UserChannel.CHINA_HONOR; + case 'OFFICIAL': + return UserChannel.OFFICIAL; + case 'GLOBAL_APPLE': + return UserChannel.GLOBAL_APPLE; + case 'GLOBAL_GOOGLE': + return UserChannel.GLOBAL_GOOGLE; + default: + return UserChannel.UNKNOWN; + } + } + // JSON 序列化时返回数字值 int toJson() => value; diff --git a/lib/data/services/version_update_service.dart b/lib/data/services/version_update_service.dart index f624ae7aa..4c408e107 100644 --- a/lib/data/services/version_update_service.dart +++ b/lib/data/services/version_update_service.dart @@ -5,6 +5,7 @@ import 'package:package_info_plus/package_info_plus.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:logger/logger.dart'; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import '../models/channel_app_model.dart'; import 'network/api.dart'; import 'dart:math' as math; @@ -13,15 +14,62 @@ import 'dart:math' as math; class VersionUpdateService extends GetxService { static VersionUpdateService get to => Get.find(); - final Logger _logger = Logger(); + // 静态应用信息(内存缓存) + static String? _appVersion = ""; //应用版本号 + static String? _buildNumber = ""; //构建号 + static String? _platform = ""; //平台类型 + static String? _deviceBrand = ""; //设备品牌 + static UserChannel? _channel; //渠道 + static String? _latestVersion = ""; //最新版本号+构建号 + static bool? _hasUpdate = false; //是否有更新 + static bool? _isForceUpdate = false; //是否强制更新 + static String? _updateUrl = ""; //更新链接 + static bool? _isShowTourists = false; //是否显示游客登录 + static DateTime? _lastCheckTime; //上次检查时间 + static const int _cacheIntervalMinutes = 10; // 可配置化 + + // 添加 getter 方法来访问缓存的静态数据 + /// 获取缓存的应用版本 + String get cachedAppVersion => _appVersion ?? ''; + + /// 获取缓存的构建号 + String get cachedBuildNumber => _buildNumber ?? ''; + + /// 获取缓存的平台信息 + String get cachedPlatform => _platform ?? ''; + + /// 获取缓存的设备品牌 + String get cachedDeviceBrand => _deviceBrand ?? ''; + + /// 获取缓存的渠道信息 + UserChannel get cachedChannel => _channel ?? UserChannel.UNKNOWN; + + /// 获取缓存的最新版本 + String get cachedLatestVersion => _latestVersion ?? ''; + + /// 获取缓存的是否有更新 + bool get cachedHasUpdate => _hasUpdate ?? false; + + /// 获取缓存的是否强制更新 + bool get cachedIsForceUpdate => _isForceUpdate ?? false; + + /// 获取缓存的更新地址 + String get cachedUpdateUrl => _updateUrl ?? ''; + + /// 获取缓存的游客登录状态 + bool get cachedShowTourists => _isShowTourists ?? false; - // 游客登录显示状态 - final isShowTourists = false.obs; + /// 获取上次检查时间 + DateTime? get lastCheckTime => _lastCheckTime; + + final Logger _logger = Logger(); /// 获取当前应用版本信息 Future getCurrentVersion() async { try { final packageInfo = await PackageInfo.fromPlatform(); + _appVersion = packageInfo.version; + _buildNumber = packageInfo.buildNumber; return '${packageInfo.version}+${packageInfo.buildNumber}'; } catch (e) { _logger.e('获取当前版本信息失败: $e'); @@ -31,14 +79,6 @@ class VersionUpdateService extends GetxService { /// 获取当前平台信息 Future getCurrentPlatformInfo() async { - if (kIsWeb) { - return const PlatformInfo( - platform: 'web', - storeType: AppStoreType.official, - channel: UserChannel.OFFICIAL, - ); - } - if (Platform.isIOS) { return const PlatformInfo( platform: 'ios', @@ -66,10 +106,14 @@ class VersionUpdateService extends GetxService { final androidInfo = await deviceInfo.androidInfo; final brand = androidInfo.brand.toLowerCase(); - return const PlatformInfo( + _deviceBrand = brand; + String channelFromEnv = dotenv.env['Channel'] ?? 'OFFICIAL'; + _channel = UserChannel.fromName(channelFromEnv); + + return PlatformInfo( platform: 'android', storeType: AppStoreType.official, - channel: UserChannel.OFFICIAL, + channel: _channel ?? UserChannel.OFFICIAL, ); // switch (brand) { @@ -121,10 +165,27 @@ class VersionUpdateService extends GetxService { /// 检查版本更新 Future checkForUpdate() async { + if (_lastCheckTime != null && + DateTime.now().difference(_lastCheckTime!).inMinutes < + _cacheIntervalMinutes) { + return VersionUpdateInfo( + hasUpdate: _hasUpdate ?? false, + currentVersion: _appVersion ?? '1.0.0', + latestVersion: (_latestVersion ?? '1.0.0').split('+')[0], + updateType: _hasUpdate! + ? (_isForceUpdate! ? UpdateType.force : UpdateType.optional) + : UpdateType.none, + ); + } + try { final currentVersion = await getCurrentVersion(); final platformInfo = await getCurrentPlatformInfo(); + _platform = platformInfo.platform; + _channel = platformInfo.channel; + _lastCheckTime = DateTime.now(); + // 调用后端接口获取最新版本信息 final response = await Api.getChannelApp({'channel': platformInfo.channel.value}); @@ -144,9 +205,11 @@ class VersionUpdateService extends GetxService { // 直接从response中获取app信息 final appInfo = AppInfo.fromJson(response['app']); _logger.d('获取到的最新版本信息: ${appInfo.toJson()}'); + _latestVersion = appInfo.version; + _updateUrl = appInfo.address; // 设置游客登录显示状态 - isShowTourists.value = appInfo.tourists; + _isShowTourists = appInfo.tourists; _logger.d('从服务器获取游客登录配置: ${appInfo.tourists}'); // if (channelAppResponse.code != 0 || channelAppResponse.data == null) { @@ -160,18 +223,17 @@ class VersionUpdateService extends GetxService { // } // final appInfo = channelAppResponse.data!.app; - final hasUpdate = _compareVersions(currentVersion, appInfo.version); + _hasUpdate = _compareVersions(currentVersion, appInfo.version); // 判断更新类型:如果主版本号不同则强制更新 UpdateType updateType = UpdateType.none; - if (hasUpdate) { - final isForceUpdate = - _shouldForceUpdate(currentVersion, appInfo.version); - updateType = isForceUpdate ? UpdateType.force : UpdateType.optional; + if (_hasUpdate!) { + _isForceUpdate = _shouldForceUpdate(currentVersion, appInfo.version); + updateType = _isForceUpdate! ? UpdateType.force : UpdateType.optional; } return VersionUpdateInfo( - hasUpdate: hasUpdate, + hasUpdate: _hasUpdate!, currentVersion: currentVersion.split('+')[0], latestVersion: appInfo.version.split('+')[0], appInfo: appInfo, @@ -180,7 +242,7 @@ class VersionUpdateService extends GetxService { } catch (e) { _logger.e('检查版本更新失败: $e'); // 发生错误时,保持默认值 false - isShowTourists.value = false; + _isShowTourists = false; final currentVersion = await getCurrentVersion(); return VersionUpdateInfo( hasUpdate: false, @@ -270,84 +332,16 @@ class VersionUpdateService extends GetxService { return false; } - //final platformInfo = await getCurrentPlatformInfo(); - try { - // switch (platformInfo.storeType) { - // case AppStoreType.appStore: - // return await _openAppStore(); - // case AppStoreType.googlePlay: - // return await _openGooglePlay(); - // case AppStoreType.huawei: - // return await _openHuaweiStore(); - // case AppStoreType.xiaomi: - // return await _openXiaomiStore(); - // case AppStoreType.oppo: - // return await _openOppoStore(); - // case AppStoreType.vivo: - // return await _openVivoStore(); - // case AppStoreType.honor: - // return await _openHonorStore(); - // case AppStoreType.official: - // return await _openOfficialDownload(updateInfo.appInfo!.address!); - // default: - return await _openOfficialDownload(updateInfo.appInfo!.address!); - // } + return await _openDownloadUrl(updateInfo.appInfo!.address!); } catch (e) { _logger.e('执行更新失败: $e'); return false; } } - /// 打开iOS App Store - Future _openAppStore() async { - // 这里需要替换为实际的App Store ID - const appStoreUrl = 'https://apps.apple.com/app/id你的应用ID'; - return await _launchUrl(appStoreUrl); - } - - /// 打开Google Play - Future _openGooglePlay() async { - // 这里需要替换为实际的包名 - const packageName = 'com.yourcompany.deepvoice'; - const playStoreUrl = - 'https://play.google.com/store/apps/details?id=$packageName'; - return await _launchUrl(playStoreUrl); - } - - /// 打开华为应用市场 - Future _openHuaweiStore() async { - const huaweiStoreUrl = 'appmarket://details?id=com.yourcompany.deepvoice'; - return await _launchUrl(huaweiStoreUrl); - } - - /// 打开小米应用商店 - Future _openXiaomiStore() async { - const xiaomiStoreUrl = 'mimarket://details?id=com.yourcompany.deepvoice'; - return await _launchUrl(xiaomiStoreUrl); - } - - /// 打开OPPO软件商店 - Future _openOppoStore() async { - const oppoStoreUrl = - 'oppomarket://details?packagename=com.yourcompany.deepvoice'; - return await _launchUrl(oppoStoreUrl); - } - - /// 打开vivo应用商店 - Future _openVivoStore() async { - const vivoStoreUrl = 'vivomarket://details?id=com.yourcompany.deepvoice'; - return await _launchUrl(vivoStoreUrl); - } - - /// 打开荣耀应用市场 - Future _openHonorStore() async { - const honorStoreUrl = 'honormarket://details?id=com.yourcompany.deepvoice'; - return await _launchUrl(honorStoreUrl); - } - - /// 打开官网下载 - Future _openOfficialDownload(String downloadUrl) async { + /// 打开下载链接 + Future _openDownloadUrl(String downloadUrl) async { return await _launchUrl(downloadUrl); } diff --git a/lib/modules/login/controllers/login_controller.dart b/lib/modules/login/controllers/login_controller.dart index 5b67a8d8a..292ef376d 100644 --- a/lib/modules/login/controllers/login_controller.dart +++ b/lib/modules/login/controllers/login_controller.dart @@ -1,23 +1,23 @@ import 'dart:async'; +import 'dart:io'; -import '../../../data/models/appconfig.dart'; -import '../../../data/models/appconfig_model.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:logger/web.dart'; -import '../../../routes/app_routes.dart'; +import 'package:get_storage/get_storage.dart'; +import 'package:device_info_plus/device_info_plus.dart'; import 'dart:convert'; import 'facebookLogin.dart'; import 'googleLogin.dart'; import 'weixinLogin.dart'; import 'appleLogin.dart'; +import '../../../routes/app_routes.dart'; +import '../../../data/models/appconfig.dart'; +import '../../../data/models/appconfig_model.dart'; import '../../../data/services/network/api.dart'; import '../../../../data/models/user_Info.dart'; -import 'package:get_storage/get_storage.dart'; -import 'package:device_info_plus/device_info_plus.dart'; -import 'dart:io'; -import 'package:package_info_plus/package_info_plus.dart'; +import '../../../data/models/channel_app_model.dart'; import '../../../data/services/version_update_service.dart'; import '../../../modules/common/widgets/privacy_policy_dialog.dart'; @@ -27,20 +27,20 @@ enum LoginViewState { } // 用户渠道枚举 -enum UserChannel { - UNKNOWN(0), // 未知渠道 - CHINA_HUAWEI(1), // 中国-华为 - CHINA_XIAOMI(2), // 中国-小米 - CHINA_OPPO(3), // 中国-OPPO - CHINA_VIVO(4), // 中国-VIVO - CHINA_HONOR(5), // 中国-荣耀 - OFFICIAL(100), // 官方渠道 - GLOBAL_APPLE(101), // 全球-苹果 - GLOBAL_GOOGLE(102); // 全球-谷歌 - - const UserChannel(this.value); - final int value; -} +// enum UserChannel { +// UNKNOWN(0), // 未知渠道 +// CHINA_HUAWEI(1), // 中国-华为 +// CHINA_XIAOMI(2), // 中国-小米 +// CHINA_OPPO(3), // 中国-OPPO +// CHINA_VIVO(4), // 中国-VIVO +// CHINA_HONOR(5), // 中国-荣耀 +// OFFICIAL(100), // 官方渠道 +// GLOBAL_APPLE(101), // 全球-苹果 +// GLOBAL_GOOGLE(102); // 全球-谷歌 + +// const UserChannel(this.value); +// final int value; +// } class LoginController extends GetxController { static LoginController get to => Get.find(); @@ -212,6 +212,7 @@ class LoginController extends GetxController { String get contactValue => _contactValue.value; String get displayContact => _displayContact.value; List get verificationCode => _verificationCode; + final versionService = VersionUpdateService.to; // 文本控制器 TextEditingController contactController = TextEditingController(); @@ -246,20 +247,9 @@ class LoginController extends GetxController { // 检查游客登录配置 Future _checkGuestLoginConfig() async { try { - final versionService = VersionUpdateService.to; - - // 先检查版本更新,这会同时设置 isShowTourists 的值 - await versionService.checkForUpdate(); + _isGuestLoginVisible.value = versionService.cachedShowTourists; - // 直接使用 VersionUpdateService 中的 isShowTourists 值 - _isGuestLoginVisible.value = versionService.isShowTourists.value; Logger().d('游客登录显示状态: ${_isGuestLoginVisible.value}'); - - // 监听 isShowTourists 的变化 - versionService.isShowTourists.listen((value) { - _isGuestLoginVisible.value = value; - Logger().d('游客登录显示状态更新: $value'); - }); } catch (e) { Logger().e('检查游客登录配置失败: $e'); // 默认不显示游客登录 @@ -301,9 +291,7 @@ class LoginController extends GetxController { // 新增:初始化APP信息(版本号、渠道、国家代码) Future _initAppInfo() async { try { - // 获取APP版本号 - final packageInfo = await PackageInfo.fromPlatform(); - _appVersion = '${packageInfo.version}+${packageInfo.buildNumber}'; + _appVersion = versionService.cachedAppVersion; Logger().d('appVersion: $_appVersion'); // 获取国家代码 @@ -311,7 +299,7 @@ class LoginController extends GetxController { Logger().d('countryCode: $_countryCode'); // 获取用户渠道(根据平台和设备信息确定) - _userChannel = UserChannel.OFFICIAL; + _userChannel = versionService.cachedChannel; Logger().d('userChannel: ${_userChannel.value}'); } catch (e) { Logger().e('获取APP信息失败: $e'); diff --git a/lib/modules/settings/views/settings_view.dart b/lib/modules/settings/views/settings_view.dart index 784c905ed..571c1731c 100644 --- a/lib/modules/settings/views/settings_view.dart +++ b/lib/modules/settings/views/settings_view.dart @@ -16,13 +16,6 @@ import '../../profile/views/unified_avatar.dart'; class SettingsView extends GetView { const SettingsView({Key? key}) : super(key: key); - // 正确获取用户名方式 - // String get userName => User.getname(); - - // String get deviceInfo => User.getdeviceInfo(); - // String get userId => User.getuserId(); - // String get standing => User.getstanding(); - // String get avatar => User.getnavatar(); @override Widget build(BuildContext context) { // 直接使用 Theme.of(context) 获取当前主题