Commit 99b94d6c8c09e2acd87603a1e61ee770cc607bbf
1 parent
09fb1af9
feat:首页增加信息弹窗
Showing
10 changed files
with
187 additions
and
2 deletions
lib/common/request/api_response/api_response_entity.dart
lib/common/request/dao/system_dao.dart
| 1 | +import 'package:wow_english/models/popup_entity.dart'; | ||
| 2 | + | ||
| 1 | import '../../../models/app_config_entity.dart'; | 3 | import '../../../models/app_config_entity.dart'; | 
| 2 | import '../../../models/app_version_entity.dart'; | 4 | import '../../../models/app_version_entity.dart'; | 
| 3 | import '../request_client.dart'; | 5 | import '../request_client.dart'; | 
| @@ -13,4 +15,9 @@ class SystemDao { | @@ -13,4 +15,9 @@ class SystemDao { | ||
| 13 | static Future<AppVersionEntity?> getVersionInfo() async { | 15 | static Future<AppVersionEntity?> getVersionInfo() async { | 
| 14 | return await requestClient.get(Apis.appVersion); | 16 | return await requestClient.get(Apis.appVersion); | 
| 15 | } | 17 | } | 
| 18 | + | ||
| 19 | + // 获取弹窗信息 | ||
| 20 | + static Future<PopupEntity?> getPopupInfo() async { | ||
| 21 | + return await requestClient.get(Apis.homePopup); | ||
| 22 | + } | ||
| 16 | } | 23 | } | 
lib/generated/json/base/json_convert_content.dart
| @@ -14,6 +14,7 @@ import 'package:wow_english/models/course_section_entity.dart'; | @@ -14,6 +14,7 @@ import 'package:wow_english/models/course_section_entity.dart'; | ||
| 14 | import 'package:wow_english/models/course_unit_entity.dart'; | 14 | import 'package:wow_english/models/course_unit_entity.dart'; | 
| 15 | import 'package:wow_english/models/follow_read_entity.dart'; | 15 | import 'package:wow_english/models/follow_read_entity.dart'; | 
| 16 | import 'package:wow_english/models/listen_entity.dart'; | 16 | import 'package:wow_english/models/listen_entity.dart'; | 
| 17 | +import 'package:wow_english/models/popup_entity.dart'; | ||
| 17 | import 'package:wow_english/models/product_entity.dart'; | 18 | import 'package:wow_english/models/product_entity.dart'; | 
| 18 | import 'package:wow_english/models/read_content_entity.dart'; | 19 | import 'package:wow_english/models/read_content_entity.dart'; | 
| 19 | import 'package:wow_english/models/singsound_result_detail_entity.dart'; | 20 | import 'package:wow_english/models/singsound_result_detail_entity.dart'; | 
| @@ -225,6 +226,10 @@ class JsonConvert { | @@ -225,6 +226,10 @@ class JsonConvert { | ||
| 225 | return data.map<ListenEntity>((Map<String, dynamic> e) => | 226 | return data.map<ListenEntity>((Map<String, dynamic> e) => | 
| 226 | ListenEntity.fromJson(e)).toList() as M; | 227 | ListenEntity.fromJson(e)).toList() as M; | 
| 227 | } | 228 | } | 
| 229 | + if (<PopupEntity>[] is M) { | ||
| 230 | + return data.map<PopupEntity>((Map<String, dynamic> e) => | ||
| 231 | + PopupEntity.fromJson(e)).toList() as M; | ||
| 232 | + } | ||
| 228 | if (<ProductEntity>[] is M) { | 233 | if (<ProductEntity>[] is M) { | 
| 229 | return data.map<ProductEntity>((Map<String, dynamic> e) => | 234 | return data.map<ProductEntity>((Map<String, dynamic> e) => | 
| 230 | ProductEntity.fromJson(e)).toList() as M; | 235 | ProductEntity.fromJson(e)).toList() as M; | 
| @@ -281,6 +286,7 @@ class JsonConvertClassCollection { | @@ -281,6 +286,7 @@ class JsonConvertClassCollection { | ||
| 281 | (CourseUnitDetail).toString(): CourseUnitDetail.fromJson, | 286 | (CourseUnitDetail).toString(): CourseUnitDetail.fromJson, | 
| 282 | (FollowReadEntity).toString(): FollowReadEntity.fromJson, | 287 | (FollowReadEntity).toString(): FollowReadEntity.fromJson, | 
| 283 | (ListenEntity).toString(): ListenEntity.fromJson, | 288 | (ListenEntity).toString(): ListenEntity.fromJson, | 
| 289 | + (PopupEntity).toString(): PopupEntity.fromJson, | ||
| 284 | (ProductEntity).toString(): ProductEntity.fromJson, | 290 | (ProductEntity).toString(): ProductEntity.fromJson, | 
| 285 | (ReadContentEntity).toString(): ReadContentEntity.fromJson, | 291 | (ReadContentEntity).toString(): ReadContentEntity.fromJson, | 
| 286 | (SingsoundResultDetailEntity).toString(): SingsoundResultDetailEntity | 292 | (SingsoundResultDetailEntity).toString(): SingsoundResultDetailEntity | 
lib/generated/json/popup_entity.g.dart
0 → 100644
| 1 | +import 'package:wow_english/generated/json/base/json_convert_content.dart'; | ||
| 2 | +import 'package:wow_english/models/popup_entity.dart'; | ||
| 3 | + | ||
| 4 | +PopupEntity $PopupEntityFromJson(Map<String, dynamic> json) { | ||
| 5 | + final PopupEntity popupEntity = PopupEntity(); | ||
| 6 | + final String? actionType = jsonConvert.convert<String>(json['actionType']); | ||
| 7 | + if (actionType != null) { | ||
| 8 | + popupEntity.actionType = actionType; | ||
| 9 | + } | ||
| 10 | + final String? actionValue = jsonConvert.convert<String>(json['actionValue']); | ||
| 11 | + if (actionValue != null) { | ||
| 12 | + popupEntity.actionValue = actionValue; | ||
| 13 | + } | ||
| 14 | + final int? dayNum = jsonConvert.convert<int>(json['dayNum']); | ||
| 15 | + if (dayNum != null) { | ||
| 16 | + popupEntity.dayNum = dayNum; | ||
| 17 | + } | ||
| 18 | + final String? id = jsonConvert.convert<String>(json['id']); | ||
| 19 | + if (id != null) { | ||
| 20 | + popupEntity.id = id; | ||
| 21 | + } | ||
| 22 | + final String? imageId = jsonConvert.convert<String>(json['imageId']); | ||
| 23 | + if (imageId != null) { | ||
| 24 | + popupEntity.imageId = imageId; | ||
| 25 | + } | ||
| 26 | + final int? status = jsonConvert.convert<int>(json['status']); | ||
| 27 | + if (status != null) { | ||
| 28 | + popupEntity.status = status; | ||
| 29 | + } | ||
| 30 | + return popupEntity; | ||
| 31 | +} | ||
| 32 | + | ||
| 33 | +Map<String, dynamic> $PopupEntityToJson(PopupEntity entity) { | ||
| 34 | + final Map<String, dynamic> data = <String, dynamic>{}; | ||
| 35 | + data['actionType'] = entity.actionType; | ||
| 36 | + data['actionValue'] = entity.actionValue; | ||
| 37 | + data['dayNum'] = entity.dayNum; | ||
| 38 | + data['id'] = entity.id; | ||
| 39 | + data['imageId'] = entity.imageId; | ||
| 40 | + data['status'] = entity.status; | ||
| 41 | + return data; | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +extension PopupEntityExtension on PopupEntity { | ||
| 45 | + PopupEntity copyWith({ | ||
| 46 | + String? actionType, | ||
| 47 | + String? actionValue, | ||
| 48 | + int? dayNum, | ||
| 49 | + String? id, | ||
| 50 | + String? imageId, | ||
| 51 | + int? status, | ||
| 52 | + }) { | ||
| 53 | + return PopupEntity() | ||
| 54 | + ..actionType = actionType ?? this.actionType | ||
| 55 | + ..actionValue = actionValue ?? this.actionValue | ||
| 56 | + ..dayNum = dayNum ?? this.dayNum | ||
| 57 | + ..id = id ?? this.id | ||
| 58 | + ..imageId = imageId ?? this.imageId | ||
| 59 | + ..status = status ?? this.status; | ||
| 60 | + } | ||
| 61 | +} | ||
| 0 | \ No newline at end of file | 62 | \ No newline at end of file | 
lib/models/popup_entity.dart
0 → 100644
| 1 | +import 'package:wow_english/generated/json/base/json_field.dart'; | ||
| 2 | +import 'package:wow_english/generated/json/popup_entity.g.dart'; | ||
| 3 | +import 'dart:convert'; | ||
| 4 | + | ||
| 5 | +@JsonSerializable() | ||
| 6 | +class PopupEntity { | ||
| 7 | + late String actionType; | ||
| 8 | + late String actionValue; | ||
| 9 | + late int dayNum; | ||
| 10 | + late String id; | ||
| 11 | + late String imageId; | ||
| 12 | + late int status; | ||
| 13 | + | ||
| 14 | + PopupEntity(); | ||
| 15 | + | ||
| 16 | + factory PopupEntity.fromJson(Map<String, dynamic> json) => $PopupEntityFromJson(json); | ||
| 17 | + | ||
| 18 | + Map<String, dynamic> toJson() => $PopupEntityToJson(this); | ||
| 19 | + | ||
| 20 | + @override | ||
| 21 | + String toString() { | ||
| 22 | + return jsonEncode(this); | ||
| 23 | + } | ||
| 24 | +} | ||
| 0 | \ No newline at end of file | 25 | \ No newline at end of file | 
lib/pages/home/PopupType.dart
0 → 100644
lib/pages/home/bloc.dart
| @@ -2,6 +2,7 @@ import 'dart:async'; | @@ -2,6 +2,7 @@ import 'dart:async'; | ||
| 2 | 2 | ||
| 3 | import 'package:bloc/bloc.dart'; | 3 | import 'package:bloc/bloc.dart'; | 
| 4 | import 'package:wow_english/common/core/user_util.dart'; | 4 | import 'package:wow_english/common/core/user_util.dart'; | 
| 5 | +import 'package:wow_english/models/popup_entity.dart'; | ||
| 5 | import 'package:wow_english/utils/audio_player_util.dart'; | 6 | import 'package:wow_english/utils/audio_player_util.dart'; | 
| 6 | 7 | ||
| 7 | import '../../common/core/app_config_helper.dart'; | 8 | import '../../common/core/app_config_helper.dart'; | 
| @@ -24,6 +25,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | @@ -24,6 +25,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | ||
| 24 | AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.touch); | 25 | AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.touch); | 
| 25 | } | 26 | } | 
| 26 | await _checkUpdate(emit); | 27 | await _checkUpdate(emit); | 
| 28 | + await _getPopupInfo(emit); | ||
| 27 | } | 29 | } | 
| 28 | 30 | ||
| 29 | void _exchangeSuccess( | 31 | void _exchangeSuccess( | 
| @@ -51,4 +53,14 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | @@ -51,4 +53,14 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { | ||
| 51 | appVersionEntity)); | 53 | appVersionEntity)); | 
| 52 | } | 54 | } | 
| 53 | } | 55 | } | 
| 56 | + | ||
| 57 | + Future<void> _getPopupInfo(Emitter<HomeState> emit) async { | ||
| 58 | + PopupEntity? popupEntity = await SystemDao.getPopupInfo(); | ||
| 59 | + Log.d( | ||
| 60 | + "HomeBloc _getPopupInfo _getPopupInfo: $popupEntity"); | ||
| 61 | + if (popupEntity == null) { | ||
| 62 | + return; | ||
| 63 | + } | ||
| 64 | + emit(PopupDialogState(popupEntity)); | ||
| 65 | + } | ||
| 54 | } | 66 | } | 
lib/pages/home/state.dart
| 1 | import 'package:wow_english/models/app_version_entity.dart'; | 1 | import 'package:wow_english/models/app_version_entity.dart'; | 
| 2 | +import 'package:wow_english/models/popup_entity.dart'; | ||
| 2 | 3 | ||
| 3 | class HomeState { | 4 | class HomeState { | 
| 4 | HomeState init() { | 5 | HomeState init() { | 
| @@ -18,3 +19,10 @@ class UpdateDialogState extends HomeState { | @@ -18,3 +19,10 @@ class UpdateDialogState extends HomeState { | ||
| 18 | 19 | ||
| 19 | UpdateDialogState(this.forceUpdate, this.appVersionEntity); | 20 | UpdateDialogState(this.forceUpdate, this.appVersionEntity); | 
| 20 | } | 21 | } | 
| 22 | + | ||
| 23 | +class PopupDialogState extends HomeState { | ||
| 24 | + | ||
| 25 | + final PopupEntity popupEntity; | ||
| 26 | + | ||
| 27 | + PopupDialogState(this.popupEntity); | ||
| 28 | +} | 
lib/pages/home/view.dart
| 1 | import 'dart:io'; | 1 | import 'dart:io'; | 
| 2 | 2 | ||
| 3 | +import 'package:flutter/cupertino.dart'; | ||
| 3 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; | 
| 4 | import 'package:flutter/services.dart'; | 5 | import 'package:flutter/services.dart'; | 
| 5 | import 'package:flutter_app_update/azhon_app_update.dart'; | 6 | import 'package:flutter_app_update/azhon_app_update.dart'; | 
| @@ -11,6 +12,8 @@ import 'package:wow_english/common/core/app_config_helper.dart'; | @@ -11,6 +12,8 @@ import 'package:wow_english/common/core/app_config_helper.dart'; | ||
| 11 | import 'package:wow_english/common/core/app_consts.dart'; | 12 | import 'package:wow_english/common/core/app_consts.dart'; | 
| 12 | import 'package:wow_english/common/extension/string_extension.dart'; | 13 | import 'package:wow_english/common/extension/string_extension.dart'; | 
| 13 | import 'package:wow_english/models/app_version_entity.dart'; | 14 | import 'package:wow_english/models/app_version_entity.dart'; | 
| 15 | +import 'package:wow_english/models/popup_entity.dart'; | ||
| 16 | +import 'package:wow_english/pages/home/PopupType.dart'; | ||
| 14 | import 'package:wow_english/pages/home/state.dart'; | 17 | import 'package:wow_english/pages/home/state.dart'; | 
| 15 | import 'package:wow_english/pages/home/widgets/BaseHomeHeaderWidget.dart'; | 18 | import 'package:wow_english/pages/home/widgets/BaseHomeHeaderWidget.dart'; | 
| 16 | import 'package:wow_english/pages/home/widgets/ShakeImage.dart'; | 19 | import 'package:wow_english/pages/home/widgets/ShakeImage.dart'; | 
| @@ -20,6 +23,7 @@ import 'package:wow_english/utils/audio_player_util.dart'; | @@ -20,6 +23,7 @@ import 'package:wow_english/utils/audio_player_util.dart'; | ||
| 20 | import '../../common/core/user_util.dart'; | 23 | import '../../common/core/user_util.dart'; | 
| 21 | import '../../common/dialogs/show_dialog.dart'; | 24 | import '../../common/dialogs/show_dialog.dart'; | 
| 22 | import '../../common/utils/click_with_music_controller.dart'; | 25 | import '../../common/utils/click_with_music_controller.dart'; | 
| 26 | +import '../../common/widgets/ow_image_widget.dart'; | ||
| 23 | import 'bloc.dart'; | 27 | import 'bloc.dart'; | 
| 24 | import 'event.dart'; | 28 | import 'event.dart'; | 
| 25 | import 'package:flutter_screenutil/flutter_screenutil.dart'; | 29 | import 'package:flutter_screenutil/flutter_screenutil.dart'; | 
| @@ -49,6 +53,8 @@ class _HomePageView extends StatelessWidget { | @@ -49,6 +53,8 @@ class _HomePageView extends StatelessWidget { | ||
| 49 | if (state is UpdateDialogState) { | 53 | if (state is UpdateDialogState) { | 
| 50 | _showUpdateDialog( | 54 | _showUpdateDialog( | 
| 51 | context, state.forceUpdate, state.appVersionEntity); | 55 | context, state.forceUpdate, state.appVersionEntity); | 
| 56 | + } else if (state is PopupDialogState) { | ||
| 57 | + _showPopupDialog(context, state.popupEntity); | ||
| 52 | } | 58 | } | 
| 53 | }, | 59 | }, | 
| 54 | ), | 60 | ), | 
| @@ -314,4 +320,54 @@ class _HomePageView extends StatelessWidget { | @@ -314,4 +320,54 @@ class _HomePageView extends StatelessWidget { | ||
| 314 | throw 'Could not launch $url'; | 320 | throw 'Could not launch $url'; | 
| 315 | } | 321 | } | 
| 316 | } | 322 | } | 
| 323 | + | ||
| 324 | + ///popup对话框 | ||
| 325 | + void _showPopupDialog(BuildContext context, PopupEntity popupEntity) { | ||
| 326 | + if (popupEntity.imageId.isEmpty) { | ||
| 327 | + return; | ||
| 328 | + } | ||
| 329 | + showDialog( | ||
| 330 | + context: context, | ||
| 331 | + barrierDismissible: false, | ||
| 332 | + builder: (BuildContext context) { | ||
| 333 | + return Dialog( | ||
| 334 | + backgroundColor: Colors.transparent, | ||
| 335 | + child: Stack( | ||
| 336 | + alignment: Alignment.topRight, | ||
| 337 | + children: [ | ||
| 338 | + // 图片内容区域 | ||
| 339 | + ClipRRect( | ||
| 340 | + borderRadius: BorderRadius.circular(16), // 可选:圆角 | ||
| 341 | + child: GestureDetector( | ||
| 342 | + onTap: () { | ||
| 343 | + if (popupEntity.actionType == PopupType.h5.name && | ||
| 344 | + popupEntity.actionValue.isNotEmpty) { | ||
| 345 | + Navigator.of(context).pop(); | ||
| 346 | + Navigator.of(context).pushNamed(AppRouteName.webView, | ||
| 347 | + arguments: {'urlStr': popupEntity.actionValue}); | ||
| 348 | + } | ||
| 349 | + }, | ||
| 350 | + child: OwImageWidget( | ||
| 351 | + height: MediaQuery.of(context).size.height * 0.8, | ||
| 352 | + name: popupEntity.imageId, | ||
| 353 | + fit: BoxFit.fitHeight), | ||
| 354 | + ), | ||
| 355 | + ), | ||
| 356 | + Positioned( | ||
| 357 | + top: 0, | ||
| 358 | + right: 0, | ||
| 359 | + child: IconButton( | ||
| 360 | + icon: const Icon(Icons.close, color: Colors.white, opticalSize: 2), | ||
| 361 | + onPressed: () { | ||
| 362 | + Navigator.of(context).pop(); | ||
| 363 | + }, | ||
| 364 | + ), | ||
| 365 | + ), | ||
| 366 | + ], | ||
| 367 | + // 图片宽度和高度是屏幕高度的80%,右上角有一个关闭按钮,点击关闭按钮关闭对话框,图片水平居中,高度在按钮垂直方向下方 | ||
| 368 | + ), | ||
| 369 | + ); | ||
| 370 | + }, | ||
| 371 | + ); | ||
| 372 | + } | ||
| 317 | } | 373 | } | 
lib/route/route.dart
| @@ -217,7 +217,7 @@ class AppRouter { | @@ -217,7 +217,7 @@ class AppRouter { | ||
| 217 | case AppRouteName.webView: | 217 | case AppRouteName.webView: | 
| 218 | final urlStr = (settings.arguments as Map)['urlStr'] as String; | 218 | final urlStr = (settings.arguments as Map)['urlStr'] as String; | 
| 219 | final webViewTitle = | 219 | final webViewTitle = | 
| 220 | - (settings.arguments as Map)['webViewTitle'] as String; | 220 | + (settings.arguments as Map)['webViewTitle'] as String?; | 
| 221 | return CupertinoPageRoute( | 221 | return CupertinoPageRoute( | 
| 222 | builder: (_) => WowWebViewPage( | 222 | builder: (_) => WowWebViewPage( | 
| 223 | urlStr: urlStr, | 223 | urlStr: urlStr, | 
