Commit 228651ed158a20289130e7f93e33e8c051b6166b

Authored by 吴启风
1 parent 0963e27a

feat:弹窗最多次数逻辑

lib/common/utils/popup_manager.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:intl/intl.dart';
  3 +
  4 +import '../../models/popup_entity.dart';
  5 +import '../../pages/home/PopupType.dart';
  6 +import '../../route/route.dart';
  7 +import '../../utils/log_util.dart';
  8 +import '../../utils/sp_util.dart';
  9 +import '../widgets/ow_image_widget.dart';
  10 +
  11 +class PopupManager {
  12 + // 获取今日弹窗次数的键
  13 + static String _getPopupCountKey(String popupId) {
  14 + String today = DateFormat('yyyy-MM-dd').format(DateTime.now());
  15 + return 'popup_count_$popupId\_$today';
  16 + }
  17 +
  18 + // 获取今日弹窗次数
  19 + static int _getPopupCount(String popupId) {
  20 + String key = _getPopupCountKey(popupId);
  21 + return SpUtil.getInstance().get(key) ?? 0;
  22 + }
  23 +
  24 + // 更新今日弹窗次数
  25 + static void _incrementPopupCount(String popupId) {
  26 + String key = _getPopupCountKey(popupId);
  27 + int currentCount = _getPopupCount(popupId);
  28 + SpUtil.getInstance().setData(key, currentCount + 1);
  29 + }
  30 +
  31 + // 检查是否可以弹窗
  32 + static bool canShowPopup(PopupEntity popupEntity) {
  33 + int todayPopupCount = _getPopupCount(popupEntity.id);
  34 + return todayPopupCount < popupEntity.dayNum;
  35 + }
  36 +
  37 + // 显示弹窗逻辑
  38 + static Future<void> showPopupIfAllowed(
  39 + BuildContext context, PopupEntity popupEntity) async {
  40 + if (popupEntity.imageUrl.isEmpty) {
  41 + return;
  42 + }
  43 + if (canShowPopup(popupEntity)) {
  44 + /// 弹窗内容:图片和关闭按钮
  45 + await showDialog(
  46 + context: context,
  47 + barrierDismissible: false,
  48 + builder: (BuildContext context) {
  49 + return Dialog(
  50 + shape: RoundedRectangleBorder(
  51 + borderRadius: BorderRadius.circular(8.0)),
  52 + child: Stack(
  53 + alignment: Alignment.topRight,
  54 + children: [
  55 + // 图片内容区域
  56 + ClipRRect(
  57 + borderRadius: BorderRadius.circular(16), // 可选:圆角
  58 + child: GestureDetector(
  59 + onTap: () {
  60 + if (popupEntity.actionType == PopupType.h5.name &&
  61 + popupEntity.actionValue.isNotEmpty) {
  62 + Navigator.of(context).pop();
  63 + Navigator.of(context).pushNamed(AppRouteName.webView,
  64 + arguments: {'urlStr': popupEntity.actionValue});
  65 + }
  66 + },
  67 + child: OwImageWidget(
  68 + height: MediaQuery.of(context).size.height * 0.8,
  69 + name: popupEntity.imageUrl,
  70 + fit: BoxFit.fitHeight),
  71 + ),
  72 + ),
  73 + Positioned(
  74 + top: 0,
  75 + right: 0,
  76 + child: IconButton(
  77 + icon: const Icon(Icons.close,
  78 + color: Colors.white,
  79 + opticalSize: 2,
  80 + shadows: [Shadow(color: Colors.black, blurRadius: 24)]),
  81 + onPressed: () {
  82 + Navigator.of(context).pop();
  83 + },
  84 + ),
  85 + ),
  86 + ],
  87 + ),
  88 + );
  89 + },
  90 + );
  91 +
  92 + // 更新今日弹窗次数
  93 + _incrementPopupCount(popupEntity.id);
  94 + }
  95 + }
  96 +}
