diff --git a/lib/common/core/app_config_helper.dart b/lib/common/core/app_config_helper.dart index 8b2a7e2..c105ec7 100644 --- a/lib/common/core/app_config_helper.dart +++ b/lib/common/core/app_config_helper.dart @@ -17,6 +17,9 @@ class AppConfigHelper { static String _versionCode = ''; + // 是否检测过更新,因为路由混乱导致首页会多次启动,避免重复检测更新,先临时处理 + static bool checkedUpdate = false; + // 获取用户信息 static Future getAppConfig() async { if (configEntityEntity != null) { diff --git a/lib/common/request/apis.dart b/lib/common/request/apis.dart index 03d8800..71f960e 100644 --- a/lib/common/request/apis.dart +++ b/lib/common/request/apis.dart @@ -6,6 +6,9 @@ class Apis { /// 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897678 static const String appConfig = 'system/app/config'; + /// app版本信息 + static const String appVersion = 'system/app/version'; + /// 登录 static const String login = 'login'; diff --git a/lib/common/request/dao/system_dao.dart b/lib/common/request/dao/system_dao.dart index 21cdb54..78c04c5 100644 --- a/lib/common/request/dao/system_dao.dart +++ b/lib/common/request/dao/system_dao.dart @@ -1,4 +1,5 @@ import '../../../models/app_config_entity.dart'; +import '../../../models/app_version_entity.dart'; import '../request_client.dart'; class SystemDao { @@ -7,4 +8,9 @@ class SystemDao { static Future getAppConfig() async { return await requestClient.get(Apis.appConfig); } + + // 获取app版本信息 + static Future getVersionInfo() async { + return await requestClient.get(Apis.appVersion); + } } diff --git a/lib/common/request/token_interceptor.dart b/lib/common/request/token_interceptor.dart index 165af84..e5e7233 100644 --- a/lib/common/request/token_interceptor.dart +++ b/lib/common/request/token_interceptor.dart @@ -1,4 +1,5 @@ import 'package:dio/dio.dart'; +import 'package:flutter/foundation.dart'; import 'package:wow_english/common/core/user_util.dart'; import '../core/app_config_helper.dart'; @@ -13,6 +14,7 @@ class TokenInterceptor extends Interceptor { // 在发送请求之前获取版本号 String version = await AppConfigHelper.getAppVersion(); options.headers["version"] = version; + options.headers["User-Agent"] = defaultTargetPlatform == TargetPlatform.iOS ? "ios" : "android"; super.onRequest(options, handler); } } diff --git a/lib/generated/json/app_config_entity.g.dart b/lib/generated/json/app_config_entity.g.dart index c04a542..82091e3 100644 --- a/lib/generated/json/app_config_entity.g.dart +++ b/lib/generated/json/app_config_entity.g.dart @@ -3,49 +3,6 @@ import 'package:wow_english/models/app_config_entity.dart'; AppConfigEntity $AppConfigEntityFromJson(Map json) { final AppConfigEntity appConfigEntity = AppConfigEntity(); - final bool? androidForceUpdate = jsonConvert.convert( - json['androidForceUpdate']); - if (androidForceUpdate != null) { - appConfigEntity.androidForceUpdate = androidForceUpdate; - } - final bool? androidRecommendUpdate = jsonConvert.convert( - json['androidRecommendUpdate']); - if (androidRecommendUpdate != null) { - appConfigEntity.androidRecommendUpdate = androidRecommendUpdate; - } - final String? androidUpdatePackageUrl = jsonConvert.convert( - json['androidUpdatePackageUrl']); - if (androidUpdatePackageUrl != null) { - appConfigEntity.androidUpdatePackageUrl = androidUpdatePackageUrl; - } - final int? androidVersion = jsonConvert.convert(json['androidVersion']); - if (androidVersion != null) { - appConfigEntity.androidVersion = androidVersion; - } - final bool? iosForceUpdate = jsonConvert.convert( - json['iosForceUpdate']); - if (iosForceUpdate != null) { - appConfigEntity.iosForceUpdate = iosForceUpdate; - } - final bool? iosRecommendUpdate = jsonConvert.convert( - json['iosRecommendUpdate']); - if (iosRecommendUpdate != null) { - appConfigEntity.iosRecommendUpdate = iosRecommendUpdate; - } - final int? iosVersion = jsonConvert.convert(json['iosVersion']); - if (iosVersion != null) { - appConfigEntity.iosVersion = iosVersion; - } - final String? updatePackageDescription = jsonConvert.convert( - json['updatePackageDescription']); - if (updatePackageDescription != null) { - appConfigEntity.updatePackageDescription = updatePackageDescription; - } - final String? noticeBeforePurchaseUrl = jsonConvert.convert( - json['noticeBeforePurchaseUrl']); - if (noticeBeforePurchaseUrl != null) { - appConfigEntity.noticeBeforePurchaseUrl = noticeBeforePurchaseUrl; - } final String? safe = jsonConvert.convert(json['safe']); if (safe != null) { appConfigEntity.safe = safe; @@ -55,46 +12,15 @@ AppConfigEntity $AppConfigEntityFromJson(Map json) { Map $AppConfigEntityToJson(AppConfigEntity entity) { final Map data = {}; - data['androidForceUpdate'] = entity.androidForceUpdate; - data['androidRecommendUpdate'] = entity.androidRecommendUpdate; - data['androidUpdatePackageUrl'] = entity.androidUpdatePackageUrl; - data['androidVersion'] = entity.androidVersion; - data['iosForceUpdate'] = entity.iosForceUpdate; - data['iosRecommendUpdate'] = entity.iosRecommendUpdate; - data['iosVersion'] = entity.iosVersion; - data['updatePackageDescription'] = entity.updatePackageDescription; - data['noticeBeforePurchaseUrl'] = entity.noticeBeforePurchaseUrl; data['safe'] = entity.safe; return data; } extension AppConfigEntityExtension on AppConfigEntity { AppConfigEntity copyWith({ - bool? androidForceUpdate, - bool? androidRecommendUpdate, - String? androidUpdatePackageUrl, - int? androidVersion, - bool? iosForceUpdate, - bool? iosRecommendUpdate, - int? iosVersion, - String? updatePackageDescription, - String? noticeBeforePurchaseUrl, String? safe, }) { return AppConfigEntity() - ..androidForceUpdate = androidForceUpdate ?? this.androidForceUpdate - ..androidRecommendUpdate = androidRecommendUpdate ?? - this.androidRecommendUpdate - ..androidUpdatePackageUrl = androidUpdatePackageUrl ?? - this.androidUpdatePackageUrl - ..androidVersion = androidVersion ?? this.androidVersion - ..iosForceUpdate = iosForceUpdate ?? this.iosForceUpdate - ..iosRecommendUpdate = iosRecommendUpdate ?? this.iosRecommendUpdate - ..iosVersion = iosVersion ?? this.iosVersion - ..updatePackageDescription = updatePackageDescription ?? - this.updatePackageDescription - ..noticeBeforePurchaseUrl = noticeBeforePurchaseUrl ?? - this.noticeBeforePurchaseUrl ..safe = safe ?? this.safe; } } \ No newline at end of file diff --git a/lib/generated/json/app_version_entity.g.dart b/lib/generated/json/app_version_entity.g.dart new file mode 100644 index 0000000..6cfe7b2 --- /dev/null +++ b/lib/generated/json/app_version_entity.g.dart @@ -0,0 +1,76 @@ +import 'package:wow_english/generated/json/base/json_convert_content.dart'; +import 'package:wow_english/models/app_version_entity.dart'; + +AppVersionEntity $AppVersionEntityFromJson(Map json) { + final AppVersionEntity appVersionEntity = AppVersionEntity(); + final String? packageUrl = jsonConvert.convert(json['packageUrl']); + if (packageUrl != null) { + appVersionEntity.packageUrl = packageUrl; + } + final String? packageName = jsonConvert.convert(json['packageName']); + if (packageName != null) { + appVersionEntity.packageName = packageName; + } + final String? packageSize = jsonConvert.convert(json['packageSize']); + if (packageSize != null) { + appVersionEntity.packageSize = packageSize; + } + final String? platformType = jsonConvert.convert( + json['platformType']); + if (platformType != null) { + appVersionEntity.platformType = platformType; + } + final String? remark = jsonConvert.convert(json['remark']); + if (remark != null) { + appVersionEntity.remark = remark; + } + final String? status = jsonConvert.convert(json['status']); + if (status != null) { + appVersionEntity.status = status; + } + final String? version = jsonConvert.convert(json['version']); + if (version != null) { + appVersionEntity.version = version; + } + final String? volType = jsonConvert.convert(json['volType']); + if (volType != null) { + appVersionEntity.volType = volType; + } + return appVersionEntity; +} + +Map $AppVersionEntityToJson(AppVersionEntity entity) { + final Map data = {}; + data['packageUrl'] = entity.packageUrl; + data['packageName'] = entity.packageName; + data['packageSize'] = entity.packageSize; + data['platformType'] = entity.platformType; + data['remark'] = entity.remark; + data['status'] = entity.status; + data['version'] = entity.version; + data['volType'] = entity.volType; + return data; +} + +extension AppVersionEntityExtension on AppVersionEntity { + AppVersionEntity copyWith({ + String? packageUrl, + String? packageName, + String? packageSize, + String? platformType, + String? remark, + String? status, + String? version, + String? volType, + }) { + return AppVersionEntity() + ..packageUrl = packageUrl ?? this.packageUrl + ..packageName = packageName ?? this.packageName + ..packageSize = packageSize ?? this.packageSize + ..platformType = platformType ?? this.platformType + ..remark = remark ?? this.remark + ..status = status ?? this.status + ..version = version ?? this.version + ..volType = volType ?? this.volType; + } +} \ No newline at end of file diff --git a/lib/generated/json/base/json_convert_content.dart b/lib/generated/json/base/json_convert_content.dart index 874fd55..9abac24 100644 --- a/lib/generated/json/base/json_convert_content.dart +++ b/lib/generated/json/base/json_convert_content.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart' show debugPrint; import 'package:wow_english/models/aliyun_oss_upload_sts_entity.dart'; import 'package:wow_english/models/app_config_entity.dart'; +import 'package:wow_english/models/app_version_entity.dart'; import 'package:wow_english/models/course_entity.dart'; import 'package:wow_english/models/course_module_entity.dart'; import 'package:wow_english/models/course_process_entity.dart'; @@ -160,6 +161,10 @@ class JsonConvert { return data.map((Map e) => AppConfigEntity.fromJson(e)).toList() as M; } + if ([] is M) { + return data.map((Map e) => + AppVersionEntity.fromJson(e)).toList() as M; + } if ([] is M) { return data.map((Map e) => CourseEntity.fromJson(e)).toList() as M; @@ -246,6 +251,7 @@ class JsonConvertClassCollection { (AliyunOssUploadStsCallbackParam) .toString(): AliyunOssUploadStsCallbackParam.fromJson, (AppConfigEntity).toString(): AppConfigEntity.fromJson, + (AppVersionEntity).toString(): AppVersionEntity.fromJson, (CourseEntity).toString(): CourseEntity.fromJson, (CourseCourseLessons).toString(): CourseCourseLessons.fromJson, (CourseModuleEntity).toString(): CourseModuleEntity.fromJson, diff --git a/lib/models/app_config_entity.dart b/lib/models/app_config_entity.dart index 8df900c..97487cc 100644 --- a/lib/models/app_config_entity.dart +++ b/lib/models/app_config_entity.dart @@ -7,31 +7,6 @@ import '../generated/json/app_config_entity.g.dart'; @JsonSerializable() class AppConfigEntity { - // 安卓是否强制更新 - bool? androidForceUpdate; - - // 安卓是否推荐更新 - bool? androidRecommendUpdate; - - // 安卓更新包地址 - String? androidUpdatePackageUrl; - - // 安卓当前版本号 - int? androidVersion; - - bool? iosForceUpdate; - - bool? iosRecommendUpdate; - - // ios版本 - int? iosVersion; - - // 更新说明 - String? updatePackageDescription; - - // 购前须知图片 - String? noticeBeforePurchaseUrl; - // 当前是否安全,safe-安全 otherwise-隐藏pay String? safe; diff --git a/lib/models/app_version_entity.dart b/lib/models/app_version_entity.dart new file mode 100644 index 0000000..6cf7394 --- /dev/null +++ b/lib/models/app_version_entity.dart @@ -0,0 +1,55 @@ +import 'package:wow_english/generated/json/base/json_field.dart'; +import 'package:wow_english/generated/json/app_version_entity.g.dart'; +import 'dart:convert'; +export 'package:wow_english/generated/json/app_version_entity.g.dart'; + +@JsonSerializable() +class AppVersionEntity { + + // 更新包地址 + String? packageUrl; + + // 更新包名 + String? packageName; + + // 更新包大小 + String? packageSize; + + // 平台类型 + String? platformType; + + // 更新说明 + String? remark; + + // 状态 + String? status; + + // app版本号 + String? version; + + // 强更类型 + String? volType; + + + AppVersionEntity(); + + factory AppVersionEntity.fromJson(Map json) => $AppVersionEntityFromJson(json); + + Map toJson() => $AppVersionEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} + +enum UpdateStrategy { + SUGGEST("suggest", "建议更新"), + FORCE("force", "强制更新"); + + const UpdateStrategy(this.name, this.chineseName); + + final String name; + + final String chineseName; +} \ No newline at end of file diff --git a/lib/pages/moduleSelect/bloc.dart b/lib/pages/moduleSelect/bloc.dart index 518e914..62e25c7 100644 --- a/lib/pages/moduleSelect/bloc.dart +++ b/lib/pages/moduleSelect/bloc.dart @@ -4,6 +4,9 @@ import 'package:flutter/foundation.dart'; import 'package:wow_english/models/app_config_entity.dart'; import '../../common/core/app_config_helper.dart'; +import '../../common/request/dao/system_dao.dart'; +import '../../models/app_version_entity.dart'; +import '../../utils/log_util.dart'; import 'event.dart'; import 'state.dart'; @@ -18,23 +21,25 @@ class ModuleSelectBloc extends Bloc { } Future _checkUpdate(Emitter emit) async { + if (AppConfigHelper.checkedUpdate) { + return; + } int localVersion = int.parse(await AppConfigHelper.getAppVersion()); - AppConfigEntity? appConfigEntity = await AppConfigHelper.getAppConfig(); - if (appConfigEntity == null) { + AppVersionEntity? appVersionEntity = await SystemDao.getVersionInfo(); + AppConfigHelper.checkedUpdate = true; + if (appVersionEntity == null) { return; } + Log.d("WQF _checkUpdate appVersionEntity: $appVersionEntity localVersion=$localVersion"); if (defaultTargetPlatform == TargetPlatform.iOS) { - if (localVersion < (appConfigEntity.iosVersion ?? 0) && - appConfigEntity.iosRecommendUpdate == true) { + if (localVersion < int.parse(appVersionEntity.version ?? '0')) { emit(UpdateDialogState( - appConfigEntity.iosForceUpdate ?? false, appConfigEntity)); + appVersionEntity.volType == UpdateStrategy.FORCE.name, appVersionEntity)); } } else { - if (localVersion < (appConfigEntity.androidVersion ?? 0) && - appConfigEntity.androidRecommendUpdate == true) { + if (localVersion < int.parse(appVersionEntity.version ?? '0')) { emit(UpdateDialogState( - appConfigEntity.androidForceUpdate ?? false, appConfigEntity, - )); + appVersionEntity.volType == UpdateStrategy.FORCE.name, appVersionEntity)); } } } diff --git a/lib/pages/moduleSelect/state.dart b/lib/pages/moduleSelect/state.dart index 34cfc2d..98e2581 100644 --- a/lib/pages/moduleSelect/state.dart +++ b/lib/pages/moduleSelect/state.dart @@ -1,4 +1,4 @@ -import '../../models/app_config_entity.dart'; +import 'package:wow_english/models/app_version_entity.dart'; class ModuleSelectState { ModuleSelectState init() { @@ -12,9 +12,9 @@ class ModuleSelectState { class UpdateDialogState extends ModuleSelectState { - final AppConfigEntity appConfigEntity; + final AppVersionEntity appVersionEntity; final bool forceUpdate; - UpdateDialogState(this.forceUpdate, this.appConfigEntity); + UpdateDialogState(this.forceUpdate, this.appVersionEntity); } diff --git a/lib/pages/moduleSelect/view.dart b/lib/pages/moduleSelect/view.dart index 379bcdd..e191286 100644 --- a/lib/pages/moduleSelect/view.dart +++ b/lib/pages/moduleSelect/view.dart @@ -8,13 +8,14 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:wow_english/common/core/app_config_helper.dart'; import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/models/app_version_entity.dart'; import 'package:wow_english/pages/moduleSelect/state.dart'; import 'package:wow_english/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart'; import 'package:wow_english/pages/user/bloc/user_bloc.dart'; import '../../common/core/user_util.dart'; import '../../common/dialogs/show_dialog.dart'; -import '../../models/app_config_entity.dart'; +import '../../utils/log_util.dart'; import 'bloc.dart'; import 'event.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -44,7 +45,7 @@ class _HomePageView extends StatelessWidget { BlocListener( listener: (context, state) { if (state is UpdateDialogState) { - _showUpdateDialog(context, state.forceUpdate, state.appConfigEntity); + _showUpdateDialog(context, state.forceUpdate, state.appVersionEntity); } }, ), @@ -169,7 +170,7 @@ class _HomePageView extends StatelessWidget { ///Flutter侧处理升级对话框 ///[forcedUpgrade] 是否强制升级 _showUpdateDialog(BuildContext context, bool forcedUpgrade, - AppConfigEntity appConfigEntity) { + AppVersionEntity appVersionEntity) { showDialog( context: context, // 当我们点击除开对话框内容以外的区域是否关闭对话需用用到barrierDismissible参数 . 这个参数默认值是true ,但不能为null . @@ -180,7 +181,7 @@ class _HomePageView extends StatelessWidget { child: AlertDialog( title: const Text('发现新版本'), content: Text( - appConfigEntity.updatePackageDescription ?? + appVersionEntity.remark ?? '修复了一些已知问题'), actions: [ TextButton( @@ -202,7 +203,7 @@ class _HomePageView extends StatelessWidget { _launchAppStore("6450870731"); return; } - final String? apkUrl = appConfigEntity.androidUpdatePackageUrl; + final String? apkUrl = appVersionEntity.packageUrl; if (apkUrl == null || apkUrl.isEmpty) { return; }