Commit 99b94d6c8c09e2acd87603a1e61ee770cc607bbf

Authored by 吴启风
1 parent 09fb1af9

feat:首页增加信息弹窗

lib/common/request/api_response/api_response_entity.dart
1 import 'dart:convert'; 1 import 'dart:convert';
2 2
3 -import 'api_response_entity.g.dart'; 3 +import 'package:wow_english/common/request/api_response/api_response_entity.g.dart';
  4 +
4 5
5 class ApiResponse<T> { 6 class ApiResponse<T> {
6 int? code; 7 int? code;
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 &#39;package:wow_english/models/course_section_entity.dart&#39;; @@ -14,6 +14,7 @@ import &#39;package:wow_english/models/course_section_entity.dart&#39;;
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
  1 +enum PopupType {
  2 + ///无交互
  3 + none,
  4 +
  5 + ///网页
  6 + h5,
  7 +
  8 + ///协议。如果是协议的话 获得的就是一个协议链接 jump://home/buy?courseMealId=1(暂时没有使用场景)
  9 + protocol
  10 +}
0 \ No newline at end of file 11 \ No newline at end of file
lib/pages/home/bloc.dart
@@ -2,6 +2,7 @@ import &#39;dart:async&#39;; @@ -2,6 +2,7 @@ import &#39;dart:async&#39;;
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&lt;HomeEvent, HomeState&gt; { @@ -24,6 +25,7 @@ class HomeBloc extends Bloc&lt;HomeEvent, HomeState&gt; {
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&lt;HomeEvent, HomeState&gt; { @@ -51,4 +53,14 @@ class HomeBloc extends Bloc&lt;HomeEvent, HomeState&gt; {
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 &#39;package:wow_english/common/core/app_config_helper.dart&#39;; @@ -11,6 +12,8 @@ import &#39;package:wow_english/common/core/app_config_helper.dart&#39;;
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 &#39;package:wow_english/utils/audio_player_util.dart&#39;; @@ -20,6 +23,7 @@ import &#39;package:wow_english/utils/audio_player_util.dart&#39;;
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,