lib/models/popup_entity.dart
@@ -6,6 +6,7 @@ import &#39;dart:convert&#39;; @@ -6,6 +6,7 @@ import &#39;dart:convert&#39;;
6 class PopupEntity { 6 class PopupEntity {
7 late String actionType; 7 late String actionType;
8 late String actionValue; 8 late String actionValue;
  9 + ///一天最多弹窗次数
9 late int dayNum; 10 late int dayNum;
10 late String id; 11 late String id;
11 late String imageUrl; 12 late String imageUrl;
lib/pages/home/view.dart
@@ -11,9 +11,8 @@ import &#39;package:url_launcher/url_launcher.dart&#39;; @@ -11,9 +11,8 @@ import &#39;package:url_launcher/url_launcher.dart&#39;;
11 import 'package:wow_english/common/core/app_config_helper.dart'; 11 import 'package:wow_english/common/core/app_config_helper.dart';
12 import 'package:wow_english/common/core/app_consts.dart'; 12 import 'package:wow_english/common/core/app_consts.dart';
13 import 'package:wow_english/common/extension/string_extension.dart'; 13 import 'package:wow_english/common/extension/string_extension.dart';
  14 +import 'package:wow_english/common/utils/popup_manager.dart';
14 import 'package:wow_english/models/app_version_entity.dart'; 15 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';  
17 import 'package:wow_english/pages/home/state.dart'; 16 import 'package:wow_english/pages/home/state.dart';
18 import 'package:wow_english/pages/home/widgets/BaseHomeHeaderWidget.dart'; 17 import 'package:wow_english/pages/home/widgets/BaseHomeHeaderWidget.dart';
19 import 'package:wow_english/pages/home/widgets/ShakeImage.dart'; 18 import 'package:wow_english/pages/home/widgets/ShakeImage.dart';
@@ -23,7 +22,6 @@ import &#39;package:wow_english/utils/audio_player_util.dart&#39;; @@ -23,7 +22,6 @@ import &#39;package:wow_english/utils/audio_player_util.dart&#39;;
23 import '../../common/core/user_util.dart'; 22 import '../../common/core/user_util.dart';
24 import '../../common/dialogs/show_dialog.dart'; 23 import '../../common/dialogs/show_dialog.dart';
25 import '../../common/utils/click_with_music_controller.dart'; 24 import '../../common/utils/click_with_music_controller.dart';
26 -import '../../common/widgets/ow_image_widget.dart';  
27 import 'bloc.dart'; 25 import 'bloc.dart';
28 import 'event.dart'; 26 import 'event.dart';
29 import 'package:flutter_screenutil/flutter_screenutil.dart'; 27 import 'package:flutter_screenutil/flutter_screenutil.dart';
@@ -54,7 +52,7 @@ class _HomePageView extends StatelessWidget { @@ -54,7 +52,7 @@ class _HomePageView extends StatelessWidget {
54 _showUpdateDialog( 52 _showUpdateDialog(
55 context, state.forceUpdate, state.appVersionEntity); 53 context, state.forceUpdate, state.appVersionEntity);
56 } else if (state is PopupDialogState) { 54 } else if (state is PopupDialogState) {
57 - _showPopupDialog(context, state.popupEntity); 55 + PopupManager.showPopupIfAllowed(context, state.popupEntity);
58 } 56 }
59 }, 57 },
60 ), 58 ),
@@ -320,59 +318,4 @@ class _HomePageView extends StatelessWidget { @@ -320,59 +318,4 @@ class _HomePageView extends StatelessWidget {
320 throw 'Could not launch $url'; 318 throw 'Could not launch $url';
321 } 319 }
322 } 320 }
323 -  
324 - ///popup对话框  
325 - void _showPopupDialog(BuildContext context, PopupEntity popupEntity) {  
326 - if (popupEntity.imageUrl.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.imageUrl,  
353 - fit: BoxFit.fitHeight),  
354 - ),  
355 - ),  
356 - Positioned(  
357 - top: 0,  
358 - right: 0,  
359 - child: IconButton(  
360 - icon: const Icon(  
361 - Icons.close,  
362 - color: Colors.white,  
363 - opticalSize: 2,  
364 - shadows: [Shadow(color: Colors.black, blurRadius: 24)],  
365 - ),  
366 - onPressed: () {  
367 - Navigator.of(context).pop();  
368 - },  
369 - ),  
370 - ),  
371 - ],  
372 - // 图片宽度和高度是屏幕高度的80%,右上角有一个关闭按钮,点击关闭按钮关闭对话框,图片水平居中,高度在按钮垂直方向下方  
373 - ),  
374 - );  
375 - },  
376 - );  
377 - }  
378 } 321 }
pubspec.yaml
@@ -120,6 +120,8 @@ dependencies: @@ -120,6 +120,8 @@ dependencies:
120 percent_indicator: ^4.2.3 120 percent_indicator: ^4.2.3
121 # lottie动画 https://pub.dev/packages/lottie 121 # lottie动画 https://pub.dev/packages/lottie
122 lottie: ^3.1.2 122 lottie: ^3.1.2
  123 + # 提供国际化和本地化功能,包括消息翻译、复数和性别、日期/数字格式设置和解析以及双向文本。https://pub.dev/packages/intl
  124 + intl: ^0.19.0
123 125
124 dependency_overrides: 126 dependency_overrides:
125 # lottie 3.1.2 depends on http ^1.0.0 umeng_apm_sdk >=2.0.1 depends on http ^0.13.1 127 # lottie 3.1.2 depends on http ^1.0.0 umeng_apm_sdk >=2.0.1 depends on http ^0.13.1