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 class PopupEntity {
7 7 late String actionType;
8 8 late String actionValue;
  9 + ///一天最多弹窗次数
9 10 late int dayNum;
10 11 late String id;
11 12 late String imageUrl;
... ...
lib/pages/home/view.dart
... ... @@ -11,9 +11,8 @@ import &#39;package:url_launcher/url_launcher.dart&#39;;
11 11 import 'package:wow_english/common/core/app_config_helper.dart';
12 12 import 'package:wow_english/common/core/app_consts.dart';
13 13 import 'package:wow_english/common/extension/string_extension.dart';
  14 +import 'package:wow_english/common/utils/popup_manager.dart';
14 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 16 import 'package:wow_english/pages/home/state.dart';
18 17 import 'package:wow_english/pages/home/widgets/BaseHomeHeaderWidget.dart';
19 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 22 import '../../common/core/user_util.dart';
24 23 import '../../common/dialogs/show_dialog.dart';
25 24 import '../../common/utils/click_with_music_controller.dart';
26   -import '../../common/widgets/ow_image_widget.dart';
27 25 import 'bloc.dart';
28 26 import 'event.dart';
29 27 import 'package:flutter_screenutil/flutter_screenutil.dart';
... ... @@ -54,7 +52,7 @@ class _HomePageView extends StatelessWidget {
54 52 _showUpdateDialog(
55 53 context, state.forceUpdate, state.appVersionEntity);
56 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 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 120 percent_indicator: ^4.2.3
121 121 # lottie动画 https://pub.dev/packages/lottie
122 122 lottie: ^3.1.2
  123 + # 提供国际化和本地化功能,包括消息翻译、复数和性别、日期/数字格式设置和解析以及双向文本。https://pub.dev/packages/intl
  124 + intl: ^0.19.0
123 125  
124 126 dependency_overrides:
125 127 # lottie 3.1.2 depends on http ^1.0.0 umeng_apm_sdk >=2.0.1 depends on http ^0.13.1
... ...