From c10c89c94fa557d88ecd867af552ff2bb2818099 Mon Sep 17 00:00:00 2001
From: lxm <1274844347@qq.com>
Date: Fri, 20 Jun 2025 10:59:06 +0800
Subject: [PATCH] =?UTF-8?q?feat(=E7=89=88=E6=9C=AC=E6=9B=B4=E6=96=B0):=20?=
=?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=BA=94=E7=94=A8=E7=89=88=E6=9C=AC=E6=A3=80?=
=?UTF-8?q?=E6=9F=A5=E4=B8=8E=E6=9B=B4=E6=96=B0=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
添加版本更新服务及相关组件,包括:
1. 新增 VersionUpdateService 处理版本检查逻辑
2. 添加版本更新对话框组件 VersionUpdateDialog
3. 实现渠道包信息获取 API 接口
4. 在设置和启动页集成版本检查功能
5. 添加 url_launcher 依赖用于应用商店跳转
---
android/app/build.gradle.kts | 4 +-
ios/Runner/Info.plist | 2 +-
lib/core/bindings/initial_binding.dart | 4 +
lib/data/models/appconfig_model.g.dart | 2 +-
lib/data/models/channel_app_model.dart | 151 +++++++++
lib/data/models/channel_app_model.g.dart | 47 +++
lib/data/services/account_service.dart | 17 +-
lib/data/services/network/api.dart | 9 +
lib/data/services/version_update_service.dart | 312 ++++++++++++++++++
.../common/widgets/version_update_dialog.dart | 226 +++++++++++++
.../controllers/settings_controller.dart | 48 +++
lib/modules/settings/views/settings_view.dart | 3 +-
.../splash/controllers/splash_controller.dart | 24 ++
pubspec.yaml | 1 +
14 files changed, 843 insertions(+), 7 deletions(-)
create mode 100644 lib/data/models/channel_app_model.dart
create mode 100644 lib/data/models/channel_app_model.g.dart
create mode 100644 lib/data/services/version_update_service.dart
create mode 100644 lib/modules/common/widgets/version_update_dialog.dart
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index 20d5ead25..cbb9afd88 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -69,8 +69,8 @@ android {
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = 26 // 更新为26以满足ble_service库的要求
targetSdk = 34 // 设置为 Android 13 (API 33),以匹配 FOREGROUND_SERVICE_MEDIA_PLAYBACK 权限的要求
- versionCode = flutter.versionCode
- versionName = flutter.versionName
+ versionCode = flutter.versionCode // 对应构建号,自动同步flutter构建号
+ versionName = flutter.versionName // 对应版本号,自动同步flutter版本号
}
signingConfigs {
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index bc3f4a793..5be33da0e 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -39,7 +39,7 @@
- CFBundleVersion
+ CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
FacebookAdvertiserIDCollectionEnabled
diff --git a/lib/core/bindings/initial_binding.dart b/lib/core/bindings/initial_binding.dart
index 08bb41500..c372b985a 100644
--- a/lib/core/bindings/initial_binding.dart
+++ b/lib/core/bindings/initial_binding.dart
@@ -10,6 +10,7 @@ import '../../core/utils/logger.dart';
import '../../data/services/bluetooth_manager.dart';
import '../../data/services/ble_manager.dart';
import '../../data/services/account_service.dart';
+import '../../data/services/version_update_service.dart';
/// 初始绑定,用于管理全局依赖
class InitialBinding extends Bindings {
@@ -46,6 +47,9 @@ class InitialBinding extends Bindings {
// 账号管理服务
Get.lazyPut(() => AccountService(), fenix: true);
+ // 版本更新服务
+ Get.lazyPut(() => VersionUpdateService(), fenix: true);
+
// 杰理蓝牙服务
// // 语言管理器(需要最先初始化)
diff --git a/lib/data/models/appconfig_model.g.dart b/lib/data/models/appconfig_model.g.dart
index c4ac4cc90..ffb7f58b8 100644
--- a/lib/data/models/appconfig_model.g.dart
+++ b/lib/data/models/appconfig_model.g.dart
@@ -57,7 +57,7 @@ Map _$DBAgentToJson(DBAgent instance) => {
DBMCPServer _$DBMCPServerFromJson(Map json) => DBMCPServer(
servername: json['servername'] as String,
url: json['url'] as String,
- tools: json['tools'] as String? ?? '',
+ tools: json['tools'] as String,
);
Map _$DBMCPServerToJson(DBMCPServer instance) =>
diff --git a/lib/data/models/channel_app_model.dart b/lib/data/models/channel_app_model.dart
new file mode 100644
index 000000000..bddbf9f39
--- /dev/null
+++ b/lib/data/models/channel_app_model.dart
@@ -0,0 +1,151 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'channel_app_model.g.dart';
+
+/// 渠道应用信息响应模型
+@JsonSerializable()
+class ChannelAppResponse {
+ @JsonKey(name: 'code')
+ final int code;
+
+ @JsonKey(name: 'data')
+ final ChannelAppData? data;
+
+ @JsonKey(name: 'msg')
+ final String msg;
+
+ const ChannelAppResponse({
+ required this.code,
+ this.data,
+ required this.msg,
+ });
+
+ factory ChannelAppResponse.fromJson(Map json) =>
+ _$ChannelAppResponseFromJson(json);
+
+ Map toJson() => _$ChannelAppResponseToJson(this);
+}
+
+/// 渠道应用数据模型
+@JsonSerializable()
+class ChannelAppData {
+ @JsonKey(name: 'app')
+ final AppInfo app;
+
+ const ChannelAppData({
+ required this.app,
+ });
+
+ factory ChannelAppData.fromJson(Map json) =>
+ _$ChannelAppDataFromJson(json);
+
+ Map toJson() => _$ChannelAppDataToJson(this);
+}
+
+/// 应用信息模型
+@JsonSerializable()
+class AppInfo {
+ /// 下载地址
+ @JsonKey(name: 'address')
+ final String address;
+
+ /// 渠道标识
+ @JsonKey(name: 'channel')
+ final String channel;
+
+ /// 应用描述
+ @JsonKey(name: 'description')
+ final String description;
+
+ /// 最新版本号
+ @JsonKey(name: 'version')
+ final String version;
+
+ const AppInfo({
+ required this.address,
+ required this.channel,
+ required this.description,
+ required this.version,
+ });
+
+ factory AppInfo.fromJson(Map json) =>
+ _$AppInfoFromJson(json);
+
+ Map toJson() => _$AppInfoToJson(this);
+}
+
+/// 版本更新信息模型
+class VersionUpdateInfo {
+ /// 是否有新版本
+ final bool hasUpdate;
+
+ /// 当前版本
+ final String currentVersion;
+
+ /// 最新版本
+ final String latestVersion;
+
+ /// 应用信息
+ final AppInfo? appInfo;
+
+ /// 更新类型
+ final UpdateType updateType;
+
+ const VersionUpdateInfo({
+ required this.hasUpdate,
+ required this.currentVersion,
+ required this.latestVersion,
+ this.appInfo,
+ required this.updateType,
+ });
+}
+
+/// 更新类型枚举
+enum UpdateType {
+ /// 无需更新
+ none,
+ /// 可选更新
+ optional,
+ /// 强制更新
+ force,
+}
+
+/// 应用商店类型枚举
+enum AppStoreType {
+ /// iOS App Store
+ appStore,
+ /// Google Play
+ googlePlay,
+ /// 华为应用市场
+ huawei,
+ /// 小米应用商店
+ xiaomi,
+ /// OPPO软件商店
+ oppo,
+ /// vivo应用商店
+ vivo,
+ /// 荣耀应用市场
+ honor,
+ /// 官网下载
+ official,
+ /// 未知
+ unknown,
+}
+
+/// 平台信息模型
+class PlatformInfo {
+ /// 平台类型
+ final String platform;
+
+ /// 应用商店类型
+ final AppStoreType storeType;
+
+ /// 渠道标识
+ final String channel;
+
+ const PlatformInfo({
+ required this.platform,
+ required this.storeType,
+ required this.channel,
+ });
+}
diff --git a/lib/data/models/channel_app_model.g.dart b/lib/data/models/channel_app_model.g.dart
new file mode 100644
index 000000000..7d5e6aa6b
--- /dev/null
+++ b/lib/data/models/channel_app_model.g.dart
@@ -0,0 +1,47 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'channel_app_model.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+ChannelAppResponse _$ChannelAppResponseFromJson(Map json) =>
+ ChannelAppResponse(
+ code: (json['code'] as num).toInt(),
+ data: json['data'] == null
+ ? null
+ : ChannelAppData.fromJson(json['data'] as Map),
+ msg: json['msg'] as String,
+ );
+
+Map _$ChannelAppResponseToJson(ChannelAppResponse instance) =>
+ {
+ 'code': instance.code,
+ 'data': instance.data,
+ 'msg': instance.msg,
+ };
+
+ChannelAppData _$ChannelAppDataFromJson(Map json) =>
+ ChannelAppData(
+ app: AppInfo.fromJson(json['app'] as Map),
+ );
+
+Map _$ChannelAppDataToJson(ChannelAppData instance) =>
+ {
+ 'app': instance.app,
+ };
+
+AppInfo _$AppInfoFromJson(Map json) => AppInfo(
+ address: json['address'] as String,
+ channel: json['channel'] as String,
+ description: json['description'] as String,
+ version: json['version'] as String,
+ );
+
+Map _$AppInfoToJson(AppInfo instance) => {
+ 'address': instance.address,
+ 'channel': instance.channel,
+ 'description': instance.description,
+ 'version': instance.version,
+ };
diff --git a/lib/data/services/account_service.dart b/lib/data/services/account_service.dart
index 6c01ac65c..cbbe49de1 100644
--- a/lib/data/services/account_service.dart
+++ b/lib/data/services/account_service.dart
@@ -25,7 +25,7 @@ class AccountService extends GetxService {
Future clearUserData() async {
try {
// 清理所有存储
- await _storage.erase();
+ //await _storage.erase();
// 或者逐个清理关键存储项
await _storage.write("logintoken", null);
await _storage.write("user_info", null);
@@ -38,6 +38,18 @@ class AccountService extends GetxService {
}
}
+ Future clearAllUserData() async {
+ // 清理所有用户数据
+ try {
+ await _storage.erase();
+ logger.d('所有用户数据清理成功');
+ return true;
+ } catch (e) {
+ logger.e('用户数据清理失败: $e');
+ return false;
+ }
+ }
+
/// 退出第三方登录
///
/// 返回操作是否成功
@@ -105,7 +117,8 @@ class AccountService extends GetxService {
}
// 清理本地数据
- final dataCleaned = await clearUserData();
+ final dataCleaned = await clearAllUserData(); // 一次性清除所有数据
+
if (!dataCleaned) {
return AccountOperationResult(
success: false,
diff --git a/lib/data/services/network/api.dart b/lib/data/services/network/api.dart
index b2f43ac10..56eebceab 100644
--- a/lib/data/services/network/api.dart
+++ b/lib/data/services/network/api.dart
@@ -107,4 +107,13 @@ class Api {
params: params,
);
}
+
+ //获取渠道包信息
+ static getChannelApp([params]) {
+ return DioManager().request(
+ NWMethod.post,
+ '/api/home/user_getchannelapp',
+ params: params,
+ );
+ }
}
diff --git a/lib/data/services/version_update_service.dart b/lib/data/services/version_update_service.dart
new file mode 100644
index 000000000..5c62c0313
--- /dev/null
+++ b/lib/data/services/version_update_service.dart
@@ -0,0 +1,312 @@
+import 'dart:io';
+import 'package:flutter/foundation.dart';
+import 'package:get/get.dart';
+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 '../models/channel_app_model.dart';
+import 'network/api.dart';
+
+/// 版本更新服务类
+class VersionUpdateService extends GetxService {
+ static VersionUpdateService get to => Get.find();
+
+ final Logger _logger = Logger();
+
+ /// 获取当前应用版本信息
+ Future getCurrentVersion() async {
+ try {
+ final packageInfo = await PackageInfo.fromPlatform();
+ return '${packageInfo.version}+${packageInfo.buildNumber}';
+ } catch (e) {
+ _logger.e('获取当前版本信息失败: $e');
+ return '1.0.0';
+ }
+ }
+
+ /// 获取当前平台信息
+ Future getCurrentPlatformInfo() async {
+ if (kIsWeb) {
+ return const PlatformInfo(
+ platform: 'web',
+ storeType: AppStoreType.official,
+ channel: '官方网站',
+ );
+ }
+
+ if (Platform.isIOS) {
+ return const PlatformInfo(
+ platform: 'ios',
+ storeType: AppStoreType.appStore,
+ channel: 'App Store',
+ );
+ }
+
+ if (Platform.isAndroid) {
+ // 根据设备品牌判断应用商店类型
+ return await getAndroidStoreInfoByBrand();
+ }
+
+ return const PlatformInfo(
+ platform: 'unknown',
+ storeType: AppStoreType.unknown,
+ channel: '未知',
+ );
+ }
+
+ /// 根据设备品牌获取应用商店信息
+ Future getAndroidStoreInfoByBrand() async {
+ try {
+ final deviceInfo = DeviceInfoPlugin();
+ final androidInfo = await deviceInfo.androidInfo;
+ final brand = androidInfo.brand.toLowerCase();
+
+ return const PlatformInfo(
+ platform: 'android',
+ storeType: AppStoreType.official,
+ channel: '官方内测',
+ );
+
+ // switch (brand) {
+ // case 'huawei':
+ // case 'honor':
+ // return PlatformInfo(
+ // platform: 'android',
+ // storeType:
+ // brand == 'huawei' ? AppStoreType.huawei : AppStoreType.honor,
+ // channel: brand == 'huawei' ? '华为应用市场' : '荣耀应用市场',
+ // );
+ // case 'xiaomi':
+ // case 'redmi':
+ // return const PlatformInfo(
+ // platform: 'android',
+ // storeType: AppStoreType.xiaomi,
+ // channel: '小米应用商店',
+ // );
+ // case 'oppo':
+ // case 'oneplus':
+ // return const PlatformInfo(
+ // platform: 'android',
+ // storeType: AppStoreType.oppo,
+ // channel: 'OPPO软件商店',
+ // );
+ // case 'vivo':
+ // case 'iqoo':
+ // return const PlatformInfo(
+ // platform: 'android',
+ // storeType: AppStoreType.vivo,
+ // channel: 'vivo应用商店',
+ // );
+ // default:
+ // return const PlatformInfo(
+ // platform: 'android',
+ // storeType: AppStoreType.googlePlay,
+ // channel: 'Google Play',
+ // );
+ // }
+ } catch (e) {
+ _logger.e('获取Android设备信息失败: $e');
+ return const PlatformInfo(
+ platform: 'android',
+ storeType: AppStoreType.googlePlay,
+ channel: 'Google Play',
+ );
+ }
+ }
+
+ /// 检查版本更新
+ Future checkForUpdate() async {
+ try {
+ final currentVersion = await getCurrentVersion();
+ final platformInfo = await getCurrentPlatformInfo();
+
+ // 调用后端接口获取最新版本信息
+ final response =
+ await Api.getChannelApp({'channel': platformInfo.channel});
+
+ print('获取渠道包信息:$response');
+
+ if (response == null || !response.containsKey('app')) {
+ return VersionUpdateInfo(
+ hasUpdate: false,
+ currentVersion: currentVersion,
+ latestVersion: currentVersion,
+ updateType: UpdateType.none,
+ );
+ }
+
+ //final channelAppResponse = ChannelAppResponse.fromJson(response);
+ // 直接从response中获取app信息
+ final appInfo = AppInfo.fromJson(response['app']);
+
+ // if (channelAppResponse.code != 0 || channelAppResponse.data == null) {
+ // _logger.w('获取版本信息失败: ${channelAppResponse.msg}');
+ // return VersionUpdateInfo(
+ // hasUpdate: false,
+ // currentVersion: currentVersion,
+ // latestVersion: currentVersion,
+ // updateType: UpdateType.none,
+ // );
+ // }
+
+ // final appInfo = channelAppResponse.data!.app;
+ final hasUpdate = _compareVersions(currentVersion, appInfo.version);
+
+ return VersionUpdateInfo(
+ hasUpdate: hasUpdate,
+ currentVersion: currentVersion,
+ latestVersion: appInfo.version,
+ appInfo: appInfo,
+ updateType: hasUpdate ? UpdateType.optional : UpdateType.none,
+ );
+ } catch (e) {
+ _logger.e('检查版本更新失败: $e');
+ final currentVersion = await getCurrentVersion();
+ return VersionUpdateInfo(
+ hasUpdate: false,
+ currentVersion: currentVersion,
+ latestVersion: currentVersion,
+ updateType: UpdateType.none,
+ );
+ }
+ }
+
+ /// 比较版本号
+ /// 返回true表示需要更新(远程版本更高)
+ bool _compareVersions(String currentVersion, String remoteVersion) {
+ try {
+ final current = _parseVersion(currentVersion);
+ final remote = _parseVersion(remoteVersion);
+
+ for (int i = 0; i < 3; i++) {
+ if (remote[i] > current[i]) {
+ return true;
+ } else if (remote[i] < current[i]) {
+ return false;
+ }
+ }
+ return false; // 版本相同
+ } catch (e) {
+ _logger.e('版本比较失败: $e');
+ return false;
+ }
+ }
+
+ /// 解析版本号字符串为数字数组
+ List _parseVersion(String version) {
+ final parts = version.split('.');
+ final result = [];
+
+ for (int i = 0; i < 3; i++) {
+ if (i < parts.length) {
+ result.add(int.tryParse(parts[i]) ?? 0);
+ } else {
+ result.add(0);
+ }
+ }
+
+ return result;
+ }
+
+ /// 执行更新操作
+ Future performUpdate(VersionUpdateInfo updateInfo) async {
+ if (!updateInfo.hasUpdate || updateInfo.appInfo == null) {
+ 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);
+ }
+ } 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 {
+ return await _launchUrl(downloadUrl);
+ }
+
+ /// 启动URL
+ Future _launchUrl(String url) async {
+ try {
+ final uri = Uri.parse(url);
+ if (await canLaunchUrl(uri)) {
+ return await launchUrl(uri, mode: LaunchMode.externalApplication);
+ }
+ return false;
+ } catch (e) {
+ _logger.e('启动URL失败: $e');
+ return false;
+ }
+ }
+}
diff --git a/lib/modules/common/widgets/version_update_dialog.dart b/lib/modules/common/widgets/version_update_dialog.dart
new file mode 100644
index 000000000..a52077bdf
--- /dev/null
+++ b/lib/modules/common/widgets/version_update_dialog.dart
@@ -0,0 +1,226 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:get/get.dart';
+import '../../../data/models/channel_app_model.dart';
+import '../../../data/services/version_update_service.dart';
+
+/// 版本更新提示对话框
+class VersionUpdateDialog extends StatelessWidget {
+ final VersionUpdateInfo updateInfo;
+ final VoidCallback? onCancel;
+ final VoidCallback? onUpdate;
+
+ const VersionUpdateDialog({
+ super.key,
+ required this.updateInfo,
+ this.onCancel,
+ this.onUpdate,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ final isDarkMode = Theme.of(context).brightness == Brightness.dark;
+
+ return Dialog(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(16.r),
+ ),
+ child: Container(
+ width: 320.w,
+ padding: EdgeInsets.all(24.w),
+ decoration: BoxDecoration(
+ color: isDarkMode ? Colors.grey[900] : Colors.white,
+ borderRadius: BorderRadius.circular(16.r),
+ ),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ // 标题图标
+ Container(
+ width: 64.w,
+ height: 64.w,
+ decoration: BoxDecoration(
+ color: Colors.blue.withOpacity(0.1),
+ borderRadius: BorderRadius.circular(32.r),
+ ),
+ child: Icon(
+ Icons.system_update,
+ size: 32.sp,
+ color: Colors.blue,
+ ),
+ ),
+
+ SizedBox(height: 16.h),
+
+ // 标题
+ Text(
+ '发现新版本',
+ style: TextStyle(
+ fontSize: 20.sp,
+ fontWeight: FontWeight.bold,
+ color: isDarkMode ? Colors.white : Colors.black87,
+ ),
+ ),
+
+ SizedBox(height: 8.h),
+
+ // 版本信息
+ Text(
+ '${updateInfo.currentVersion} → ${updateInfo.latestVersion}',
+ style: TextStyle(
+ fontSize: 14.sp,
+ color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
+ ),
+ ),
+
+ SizedBox(height: 16.h),
+
+ // 更新描述
+ if (updateInfo.appInfo?.description.isNotEmpty == true) ...[
+ Container(
+ width: double.infinity,
+ padding: EdgeInsets.all(12.w),
+ decoration: BoxDecoration(
+ color: isDarkMode ? Colors.grey[800] : Colors.grey[100],
+ borderRadius: BorderRadius.circular(8.r),
+ ),
+ child: Text(
+ updateInfo.appInfo!.description,
+ style: TextStyle(
+ fontSize: 14.sp,
+ color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
+ height: 1.4,
+ ),
+ ),
+ ),
+ SizedBox(height: 20.h),
+ ],
+
+ // 按钮区域
+ Row(
+ children: [
+ // 取消按钮(仅在非强制更新时显示)
+ if (updateInfo.updateType != UpdateType.force) ...[
+ Expanded(
+ child: TextButton(
+ onPressed: () {
+ Get.back();
+ onCancel?.call();
+ },
+ style: TextButton.styleFrom(
+ padding: EdgeInsets.symmetric(vertical: 12.h),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(8.r),
+ side: BorderSide(
+ color: isDarkMode ? Colors.grey[600]! : Colors.grey[300]!,
+ ),
+ ),
+ ),
+ child: Text(
+ '稍后提醒',
+ style: TextStyle(
+ fontSize: 16.sp,
+ color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
+ ),
+ ),
+ ),
+ ),
+ SizedBox(width: 12.w),
+ ],
+
+ // 更新按钮
+ Expanded(
+ child: ElevatedButton(
+ onPressed: () async {
+ Get.back();
+ await _handleUpdate();
+ onUpdate?.call();
+ },
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Colors.blue,
+ foregroundColor: Colors.white,
+ padding: EdgeInsets.symmetric(vertical: 12.h),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(8.r),
+ ),
+ elevation: 0,
+ ),
+ child: Text(
+ _getUpdateButtonText(),
+ style: TextStyle(
+ fontSize: 16.sp,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ /// 获取更新按钮文本
+ String _getUpdateButtonText() {
+ switch (updateInfo.updateType) {
+ case UpdateType.force:
+ return '立即更新';
+ case UpdateType.optional:
+ return '立即更新';
+ default:
+ return '检查更新';
+ }
+ }
+
+ /// 处理更新操作
+ Future _handleUpdate() async {
+ try {
+ // 显示加载提示
+ Get.dialog(
+ const Center(
+ child: CircularProgressIndicator(),
+ ),
+ barrierDismissible: false,
+ );
+
+ final versionService = VersionUpdateService.to;
+ final success = await versionService.performUpdate(updateInfo);
+
+ // 关闭加载提示
+ Get.back();
+
+ if (!success) {
+ Get.snackbar(
+ '更新失败',
+ '无法打开应用商店,请手动前往应用商店更新',
+ snackPosition: SnackPosition.TOP,
+ backgroundColor: Colors.red.withOpacity(0.8),
+ colorText: Colors.white,
+ );
+ }
+ } catch (e) {
+ // 关闭加载提示
+ if (Get.isDialogOpen == true) {
+ Get.back();
+ }
+
+ Get.snackbar(
+ '更新失败',
+ '更新过程中发生错误,请稍后重试',
+ snackPosition: SnackPosition.TOP,
+ backgroundColor: Colors.red.withOpacity(0.8),
+ colorText: Colors.white,
+ );
+ }
+ }
+
+ /// 显示版本更新对话框
+ static Future show(VersionUpdateInfo updateInfo) async {
+ await Get.dialog(
+ VersionUpdateDialog(updateInfo: updateInfo),
+ barrierDismissible: updateInfo.updateType != UpdateType.force,
+ );
+ }
+}
diff --git a/lib/modules/settings/controllers/settings_controller.dart b/lib/modules/settings/controllers/settings_controller.dart
index 36fd66fe3..285f687a0 100644
--- a/lib/modules/settings/controllers/settings_controller.dart
+++ b/lib/modules/settings/controllers/settings_controller.dart
@@ -16,6 +16,8 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'dart:async';
import 'package:app_settings/app_settings.dart';
+import '../../../data/services/version_update_service.dart';
+import '../../common/widgets/version_update_dialog.dart';
class SettingsController extends GetxController {
// 语言设置
@@ -490,4 +492,50 @@ class SettingsController extends GetxController {
}
}
}
+
+ /// 手动检查版本更新
+ Future checkForUpdate() async {
+ try {
+ // 显示加载提示
+ Get.dialog(
+ const Center(
+ child: CircularProgressIndicator(),
+ ),
+ barrierDismissible: false,
+ );
+
+ final versionService = VersionUpdateService.to;
+ final updateInfo = await versionService.checkForUpdate();
+
+ // 关闭加载提示
+ Get.back();
+
+ if (updateInfo.hasUpdate) {
+ // 显示更新对话框
+ await VersionUpdateDialog.show(updateInfo);
+ } else {
+ // 显示已是最新版本的提示
+ Get.snackbar(
+ '检查更新',
+ '当前已是最新版本 ${updateInfo.currentVersion}',
+ snackPosition: SnackPosition.TOP,
+ backgroundColor: Colors.green.withOpacity(0.8),
+ colorText: Colors.white,
+ );
+ }
+ } catch (e) {
+ // 关闭加载提示
+ if (Get.isDialogOpen == true) {
+ Get.back();
+ }
+
+ Get.snackbar(
+ '检查更新失败',
+ '网络连接异常,请稍后重试',
+ snackPosition: SnackPosition.TOP,
+ backgroundColor: Colors.red.withOpacity(0.8),
+ colorText: Colors.white,
+ );
+ }
+ }
}
diff --git a/lib/modules/settings/views/settings_view.dart b/lib/modules/settings/views/settings_view.dart
index 195daf552..fb943bc36 100644
--- a/lib/modules/settings/views/settings_view.dart
+++ b/lib/modules/settings/views/settings_view.dart
@@ -858,7 +858,8 @@ class SettingsView extends GetView {
),
InkWell(
onTap: () {
- // 在这里添加检查更新的逻辑
+ // 调用检查更新方法
+ controller.checkForUpdate();
},
child: Container(
constraints: BoxConstraints(
diff --git a/lib/modules/splash/controllers/splash_controller.dart b/lib/modules/splash/controllers/splash_controller.dart
index e53f146dc..5bd7eb027 100644
--- a/lib/modules/splash/controllers/splash_controller.dart
+++ b/lib/modules/splash/controllers/splash_controller.dart
@@ -8,6 +8,8 @@ import '../../../data/models/user_Info.dart';
import '../../../routes/app_routes.dart';
import '../../../core/themes/theme_service.dart';
import '../../../data/services/network/api.dart';
+import '../../../data/services/version_update_service.dart';
+import '../../../modules/common/widgets/version_update_dialog.dart';
class SplashController extends GetxController {
final GetStorage _storage = GetStorage();
@@ -73,6 +75,9 @@ class SplashController extends GetxController {
// await _loadImages();
// await _initDatabase();
+ // 检查版本更新(在后台进行,不阻塞启动流程)
+ _checkVersionUpdate();
+
_isResourceLoaded.value = true;
_checkNavigateCondition();
} catch (e) {
@@ -151,4 +156,23 @@ class SplashController extends GetxController {
return false;
}
}
+
+ /// 检查版本更新(后台执行,不阻塞启动流程)
+ void _checkVersionUpdate() {
+ // 延迟执行版本检查,避免影响启动速度
+ Timer(const Duration(seconds: 2), () async {
+ try {
+ final versionService = VersionUpdateService.to;
+ final updateInfo = await versionService.checkForUpdate();
+
+ if (updateInfo.hasUpdate) {
+ // 显示更新对话框
+ await VersionUpdateDialog.show(updateInfo);
+ }
+ } catch (e) {
+ print('版本检查失败: $e');
+ // 版本检查失败不影响用户使用,静默处理
+ }
+ });
+ }
}
diff --git a/pubspec.yaml b/pubspec.yaml
index ccd4d7c49..ca1cc9712 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -57,6 +57,7 @@ dependencies:
lottie: ^3.3.1
app_settings: 5.2.0
fluwx: ^5.4.1
+ url_launcher: ^6.3.1
firebase_core: ^3.12.1
firebase_auth: ^5.5.1
google_sign_in: ^6.2.2