删除埋点,im和客服
This commit is contained in:
@@ -6,7 +6,6 @@ import '../../hj_model/splash/ads_model.dart';
|
||||
import '../../hj_utils/screen.dart';
|
||||
import '../../tools_base/banner/ads_banner.dart';
|
||||
import '../../tools_base/banner/ads_item.dart';
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
|
||||
class AppCenterDialog extends StatefulWidget {
|
||||
final List<AdsInfoModel>? appList;
|
||||
@@ -60,7 +59,6 @@ class _AppCenterDialogState extends State<AppCenterDialog> {
|
||||
width: 329,
|
||||
height: 88,
|
||||
autoPlayMs: 5000,
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.home, adType: AdType.moreIcon),
|
||||
),
|
||||
),
|
||||
//Flexible 兜住矮屏:内容再多也不会顶破屏幕
|
||||
@@ -81,7 +79,6 @@ class _AppCenterDialogState extends State<AppCenterDialog> {
|
||||
itemBuilder: (context, index) {
|
||||
return AdsItem(
|
||||
adInfo: _appList[index],
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.home, adType: AdType.moreIcon),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:jydj/hj_model/splash/ads_model.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
|
||||
import '../../tools_base/banner/ads_item.dart';
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
|
||||
/// 系统公告--图片公告
|
||||
class NoticeImageDialog extends StatelessWidget {
|
||||
@@ -30,7 +29,6 @@ class NoticeImageDialog extends StatelessWidget {
|
||||
adInfo: model!,
|
||||
showType: AdShowType.img,
|
||||
aspectRatio: 6 / 8,
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.home, adType: AdType.dialog),
|
||||
),
|
||||
20.sizeBoxH,
|
||||
InkWell(enableFeedback: false,
|
||||
@@ -71,7 +69,6 @@ class SystemImagesDialog extends StatelessWidget {
|
||||
adInfo: ads![index],
|
||||
showType: AdShowType.img,
|
||||
aspectRatio: 6 / 8,
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.home, adType: AdType.dialog),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:easy_rich_text/easy_rich_text.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
@@ -12,7 +10,6 @@ import 'package:jydj/tools_base/unique_tag_mixin.dart';
|
||||
import 'package:jydj/tools_base/widget/sheet_handle_bar.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../assets_tool/images.dart';
|
||||
import '../../hj_model/splash/domain_source_model.dart';
|
||||
import '../../hj_page/main_page/provider/msg_provider.dart';
|
||||
import '../../hj_page/mine/mine_vip/mine_charge_vip_logic.dart';
|
||||
@@ -22,7 +19,6 @@ import '../../hj_page/mine/mine_vip/vip_pay_button.dart';
|
||||
import '../../hj_page/mine/mine_vip/vip_product_manager.dart';
|
||||
import '../../hj_page/mine/mine_vip/vip_support_model.dart';
|
||||
import '../../hj_page/mine/mine_vip/vip_ui_kit.dart';
|
||||
import '../../routers/jump_router.dart';
|
||||
import '../../tools_base/loading/loading_center_widget.dart';
|
||||
import 'buy_vip_alert_logic.dart';
|
||||
|
||||
@@ -207,18 +203,6 @@ class _BuyVipAlertState extends State<BuyVipAlert> with UniqueTagMixin {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_selectionBuilder((l) => VipPayButton(l, classic: classic)),
|
||||
12.sizeBoxH,
|
||||
EasyRichText(
|
||||
'支付问题反馈,点击联系 在线客服',
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString: '在线客服',
|
||||
style: const TextStyle(color: Color(0xFFFFD460), fontSize: 12),
|
||||
recognizer: TapGestureRecognizer()..onTap = () => pushToCustomService(),
|
||||
)
|
||||
],
|
||||
defaultStyle: const TextStyle(color: Color(0xffDCDCDC), fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -323,53 +307,6 @@ class _BuyVipAlertState extends State<BuyVipAlert> with UniqueTagMixin {
|
||||
});
|
||||
}
|
||||
|
||||
// 核心权益:横向滚动卡片 —— B 改版
|
||||
Widget _buildCorePrivileges(List<NewPrivilege> list) {
|
||||
if (list.isEmpty) return const SizedBox.shrink();
|
||||
return Column(
|
||||
children: [
|
||||
const VipCoreSectionTitleImage(),
|
||||
16.sizeBoxH,
|
||||
SizedBox(
|
||||
height: 92,
|
||||
child: ListView.separated(
|
||||
clipBehavior: Clip.none,
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.fromLTRB(16, 2, 16, 26),
|
||||
itemCount: list.length,
|
||||
separatorBuilder: (_, __) => 8.sizeBoxW,
|
||||
itemBuilder: (_, i) => VipCorePrivilegeCard(list[i]),
|
||||
),
|
||||
),
|
||||
16.sizeBoxH,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// 核心权益:一行金边方卡横向滑动 —— A / DISABLED
|
||||
Widget _buildClassicCorePrivileges(List<NewPrivilege> list) {
|
||||
if (list.isEmpty) return const SizedBox.shrink();
|
||||
return Column(
|
||||
children: [
|
||||
const VipSectionTitle('我的核心权益', classic: true),
|
||||
16.sizeBoxH,
|
||||
SizedBox(
|
||||
//设计稿一行放得下 4 张多一点,第 5 张露半张提示可以划
|
||||
height: 72,
|
||||
child: ListView.separated(
|
||||
clipBehavior: Clip.none, // 金边有外发光,裁了会缺一圈
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
itemCount: list.length,
|
||||
separatorBuilder: (_, __) => 8.sizeBoxW,
|
||||
itemBuilder: (_, i) => SizedBox(width: 72, child: VipCorePrivilegeCard(list[i], classic: true)),
|
||||
),
|
||||
),
|
||||
16.sizeBoxH,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// 更多权益:深色圆角 + 四列网格 —— B 改版
|
||||
Widget _buildMorePrivileges(List<NewPrivilege> list) {
|
||||
if (list.isEmpty) return const SizedBox.shrink();
|
||||
|
||||
@@ -3,9 +3,9 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/config/config.dart';
|
||||
import 'package:jydj/hj_model/user/user_info_model.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/toast.dart';
|
||||
import 'package:jydj/tools_base/widget/common_dialog.dart';
|
||||
@@ -72,7 +72,7 @@ class _ShareMediaDialogState extends State<ShareMediaDialog> {
|
||||
//app 图标 + 名称 + 标语
|
||||
Row(
|
||||
children: [
|
||||
Image.asset(HolidayTheme.theme.appIcon, width: 48.w, height: 48.w),
|
||||
Image.asset('ic_launcher.webp'.commonImgPath, width: 48.w, height: 48.w),
|
||||
10.w.sizeBoxW,
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -124,7 +124,7 @@ class _ShareMediaDialogState extends State<ShareMediaDialog> {
|
||||
),
|
||||
20.sizeBoxH,
|
||||
Text(
|
||||
'每邀请 1人 送 1天 会员 ${Address.groundUrl ?? ""}',
|
||||
'每邀请 1人 送 1天 会员 ${Address.groundUrl}',
|
||||
maxLines: 2,
|
||||
style: TextStyle(fontSize: 12, color: Colors.white.withValues(alpha: .55)),
|
||||
),
|
||||
|
||||
@@ -22,6 +22,4 @@ extension ImageLoad on String {
|
||||
String get launchPath => 'assets/images/launch/$this';
|
||||
//app icon
|
||||
String get appImgPath => 'assets/images/app_icon/$this';
|
||||
//节日皮肤
|
||||
String get holidayPath => 'assets/images/holiday/$this';
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import '../../tools_base/banner/ads_grid_view.dart';
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
|
||||
/// 广告信息
|
||||
class AdsInfoModel {
|
||||
@@ -59,13 +58,6 @@ class AdsInfoModel {
|
||||
_ => AdStyle.twoAutoScroll,
|
||||
};
|
||||
|
||||
/// 广告样式对应的埋点类型
|
||||
AdType get adType => switch (coverImgSize) {
|
||||
'vertical-cube' => AdType.verticalIcon,
|
||||
'banner-720300' => AdType.bigBanner,
|
||||
_ => AdType.smallIcon,
|
||||
};
|
||||
|
||||
//同时兼容 Adv(image/name/url) 与 ShuApp(icon/name/url) 字段
|
||||
AdsInfoModel.fromJson(dynamic json) {
|
||||
json ??= {};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/im_manager/im_manager.dart';
|
||||
|
||||
/// 用户信息
|
||||
class UserInfoModel {
|
||||
@@ -52,11 +51,6 @@ class UserInfoModel {
|
||||
// —— 状态 / 权限 ——
|
||||
int? adverAbTestShowType; // 广告AB -1-首次进app免广告 0-全部展示 其他N-注册后N分钟内免广告(分层后固定不变)
|
||||
|
||||
// —— IM 私信 ——
|
||||
String? imToken; // IM SDK 登录令牌
|
||||
int? imUserId; // IM 用户 id
|
||||
int? sendMsgPrice; // 私信消费金币
|
||||
|
||||
// ============ 计算属性 ============
|
||||
|
||||
/// 观影券总数量
|
||||
@@ -127,17 +121,6 @@ class UserInfoModel {
|
||||
level = map['level'];
|
||||
|
||||
adverAbTestShowType = map['adverAbTestShowType'];
|
||||
|
||||
imToken = map['imToken'];
|
||||
imUserId = map['imUserId'];
|
||||
sendMsgPrice = map['sendMsgPrice'];
|
||||
// IM SDK 连接配置随登录返回,写入 ImManager 供初始化使用
|
||||
if (map['socketURL']?.toString().isNotEmpty == true) {
|
||||
ImManager().socketURL = map['socketURL'];
|
||||
}
|
||||
if (map['dynamicConfigDomain']?.toString().isNotEmpty == true) {
|
||||
ImManager().dynamicConfigDomain = map['dynamicConfigDomain'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:jydj/tools_base/widget/keep_alive_widget.dart';
|
||||
|
||||
import '../../hj_utils/holiday_theme.dart';
|
||||
import '../../hj_utils/widget_util.dart';
|
||||
import 'ai_home_logic.dart';
|
||||
import 'ai_record/ai_main_record_page.dart';
|
||||
@@ -21,20 +20,11 @@ class AiHomePage extends StatelessWidget {
|
||||
builder: (logic) {
|
||||
return Stack(
|
||||
children: [
|
||||
if (holidayTheme.openHoliday) ...[
|
||||
Container(color: AppColors.primaryColor),
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Image.asset(HolidayTheme.theme.mainBg, fit: BoxFit.fitWidth),
|
||||
),
|
||||
],
|
||||
Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: AppBar(
|
||||
title: Text('AI科技'),
|
||||
backgroundColor: holidayTheme.openHoliday ? Colors.transparent : AppColors.primaryColor,
|
||||
backgroundColor: AppColors.primaryColor,
|
||||
actions: [
|
||||
Center(
|
||||
child: InkWell(
|
||||
|
||||
@@ -124,8 +124,7 @@ class AIModDetailPage extends StatelessWidget {
|
||||
'''1. 选择一张人脸清晰,不得有任何遮挡的照片上传(注意:只含一个人物和脸部,图片不能过暗)
|
||||
2. 选择一个心仪的视频或图片模板,点击生成,生成时间需要3-5分钟,耐心等待。(图片模板可自行上传)
|
||||
3. 在右上角记录查看生成进度,生成成功后可以点击进行下载,也可以在线观看。
|
||||
4. 按照上方操作,有问题随时联系在线客服进行处理。
|
||||
5. 不支持多人图片,禁止未成年人图片''',
|
||||
4. 不支持多人图片,禁止未成年人图片''',
|
||||
style: TextStyle(
|
||||
color: Color(0xff656565),
|
||||
fontSize: 12,
|
||||
|
||||
@@ -167,7 +167,7 @@ class AIStripSubPage extends StatelessWidget {
|
||||
indicatorStyle: IndicatorStyle.dot,
|
||||
onTap: (index) {
|
||||
final ad = (logic.modList!.aiUndressMod ?? [])[index];
|
||||
pushToPageByLink(ad.href, id: ad.id);
|
||||
pushToPageByLink(ad.href);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import 'package:easy_rich_text/easy_rich_text.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/hj_utils/api_service/ai_service.dart';
|
||||
import 'package:jydj/routers/jump_router.dart';
|
||||
import 'package:jydj/tools_base/debug_log.dart';
|
||||
@@ -26,20 +23,11 @@ class AIGirlSheet extends StatefulWidget {
|
||||
class _AIGirlSheetState extends State<AIGirlSheet> {
|
||||
int selectIndex = 0;
|
||||
|
||||
//TapGestureRecognizer 必须自己释放,建一次复用,别在 build 里 new
|
||||
final _serviceTap = TapGestureRecognizer()..onTap = pushToCustomService;
|
||||
|
||||
List<AIGirlFriendCurrency> get _items => widget.list ?? [];
|
||||
|
||||
//列表可能为空,取不到就没得选
|
||||
AIGirlFriendCurrency? get _selected => selectIndex < _items.length ? _items[selectIndex] : null;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_serviceTap.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
@@ -107,20 +95,6 @@ class _AIGirlSheetState extends State<AIGirlSheet> {
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
EasyRichText(
|
||||
'支付中如有问题 请联系在线客服',
|
||||
textAlign: TextAlign.center,
|
||||
defaultStyle: textStyle(12, Colors.white.withValues(alpha: .6), FontWeight.w400),
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString: '在线客服',
|
||||
matchOption: 'first',
|
||||
style: const TextStyle(color: AppColors.primaryHighColor),
|
||||
recognizer: _serviceTap,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'package:jydj/tools_base/toast.dart';
|
||||
import 'package:jydj/tools_base/video_download/video_cache_store.dart';
|
||||
import 'package:jydj/tools_base/video_download/video_download_manager.dart';
|
||||
import 'package:jydj/tools_base/widget/image_browser_page.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
import '../../video/simple_video_player_page.dart';
|
||||
import '../ai_sub_type/ai_function_logic.dart';
|
||||
@@ -145,12 +144,6 @@ class AIImageRecord extends StatelessWidget {
|
||||
await VideoCacheStore.instance.saveVideoInfo(MediaStyle.Video, viewModel);
|
||||
}
|
||||
|
||||
Future<bool> _checkPermission() async {
|
||||
var status = await Permission.storage.status;
|
||||
if (!status.isGranted) status = await Permission.storage.request();
|
||||
return status.isGranted;
|
||||
}
|
||||
|
||||
//视频换脸的结果位单独接播放器,链接由 VideoModel 拼(和 AiRecordModel.realVideoUrl 的 query 不一样)
|
||||
void _playResultVideo() {
|
||||
final videoModel = VideoModel()..sourceURL = model.url;
|
||||
|
||||
@@ -67,7 +67,7 @@ class _AudioPlayerContentState extends State<AudioPlayerContent> {
|
||||
18.sizeBoxH,
|
||||
_progressRow(audioValue, progress, max),
|
||||
14.sizeBoxH,
|
||||
_controlRow(audioValue, progress),
|
||||
_controlRow(audioValue),
|
||||
18.sizeBoxH,
|
||||
],
|
||||
);
|
||||
@@ -142,7 +142,7 @@ class _AudioPlayerContentState extends State<AudioPlayerContent> {
|
||||
}
|
||||
|
||||
// 控制行:循环模式、上一集/播放暂停/下一集、播放列表
|
||||
Widget _controlRow(AudioPlayerValue audioValue, double progress) {
|
||||
Widget _controlRow(AudioPlayerValue audioValue) {
|
||||
final isLoop = playMod == AudioPlayMod.loop;
|
||||
final isPlaying = audioValue.isPlaying ?? false;
|
||||
return Row(
|
||||
@@ -179,7 +179,7 @@ class _AudioPlayerContentState extends State<AudioPlayerContent> {
|
||||
children: [
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => manager.playForward(progress),
|
||||
onTap: () => manager.playForward(),
|
||||
child: Image.asset('forward.png'.acgImgPath, width: 24),
|
||||
),
|
||||
40.sizeBoxW,
|
||||
@@ -199,7 +199,7 @@ class _AudioPlayerContentState extends State<AudioPlayerContent> {
|
||||
40.sizeBoxW,
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => manager.playNext(progress),
|
||||
onTap: () => manager.playNext(),
|
||||
child: Image.asset('next.png'.acgImgPath, width: 24),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analytics_sdk/enum/read_behavior_enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_model/media_content.dart';
|
||||
@@ -8,7 +7,6 @@ import 'package:jydj/tools_base/toast.dart';
|
||||
import 'package:jydj/tools_base/widget/scroll_positioned_list/src/item_positions_listener.dart';
|
||||
import 'package:jydj/tools_base/widget/scroll_positioned_list/src/scrollable_positioned_list.dart';
|
||||
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
import 'widget/acg_source_manager.dart';
|
||||
|
||||
class CartoonReadLogic extends GetxController {
|
||||
@@ -21,7 +19,6 @@ class CartoonReadLogic extends GetxController {
|
||||
bool showProgress = false; // 展示进度
|
||||
bool sortType = true; // 排序类型 true-正序 false-倒序
|
||||
bool autoPlay = false; // 是否自动播放
|
||||
bool playFinish = false; // 是否触底播放完成
|
||||
double readScale = 0; // 播放比例
|
||||
double bottomHeight = 155;
|
||||
int animationTime = 250; // 显示时间(ms)
|
||||
@@ -74,7 +71,7 @@ class CartoonReadLogic extends GetxController {
|
||||
showToast('这是最后一${manager.mediaInfo?.unit}了喔~');
|
||||
return;
|
||||
}
|
||||
_openEpisode(index, behavior: next ? ReadBehaviorEnum.PAGE_NEXT : ReadBehaviorEnum.PAGE_PREV);
|
||||
_openEpisode(index);
|
||||
}
|
||||
|
||||
// 目录点击切章
|
||||
@@ -105,7 +102,7 @@ class CartoonReadLogic extends GetxController {
|
||||
// 松手:jumpTo 的位置回调下一帧才到,延后一帧再放开
|
||||
void onSeekEnd(double value) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// 拖动期间位置回调被屏蔽,松手补一次触底结算,别把「读完」埋点漏了;
|
||||
// 拖动期间位置回调被屏蔽,松手补一次触底结算(停自动播放);
|
||||
// 放在解锁之前,免得这一步引起的滚动又被 onScrollAction 收了菜单
|
||||
_checkReachBottom();
|
||||
_isSeeking = false;
|
||||
@@ -155,9 +152,9 @@ class CartoonReadLogic extends GetxController {
|
||||
}
|
||||
|
||||
// ========== 私有方法 ==========
|
||||
/// 切章统一入口:权限/缓存都在 manager 里,这里只管埋点顺序和刷新
|
||||
/// [behavior] 非空则先补一条翻页行为(用旧章数据),[isFirstLoad] 失败时才进错误页
|
||||
Future<void> _openEpisode(int index, {ReadBehaviorEnum? behavior, bool isFirstLoad = false}) async {
|
||||
/// 切章统一入口:权限/缓存都在 manager 里,这里只管状态重置和刷新
|
||||
/// [isFirstLoad] 失败时才进错误页
|
||||
Future<void> _openEpisode(int index, {bool isFirstLoad = false}) async {
|
||||
// 首次进入页面已有全屏 loading,不再叠遮罩
|
||||
final model = await manager.getComicsMediaContent(index: index, showLoading: !isFirstLoad);
|
||||
if (model == null) {
|
||||
@@ -165,29 +162,10 @@ class CartoonReadLogic extends GetxController {
|
||||
update();
|
||||
return;
|
||||
}
|
||||
// 上下翻页,先上传切换行为(旧章的进度和集号),再上传展示行为
|
||||
if (behavior != null) {
|
||||
TrackVideoManager.comicEvent(
|
||||
behavior,
|
||||
model: manager.mediaInfo,
|
||||
readProgress: (readScale * 100).floor(),
|
||||
pageNo: currentEpisode + 1,
|
||||
mediaContent: detailInfo,
|
||||
);
|
||||
}
|
||||
currentEpisode = index;
|
||||
detailInfo = model;
|
||||
readIndex = 0;
|
||||
readScale = 0;
|
||||
playFinish = false; // 重置播放完成状态
|
||||
// 漫画展示
|
||||
TrackVideoManager.comicEvent(
|
||||
ReadBehaviorEnum.VIEW,
|
||||
model: manager.mediaInfo,
|
||||
readProgress: 0,
|
||||
pageNo: currentEpisode + 1,
|
||||
mediaContent: model,
|
||||
);
|
||||
update();
|
||||
// 首次加载时列表还没 build,controller 未 attach,跳转会空断言崩
|
||||
if (itemScrollCtr.isAttached) itemScrollCtr.jumpTo(index: 0);
|
||||
@@ -205,24 +183,14 @@ class CartoonReadLogic extends GetxController {
|
||||
update(['slider']);
|
||||
}
|
||||
|
||||
// 触底:停自动播放(顺带弹回菜单)+ 上报读完
|
||||
// 触底:停自动播放(顺带弹回菜单)
|
||||
void _checkReachBottom() {
|
||||
final positions = itemListener.itemPositions.value;
|
||||
if (positions.isEmpty) return;
|
||||
final count = detailInfo?.urlSet?.length ?? 0;
|
||||
// 首图还在视野内就不算触底(整章不足一屏时不上报读完)
|
||||
// 首图还在视野内就不算触底(整章不足一屏时不处理)
|
||||
if (positions.first.index == 0 || positions.last.index != count - 1) return;
|
||||
onChangeAutoPlay(false);
|
||||
// 播放完毕只记录一次
|
||||
if (playFinish) return;
|
||||
playFinish = true;
|
||||
TrackVideoManager.comicEvent(
|
||||
ReadBehaviorEnum.COMPLETE,
|
||||
model: manager.mediaInfo,
|
||||
readProgress: 100,
|
||||
pageNo: manager.index + 1,
|
||||
mediaContent: detailInfo,
|
||||
);
|
||||
}
|
||||
|
||||
void _startTimer() {
|
||||
|
||||
@@ -21,6 +21,6 @@ class CartoonSubDetailPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CartoonSubGridPage(tagData: tagData, type: type, scrollCtr: scroll, tabIndex: index).keepAlive;
|
||||
return CartoonSubGridPage(tagData: tagData, type: type, scrollCtr: scroll).keepAlive;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import 'package:jydj/hj_utils/api_service/vid_service.dart';
|
||||
import 'package:jydj/hj_utils/const.dart';
|
||||
import 'package:jydj/tools_base/base_list_controller.dart';
|
||||
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
|
||||
class CartoonSubGridLogic extends ListBaseLogic {
|
||||
final MediaStyle type; //-1:动漫和漫画 0:图集 1:黄游 2:小说
|
||||
final ModuleData? tagData; //模块model
|
||||
@@ -30,14 +28,6 @@ class CartoonSubGridLogic extends ListBaseLogic {
|
||||
return 1;
|
||||
}
|
||||
|
||||
TrackEventPageType get pageType {
|
||||
if (type == MediaStyle.Cartoon) return TrackEventPageType.home;
|
||||
if (type == MediaStyle.Pic) return TrackEventPageType.commImg;
|
||||
if (type == MediaStyle.Game) return TrackEventPageType.commNovel;
|
||||
if (type == MediaStyle.Novel) return TrackEventPageType.commNovel;
|
||||
return TrackEventPageType.home;
|
||||
}
|
||||
|
||||
String get newsType {
|
||||
if (tagData?.moduleName == '热门推荐' && tagData?.type == -100) return 'PIC';
|
||||
if (tagData?.moduleName == '热门推荐' && tagData?.type == -101) return 'SEED_LINK';
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'package:jydj/hj_utils/sliver_delegate.dart';
|
||||
import 'package:jydj/tools_base/banner/ads_grid_view.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:jydj/tools_base/refresh/pull_refresh.dart';
|
||||
import 'package:jydj/track_event_manager/track_manager.dart';
|
||||
|
||||
import '../home/home_cell_style/quick_entry_row.dart';
|
||||
import '../home/home_cell_style/video_simple_cell.dart';
|
||||
@@ -21,14 +20,12 @@ class CartoonSubGridPage extends StatelessWidget {
|
||||
final ModuleData? tagData; //模块model
|
||||
final MediaStyle type; //-1:动漫和漫画 0:图集 1:黄游 2:小说
|
||||
final ScrollController? scrollCtr;
|
||||
final int tabIndex; //所属 tab 下标,只用于广告曝光埋点
|
||||
|
||||
const CartoonSubGridPage({
|
||||
super.key,
|
||||
this.tagData,
|
||||
this.type = MediaStyle.Pic,
|
||||
this.scrollCtr,
|
||||
this.tabIndex = 0,
|
||||
});
|
||||
|
||||
// 多 type/模块 tab 经 keepAlive 并存,按 id+type 隔离各自的 logic
|
||||
@@ -58,7 +55,6 @@ class CartoonSubGridPage extends StatelessWidget {
|
||||
type == MediaStyle.Cartoon ? 4 : 7, //广告位标识
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
|
||||
autoStyle: true,
|
||||
exposureModel: AdExposureModel(pageType: logic.pageType, tabIndex: tabIndex),
|
||||
),
|
||||
),
|
||||
// 这两块只有动漫/漫画有
|
||||
@@ -139,7 +135,6 @@ class CartoonSubGridPage extends StatelessWidget {
|
||||
videoModel: list[index],
|
||||
isFromHY: true,
|
||||
textLines: 1,
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.acgHome),
|
||||
),
|
||||
_ => const SizedBox.shrink(),
|
||||
},
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:analytics_sdk/enum/read_behavior_enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_model/media_content.dart';
|
||||
@@ -8,7 +7,6 @@ import 'package:jydj/tools_base/toast.dart';
|
||||
import '../../hj_model/acg/comic_chapters_model.dart';
|
||||
import '../../hj_model/cartoon_media_info.dart';
|
||||
import '../../tools_base/loading/loading_helper.dart';
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
import 'widget/acg_source_manager.dart';
|
||||
|
||||
// 文字小说阅读 logic
|
||||
@@ -23,10 +21,7 @@ class TextNovelReadLogic extends GetxController {
|
||||
bool showMenu = true;
|
||||
bool isDark = true;
|
||||
bool isAscend = true; // 排序类型 true-正序 false-倒序
|
||||
bool playFinish = false; // 是否触底播放完成
|
||||
bool isSwitching = false; // 是否正在切换集,避免竞态
|
||||
int durationTime = 250;
|
||||
int progress = 0; // 0 ~ 100
|
||||
|
||||
final ScrollController scrollCtr = ScrollController();
|
||||
|
||||
@@ -37,7 +32,6 @@ class TextNovelReadLogic extends GetxController {
|
||||
super.onInit();
|
||||
mediaInfo = manager.mediaInfo;
|
||||
currentEpisode = manager.index;
|
||||
scrollCtr.addListener(_onScroll);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -49,7 +43,6 @@ class TextNovelReadLogic extends GetxController {
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
scrollCtr.removeListener(_onScroll);
|
||||
scrollCtr.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
@@ -68,9 +61,7 @@ class TextNovelReadLogic extends GetxController {
|
||||
|
||||
// true 下一集 / false 上一集
|
||||
void loadOtherEpisode(bool next, {bool showLoading = false}) async {
|
||||
isSwitching = true;
|
||||
final index = next ? currentEpisode + 1 : currentEpisode - 1;
|
||||
final pageNo = next ? index : currentEpisode + 1;
|
||||
if (index < 0) {
|
||||
showToast('这是第一${mediaInfo?.unit}了喔~');
|
||||
return;
|
||||
@@ -81,14 +72,6 @@ class TextNovelReadLogic extends GetxController {
|
||||
}
|
||||
final model = await manager.getComicsMediaContent(index: index);
|
||||
if (model == null) return;
|
||||
TrackVideoManager.novelEvent(
|
||||
next ? ReadBehaviorEnum.PAGE_NEXT : ReadBehaviorEnum.PAGE_PREV,
|
||||
model: manager.mediaInfo,
|
||||
readProgress: progress,
|
||||
pageNo: pageNo,
|
||||
chapterId: detailInfo?.id,
|
||||
chapterName: detailInfo?.name,
|
||||
);
|
||||
currentEpisode = index;
|
||||
_setData(model);
|
||||
update();
|
||||
@@ -138,19 +121,8 @@ class TextNovelReadLogic extends GetxController {
|
||||
void _setData(MediaContent? model) {
|
||||
if (model != null) {
|
||||
detailInfo = model;
|
||||
playFinish = false;
|
||||
progress = 0;
|
||||
manager.changeEpisodesIndex((model.episodeNumber ?? 1) - 1);
|
||||
update();
|
||||
// 小说展示
|
||||
TrackVideoManager.novelEvent(
|
||||
ReadBehaviorEnum.VIEW,
|
||||
model: manager.mediaInfo,
|
||||
readProgress: progress,
|
||||
pageNo: manager.index + 1,
|
||||
chapterId: model.id,
|
||||
chapterName: model.name,
|
||||
);
|
||||
} else {
|
||||
detailInfo = MediaContent();
|
||||
}
|
||||
@@ -160,26 +132,6 @@ class TextNovelReadLogic extends GetxController {
|
||||
void _toTop() {
|
||||
Future.delayed(const Duration(milliseconds: 100)).then((_) {
|
||||
scrollCtr.jumpTo(0);
|
||||
isSwitching = false;
|
||||
});
|
||||
}
|
||||
|
||||
void _onScroll() {
|
||||
if (!scrollCtr.hasClients) return;
|
||||
final position = scrollCtr.position;
|
||||
final max = position.maxScrollExtent;
|
||||
final current = position.pixels;
|
||||
progress = max > 0 ? ((current / max).clamp(0.0, 1.0) * 100).round() : 0;
|
||||
if (current >= max - 20 && !playFinish && !isSwitching) {
|
||||
playFinish = true;
|
||||
TrackVideoManager.novelEvent(
|
||||
ReadBehaviorEnum.COMPLETE,
|
||||
model: manager.mediaInfo,
|
||||
readProgress: progress,
|
||||
pageNo: manager.index + 1,
|
||||
chapterId: detailInfo?.id,
|
||||
chapterName: detailInfo?.name,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analytics_sdk/enum/read_behavior_enum.dart';
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -17,7 +16,6 @@ import '../../../alert/video/vip_acg_dialog.dart';
|
||||
import '../../../hj_model/acg/comic_chapters_model.dart';
|
||||
import '../../../hj_utils/api_service/acg_service.dart';
|
||||
import '../../../tools_base/global_store/store.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
|
||||
/// 小说/漫画/有声资源管理器
|
||||
class ACGSourceManager extends ChangeNotifier {
|
||||
@@ -245,14 +243,6 @@ class AudioPlayerManager {
|
||||
|
||||
double playSpeed = 1;
|
||||
|
||||
ComicChapterInfo? _currentEpisode() {
|
||||
final manager = sourceManger;
|
||||
if (manager == null || manager.index < 0 || manager.index >= manager.allEpisodes.length) {
|
||||
return null;
|
||||
}
|
||||
return manager.allEpisodes[manager.index];
|
||||
}
|
||||
|
||||
void initPlayer() {
|
||||
if (_audioPlayer != null) return; // 防重入:已初始化则跳过,避免 5 个 stream 监听重复注册、旧 sub 泄漏
|
||||
_audioPlayer = AudioPlayer();
|
||||
@@ -290,15 +280,7 @@ class AudioPlayerManager {
|
||||
_audioCompleSub = _audioPlayer?.onPlayerComplete.listen((event) {
|
||||
if (playMod == AudioPlayMod.loopList && (value.isPlaying ?? false)) {
|
||||
audioValue.value = AudioPlayerValue.copyWith(value..isPlaying = false);
|
||||
TrackVideoManager.novelEvent(
|
||||
ReadBehaviorEnum.COMPLETE,
|
||||
model: sourceManger?.mediaInfo,
|
||||
readProgress: 100,
|
||||
pageNo: (sourceManger?.index ?? 0) + 1,
|
||||
chapterId: _currentEpisode()?.id,
|
||||
chapterName: _currentEpisode()?.name,
|
||||
);
|
||||
playNext(0);
|
||||
playNext();
|
||||
} else {
|
||||
audioValue.value = AudioPlayerValue.copyWith(value
|
||||
..isCompleted = true
|
||||
@@ -340,30 +322,12 @@ class AudioPlayerManager {
|
||||
..duration = null);
|
||||
showToast('音频加载失败');
|
||||
});
|
||||
if (sourceManger?.mediaInfo != null) {
|
||||
TrackVideoManager.novelEvent(
|
||||
ReadBehaviorEnum.VIEW,
|
||||
model: sourceManger?.mediaInfo,
|
||||
readProgress: 0,
|
||||
pageNo: (sourceManger?.index ?? 0) + 1,
|
||||
chapterId: _currentEpisode()?.id,
|
||||
chapterName: _currentEpisode()?.name,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 上一集
|
||||
Future<void> playForward(double progress) async {
|
||||
Future<void> playForward() async {
|
||||
final epm = await sourceManger?.backToForward();
|
||||
if (epm != null) {
|
||||
TrackVideoManager.novelEvent(
|
||||
ReadBehaviorEnum.PAGE_PREV,
|
||||
model: sourceManger?.mediaInfo,
|
||||
readProgress: (progress * 100).round(),
|
||||
pageNo: (sourceManger?.index ?? 0) + 2,
|
||||
chapterId: epm.id,
|
||||
chapterName: epm.name,
|
||||
);
|
||||
play(epm.getRealAudioUrl);
|
||||
} else {
|
||||
pause();
|
||||
@@ -371,17 +335,9 @@ class AudioPlayerManager {
|
||||
}
|
||||
|
||||
/// 下一集
|
||||
Future<void> playNext(double progress) async {
|
||||
Future<void> playNext() async {
|
||||
final epm = await sourceManger?.jumpToNext();
|
||||
if (epm != null) {
|
||||
TrackVideoManager.novelEvent(
|
||||
ReadBehaviorEnum.PAGE_NEXT,
|
||||
model: sourceManger?.mediaInfo,
|
||||
readProgress: (progress * 100).round(),
|
||||
pageNo: sourceManger?.index ?? 0,
|
||||
chapterId: epm.id,
|
||||
chapterName: epm.name,
|
||||
);
|
||||
play(epm.getRealAudioUrl);
|
||||
} else {
|
||||
pause();
|
||||
|
||||
@@ -26,7 +26,7 @@ class CommentRichText extends StatelessWidget {
|
||||
if (i != parts.length - 1)
|
||||
WidgetSpan(
|
||||
child: GestureDetector(
|
||||
onTap: () => pushToPageByLink(model?.linkStr, id: model?.id),
|
||||
onTap: () => pushToPageByLink(model?.linkStr),
|
||||
child: Text(
|
||||
keyword,
|
||||
style: const TextStyle(color: Color(0xffF68804), fontSize: 14, height: 1.2),
|
||||
|
||||
@@ -11,7 +11,6 @@ import '../../../hj_model/home/plate_model.dart';
|
||||
import '../../../hj_model/video_model.dart';
|
||||
import '../../../hj_utils/sliver_delegate.dart';
|
||||
import '../../../tools_base/widget/net_image_widget.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
import '../widget/community_middle_header.dart';
|
||||
import '../widget/community_post_widget.dart';
|
||||
import 'community_tab_logic.dart';
|
||||
@@ -48,10 +47,6 @@ class CommunityTabPage extends StatelessWidget {
|
||||
7,
|
||||
autoStyle: true,
|
||||
padding: EdgeInsets.fromLTRB(16.w, 0, 16.w, 10.h),
|
||||
exposureModel: AdExposureModel(
|
||||
pageType: TrackEventPageType.commPost,
|
||||
tabIndex: index,
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
|
||||
@@ -16,19 +16,16 @@ class CommunityMainLogic extends GetxController with GetTickerProviderStateMixin
|
||||
title: '社区',
|
||||
imageNor: 'community_main_sel.png'.communityPath,
|
||||
imageSel: 'community_main_sel.png'.communityPath,
|
||||
trackKey: 'Community',
|
||||
),
|
||||
MainTabModel(
|
||||
title: '色图',
|
||||
imageNor: 'community_pic_sel.png'.communityPath,
|
||||
imageSel: 'community_pic_sel.png'.communityPath,
|
||||
trackKey: 'Pic',
|
||||
),
|
||||
MainTabModel(
|
||||
title: '小说',
|
||||
imageNor: 'community_noval_sel.png'.communityPath,
|
||||
imageSel: 'community_noval_sel.png'.communityPath,
|
||||
trackKey: 'Novel',
|
||||
),
|
||||
];
|
||||
|
||||
|
||||
@@ -2,11 +2,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_utils/const.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/widget/keep_alive_widget.dart';
|
||||
|
||||
import '../../../assets_tool/app_colors.dart';
|
||||
import '../../../config/config.dart';
|
||||
import '../../cartoon/cartoon_sub_module_page.dart';
|
||||
import '../../home/search_page/search_main_page.dart';
|
||||
@@ -48,15 +46,6 @@ class CommunityMainPageState extends State<CommunityMainPage> with SingleTickerP
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
if (holidayTheme.openHoliday) ...[
|
||||
Container(color: AppColors.primaryColor),
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Image.asset(HolidayTheme.theme.findBg, fit: BoxFit.fitWidth),
|
||||
),
|
||||
],
|
||||
Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
body: GetBuilder(
|
||||
|
||||
@@ -6,7 +6,6 @@ import 'package:jydj/tools_base/banner/ads_grid_view.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:jydj/tools_base/refresh/pull_refresh.dart';
|
||||
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
import 'group_chat_logic.dart';
|
||||
import 'widget/chat_group_cell.dart';
|
||||
|
||||
@@ -31,9 +30,6 @@ class GroupChatPage extends StatelessWidget {
|
||||
6,
|
||||
autoStyle: true,
|
||||
padding: EdgeInsets.fromLTRB(16, 12, 16, 18),
|
||||
exposureModel: AdExposureModel(
|
||||
pageType: TrackEventPageType.commGroup,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (logic.groupList == null)
|
||||
|
||||
@@ -10,7 +10,6 @@ import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:jydj/tools_base/refresh/pull_refresh.dart';
|
||||
import 'package:jydj/tools_base/unique_tag_mixin.dart';
|
||||
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
import '../../comment/widget/comment_foot_view.dart';
|
||||
import '../../home/widget/quick_search_view.dart';
|
||||
import '../widget/post_user_info_view.dart';
|
||||
@@ -89,7 +88,6 @@ class _PostDetailPageState extends State<PostDetailPage> with UniqueTagMixin {
|
||||
child: AdsGridView(
|
||||
7,
|
||||
autoStyle: true,
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.postDetail),
|
||||
),
|
||||
),
|
||||
//评论数 + 快捷搜索词
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
|
||||
class CommunitySortHeader extends StatefulWidget {
|
||||
final Function(int sort) sortOnTap;
|
||||
final TabController? controller;
|
||||
final bool isInTop; //吸顶时才在节日主题下叠渐变底
|
||||
const CommunitySortHeader({
|
||||
super.key,
|
||||
required this.sortOnTap,
|
||||
this.controller,
|
||||
this.isInTop = false,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -44,16 +41,6 @@ class _CommunitySortHeaderState extends State<CommunitySortHeader> with SingleTi
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primaryColor,
|
||||
gradient: (widget.isInTop && holidayTheme.openHoliday)
|
||||
? LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Color(0xff3e161c),
|
||||
Color(0xff26161c),
|
||||
],
|
||||
)
|
||||
: null,
|
||||
),
|
||||
child: TabBar(
|
||||
isScrollable: true,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:jydj/hj_model/drama/drama_models.dart';
|
||||
import 'package:jydj/hj_model/video_model.dart';
|
||||
import 'package:jydj/hj_utils/api_service/drama_service.dart';
|
||||
import 'package:jydj/tools_base/base_list_controller.dart';
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_model/video_model.dart';
|
||||
import 'package:jydj/hj_page/drama/drama_detail_page.dart';
|
||||
import 'package:jydj/hj_page/drama/drama_list_logic.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:jydj/tools_base/refresh/pull_refresh.dart';
|
||||
@@ -143,10 +141,6 @@ class _DramaListPageState extends State<DramaListPage> with UniqueTagMixin {
|
||||
);
|
||||
}
|
||||
|
||||
void _openDrama(VideoModel model) {
|
||||
Get.to(() => DramaDetailPage(drama: model.dramaInfo));
|
||||
}
|
||||
|
||||
Widget _buildBody(DramaListLogic logic) {
|
||||
if (logic.isLoading) return const LoadingCenterWidget();
|
||||
if (logic.isEmptyData) return CErrorWidget(retryOnTap: () => logic.loadData());
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:jydj/hj_model/video_model.dart';
|
||||
import 'package:jydj/hj_utils/api_service/drama_service.dart';
|
||||
import 'package:jydj/hj_utils/const.dart';
|
||||
import 'package:jydj/tools_base/base_list_controller.dart';
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_model/video_model.dart';
|
||||
import 'package:jydj/hj_page/drama/drama_detail_page.dart';
|
||||
import 'package:jydj/hj_page/drama/drama_tag_detail_logic.dart';
|
||||
import 'package:jydj/hj_page/home/home_cell_style/video_simple_cell.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:jydj/tools_base/refresh/pull_refresh.dart';
|
||||
import 'package:jydj/tools_base/unique_tag_mixin.dart';
|
||||
@@ -83,10 +81,6 @@ class _DramaTagDetailPageState extends State<DramaTagDetailPage> with UniqueTagM
|
||||
);
|
||||
}
|
||||
|
||||
void _openDrama(VideoModel model) {
|
||||
Get.to(() => DramaDetailPage(drama: model.dramaInfo));
|
||||
}
|
||||
|
||||
Widget _buildBody(DramaTagDetailLogic logic) {
|
||||
if (logic.isLoading) return const LoadingCenterWidget();
|
||||
if (logic.isEmptyData) return CErrorWidget(retryOnTap: () => logic.loadData());
|
||||
|
||||
@@ -10,7 +10,6 @@ import 'package:jydj/tools_base/widget/scroll_positioned_list/src/item_positions
|
||||
import 'package:jydj/tools_base/widget/scroll_positioned_list/src/scrollable_positioned_list.dart';
|
||||
|
||||
import '../../../alert/video/video_buy_bottom_sheet.dart';
|
||||
import '../../../alert/video/vip_acg_dialog.dart';
|
||||
import '../../mine/mine_vip/mine_charge_vip_page.dart';
|
||||
|
||||
class PicsDetailLogic extends GetxController {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:jydj/hj_page/find/rank_module/rank_sort_tab_bar.dart';
|
||||
import 'package:jydj/hj_utils/const.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/widget/keep_alive_widget.dart';
|
||||
|
||||
import 'rank_sub_page.dart';
|
||||
|
||||
@@ -183,7 +183,7 @@ class _HomeFloatBannerState extends State<HomeFloatBanner> {
|
||||
return InkWell(
|
||||
enableFeedback: false,
|
||||
// 内链可配到会员/金币页,来源统一记首页浮窗
|
||||
onTap: () => pushToPageByLink(_banner.url, id: _banner.id, sourcePage: PaySourcePage.homeFloatWindow),
|
||||
onTap: () => pushToPageByLink(_banner.url, sourcePage: PaySourcePage.homeFloatWindow),
|
||||
child: SizedBox(
|
||||
width: widget.width,
|
||||
height: widget.height,
|
||||
|
||||
@@ -134,7 +134,6 @@ class _SwiperFloatingWidgetState extends State<SwiperFloatingWidget> {
|
||||
// 内链可配到会员/金币页,来源统一记首页浮窗
|
||||
pushToPageByLink(
|
||||
ad.url,
|
||||
id: ad.id ?? (ad.position ?? 0).toString(),
|
||||
sourcePage: PaySourcePage.homeFloatWindow,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class QuickEntryRow extends StatelessWidget {
|
||||
margin: const EdgeInsets.only(right: 16),
|
||||
child: InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => pushToPageByLink(model.linkUrl, id: model.id),
|
||||
onTap: () => pushToPageByLink(model.linkUrl),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_utils/api_service/common_service.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/routers/jump_router.dart';
|
||||
|
||||
@@ -50,7 +51,8 @@ class TiktokSimpleCell extends StatelessWidget {
|
||||
|
||||
void _onTap() {
|
||||
if (videoModel?.isRandomAd() == true) {
|
||||
pushToPageByLink(videoModel?.randomAdsInfo?.href, id: videoModel?.randomAdsInfo?.id);
|
||||
pushToPageByLink(videoModel?.randomAdsInfo?.href);
|
||||
CommonService.adsClick(videoModel?.randomAdsInfo?.id);
|
||||
return;
|
||||
}
|
||||
pushToVideoPage(videoModel: videoModel);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:jydj/hj_utils/api_service/common_service.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
|
||||
import '../../../hj_model/video_model.dart';
|
||||
@@ -76,7 +77,8 @@ class VideoHorCell extends StatelessWidget {
|
||||
|
||||
void _onTap() {
|
||||
if (videoModel?.isRandomAd() == true) {
|
||||
pushToPageByLink(videoModel?.randomAdsInfo?.href, id: videoModel?.randomAdsInfo?.id);
|
||||
pushToPageByLink(videoModel?.randomAdsInfo?.href);
|
||||
CommonService.adsClick(videoModel?.randomAdsInfo?.id);
|
||||
return;
|
||||
}
|
||||
pushToVideoPage(videoModel: videoModel);
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/config/config.dart';
|
||||
import 'package:jydj/extension/extensions.dart';
|
||||
import 'package:jydj/hj_utils/api_service/common_service.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/routers/jump_router.dart';
|
||||
import 'package:jydj/tools_base/banner/ads_item.dart';
|
||||
@@ -14,7 +15,6 @@ import '../../../hj_utils/free_play_manager.dart';
|
||||
import '../../../tools_base/banner/ads_banner.dart';
|
||||
import '../../../tools_base/widget/net_image_widget.dart';
|
||||
import 'level_mark_chip.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
|
||||
/// 竖版视频 item:封面(角标/售卖标/暗网遮罩) + 标题 +(可选)标签/评论数。
|
||||
/// 命中广告数据时整体换成 [VideoSimpleAdsCell]
|
||||
@@ -26,7 +26,6 @@ class VideoSimpleCell extends StatelessWidget {
|
||||
final bool isFromHY; // 黄油风格
|
||||
final bool isShowBottom; // true 显示底部标签和评论数
|
||||
final bool isFromSearch;
|
||||
final AdExposureModel? exposureModel;
|
||||
final double titleFontSize; // 标题字号,小卡场景传小值
|
||||
final double coverFontSize; // 封面底部播放量/时长字号,小卡场景传小值避免溢出
|
||||
final String? coverRightText; // 封面右下角文案,默认时长;短剧传「共N集」
|
||||
@@ -42,7 +41,6 @@ class VideoSimpleCell extends StatelessWidget {
|
||||
this.isFromHY = false,
|
||||
this.isShowBottom = false,
|
||||
this.isFromSearch = false,
|
||||
this.exposureModel,
|
||||
this.titleFontSize = 12,
|
||||
this.coverFontSize = 10,
|
||||
this.coverRightText,
|
||||
@@ -65,7 +63,6 @@ class VideoSimpleCell extends StatelessWidget {
|
||||
? VideoSimpleAdsCell(
|
||||
videoModel: videoModel,
|
||||
textLines: textLines,
|
||||
exposureModel: exposureModel,
|
||||
isShowBottom: isShowBottom,
|
||||
)
|
||||
: _buildContent(),
|
||||
@@ -74,7 +71,8 @@ class VideoSimpleCell extends StatelessWidget {
|
||||
|
||||
void _onTap() {
|
||||
if (videoModel?.isRandomAd() == true) {
|
||||
pushToPageByLink(videoModel?.randomAdsInfo?.href, id: videoModel?.randomAdsInfo?.id);
|
||||
pushToPageByLink(videoModel?.randomAdsInfo?.href);
|
||||
CommonService.adsClick(videoModel?.randomAdsInfo?.id);
|
||||
return;
|
||||
}
|
||||
if (_needVipUnlock) {
|
||||
@@ -279,14 +277,12 @@ class VideoSimpleCell extends StatelessWidget {
|
||||
class VideoSimpleAdsCell extends StatefulWidget {
|
||||
final VideoModel? videoModel;
|
||||
final int textLines;
|
||||
final AdExposureModel? exposureModel;
|
||||
final bool isShowBottom;
|
||||
|
||||
const VideoSimpleAdsCell({
|
||||
super.key,
|
||||
this.videoModel,
|
||||
this.textLines = 2,
|
||||
this.exposureModel,
|
||||
this.isShowBottom = false,
|
||||
});
|
||||
|
||||
@@ -303,18 +299,11 @@ class _VideoSimpleAdsCellState extends State<VideoSimpleAdsCell> {
|
||||
|
||||
AdsInfoModel? get adsModel => videoModel?.randomAdsInfo;
|
||||
|
||||
// 广告点击:跳落地页并带曝光埋点参数
|
||||
// 广告点击:跳落地页并上报点击
|
||||
void _onAdTap() {
|
||||
final ad = adsInfoArr![adIndex];
|
||||
pushToPageByLink(
|
||||
ad.href,
|
||||
id: ad.id,
|
||||
arguments: {
|
||||
'pageType': widget.exposureModel?.pageType,
|
||||
'adInfo': ad,
|
||||
'payload': {'ad_type': widget.exposureModel?.adType?.value ?? ''},
|
||||
},
|
||||
);
|
||||
pushToPageByLink(ad.href);
|
||||
CommonService.adsClick(ad.id);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -345,7 +334,6 @@ class _VideoSimpleAdsCellState extends State<VideoSimpleAdsCell> {
|
||||
child: AdsBanner(
|
||||
adsInfoArr,
|
||||
autoPlayMs: 3000,
|
||||
exposureModel: widget.exposureModel,
|
||||
borderRadius: 4,
|
||||
onIndexChanged: (index) {
|
||||
adIndex = index;
|
||||
@@ -414,7 +402,6 @@ class _VideoSimpleAdsCellState extends State<VideoSimpleAdsCell> {
|
||||
children: [
|
||||
AdsItem(
|
||||
adInfo: adModel!,
|
||||
exposureModel: widget.exposureModel,
|
||||
borderRadius: 4,
|
||||
showType: AdShowType.img,
|
||||
),
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_page/home/provider/home_update_marker_provider.dart';
|
||||
import 'package:jydj/hj_utils/const.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/indicator/custom_tab_indicator.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
@@ -33,47 +31,30 @@ class HomeMainPage extends StatelessWidget {
|
||||
init: HomeMainLogic(),
|
||||
tag: "HomeMainLogic",
|
||||
builder: (logic) {
|
||||
final isHoliday = holidayTheme.openHoliday;
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
//节日皮肤:铺底色 + 顶部通栏背景图
|
||||
if (isHoliday) ...[
|
||||
Container(color: AppColors.primaryColor),
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Image.asset(HolidayTheme.theme.mainBg, fit: BoxFit.fitWidth),
|
||||
),
|
||||
return Scaffold(
|
||||
key: logic.scaffoldKey,
|
||||
endDrawer: HSHomeDrawer(homeLogic: logic),
|
||||
//浮窗放 body 里,endDrawer 才能盖住,避免挡住抽屉里的模块点击
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
_body(logic),
|
||||
const Positioned(right: 12, bottom: 40, child: HomeFloatWidget()),
|
||||
],
|
||||
Scaffold(
|
||||
key: logic.scaffoldKey,
|
||||
backgroundColor: isHoliday ? Colors.transparent : null,
|
||||
endDrawer: HSHomeDrawer(homeLogic: logic),
|
||||
//浮窗放 body 里,endDrawer 才能盖住,避免挡住抽屉里的模块点击
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
_body(logic, isHoliday),
|
||||
const Positioned(right: 12, bottom: 40, child: HomeFloatWidget()),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _body(HomeMainLogic logic, bool isHoliday) {
|
||||
Widget _body(HomeMainLogic logic) {
|
||||
if (logic.isLoading) return const LoadingCenterWidget();
|
||||
return Column(
|
||||
children: [
|
||||
//顶部搜索栏(状态栏 + 导航栏高度)
|
||||
Container(
|
||||
color: isHoliday ? Colors.transparent : Colors.black,
|
||||
color: Colors.black,
|
||||
padding: EdgeInsets.only(top: screen.paddingTop),
|
||||
height: kToolbarHeight + screen.paddingTop,
|
||||
child: CommonSearchBarView(logic: logic),
|
||||
@@ -147,12 +128,11 @@ class _HomeTabViewState extends State<HomeTabView> with SingleTickerProviderStat
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isHoliday = holidayTheme.openHoliday;
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 48.h,
|
||||
color: isHoliday ? Colors.transparent : Colors.black,
|
||||
color: Colors.black,
|
||||
child: _tabBar(),
|
||||
),
|
||||
Expanded(
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_model/drama_media_info.dart';
|
||||
import 'package:jydj/hj_utils/api_service/acg_service.dart';
|
||||
import 'package:jydj/tools_base/debug_log.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
|
||||
import '../../../hj_model/home/module_detail_model.dart';
|
||||
import '../../../hj_model/home/plate_model.dart';
|
||||
import '../../../hj_utils/api_service/vid_service.dart';
|
||||
import 'home_tab_base_logic.dart';
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:jydj/track_event_manager/track_manager.dart';
|
||||
|
||||
import '../../../hj_model/home/plate_model.dart';
|
||||
import '../../../hj_model/home/module_detail_model.dart';
|
||||
@@ -51,10 +50,6 @@ class _HomeTabSectionPageState extends State<HomeTabSectionPage> with UniqueTagM
|
||||
4,
|
||||
autoStyle: true,
|
||||
padding: EdgeInsets.fromLTRB(12, 0, 12, 12),
|
||||
exposureModel: AdExposureModel(
|
||||
pageType: widget.isDarkStyle ? TrackEventPageType.darkweb : TrackEventPageType.home,
|
||||
tabIndex: widget.tabIndex,
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(child: QuickEntryRow(widget.tabModel)),
|
||||
@@ -95,10 +90,6 @@ class _HomeTabSectionPageState extends State<HomeTabSectionPage> with UniqueTagM
|
||||
-1,
|
||||
ads: section.adsInfoArr ?? [],
|
||||
padding: EdgeInsets.fromLTRB(12, 0, 12, 16),
|
||||
exposureModel: AdExposureModel(
|
||||
pageType: widget.isDarkStyle ? TrackEventPageType.darkweb : TrackEventPageType.home,
|
||||
tabIndex: widget.tabIndex * 100 + index,
|
||||
),
|
||||
);
|
||||
} else if (logic.lastIsGuessLike && index == logic.allSection.length - 1) {
|
||||
return SizedBox(); // 最后一个猜你喜欢列表单独处理
|
||||
|
||||
@@ -12,7 +12,6 @@ import '../../../hj_model/video_model.dart';
|
||||
import '../../../hj_utils/sliver_delegate.dart';
|
||||
import '../../../tools_base/banner/ads_grid_view.dart';
|
||||
import '../../../tools_base/refresh/pull_refresh.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
import '../../cartoon/acg_widget_item.dart';
|
||||
import '../home_cell_style/quick_entry_row.dart';
|
||||
import '../home_cell_style/video_simple_cell.dart';
|
||||
@@ -61,10 +60,6 @@ class _HomeTabSortPageState extends State<HomeTabSortPage> with UniqueTagMixin {
|
||||
4,
|
||||
autoStyle: true,
|
||||
padding: EdgeInsets.fromLTRB(12, 0, 12, 12),
|
||||
exposureModel: AdExposureModel(
|
||||
pageType: widget.isDarkStyle ? TrackEventPageType.darkweb : TrackEventPageType.home,
|
||||
tabIndex: widget.tabIndex,
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(child: QuickEntryRow(widget.tabModel)),
|
||||
@@ -96,9 +91,11 @@ class _HomeTabSortPageState extends State<HomeTabSortPage> with UniqueTagMixin {
|
||||
},
|
||||
child: Obx(
|
||||
() {
|
||||
//非暗网风格也要读一次:Obx 读不到可观察变量会抛 improper use of a GetX
|
||||
final isInTop = logic.isSortMenuInTop.value;
|
||||
Color? bgColor;
|
||||
if (widget.isDarkStyle) {
|
||||
if (logic.isSortMenuInTop.value) {
|
||||
if (isInTop) {
|
||||
bgColor = Colors.transparent;
|
||||
} else {
|
||||
bgColor = Colors.black;
|
||||
@@ -108,7 +105,6 @@ class _HomeTabSortPageState extends State<HomeTabSortPage> with UniqueTagMixin {
|
||||
isLatest: logic.isNewestStyle,
|
||||
labelPadding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
tabs: logic.isNewestStyle ? logic.lastestSortTitles : logic.sortTitles,
|
||||
isPinned: !logic.isSortMenuInTop.value,
|
||||
bgColor: bgColor,
|
||||
onSort: logic.sortMenuEvent,
|
||||
rightWidget: logic.isNewestStyle ? null : _buildSortStyleMenu(logic),
|
||||
@@ -222,10 +218,6 @@ class _HomeTabSortPageState extends State<HomeTabSortPage> with UniqueTagMixin {
|
||||
child: VideoSimpleCell(
|
||||
videoModel: videoModel,
|
||||
textLines: logic.isGridStyle.value ? 2 : 1,
|
||||
exposureModel: AdExposureModel(
|
||||
pageType: widget.isDarkStyle ? TrackEventPageType.darkweb : TrackEventPageType.home,
|
||||
tabIndex: widget.tabIndex * 100 + index,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -260,10 +252,6 @@ class _HomeTabSortPageState extends State<HomeTabSortPage> with UniqueTagMixin {
|
||||
VideoModel videoModel = subList[index];
|
||||
return VideoSimpleCell(
|
||||
videoModel: videoModel,
|
||||
exposureModel: AdExposureModel(
|
||||
pageType: widget.isDarkStyle ? TrackEventPageType.darkweb : TrackEventPageType.home,
|
||||
tabIndex: widget.tabIndex * 100 + i * gapValue + index,
|
||||
),
|
||||
);
|
||||
},
|
||||
childCount: subList.length,
|
||||
@@ -300,10 +288,6 @@ class _HomeTabSortPageState extends State<HomeTabSortPage> with UniqueTagMixin {
|
||||
VideoModel videoModel = subList[index];
|
||||
return VideoSimpleCell(
|
||||
videoModel: videoModel,
|
||||
exposureModel: AdExposureModel(
|
||||
pageType: widget.isDarkStyle ? TrackEventPageType.darkweb : TrackEventPageType.home,
|
||||
tabIndex: widget.tabIndex * 100 + allIndex * gapValue + index,
|
||||
),
|
||||
);
|
||||
},
|
||||
childCount: subList.length,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/hj_page/home/provider/home_update_marker_provider.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
/// 首页模块的排序切换栏(热门推荐 / 最新上架 / ...)
|
||||
@@ -10,7 +9,6 @@ class HomeSortHeader extends StatefulWidget {
|
||||
final ValueChanged<int> onSort;
|
||||
final List<String>? tabs;
|
||||
final EdgeInsets? labelPadding;
|
||||
final bool isPinned; //已吸顶:节日主题下只有吸顶才铺底色,未吸顶保持透明露出节日背景图
|
||||
final Widget? rightWidget;
|
||||
final Color? bgColor;
|
||||
final bool isLatest;
|
||||
@@ -20,7 +18,6 @@ class HomeSortHeader extends StatefulWidget {
|
||||
required this.onSort,
|
||||
this.tabs,
|
||||
this.labelPadding,
|
||||
this.isPinned = false,
|
||||
this.rightWidget,
|
||||
this.bgColor,
|
||||
this.isLatest = false,
|
||||
@@ -45,12 +42,9 @@ class _HomeSortHeaderState extends State<HomeSortHeader> with SingleTickerProvid
|
||||
if (widget.isLatest) {
|
||||
return _buildNewsetsStyle();
|
||||
}else {
|
||||
final showBg = !holidayTheme.openHoliday || widget.isPinned;
|
||||
return Container(
|
||||
height: 38,
|
||||
color: showBg ? (widget.bgColor ?? Theme
|
||||
.of(context)
|
||||
.scaffoldBackgroundColor) : Colors.transparent,
|
||||
color: widget.bgColor ?? Theme.of(context).scaffoldBackgroundColor,
|
||||
child: widget.rightWidget == null
|
||||
? _tabBar()
|
||||
: Row(children: [Expanded(child: _tabBar()), widget.rightWidget!]),
|
||||
@@ -79,10 +73,9 @@ class _HomeSortHeaderState extends State<HomeSortHeader> with SingleTickerProvid
|
||||
|
||||
/// 「最新」页专用:字号更小、选中态红色胶囊、首个 tab 带更新红点
|
||||
Widget _buildNewsetsStyle() {
|
||||
final showBg = !holidayTheme.openHoliday || widget.isPinned;
|
||||
return Container(
|
||||
height: 38,
|
||||
color: showBg ? (widget.bgColor ?? Theme.of(context).scaffoldBackgroundColor) : Colors.transparent,
|
||||
color: widget.bgColor ?? Theme.of(context).scaffoldBackgroundColor,
|
||||
child: TabBar(
|
||||
controller: tabCtr,
|
||||
isScrollable: true,
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_utils/const.dart';
|
||||
import 'package:jydj/tools_base/banner/ads_grid_view.dart';
|
||||
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
import '../../find/rank_module/rank_main_page.dart';
|
||||
import '../../find/rank_module/rank_sub_page.dart';
|
||||
import 'search_main_logic.dart';
|
||||
@@ -58,7 +57,6 @@ class SearchMainPage extends StatelessWidget {
|
||||
32,
|
||||
autoStyle: true,
|
||||
padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 12.w),
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.search),
|
||||
),
|
||||
),
|
||||
//搜索历史:随增删局部刷新,不带动整页(id 要和 logic 里 update 的一致)
|
||||
|
||||
@@ -9,8 +9,6 @@ import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import '../../../../hj_model/acg/cartoon_more_list.dart';
|
||||
import '../../../../hj_model/cartoon_media_info.dart';
|
||||
import '../../../../tools_base/refresh/pull_refresh.dart';
|
||||
import '../../../../tools_base/widget/multitap_recognizer.dart';
|
||||
import '../../../../track_event_manager/track_manager.dart';
|
||||
import '../../../cartoon/acg_widget_item.dart';
|
||||
|
||||
class SearchACGResultPage extends StatefulWidget {
|
||||
@@ -51,12 +49,6 @@ class _SearchACGResultPageState extends State<SearchACGResultPage> {
|
||||
}
|
||||
videoList?.addAll(retResp?.list ?? []);
|
||||
retResp?.hasNext == false ? refreshController?.loadNoData() : refreshController?.loadComplete();
|
||||
searchClickManager.searchKeyword(
|
||||
keyword: widget.keywords,
|
||||
count: retResp?.list?.length ?? 0,
|
||||
searchId: '',
|
||||
traceId: '',
|
||||
);
|
||||
} catch (e) {
|
||||
refreshController?.loadComplete();
|
||||
debugLog(e);
|
||||
@@ -93,17 +85,7 @@ class _SearchACGResultPageState extends State<SearchACGResultPage> {
|
||||
),
|
||||
itemCount: videoList?.length ?? 0,
|
||||
itemBuilder: (context, index) {
|
||||
return MultiTap(
|
||||
onTap: () {
|
||||
searchClickManager.searchClicks(
|
||||
keyword: widget.keywords,
|
||||
clickType: TrackEventSearchType.acg,
|
||||
id: videoList![index].id,
|
||||
index: index,
|
||||
traceId: '',
|
||||
);
|
||||
},
|
||||
child: AcgItemWidget(info: videoList![index]));
|
||||
return AcgItemWidget(info: videoList![index]);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2,9 +2,7 @@ import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_model/drama_media_info.dart';
|
||||
import 'package:jydj/hj_model/video_model.dart';
|
||||
import 'package:jydj/hj_page/drama/drama_detail_page.dart';
|
||||
import 'package:jydj/hj_page/drama/drama_tag_detail_page.dart';
|
||||
import 'package:jydj/hj_utils/api_service/drama_service.dart';
|
||||
import 'package:jydj/hj_utils/api_service/search_service.dart';
|
||||
@@ -16,8 +14,6 @@ import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
|
||||
import '../../../../hj_model/home/video_list_model.dart';
|
||||
import '../../../../tools_base/refresh/pull_refresh.dart';
|
||||
import '../../../../tools_base/widget/multitap_recognizer.dart';
|
||||
import '../../../../track_event_manager/track_manager.dart';
|
||||
import '../../../cartoon/photo_gallery_item.dart';
|
||||
import '../../../community/widget/community_post_widget.dart';
|
||||
import '../../home_cell_style/drama_cover_card.dart';
|
||||
@@ -83,12 +79,6 @@ class _SearchVideoResultPageState extends State<SearchVideoResultPage> {
|
||||
videoList ??= [];
|
||||
videoList?.addAll(retResp?.list.map((e) => e.toVideoModel(null)) ?? []);
|
||||
retResp?.hasNext != true ? refreshController?.loadNoData() : refreshController?.loadComplete();
|
||||
searchClickManager.searchKeyword(
|
||||
keyword: widget.keywords,
|
||||
count: retResp?.list.length ?? 0,
|
||||
searchId: '',
|
||||
traceId: '',
|
||||
);
|
||||
} else {
|
||||
VideoListResp? retResp = await SearchService.searchMedia(widget.keywords,
|
||||
pageNumber: page, pageSize: size, realm: widget.type.searchRealm, sortType: sortValue);
|
||||
@@ -103,12 +93,6 @@ class _SearchVideoResultPageState extends State<SearchVideoResultPage> {
|
||||
tagID = retResp?.tagID;
|
||||
}
|
||||
retResp?.hasNext == false ? refreshController?.loadNoData() : refreshController?.loadComplete();
|
||||
searchClickManager.searchKeyword(
|
||||
keyword: widget.keywords,
|
||||
count: retResp?.videos?.length ?? 0,
|
||||
searchId: '',
|
||||
traceId: '',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
refreshController?.loadComplete();
|
||||
@@ -186,18 +170,6 @@ class _SearchVideoResultPageState extends State<SearchVideoResultPage> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 进短剧二级页;搜索列表不一定带 dramaInfo,最少用 id/标题/封面兜底
|
||||
void _openDrama(VideoModel model) {
|
||||
final drama = model.dramaInfo ??
|
||||
(DramaMediaInfo()
|
||||
..id = model.id
|
||||
..title = model.title
|
||||
..verticalCover = model.cover
|
||||
..horizontalCover = model.cover
|
||||
..totalEpisode = model.totalEpisode);
|
||||
Get.to(() => DramaDetailPage(drama: drama));
|
||||
}
|
||||
|
||||
Widget _buildTypeList() {
|
||||
if (widget.type == MediaStyle.Drama) {
|
||||
return GridView.builder(
|
||||
@@ -211,18 +183,7 @@ class _SearchVideoResultPageState extends State<SearchVideoResultPage> {
|
||||
itemCount: videoList?.length ?? 0,
|
||||
itemBuilder: (context, index) {
|
||||
final model = videoList![index];
|
||||
return MultiTap(
|
||||
onTap: () {
|
||||
searchClickManager.searchClicks(
|
||||
keyword: widget.keywords,
|
||||
clickType: TrackEventSearchType.video,
|
||||
id: '${model.id}',
|
||||
index: index,
|
||||
traceId: '',
|
||||
);
|
||||
},
|
||||
child: DramaCoverCard(mediaInfo: model.dramaInfo!),
|
||||
);
|
||||
return DramaCoverCard(mediaInfo: model.dramaInfo!);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -238,22 +199,12 @@ class _SearchVideoResultPageState extends State<SearchVideoResultPage> {
|
||||
),
|
||||
itemCount: videoList?.length ?? 0,
|
||||
itemBuilder: (context, index) {
|
||||
return MultiTap(
|
||||
onTap: () {
|
||||
searchClickManager.searchClicks(
|
||||
keyword: widget.keywords,
|
||||
clickType: TrackEventSearchType.video,
|
||||
id: "${videoList![index].id}",
|
||||
index: index,
|
||||
traceId: '',
|
||||
);
|
||||
},
|
||||
child: VideoSimpleCell(
|
||||
videoModel: videoList![index],
|
||||
textLines: isShort ? 1 : 2,
|
||||
isFromSearch: true,
|
||||
isShort: isShort,
|
||||
));
|
||||
return VideoSimpleCell(
|
||||
videoModel: videoList![index],
|
||||
textLines: isShort ? 1 : 2,
|
||||
isFromSearch: true,
|
||||
isShort: isShort,
|
||||
);
|
||||
},
|
||||
);
|
||||
} else if (widget.type == MediaStyle.Pic) {
|
||||
@@ -267,17 +218,7 @@ class _SearchVideoResultPageState extends State<SearchVideoResultPage> {
|
||||
),
|
||||
itemCount: videoList?.length ?? 0,
|
||||
itemBuilder: (context, index) {
|
||||
return MultiTap(
|
||||
onTap: () {
|
||||
searchClickManager.searchClicks(
|
||||
keyword: widget.keywords,
|
||||
clickType: TrackEventSearchType.image,
|
||||
id: "${videoList![index].id}",
|
||||
index: index,
|
||||
traceId: '',
|
||||
);
|
||||
},
|
||||
child: PhotoGalleryItem(videoModel: videoList![index], textline: 1));
|
||||
return PhotoGalleryItem(videoModel: videoList![index], textline: 1);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
@@ -285,20 +226,10 @@ class _SearchVideoResultPageState extends State<SearchVideoResultPage> {
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: videoList?.length ?? 0,
|
||||
itemBuilder: (context, index) {
|
||||
return MultiTap(
|
||||
onTap: () {
|
||||
searchClickManager.searchClicks(
|
||||
keyword: widget.keywords,
|
||||
clickType: TrackEventSearchType.post,
|
||||
id: "${videoList![index].id}",
|
||||
index: index,
|
||||
traceId: '',
|
||||
);
|
||||
},
|
||||
child: CommunityPostWidget(
|
||||
videoModel: videoList![index],
|
||||
videoModels: videoList,
|
||||
));
|
||||
return CommunityPostWidget(
|
||||
videoModel: videoList![index],
|
||||
videoModels: videoList,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -330,10 +261,7 @@ class _SearchVideoResultPageState extends State<SearchVideoResultPage> {
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
final videoModel = tagVidList![index];
|
||||
return MultiTap(
|
||||
onTap: (){},
|
||||
child: DramaCoverCard(mediaInfo: videoModel.dramaInfo!),
|
||||
);
|
||||
return DramaCoverCard(mediaInfo: videoModel.dramaInfo!);
|
||||
},
|
||||
),
|
||||
if (tagID?.isNotEmpty == true) ...[
|
||||
@@ -391,22 +319,11 @@ class _SearchVideoResultPageState extends State<SearchVideoResultPage> {
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
VideoModel videoModel = tagVidList![index];
|
||||
return MultiTap(
|
||||
onTap: () {
|
||||
searchClickManager.searchClicks(
|
||||
keyword: widget.keywords,
|
||||
clickType: TrackEventSearchType.video,
|
||||
id: "${videoModel.id}",
|
||||
index: index,
|
||||
traceId: '',
|
||||
);
|
||||
},
|
||||
child: VideoSimpleCell(
|
||||
videoModel: videoModel,
|
||||
textLines: isShort ? 1 : 2,
|
||||
isFromSearch: true,
|
||||
isShort: isShort,
|
||||
),
|
||||
return VideoSimpleCell(
|
||||
videoModel: videoModel,
|
||||
textLines: isShort ? 1 : 2,
|
||||
isFromSearch: true,
|
||||
isShort: isShort,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/config/config.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
|
||||
import '../../../../hj_utils/holiday_theme.dart';
|
||||
import '../../../../tools_base/widget/marquee_widget.dart';
|
||||
import '../../../../tools_base/widget/net_image_widget.dart';
|
||||
import '../../../mine/welfare/sign_daily_page.dart';
|
||||
@@ -113,7 +112,6 @@ class _CommonSearchBarViewState extends State<CommonSearchBarView> {
|
||||
|
||||
/// 签到入口
|
||||
Widget _buildSignIcon() {
|
||||
final useHolidayIcon = holidayTheme.openHoliday && HolidayTheme.theme.signIcon.isNotEmpty;
|
||||
return InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => Get.to(SignDailyPage()),
|
||||
|
||||
@@ -11,7 +11,6 @@ import 'package:jydj/hj_model/splash/domain_source_model.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
|
||||
import '../../../hj_utils/api_service/vid_service.dart';
|
||||
import '../../../hj_utils/holiday_theme.dart';
|
||||
import '../../../routers/jump_router.dart';
|
||||
|
||||
class HomeTxtMarQuee extends StatefulWidget {
|
||||
@@ -108,12 +107,7 @@ class HomeTxtMarQueeState extends State<HomeTxtMarQuee> with SingleTickerProvide
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
(holidayTheme.openHoliday && HolidayTheme.theme.broadcastIcon.isNotEmpty)
|
||||
? HolidayTheme.theme.broadcastIcon
|
||||
: "icon_broadcast.png".commonImgPath,
|
||||
width: widget.iconSize ?? 20,
|
||||
),
|
||||
Image.asset("icon_broadcast.png".commonImgPath, width: widget.iconSize ?? 20),
|
||||
6.sizeBoxW,
|
||||
Expanded(
|
||||
child: InfiniteMarquee(
|
||||
@@ -124,7 +118,7 @@ class HomeTxtMarQueeState extends State<HomeTxtMarQuee> with SingleTickerProvide
|
||||
return InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () {
|
||||
pushToPageByLink(model.url, id: model.id);
|
||||
pushToPageByLink(model.url);
|
||||
},
|
||||
child: Text(
|
||||
model.content ?? '',
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart'; // sizeBoxH/sizeBoxW 扩展
|
||||
import 'package:jydj/tools_base/widget/sheet_handle_bar.dart';
|
||||
|
||||
@@ -17,7 +16,7 @@ enum PublishEntry {
|
||||
|
||||
const PublishEntry(this.width, this.height);
|
||||
|
||||
String realPath() => HolidayTheme.theme.addPublish;
|
||||
String realPath() => 'publish.png'.homePath;
|
||||
}
|
||||
|
||||
class PublishButton extends StatelessWidget {
|
||||
|
||||
@@ -11,7 +11,6 @@ import 'package:jydj/tools_base/refresh/pull_refresh.dart';
|
||||
import 'package:jydj/tools_base/widget/net_image_widget.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
import '../video/video_full_page.dart';
|
||||
import 'live_detail_logic.dart';
|
||||
|
||||
@@ -295,7 +294,6 @@ class _LiveDetailPageState extends State<LiveDetailPage> {
|
||||
36,
|
||||
autoStyle: true,
|
||||
padding: const EdgeInsets.fromLTRB(16, 18, 0, 0),
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.liveDetail),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class LiveMainPage extends StatelessWidget {
|
||||
controller: logic.tabController,
|
||||
children: List.generate(
|
||||
logic.liveTabs.length,
|
||||
(index) => LiveSubPage(tagData: logic.liveTabs[index], index: index).keepAlive,
|
||||
(index) => LiveSubPage(tagData: logic.liveTabs[index]).keepAlive,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -8,16 +8,14 @@ import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:jydj/tools_base/refresh/pull_refresh.dart';
|
||||
import 'package:jydj/tools_base/widget/card_swiper/src/swiper.dart';
|
||||
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
import 'live_model.dart';
|
||||
import 'live_sub_logic.dart';
|
||||
|
||||
//直播子列表页面
|
||||
class LiveSubPage extends StatefulWidget {
|
||||
final LiveModule? tagData;
|
||||
final int index;
|
||||
|
||||
const LiveSubPage({super.key, this.tagData, this.index = 0});
|
||||
const LiveSubPage({super.key, this.tagData});
|
||||
|
||||
@override
|
||||
State<LiveSubPage> createState() => _LiveSubPageState();
|
||||
@@ -66,7 +64,6 @@ class _LiveSubPageState extends State<LiveSubPage> {
|
||||
35,
|
||||
autoStyle: true,
|
||||
padding: const EdgeInsets.fromLTRB(16, 15, 16, 15),
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.live, tabIndex: widget.index),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analytics_sdk/analytics_sdk.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/config/config.dart';
|
||||
import 'package:jydj/hj_model/home/plate_model.dart';
|
||||
import 'package:jydj/hj_page/pre_sale/pre_sale_provider.dart';
|
||||
import 'package:jydj/hj_utils/const.dart';
|
||||
import 'package:jydj/hj_utils/free_play_manager.dart';
|
||||
import 'package:jydj/im_manager/im_manager.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
|
||||
import '../../hj_utils/holiday_theme.dart';
|
||||
import '../../tools_base/event_bus/event_bus_util.dart';
|
||||
import '../../tools_base/event_bus/events.dart';
|
||||
import '../../tools_base/toast.dart';
|
||||
@@ -46,13 +44,11 @@ class MainTabModel {
|
||||
final String title; //title
|
||||
final String imageNor; //nor图片
|
||||
final String imageSel; //选中图片
|
||||
final String trackKey; //导航埋点key
|
||||
|
||||
MainTabModel({
|
||||
required this.title,
|
||||
required this.imageNor,
|
||||
required this.imageSel,
|
||||
required this.trackKey,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,40 +56,34 @@ class MainPageLogic extends GetxController {
|
||||
final tabs = <MainTabModel>[
|
||||
MainTabModel(
|
||||
title: '首页',
|
||||
imageNor: HolidayTheme.theme.homeNor,
|
||||
imageSel: HolidayTheme.theme.homeSel,
|
||||
trackKey: 'Home',
|
||||
imageNor: 'home_0_0.png'.homePath,
|
||||
imageSel: 'home_0_1.png'.homePath,
|
||||
),
|
||||
MainTabModel(
|
||||
title: '短剧',
|
||||
imageNor: HolidayTheme.theme.shortNor,
|
||||
imageSel: HolidayTheme.theme.shortSel,
|
||||
trackKey: 'ShortVideo',
|
||||
imageNor: 'home_1_0.png'.homePath,
|
||||
imageSel: 'home_1_1.png'.homePath,
|
||||
),
|
||||
if (Config.darkWebEnable)
|
||||
MainTabModel(
|
||||
title: Config.darkWebIconName?.isNotEmpty == true ? Config.darkWebIconName! : '暗网',
|
||||
imageNor: HolidayTheme.theme.darkNor,
|
||||
imageSel: HolidayTheme.theme.darkSel,
|
||||
trackKey: 'DarkWeb',
|
||||
imageNor: 'home_2_0.png'.homePath,
|
||||
imageSel: 'home_2_1.png'.homePath,
|
||||
),
|
||||
MainTabModel(
|
||||
title: 'AI',
|
||||
imageNor: HolidayTheme.theme.aiNor,
|
||||
imageSel: HolidayTheme.theme.aiSel,
|
||||
trackKey: 'AI',
|
||||
imageNor: 'home_3_0.png'.homePath,
|
||||
imageSel: 'home_3_1.png'.homePath,
|
||||
),
|
||||
MainTabModel(
|
||||
title: '社区',
|
||||
imageNor: HolidayTheme.theme.communityNor,
|
||||
imageSel: HolidayTheme.theme.communitySel,
|
||||
trackKey: 'Community',
|
||||
imageNor: 'home_4_0.png'.homePath,
|
||||
imageSel: 'home_4_1.png'.homePath,
|
||||
),
|
||||
MainTabModel(
|
||||
title: '我的',
|
||||
imageNor: HolidayTheme.theme.mineNor,
|
||||
imageSel: HolidayTheme.theme.mineSel,
|
||||
trackKey: 'Mine',
|
||||
imageNor: 'home_5_0.png'.homePath,
|
||||
imageSel: 'home_5_1.png'.homePath,
|
||||
),
|
||||
];
|
||||
|
||||
@@ -152,7 +142,6 @@ class MainPageLogic extends GetxController {
|
||||
_backToRoot();
|
||||
jumpToPage(0);
|
||||
globalStore.refreshWallet();
|
||||
unawaited(ImManager().reloginOnAccountSwitch()); //切换账号:登出旧 IM 并用新账号重连,避免私信列表残留旧数据
|
||||
MineMsgProvider().loadData(); //内含 refreshPayPopup:重拉支付分层配置,即时刷新浮窗/我的横幅/播放器横幅
|
||||
unawaited(FreePlayManager().refresh()); //切号:免费观看次数是账户维度的,不重拉会一直用着上个账号的次数
|
||||
HomeUpdateMarkerProvider().loadData();
|
||||
@@ -275,7 +264,6 @@ class MainPageLogic extends GetxController {
|
||||
void onClose() {
|
||||
_yinseSub.cancel();
|
||||
_loginSub.cancel();
|
||||
unawaited(AnalyticsSdk.instance.dispose());
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import 'package:analytics_sdk/analytics_sdk.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_page/main_page/provider/bottom_bar_provider.dart';
|
||||
import 'package:jydj/hj_page/pre_sale/pre_sale_provider.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/im_manager/im_notification.dart';
|
||||
import 'package:jydj/tools_base/widget/net_image_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
@@ -42,11 +39,6 @@ class MainPageTabbar extends StatelessWidget {
|
||||
if (index == logic.tabs.length - 1 && Get.isRegistered<MineMainLogic>()) {
|
||||
Get.find<MineMainLogic>().onRefresh();
|
||||
}
|
||||
// 用户点击底部 Tab 时调用,应早于页面切换完成
|
||||
AnalyticsSdk.instance.trackNavigation(
|
||||
pageKey: logic.tabs[index].trackKey, // 'Home'
|
||||
pageName: logic.tabs[index].title, // '主页'
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -96,7 +88,7 @@ class MainPageTabbar extends StatelessWidget {
|
||||
});
|
||||
}
|
||||
|
||||
/// 普通 tab;最后一个(我的)带私信未读小红点
|
||||
/// 普通 tab
|
||||
Widget _normalItem(int index, int cur) {
|
||||
final isSelected = index == cur;
|
||||
final imagePath = _iconPath(index, isSelected);
|
||||
@@ -104,32 +96,10 @@ class MainPageTabbar extends StatelessWidget {
|
||||
child: InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => _selectIndex(index),
|
||||
child: Stack(
|
||||
children: [
|
||||
_tabContent(
|
||||
isSelected: isSelected,
|
||||
text: logic.tabs[index].title,
|
||||
icon: Image.asset(imagePath, key: ValueKey(imagePath), width: 24),
|
||||
),
|
||||
if (index == logic.tabs.length - 1)
|
||||
Consumer<ImMsgProvider>(
|
||||
builder: (_, imPro, __) {
|
||||
if (!imPro.hasUnreadCount) return const SizedBox.shrink();
|
||||
return Positioned(
|
||||
right: 22,
|
||||
top: 24,
|
||||
child: Container(
|
||||
width: 8,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xfff74f49),
|
||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
child: _tabContent(
|
||||
isSelected: isSelected,
|
||||
text: logic.tabs[index].title,
|
||||
icon: Image.asset(imagePath, key: ValueKey(imagePath), width: 24),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -153,7 +123,7 @@ class MainPageTabbar extends StatelessWidget {
|
||||
AnimatedDefaultTextStyle(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
style: TextStyle(
|
||||
color: isSelected ? HolidayTheme.theme.tabSelColor : HolidayTheme.theme.tabNorColor,
|
||||
color: isSelected ? const Color(0xffFFC000) : const Color(0x59FFFFFF),
|
||||
fontSize: 10,
|
||||
),
|
||||
child: Text(text),
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_page/pre_sale/pre_sale_provider.dart';
|
||||
import 'package:jydj/hj_utils/api_service/vid_service.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
import 'package:jydj/hj_utils/light_model.dart';
|
||||
import 'package:jydj/hj_utils/store_keys.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
@@ -17,7 +16,6 @@ import 'package:jydj/tools_base/widget/common_alert.dart';
|
||||
|
||||
import '../../config/config.dart';
|
||||
import '../../hj_model/user/user_info_model.dart';
|
||||
import '../../routers/jump_router.dart';
|
||||
import '../main_page/provider/msg_provider.dart';
|
||||
import '../web_page/h5_page.dart';
|
||||
import 'collec_history_buy/col_his_buy_page.dart';
|
||||
@@ -61,11 +59,10 @@ class MineMainLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
("账号凭证", 'mine_menu_9.png'.mineImgPath, () => Get.dialog(MineAccountIdentityPage())),
|
||||
("锁屏密码", 'mine_menu_10.png'.mineImgPath, _toggleLockPassword),
|
||||
("我的消息", 'mine_menu_11.png'.mineImgPath, () => menuTapEvent(3)),
|
||||
("在线客服", 'mine_menu_12.png'.mineImgPath, pushToCustomService),
|
||||
];
|
||||
|
||||
List<IconBean> iconList = [
|
||||
IconBean(HolidayTheme.theme.appIcon, Config.appName),
|
||||
IconBean('ic_launcher.webp'.commonImgPath, Config.appName),
|
||||
IconBean('icon_1.webp'.appImgPath, "爱音乐"),
|
||||
IconBean('icon_2.webp'.appImgPath, "爱阅读"),
|
||||
IconBean('icon_3.webp'.appImgPath, "支付宝"),
|
||||
@@ -187,6 +184,6 @@ class MineMainLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
changeIcon(int index) async {
|
||||
if (!await CommonAlert.show(content: '您确定要更换图标吗?')) return;
|
||||
const platform = MethodChannel(DeviceInfoService.requestChannel);
|
||||
platform.invokeMethod('changeIcon', {"iconIndex": index == 0 ? holidayTheme.iconIndex : index});
|
||||
platform.invokeMethod('changeIcon', {"iconIndex": index});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:jydj/config/address.dart';
|
||||
import 'package:jydj/config/config.dart';
|
||||
import 'package:jydj/hj_page/main_page/provider/msg_provider.dart';
|
||||
import 'package:jydj/hj_page/pre_sale/pre_sale_provider.dart';
|
||||
import 'package:jydj/im_manager/im_notification.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/routers/jump_router.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
@@ -17,10 +16,8 @@ import 'package:jydj/tools_base/toast.dart';
|
||||
import 'package:jydj/tools_base/widget/net_image_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../hj_utils/holiday_theme.dart';
|
||||
import '../../hj_utils/widget_util.dart';
|
||||
import '../../tools_base/banner/ads_grid_view.dart';
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
import 'home_mine_logic.dart';
|
||||
import 'widgets/mine_info_widget.dart';
|
||||
import 'widgets/vip_entry_card.dart';
|
||||
@@ -65,14 +62,14 @@ class HomeMinePage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
//顶部背景:优先后台下发,兜底节日/默认图
|
||||
//顶部背景:优先后台下发,兜底默认图
|
||||
Widget _buildBg() {
|
||||
final bg = Config.mineBg;
|
||||
if (bg != null && bg.isNotEmpty) {
|
||||
return NetworkImageLoader(imageUrl: bg, borderRadius: 0);
|
||||
}
|
||||
return Image.asset(
|
||||
holidayTheme.openHoliday ? HolidayTheme.theme.mineBg : 'mine_bg.webp'.mineImgPath,
|
||||
'mine_bg.webp'.mineImgPath,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,7 +95,6 @@ class HomeMinePage extends StatelessWidget {
|
||||
8,
|
||||
autoStyle: true,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.mine),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 16),
|
||||
@@ -148,22 +144,12 @@ class HomeMinePage extends StatelessWidget {
|
||||
"mine_notification.png".mineImgPath,
|
||||
width: 28,
|
||||
),
|
||||
Consumer<ImMsgProvider>(
|
||||
builder: (ctx, imPro, child) {
|
||||
if (!imPro.hasUnreadCount) return const SizedBox.shrink();
|
||||
return Positioned(
|
||||
right: 2,
|
||||
top: 2,
|
||||
child: Container(
|
||||
width: 8,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xfff74f49),
|
||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
Consumer<MineMsgProvider>(
|
||||
builder: (context, model, child) => Positioned(
|
||||
right: 2,
|
||||
top: 2,
|
||||
child: model.buildTipsView(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -249,7 +235,7 @@ class HomeMinePage extends StatelessWidget {
|
||||
//永久官方地址:地址未下发时不渲染,避免点击/复制空串
|
||||
Widget _buildGroundUrl() {
|
||||
final url = Address.groundUrl;
|
||||
if (url == null || url.isEmpty) return const SizedBox.shrink();
|
||||
if (url.isEmpty) return const SizedBox.shrink();
|
||||
return GestureDetector(
|
||||
onTap: () => launchUrlToWeb(url),
|
||||
onLongPress: () {
|
||||
@@ -269,31 +255,10 @@ class HomeMinePage extends StatelessWidget {
|
||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => logic.menuTapEvent(3),
|
||||
child: Image.asset("mine_notification.png".mineImgPath, width: 24),
|
||||
),
|
||||
Consumer<ImMsgProvider>(
|
||||
builder: (ctx, imPro, child) {
|
||||
if (!imPro.hasUnreadCount) return const SizedBox.shrink();
|
||||
return Positioned(
|
||||
right: 2,
|
||||
top: 2,
|
||||
child: Container(
|
||||
width: 8,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xfff74f49),
|
||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => logic.menuTapEvent(3),
|
||||
child: Image.asset("mine_notification.png".mineImgPath, width: 24),
|
||||
),
|
||||
Spacer(),
|
||||
InkWell(
|
||||
|
||||
@@ -145,7 +145,7 @@ class MineAccountIdentityPage extends StatelessWidget {
|
||||
height: 30,
|
||||
padding: EdgeInsets.symmetric(horizontal: 18, vertical: 3),
|
||||
child: Text(
|
||||
'${Config.appName} 官网地址 ${Address.groundUrl ?? ""}',
|
||||
'${Config.appName} 官网地址 ${Address.groundUrl}',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .55),
|
||||
fontSize: 12,
|
||||
|
||||
@@ -143,7 +143,5 @@ MineWithdrawalRecordLogic instanceController(RecordType type) {
|
||||
return RechargeRecordController();
|
||||
case RecordType.income:
|
||||
return IncomeRecordController();
|
||||
default:
|
||||
throw '$type 没有找到';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:easy_rich_text/easy_rich_text.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
@@ -13,7 +12,6 @@ import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../assets_tool/app_colors.dart';
|
||||
import '../../../hj_utils/widget_util.dart';
|
||||
import '../../../routers/jump_router.dart';
|
||||
import 'in_come_entity.dart';
|
||||
import 'mine_withdrawal_record_page.dart';
|
||||
import 'withdrawal_logic.dart';
|
||||
@@ -359,18 +357,6 @@ class WithdrawalPage extends StatelessWidget {
|
||||
),
|
||||
)),
|
||||
),
|
||||
10.sizeBoxH,
|
||||
EasyRichText(
|
||||
'提现中如有问题,请联系 在线客服',
|
||||
defaultStyle: textStyle(12, Colors.white.withValues(alpha: .8), FontWeight.w400),
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString: '在线客服',
|
||||
style: TextStyle(color: Color(0xffFFD460)),
|
||||
recognizer: TapGestureRecognizer()..onTap = pushToCustomService,
|
||||
),
|
||||
],
|
||||
),
|
||||
34.sizeBoxH,
|
||||
],
|
||||
)
|
||||
|
||||
@@ -2,13 +2,15 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../hj_utils/api_service/mine_service.dart';
|
||||
import 'message_center_sub_page.dart';
|
||||
|
||||
class MessageCenterLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
MessageCenterLogic get to => Get.find<MessageCenterLogic>();
|
||||
|
||||
late TabController tabController = TabController(length: titleArr.length, vsync: this);
|
||||
|
||||
List<String> titleArr = ['私信', '评论', '公告'];
|
||||
List<String> titleArr = ['评论', '公告'];
|
||||
List<MessageType> typeArr = [MessageType.comment, MessageType.thumb]; //与 titleArr 一一对应
|
||||
|
||||
void getUnReadNum() async {
|
||||
await MineService.getUnreadNum();
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/im_manager/chat_detail_page/Im_ad_view.dart';
|
||||
import 'package:jydj/im_manager/chat_detail_page/chat_session_list_view.dart';
|
||||
import 'package:jydj/im_manager/im_ad/im_ad_manager.dart';
|
||||
import 'package:jydj/tools_base/widget/keep_alive_widget.dart';
|
||||
|
||||
import 'message_center_logic.dart';
|
||||
@@ -54,25 +51,7 @@ class MessageCenterPage extends StatelessWidget {
|
||||
controller: logic.tabController,
|
||||
children: logic.titleArr
|
||||
.asMap()
|
||||
.map((key, value) {
|
||||
final type = MessageType.values[key];
|
||||
// 私信 Tab 走 IM 会话列表 + 顶部 banner 广告,其余走原有 HTTP 消息
|
||||
if (type == MessageType.session) {
|
||||
return MapEntry(
|
||||
key,
|
||||
CustomScrollView(slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: ImAdView(
|
||||
padding: EdgeInsets.symmetric(vertical: 12, horizontal: 12),
|
||||
position: ImAdManager.kPosListBanner,
|
||||
),
|
||||
),
|
||||
const ChatSessionListView(),
|
||||
]).keepAlive,
|
||||
);
|
||||
}
|
||||
return MapEntry(key, MessageCenterSubPage(type).keepAlive);
|
||||
})
|
||||
.map((key, value) => MapEntry(key, MessageCenterSubPage(logic.typeArr[key]).keepAlive))
|
||||
.values
|
||||
.toList()),
|
||||
),
|
||||
|
||||
@@ -157,7 +157,5 @@ MineFollowSubLogic instanceController(FollowType type, {int? uid}) {
|
||||
return TopicController(uid);
|
||||
case FollowType.actress:
|
||||
return ActressController(uid);
|
||||
default:
|
||||
throw 'type 没有定义';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,9 +280,6 @@ class _GesturePasswordWidgetState extends State<GesturePasswordWidget> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
//预览小点的边长:每行 singleLineCount 个 10px 的点 + 之间 8px 间距。必须按 singleLineCount 算,
|
||||
//写死值(原来是 56)比内容宽时 Wrap 默认贴左上,整块预览会偏左偏上,且换行数只对 3x3 成立
|
||||
final previewSize = 10.0 * widget.singleLineCount + 8 * (widget.singleLineCount - 1);
|
||||
return Column(
|
||||
children: [
|
||||
/*SizedBox(
|
||||
|
||||
@@ -141,7 +141,7 @@ class _BankCardHomePageState extends State<BankCardHomePage> {
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.only(top: 10, bottom: 80),
|
||||
shrinkWrap: true,
|
||||
itemCount: aliList.length ?? 0,
|
||||
itemCount: aliList.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return _buildCardView(index, aliList[index]);
|
||||
},
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
|
||||
import '../../../hj_utils/permission_util.dart';
|
||||
import '../../../routers/jump_router.dart';
|
||||
import 'bing_phone_page.dart';
|
||||
import 'mine_scan_login_page.dart';
|
||||
|
||||
@@ -21,10 +20,6 @@ class MineFindAccountPage extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
'title': '联系客服',
|
||||
'ontap': () => pushToCustomService(),
|
||||
}
|
||||
];
|
||||
MineFindAccountPage({super.key});
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/routers/jump_router.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/config/config.dart';
|
||||
import 'package:jydj/tools_base/toast.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
|
||||
@@ -82,7 +82,5 @@ MineSettingProfilePage instanceSettingProfileController(SettingProfileType type)
|
||||
return SettingNickNameController();
|
||||
case SettingProfileType.slogan:
|
||||
return SettingSloganController();
|
||||
default:
|
||||
throw '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ class MineSharePage extends StatelessWidget {
|
||||
height: 30,
|
||||
padding: EdgeInsets.symmetric(horizontal: 18, vertical: 3),
|
||||
child: Text(
|
||||
'${Config.appName} 官网地址 ${Address.groundUrl ?? ""}',
|
||||
'${Config.appName} 官网地址 ${Address.groundUrl}',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .55),
|
||||
fontSize: 12,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'package:easy_rich_text/easy_rich_text.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -11,7 +9,6 @@ import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../hj_utils/widget_util.dart';
|
||||
import '../../../routers/jump_router.dart';
|
||||
import '../make_money/mine_withdrawal_record_page.dart';
|
||||
import 'charge_user_header.dart';
|
||||
import 'mine_charge_coin_logic.dart';
|
||||
@@ -98,16 +95,9 @@ class MineChargeCoinPage extends StatelessWidget {
|
||||
),
|
||||
SliverToBoxAdapter(child: 18.sizeBoxH),
|
||||
SliverToBoxAdapter(
|
||||
child: EasyRichText(
|
||||
'*如提示【交易失败】【账户风险】等,可重新发起订单,或在15分钟后重试支付。如支付未到账,请反馈客服订单号',
|
||||
defaultStyle: TextStyle(color: Color(0xff666666), fontSize: 12),
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString: '反馈客服订单号',
|
||||
style: TextStyle(color: Color(0xffFFD460), fontWeight: FontWeight.w500),
|
||||
recognizer: TapGestureRecognizer()..onTap = () => pushToCustomService(),
|
||||
)
|
||||
],
|
||||
child: Text(
|
||||
'*如提示【交易失败】【账户风险】等,可重新发起订单,或在15分钟后重试支付。',
|
||||
style: TextStyle(color: Color(0xff666666), fontSize: 12),
|
||||
).paddingSymmetric(horizontal: 16),
|
||||
),
|
||||
],
|
||||
@@ -122,7 +112,7 @@ class MineChargeCoinPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
// 底部支付按钮 + 客服入口
|
||||
// 底部支付按钮
|
||||
Widget _buildBottomBar(MineChargeCoinLogic controller) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -140,19 +130,6 @@ class MineChargeCoinPage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('权益长期有效 I 支持帐号找回 I ', style: textStyle(12, Color(0xffBFBFC1), FontWeight.w400)),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
pushToCustomService();
|
||||
},
|
||||
child: Text('在线客服', style: textStyle(12, Color(0xffFFD460), FontWeight.w400)),
|
||||
)
|
||||
],
|
||||
),
|
||||
// 垫上虚拟导航栏高度,避免底部内容被遮挡(edge-to-edge)
|
||||
(16 + screen.paddingBottom).sizeBoxH,
|
||||
],
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:easy_rich_text/easy_rich_text.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
@@ -12,7 +10,6 @@ import 'package:jydj/tools_base/unique_tag_mixin.dart';
|
||||
import 'package:jydj/tools_base/widget/net_image_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../routers/jump_router.dart';
|
||||
import '../../pre_sale/pre_sale_entry.dart';
|
||||
import '../make_money/mine_withdrawal_record_page.dart';
|
||||
import 'charge_user_header.dart';
|
||||
@@ -189,57 +186,6 @@ class _MineChargeVipPageState extends State<MineChargeVipPage> with UniqueTagMix
|
||||
);
|
||||
}
|
||||
|
||||
//核心权益:横向滚动卡片(左图标 + 右文案)—— B 改版
|
||||
Widget _buildCorePrivileges(List<NewPrivilege> list) {
|
||||
if (list.isEmpty) return const SizedBox.shrink();
|
||||
return Column(
|
||||
children: [
|
||||
const VipCoreSectionTitleImage(),
|
||||
16.sizeBoxH,
|
||||
SizedBox(
|
||||
height: 92,
|
||||
child: ListView.separated(
|
||||
clipBehavior: Clip.none,
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.fromLTRB(16, 2, 16, 26),
|
||||
itemCount: list.length,
|
||||
separatorBuilder: (_, __) => 8.sizeBoxW,
|
||||
itemBuilder: (_, index) => VipCorePrivilegeCard(list[index]),
|
||||
),
|
||||
),
|
||||
16.sizeBoxH,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
//核心权益:4 列金边方卡 —— A / DISABLED 旧版
|
||||
Widget _buildClassicCorePrivileges(List<NewPrivilege> list) {
|
||||
if (list.isEmpty) return const SizedBox.shrink();
|
||||
return Column(
|
||||
children: [
|
||||
const VipSectionTitle("我的核心权益", classic: true),
|
||||
16.sizeBoxH,
|
||||
GridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
crossAxisSpacing: 8,
|
||||
mainAxisSpacing: 8,
|
||||
childAspectRatio: 1,
|
||||
),
|
||||
itemCount: list.length,
|
||||
itemBuilder: (_, index) => FittedBox(
|
||||
fit: BoxFit.contain,
|
||||
child: SizedBox(width: 72, height: 72, child: VipCorePrivilegeCard(list[index], classic: true)),
|
||||
),
|
||||
),
|
||||
16.sizeBoxH,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
//更多权益:深色圆角容器 + 四列网格 + 展开/收起 —— B 改版
|
||||
Widget _buildMorePrivileges(List<NewPrivilege> list) {
|
||||
if (list.isEmpty) return const SizedBox.shrink();
|
||||
@@ -274,7 +220,7 @@ class _MineChargeVipPageState extends State<MineChargeVipPage> with UniqueTagMix
|
||||
);
|
||||
}
|
||||
|
||||
//底部支付区域:只有按钮跟选中卡走,渐变底和客服文案是静态的
|
||||
//底部支付区域:只有按钮跟选中卡走,渐变底是静态的
|
||||
Widget _buildPay({required bool classic}) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
@@ -294,18 +240,6 @@ class _MineChargeVipPageState extends State<MineChargeVipPage> with UniqueTagMix
|
||||
id: MineChargeVipLogic.kSelection,
|
||||
builder: (logic) => VipPayButton(logic, classic: classic),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
EasyRichText(
|
||||
'权益长期有效 I 支持帐号找回 I 在线客服',
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString: '在线客服',
|
||||
style: TextStyle(color: Color(0xFFFFC000), fontSize: 12),
|
||||
recognizer: TapGestureRecognizer()..onTap = () => pushToCustomService(),
|
||||
)
|
||||
],
|
||||
defaultStyle: TextStyle(color: Color(0xffBFBFC1), fontSize: 12),
|
||||
),
|
||||
// 垫上虚拟导航栏高度,避免底部内容被遮挡(edge-to-edge)
|
||||
(12 + screen.paddingBottom).sizeBoxH,
|
||||
],
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:easy_rich_text/easy_rich_text.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -154,21 +152,6 @@ class _OnlinePayPageState extends State<OnlinePayPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
18.sizeBoxH,
|
||||
//客服入口
|
||||
Center(
|
||||
child: EasyRichText(
|
||||
'支付问题反馈,点击联系 在线客服',
|
||||
defaultStyle: textStyle(12, Colors.white.withValues(alpha: .6), FontWeight.w500),
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString: '在线客服',
|
||||
style: textStyle(12, Color(0xffFFD460), FontWeight.w500),
|
||||
recognizer: TapGestureRecognizer()..onTap = () => pushToCustomService(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/widget/common_dialog.dart';
|
||||
|
||||
import '../../../routers/jump_router.dart';
|
||||
import '../../../tools_base/global_store/store.dart';
|
||||
|
||||
class PaySuccessAlert extends StatelessWidget {
|
||||
@@ -34,7 +33,7 @@ class PaySuccessAlert extends StatelessWidget {
|
||||
0.5.line,
|
||||
12.sizeBoxH,
|
||||
Text(
|
||||
'''1.订单支付后,一般会在1-10分钟内到账,如超时未到账,请联系在线客服为您处理。
|
||||
'''1.订单支付后,一般会在1-10分钟内到账。
|
||||
2.受特殊行业限制,如支付失败可尝试重新发起订单,系统将会随机切换备用的支付通道。
|
||||
3.本APP有稳定的广告收益,产品稳定安全,请放心充值使用,如遇报毒提示忽略即可。''',
|
||||
style: TextStyle(
|
||||
@@ -43,24 +42,6 @@ class PaySuccessAlert extends StatelessWidget {
|
||||
height: 1.8,
|
||||
),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
InkWell(enableFeedback: false,
|
||||
onTap: () => pushToCustomService(),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'支付遇到问题',
|
||||
style: TextStyle(color: Color(0xff999999), fontSize: 14),
|
||||
),
|
||||
2.sizeBoxW,
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_outlined,
|
||||
size: 14,
|
||||
color: Colors.white,
|
||||
)
|
||||
],
|
||||
)),
|
||||
24.sizeBoxH,
|
||||
InkWell(enableFeedback: false,
|
||||
onTap: () {
|
||||
|
||||
@@ -3,8 +3,6 @@ import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/hj_utils/widget_util.dart';
|
||||
import 'package:jydj/routers/jump_router.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -148,25 +146,6 @@ class CoinPayBottomSheet extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
16.sizeBoxH,
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
style: const TextStyle(fontSize: 12, height: 18 / 12, color: Color(0xff656565)),
|
||||
children: [
|
||||
const TextSpan(text: '*如提示【交易失败】【账户风险】等,可重新发起订单,或在15分钟后重试支付。如支付未到账,请'),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: GestureDetector(
|
||||
onTap: pushToCustomService,
|
||||
child: const Text(
|
||||
'反馈客服订单号',
|
||||
style: TextStyle(fontSize: 12, height: 18 / 12, color: Color(0xffFFD460)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
18.sizeBoxH,
|
||||
],
|
||||
),
|
||||
@@ -234,7 +213,7 @@ class CoinPayBottomSheet extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// 立即支付 + 在线客服
|
||||
/// 立即支付
|
||||
Widget _buildBottomBar(MineChargeCoinLogic logic) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -259,17 +238,6 @@ class CoinPayBottomSheet extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('支付问题反馈,点击联系 ', style: textStyle(12, const Color(0xffBFBFC1), FontWeight.w400)),
|
||||
GestureDetector(
|
||||
onTap: pushToCustomService,
|
||||
child: Text('在线客服', style: textStyle(12, const Color(0xffFFD460), FontWeight.w400)),
|
||||
),
|
||||
],
|
||||
),
|
||||
16.sizeBoxH,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -26,13 +26,13 @@ class _MineQAPageState extends State<MineQAPage> {
|
||||
{
|
||||
"question": "怎么找回账号?",
|
||||
"answer":
|
||||
"本平台登录会自动创建账号,需保存账号凭证或绑定手机号码,才能记录之前的账号信息。受行业限制,APP无法正常使用时需升级,未绑定手机号码会导致账号信息丢失。请及时绑定手机号码或保存账号凭证,以免VIP信息丢失,造成巨大财产损失!账号丢失的用户可在 『我的』页面-账号找回,原账号的VIP信息会转移至新账号上。『账号凭证』『手机绑定』都没有的情况下,如账号VIP信息丢失,可以提供VIP支付充值凭证截图联系在线客服为您查询核实恢复VIP。",
|
||||
"本平台登录会自动创建账号,需保存账号凭证或绑定手机号码,才能记录之前的账号信息。受行业限制,APP无法正常使用时需升级,未绑定手机号码会导致账号信息丢失。请及时绑定手机号码或保存账号凭证,以免VIP信息丢失,造成巨大财产损失!账号丢失的用户可在 『我的』页面-账号找回,原账号的VIP信息会转移至新账号上。",
|
||||
'isOpen': false
|
||||
},
|
||||
{
|
||||
"question": "怎么支付不成功?",
|
||||
"answer":
|
||||
"1.因超时支付无法到账,请重新发起。\n2.每天发起支付不能超过5次,连续发起且未支付,账号可能被加入黑名单。\n3.支付通道在夜间比较忙碌,尝试多次发起,后台会为您自动切换不同支付通道。\n4.若充值成功,用户权益通常会在数分钟内到账,请刷新APP或重启。\n6.若支付成功并重启APP后依然没有到账,请联系在线客服并提供付款成功凭证截图。",
|
||||
"1.因超时支付无法到账,请重新发起。\n2.每天发起支付不能超过5次,连续发起且未支付,账号可能被加入黑名单。\n3.支付通道在夜间比较忙碌,尝试多次发起,后台会为您自动切换不同支付通道。\n4.若充值成功,用户权益通常会在数分钟内到账,请刷新APP或重启。",
|
||||
'isOpen': false
|
||||
},
|
||||
{"question": "收到手机报毒提醒?", "answer": "本平台有主要收益为广告赞助,且保证APP安全无毒,因平台主要展示内容为色情属于特殊行业,某些杀毒软件会误报毒提醒,如遇此类提醒请忽略继续使用。", 'isOpen': false},
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:jydj/tools_base/unique_tag_mixin.dart';
|
||||
import 'package:jydj/tools_base/widget/keep_alive_widget.dart';
|
||||
import 'package:jydj/track_event_manager/track_manager.dart';
|
||||
|
||||
import 'lou_feng_ad_logic.dart';
|
||||
import 'widget/recommend_app_page.dart';
|
||||
@@ -92,8 +91,5 @@ class _LouFengAdPageState extends State<LouFengAdPage> with UniqueTagMixin {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _adView(LouFengAdLogic logic, int index) => RecommendAppPage(
|
||||
logic.configs[index],
|
||||
exposureModel: AdExposureModel(tabIndex: index, pageType: TrackEventPageType.appList),
|
||||
);
|
||||
Widget _adView(LouFengAdLogic logic, int index) => RecommendAppPage(logic.configs[index]);
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ class MoreFreeVideoLogic extends GetxController with GetTickerProviderStateMixin
|
||||
dataSource.clear();
|
||||
refreshController?.refreshCompleted();
|
||||
}
|
||||
res?.hasNext ?? false ? refreshController?.loadComplete() : refreshController?.loadNoData();
|
||||
dataSource.addAll(res?.list ?? []);
|
||||
res.hasNext ?? false ? refreshController?.loadComplete() : refreshController?.loadNoData();
|
||||
dataSource.addAll(res.list ?? []);
|
||||
page += 1;
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:jydj/tools_base/widget/keep_alive_widget.dart';
|
||||
|
||||
import '../../../tools_base/indicator/custom_tab_indicator.dart';
|
||||
import 'lou_feng_ad_page.dart';
|
||||
import 'mine_income_page.dart';
|
||||
|
||||
class WelfareHomePage extends StatefulWidget {
|
||||
|
||||
|
||||
@@ -3,15 +3,13 @@ import 'package:jydj/hj_model/mine/happy/happy_model.dart';
|
||||
import 'package:jydj/hj_model/splash/ads_model.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/banner/ads_banner.dart';
|
||||
import 'package:jydj/track_event_manager/track_manager.dart';
|
||||
|
||||
import '../../../../tools_base/banner/ads_item.dart';
|
||||
|
||||
class RecommendAppPage extends StatelessWidget {
|
||||
final AdTabConfig model;
|
||||
final AdExposureModel? exposureModel;
|
||||
|
||||
const RecommendAppPage(this.model, {super.key, this.exposureModel});
|
||||
const RecommendAppPage(this.model, {super.key});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomScrollView(
|
||||
@@ -24,10 +22,7 @@ class RecommendAppPage extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 343 / 143,
|
||||
child: AdsBanner(
|
||||
model.bannerAds ?? [],
|
||||
exposureModel: exposureModel?..adType = AdType.bigBanner,
|
||||
),
|
||||
child: AdsBanner(model.bannerAds ?? []),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -113,8 +108,6 @@ class RecommendAppPage extends StatelessWidget {
|
||||
_buildVItem(AdsInfoModel item, int index) {
|
||||
return AdsItem(
|
||||
adInfo: item,
|
||||
exposureModel: exposureModel?..adType = AdType.smallIcon,
|
||||
clickType: 0,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -126,8 +119,6 @@ class RecommendAppPage extends StatelessWidget {
|
||||
AdsItem(
|
||||
adInfo: item,
|
||||
showType: AdShowType.hor,
|
||||
exposureModel: exposureModel?..adType = AdType.smallIcon,
|
||||
clickType: 0,
|
||||
),
|
||||
12.sizeBoxH,
|
||||
],
|
||||
@@ -138,8 +129,6 @@ class RecommendAppPage extends StatelessWidget {
|
||||
return AdsItem(
|
||||
adInfo: item,
|
||||
showType: AdShowType.vImgText,
|
||||
exposureModel: exposureModel?..adType = AdType.smallBanner,
|
||||
clickType: 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,7 +614,7 @@ class _TaskItemState extends State<TaskItem> {
|
||||
/// 任务按钮点击:红包雨 → 跳转 link;未完成 → 去完成;待领取 → 领奖
|
||||
void _onBtnTap(DailyTask task, String btnText) {
|
||||
if (btnText == '领红包' || btnText == '待开启') {
|
||||
pushToPageByLink(task.link, id: task.id);
|
||||
pushToPageByLink(task.link);
|
||||
return;
|
||||
}
|
||||
switch (task.status) {
|
||||
@@ -623,7 +623,7 @@ class _TaskItemState extends State<TaskItem> {
|
||||
Get.to(MineChargeCoinPage());
|
||||
return;
|
||||
}
|
||||
pushToPageByLink(task.link, id: task.id);
|
||||
pushToPageByLink(task.link);
|
||||
_doTask(task);
|
||||
break;
|
||||
case 1:
|
||||
|
||||
@@ -8,9 +8,7 @@ import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
import 'package:jydj/tools_base/loading/loading_center_widget.dart';
|
||||
|
||||
import '../../../routers/jump_router.dart';
|
||||
import '../../../tools_base/loading/loading_helper.dart';
|
||||
import '../../../tools_base/widget/common_dialog.dart';
|
||||
import '../../../tools_base/widget/net_image_widget.dart';
|
||||
import 'integral_exchange_logic.dart';
|
||||
|
||||
@@ -105,90 +103,8 @@ class IntegralExchangePage extends StatelessWidget {
|
||||
final res = await MineService.integralExchange(model.id ?? '');
|
||||
LoadingHelper.dismissLoading();
|
||||
if (res) {
|
||||
if (model.type == 5) {
|
||||
Get.dialog(InputAddressAlert(model: model));
|
||||
} else {
|
||||
showToast('兑换成功~');
|
||||
}
|
||||
showToast('兑换成功~');
|
||||
globalStore.refreshWallet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class InputAddressAlert extends StatefulWidget {
|
||||
// final Function()? confirmCallback;
|
||||
final IntegralExchangeModel model;
|
||||
const InputAddressAlert({super.key, required this.model});
|
||||
|
||||
@override
|
||||
State<InputAddressAlert> createState() => _InputAddressAlertState();
|
||||
}
|
||||
|
||||
class _InputAddressAlertState extends State<InputAddressAlert> {
|
||||
final nameCtr = TextEditingController();
|
||||
final addressCtr = TextEditingController();
|
||||
final phoneCtr = TextEditingController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CommonDialog(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'温馨提示',
|
||||
style: TextStyle(color: Color(0xffffffff), fontSize: 18.sp, fontWeight: FontWeight.w800),
|
||||
),
|
||||
20.h.sizeBoxH,
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Colors.white.withValues(alpha: .1),
|
||||
),
|
||||
20.h.sizeBoxH,
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 45.h,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: 13.w),
|
||||
child: Text(
|
||||
"兑换成功!",
|
||||
style: TextStyle(color: Color(0x8CFFFFFF), fontSize: 18),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
5.h.sizeBoxH,
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 45.h,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: 13.w),
|
||||
child: Text(
|
||||
"请联系客服填写收货地址",
|
||||
style: TextStyle(color: Color(0x8CFFFFFF), fontSize: 18),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
20.h.sizeBoxH,
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 15.w),
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
pushToCustomService();
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(color: Color(0xffFFC000), borderRadius: BorderRadius.circular(6)),
|
||||
height: 48,
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'联系客服',
|
||||
style: TextStyle(color: Colors.white, fontSize: 18.sp, fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_model/video_model.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
import 'package:jydj/tools_base/toast.dart';
|
||||
@@ -13,9 +12,7 @@ import '../../home/widget/user_avatar.dart';
|
||||
import '../../home/widget/user_name_view.dart';
|
||||
import '../collec_history_buy/col_his_buy_page.dart';
|
||||
import '../home_mine_logic.dart';
|
||||
import '../mine_following/mine_following_view.dart';
|
||||
import '../mine_setting/mine_setting_page.dart';
|
||||
import '../mine_video_cache/video_cache_page.dart';
|
||||
import '../mine_vip/mine_charge_coin_page.dart';
|
||||
import '../mine_vip/mine_charge_vip_page.dart';
|
||||
import '../welfare/sign_daily_page.dart';
|
||||
@@ -157,7 +154,7 @@ class MineTaskMenuWidget extends StatelessWidget {
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => Get.to(() => MineChargeVipPage(), preventDuplicates: false),
|
||||
child: _buildItem("", HolidayTheme.theme.vipEnter, 0),
|
||||
child: _buildItem("", 'mine_vip_enter.webp'.mineImgPath, 0),
|
||||
),
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
@@ -167,14 +164,14 @@ class MineTaskMenuWidget extends StatelessWidget {
|
||||
},
|
||||
child: _buildItem(
|
||||
"余额:${(globalStore.wallet?.amount ?? 0) + (globalStore.wallet?.income ?? 0)}",
|
||||
HolidayTheme.theme.coin,
|
||||
'mine_gold_enter.webp'.mineImgPath,
|
||||
15,
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: _openAiGirlFriendDetail,
|
||||
child: _buildItem("", HolidayTheme.theme.aiEnter, 0),
|
||||
child: _buildItem("", 'mine_ai_enter.webp'.mineImgPath, 0),
|
||||
),
|
||||
];
|
||||
return Stack(
|
||||
|
||||
@@ -145,7 +145,7 @@ class _MineShareQRViewState extends State<MineShareQRView> {
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
child: Text(
|
||||
'${Config.appName} 官网地址 ${Address.groundUrl ?? ""}',
|
||||
'${Config.appName} 官网地址 ${Address.groundUrl}',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .55),
|
||||
fontSize: 12,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:jydj/hj_model/video_model.dart';
|
||||
import 'package:jydj/hj_utils/api_service/common_service.dart';
|
||||
import 'package:jydj/routers/jump_router.dart';
|
||||
|
||||
import '../../../hj_model/splash/ads_model.dart';
|
||||
@@ -14,7 +15,10 @@ class FeedAdView extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final AdsInfoModel? adv = mediaInfo?.randomAdsInfo;
|
||||
return GestureDetector(
|
||||
onTap: () => pushToPageByLink(adv?.href, id: adv?.id),
|
||||
onTap: () {
|
||||
pushToPageByLink(adv?.href);
|
||||
CommonService.adsClick(adv?.id);
|
||||
},
|
||||
// 强制全屏铺满(与视频页一致),避免 iOS 上未撑满导致显示不全
|
||||
child: SizedBox.expand(
|
||||
child: NetworkImageLoader(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_model/splash/ads_model.dart';
|
||||
import 'package:jydj/hj_utils/api_service/common_service.dart';
|
||||
import 'package:jydj/routers/jump_router.dart';
|
||||
import 'package:jydj/tools_base/ad_manager.dart';
|
||||
import 'package:jydj/tools_base/widget/net_image_widget.dart';
|
||||
@@ -34,7 +35,10 @@ class _FloatAdViewState extends State<FloatAdView> {
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => pushToPageByLink(ad.href, id: ad.id),
|
||||
onTap: () {
|
||||
pushToPageByLink(ad.href);
|
||||
CommonService.adsClick(ad.id);
|
||||
},
|
||||
child: NetworkImageLoader(
|
||||
imageUrl: cover,
|
||||
width: 70,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:analytics_sdk/enum/video_event_enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
@@ -21,7 +20,6 @@ import '../../../hj_utils/api_service/mine_service.dart';
|
||||
import '../../../tools_base/debug_log.dart';
|
||||
import '../../../tools_base/global_store/store.dart';
|
||||
import '../../../tools_base/widget/net_image_widget.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
import '../../comment/comment_alert.dart';
|
||||
import '../../home/widget/collect_status_wrapper.dart';
|
||||
import '../../user_center_page/user_center_page.dart';
|
||||
@@ -301,7 +299,6 @@ class _MediaActionMenuState extends State<MediaActionMenu> with TickerProviderSt
|
||||
void _onShareEvent() async {
|
||||
final isPlaying = widget.playerCtr?.value.isPlaying ?? false;
|
||||
widget.playerCtr?.pause();
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_SHARE, _video, widget.playerCtr);
|
||||
await Get.dialog(ShareMediaDialog(videoModel: _video));
|
||||
//短剧分享要回服务端累计互动数(推荐分要吃),eventId 幂等:同一次分享重试沿用同一个
|
||||
if (_isDrama) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:analytics_sdk/enum/video_event_enum.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_model/video_model.dart';
|
||||
@@ -10,7 +9,6 @@ import 'package:video_player/video_player.dart';
|
||||
import 'package:visibility_detector/visibility_detector.dart';
|
||||
|
||||
import '../../../tools_base/debug_log.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
|
||||
/// 竖屏播放器的**播放器管线**:建控制器、H.265 降级、可见性驱动播停、倍速、完播检测。
|
||||
/// 只放与业务无关的机制——试看拦截、付费墙、续播这些各自在子类里做。
|
||||
@@ -157,7 +155,6 @@ abstract class VideoPlayerBaseLogic extends GetxController {
|
||||
notify();
|
||||
await playerCtr?.initialize();
|
||||
if (isRetry) confirmPlatformView(); // 仅重试成功(同视频 textureView 挂、platformView 放出)才落本地
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_VIEW, video, playerCtr);
|
||||
preVideoCtr?.removeListener(_onProgress);
|
||||
preVideoCtr?.dispose(); // 切线路/刷新:释放旧控制器,避免解码器泄漏累积导致后续视频全部加载失败
|
||||
// initialize 期间可能已被销毁(快速连滑),playerCtr 已在 onClose() 里释放,
|
||||
@@ -235,20 +232,18 @@ abstract class VideoPlayerBaseLogic extends GetxController {
|
||||
//duration 为 0 的异常流 isCompleted 也是 true,必须由外层这个条件挡住,别刚起播就当播完
|
||||
if (duration.inMilliseconds > 0 &&
|
||||
(ctr.value.isCompleted || position.inMilliseconds >= duration.inMilliseconds - 300)) {
|
||||
//上报和回调都只发一次:条件成立后每个 tick 都会再进来
|
||||
//回调只发一次:条件成立后每个 tick 都会再进来
|
||||
if (!_completedSent) {
|
||||
_completedSent = true;
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_COMPLETE, video, ctr);
|
||||
onFinished();
|
||||
}
|
||||
}
|
||||
onTick(position.inSeconds);
|
||||
}
|
||||
|
||||
/// 点屏播放/暂停,顺带上报。返回操作前是否在播(子类要据此落进度)
|
||||
/// 点屏播放/暂停。返回操作前是否在播(子类要据此落进度)
|
||||
bool togglePlay() {
|
||||
final isPlaying = playerCtr?.value.isPlaying == true;
|
||||
TrackVideoManager.send(isPlaying ? VideoEventEnum.VIDEO_PAUSE : VideoEventEnum.VIDEO_PLAY, video, playerCtr);
|
||||
isPlaying ? playerCtr?.pause() : playerCtr?.play();
|
||||
return isPlaying;
|
||||
}
|
||||
@@ -256,7 +251,6 @@ abstract class VideoPlayerBaseLogic extends GetxController {
|
||||
/// 长按 2 倍速
|
||||
void speedUp() {
|
||||
showToast("长按不动,2X倍速播放");
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_FORWARD, video, playerCtr);
|
||||
playerCtr?.setPlaybackSpeed(2.0);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/hj_utils/api_service/common_service.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
|
||||
import '../../hj_model/splash/ads_model.dart';
|
||||
@@ -11,7 +12,6 @@ import '../../routers/jump_router.dart';
|
||||
import '../../tools_base/banner/ads_banner.dart';
|
||||
import '../../tools_base/banner/ads_item.dart';
|
||||
import '../../tools_base/widget/net_image_widget.dart';
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
|
||||
/// 启动页广告:3 秒倒计时后右上角按钮变为"关闭",点击触发 callback 跳首页
|
||||
class SplashAdView extends StatefulWidget {
|
||||
@@ -73,7 +73,10 @@ class _SplashAdViewState extends State<SplashAdView> {
|
||||
if (dataLen == 1) {
|
||||
final ad = widget.adData!.first;
|
||||
return GestureDetector(
|
||||
onTap: () => pushToPageByLink(ad.href ?? "", id: ad.id),
|
||||
onTap: () {
|
||||
pushToPageByLink(ad.href ?? "");
|
||||
CommonService.adsClick(ad.id);
|
||||
},
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
child: NetworkImageLoader(
|
||||
@@ -221,10 +224,6 @@ class _SplashBannerWidgetState extends State<SplashBannerWidget> {
|
||||
return AdsItem(
|
||||
adInfo: ad,
|
||||
showType: AdShowType.splash,
|
||||
exposureModel: AdExposureModel(
|
||||
pageType: TrackEventPageType.start,
|
||||
adType: AdType.splash,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:analytics_sdk/analytics_sdk.dart';
|
||||
import 'package:analytics_sdk/entity/app_install_event.dart';
|
||||
import 'package:analytics_sdk/enum/user_type_enum.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -19,12 +16,10 @@ import 'package:jydj/hj_page/pre_sale/limit_time_provider.dart';
|
||||
import 'package:jydj/hj_page/pre_sale/pre_sale_provider.dart';
|
||||
import 'package:jydj/hj_utils/api_service/common_service.dart';
|
||||
import 'package:jydj/hj_utils/detect_line_manager.dart';
|
||||
import 'package:jydj/hj_utils/holiday_theme.dart';
|
||||
import 'package:jydj/hj_utils/local_server.dart';
|
||||
import 'package:jydj/hj_utils/local_server_guard.dart';
|
||||
import 'package:jydj/hj_utils/text_util.dart';
|
||||
import 'package:jydj/hj_utils/version_util.dart';
|
||||
import 'package:jydj/im_manager/im_manager.dart';
|
||||
import 'package:jydj/tools_base/debug_log.dart';
|
||||
import 'package:jydj/tools_base/ad_manager.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
@@ -36,7 +31,6 @@ import 'package:jydj/tools_base/widget/common_alert.dart';
|
||||
import '../../alert/splash/line_error_dialog.dart';
|
||||
import '../../alert/splash/update_dialog.dart';
|
||||
import '../../hj_utils/free_play_manager.dart';
|
||||
import '../../hj_utils/install_util.dart';
|
||||
import '../../tools_base/loading/loading_alert_widget.dart';
|
||||
import '../../track_event_manager/device_service.dart';
|
||||
import '../live/live_main_page.dart';
|
||||
@@ -51,7 +45,6 @@ class SplashLogic extends GetxController {
|
||||
|
||||
// ===== 启动数据 =====
|
||||
bool isDataReady = false; //模块列表已落地
|
||||
bool _isTracked = false; //登录埋点去重
|
||||
bool _isExiting = false; //强更被拒、已请求退出 app:后续流程一律不再放行首页
|
||||
|
||||
@override
|
||||
@@ -76,19 +69,13 @@ class SplashLogic extends GetxController {
|
||||
//1. 初始化网络层
|
||||
_initNet(line);
|
||||
//2.先登录,后升级,不然渠道一升级就没有量了,先登录才能获取配置信息
|
||||
final userInfo = await _devLogin();
|
||||
ImManager().initImSDK(); // 登录后初始化 IM SDK,需先拿到动态配置(随登录返回写入 ImManager)
|
||||
await _devLogin();
|
||||
// 模块列表只依赖登录拿到的 token,请求先发出去跟下面的配置/更新检查并行跑,
|
||||
// 但结果留到更新检查之后才放行(见末尾)——强更期间不能让首页变成可跳
|
||||
// ignore():先占个监听位,免得错误在 await 到之前被当成未捕获异常上报;真正的错误照旧在 await 处抛
|
||||
final tagTask = CommonService.getTagMarks()..ignore();
|
||||
//2. 获取远程配置
|
||||
final versions = await _fetchConfig();
|
||||
ImManager().connectServer(); //登录并拿到配置后连接 IM 服务器
|
||||
//3.获取到配置信息拿到baseurl才进行埋点
|
||||
if (userInfo != null) {
|
||||
_trackEvents(userInfo);
|
||||
}
|
||||
PreSaleProvider().refreshConfig();
|
||||
MineMsgProvider().startPayTimer(); //冷启动 /ping/domain 下发支付分层配置后启动倒计时
|
||||
FreePlayManager().refresh(); //免费次数进首页才用得到,不 await、不挡启动
|
||||
@@ -107,34 +94,6 @@ class SplashLogic extends GetxController {
|
||||
update();
|
||||
}
|
||||
|
||||
//埋点事件
|
||||
Future _trackEvents(UserInfoModel userInfo) async {
|
||||
//安装
|
||||
final traceId = await DeviceInfoService.fetchTraceId();
|
||||
final isFirst = await InstallUtil.isFirstInstall();
|
||||
if (isFirst) {
|
||||
debugLog('splash', '第一次安装,执行首次安装初始化');
|
||||
// 执行首次安装的初始化操作
|
||||
await InstallUtil.markAsInstalled();
|
||||
//新增SDK埋点
|
||||
AnalyticsSdk.instance.track(AppInstallEvent(
|
||||
traceId: traceId,
|
||||
));
|
||||
} else {
|
||||
debugLog('splash', '已安装过,跳过首次安装初始化');
|
||||
}
|
||||
// 登录埋点
|
||||
if (!_isTracked) {
|
||||
_isTracked = true;
|
||||
|
||||
//新增SDK埋点
|
||||
AnalyticsSdk.setUserIdAndType(
|
||||
userId: "${userInfo.uid}",
|
||||
userTypeEnum: userInfo.isVip == true ? UserTypeEnum.vip : UserTypeEnum.normal,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
///一直检查网络直到成功
|
||||
Future<String?> _detectLine() async {
|
||||
LoadingAlertWidget.show(title: "选线中...");
|
||||
@@ -172,20 +131,11 @@ class SplashLogic extends GetxController {
|
||||
..dc = channel
|
||||
..tid = traceId;
|
||||
paste = json.encode(cutInfo.toJson());
|
||||
AnalyticsSdk.setChannel(channel);
|
||||
} else {
|
||||
//1.获取粘贴板(走缓存,避免 iOS 多次弹系统读取提示)
|
||||
final clipText = await DeviceInfoService.getClipboardTextCached();
|
||||
if (TextUtil.isNotEmpty(clipText)) {
|
||||
paste = clipText!;
|
||||
try {
|
||||
final map = jsonDecode(paste) as Map<String, dynamic>;
|
||||
final dc = map['dc'] as String?;
|
||||
//更新渠道信息
|
||||
if (dc != null) AnalyticsSdk.setChannel(dc);
|
||||
} catch (_) {
|
||||
//粘贴板内容非合法 JSON,忽略
|
||||
}
|
||||
}
|
||||
}
|
||||
final deviceId = DeviceInfoService.deviceId;
|
||||
@@ -238,15 +188,12 @@ class SplashLogic extends GetxController {
|
||||
//限时活动相关
|
||||
limitTimeProvider.bannerJump = info.bannerJump;
|
||||
Config.proxyBanner = info.proxyBannerJump;
|
||||
holidayTheme.setThemeValue(info.festivalUi ?? '');
|
||||
// holidayTheme.setThemeValue('春节');
|
||||
Config.hotWords = info.hotSearchTerms ?? [];
|
||||
Config.searchHints = info.searchHintWord ?? [];
|
||||
|
||||
Config.darkWebVipId = info.darkWebVipId;
|
||||
Config.darkWebVipName = info.darkWebVipName;
|
||||
Config.shortDramaCardId = info.shortDramaCardId;
|
||||
await AnalyticsSdk.instance.refreshDomainConfig(encryptedConfig: info.reportSdkConfig);
|
||||
} catch (e) {
|
||||
debugLog('getRemoteConfig', e.toString());
|
||||
final retry = await CommonAlert.show(
|
||||
|
||||
@@ -3,11 +3,8 @@ import 'package:get/get.dart';
|
||||
import 'package:jydj/hj_model/user/user_info_model.dart';
|
||||
import 'package:jydj/hj_utils/api_service/mine_service.dart';
|
||||
import 'package:jydj/hj_utils/const.dart';
|
||||
import 'package:jydj/im_manager/im_manager.dart';
|
||||
import 'package:jydj/im_manager/model/im_message_resp.dart';
|
||||
import 'package:jydj/tools_base/debug_log.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
import 'package:jydj/tools_base/toast.dart';
|
||||
|
||||
class UserCenterController extends GetxController with GetTickerProviderStateMixin {
|
||||
// ===== 数据 =====
|
||||
@@ -76,19 +73,6 @@ class UserCenterController extends GetxController with GetTickerProviderStateMix
|
||||
update();
|
||||
}
|
||||
|
||||
void gotoPrivateChat() {
|
||||
if (globalStore.isMe(model?.uid)) {
|
||||
showToast("不能给自己私信哦~");
|
||||
return;
|
||||
}
|
||||
// 私信走 IM(替换原 HTTP MineChatPage)
|
||||
jumpToChatDetail(IMSessionModel(
|
||||
peerId: model?.uid ?? 0,
|
||||
nickName: model?.name ?? '',
|
||||
avatar: model?.portrait,
|
||||
));
|
||||
}
|
||||
|
||||
/// 关注/取关成功后更新本地状态;[isFollow] 为操作后的最新状态(与 [FollowButton] 回调一致)
|
||||
void onUserFollowSuccess(bool isFollow) {
|
||||
if (model == null) return;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:jydj/assets_tool/app_colors.dart';
|
||||
import 'package:jydj/assets_tool/images.dart';
|
||||
import 'package:jydj/extension/extensions.dart';
|
||||
import 'package:jydj/hj_page/user_center_page/user_center_logic.dart';
|
||||
import 'package:jydj/hj_utils/screen.dart';
|
||||
import 'package:jydj/hj_utils/widget_util.dart';
|
||||
import 'package:jydj/tools_base/global_store/store.dart';
|
||||
import 'package:jydj/tools_base/widget/follow_button.dart';
|
||||
|
||||
@@ -102,24 +100,9 @@ class UserCenterHeader extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
//私信 + 关注,仅他人主页展示
|
||||
//关注,仅他人主页展示
|
||||
List<Widget> _actionButtons() {
|
||||
return [
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: logic.gotoPrivateChat,
|
||||
child: Container(
|
||||
width: 32,
|
||||
height: 24,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: const Color(0x1AF68804),
|
||||
),
|
||||
child: Text('私信', style: textStyle(10, AppColors.actionRed, FontWeight.w400)),
|
||||
),
|
||||
),
|
||||
12.sizeBoxW,
|
||||
FollowButton(
|
||||
mediaId: (logic.model?.uid ?? 0).toString(),
|
||||
followType: FollowEnum.user,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:analytics_sdk/enum/video_event_enum.dart';
|
||||
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -17,7 +16,6 @@ import 'package:video_player/video_player.dart';
|
||||
|
||||
import '../../../hj_model/acg/comic_chapters_model.dart';
|
||||
import '../../../hj_model/cartoon_media_info.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
import '../../../alert/video/share_media_dialog.dart';
|
||||
import '../../cartoon/cartoon_recommend_page.dart';
|
||||
import 'cartoon_episode_menu_alert.dart';
|
||||
@@ -103,8 +101,6 @@ class _VideoDetailCartoonViewState extends State<VideoDetailCartoonView>
|
||||
child: AdsGridView(
|
||||
6,
|
||||
padding: EdgeInsets.only(left: 12, bottom: 18),
|
||||
exposureModel:
|
||||
AdExposureModel(pageType: TrackEventPageType.videoPlay),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(child: _buildTitleMenu()),
|
||||
@@ -143,9 +139,8 @@ class _VideoDetailCartoonViewState extends State<VideoDetailCartoonView>
|
||||
);
|
||||
}
|
||||
|
||||
/// 分享:带播放器上报埋点(进度/时长),再弹分享面板
|
||||
/// 分享:弹分享面板
|
||||
void _onShare() {
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_SHARE, videoModel, widget.playCtr);
|
||||
Get.dialog(ShareMediaDialog(videoModel: videoModel));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analytics_sdk/enum/video_event_enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -38,7 +37,6 @@ import '../../tools_base/debug_log.dart';
|
||||
import '../../tools_base/event_bus/event_bus_util.dart';
|
||||
import '../../tools_base/event_bus/events.dart';
|
||||
import '../../tools_base/global_store/store.dart';
|
||||
import '../../track_event_manager/track_manager.dart';
|
||||
import '../main_page/provider/msg_provider.dart';
|
||||
import '../pre_sale/pre_sale_provider.dart';
|
||||
|
||||
@@ -342,7 +340,6 @@ class VideoLogic extends GetxController with GetSingleTickerProviderStateMixin {
|
||||
/// 注:贴片广告期间不直接 play,由广告结束回调触发本方法(见 video_page.dart 的 onFinish)
|
||||
void play() {
|
||||
if (isDispose || isShowAd) return; // 有贴片广告时不自动播,等广告结束回调
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_PLAY, videoModel, playerCtr, isPreVideo: _isPreview());
|
||||
playerCtr?.play();
|
||||
_startPayGuideTimer(); // 需付费的起播满3秒 → 前置购买引导(场景1);不满足条件的它自己会挡
|
||||
}
|
||||
@@ -399,7 +396,6 @@ class VideoLogic extends GetxController with GetSingleTickerProviderStateMixin {
|
||||
try {
|
||||
await playerCtr?.initialize();
|
||||
if (isRetry) confirmPlatformView(); // 仅重试成功(同视频 textureView 挂、platformView 放出)才落本地
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_VIEW, videoModel, playerCtr, isPreVideo: _isPreview());
|
||||
update();
|
||||
} catch (e) {
|
||||
debugLog("视频初始化失败:$e play url = $videoUrl");
|
||||
@@ -469,9 +465,6 @@ class VideoLogic extends GetxController with GetSingleTickerProviderStateMixin {
|
||||
return;
|
||||
}
|
||||
int duration = playerCtr?.value.duration.inSeconds ?? 0;
|
||||
if (duration > 0 && playerCtr!.value.position.inSeconds >= duration - 1) {
|
||||
_trackComplete();
|
||||
}
|
||||
if (_hasFreeWatchRight) return; // 免费次数/免费区/动漫已购/免费章节/VIP金币限免,整片随便看
|
||||
if (!_isPreview()) {
|
||||
//每帧都走这里,videoStatus 是重算 getter,只读一次
|
||||
@@ -572,15 +565,9 @@ class VideoLogic extends GetxController with GetSingleTickerProviderStateMixin {
|
||||
return videoModel?.previewURL?.isNotEmpty == true && videoStatus.isNeedPay;
|
||||
}
|
||||
|
||||
/// 上报当前视频播放结束(切视频/切集/退页统一入口)
|
||||
void _trackComplete() {
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_COMPLETE, videoModel, playerCtr, isPreVideo: _isPreview());
|
||||
}
|
||||
|
||||
/// 推荐区切内容(释放控制器 + 重拉详情起播,不开新页)。
|
||||
/// **必须按被点内容的 videoType 定接口**,用页面入参会串接口 → 「视频资源加载失败」
|
||||
Future<void> switchVideo(VideoModel model) async {
|
||||
_trackComplete();
|
||||
videoModel = model;
|
||||
isShowBuy.value = false;
|
||||
isCartoon = model.videoType == 1;
|
||||
@@ -601,7 +588,6 @@ class VideoLogic extends GetxController with GetSingleTickerProviderStateMixin {
|
||||
/// 切视频或切 CDN 路线:[model] 非空=切新视频,为空=同视频换 URL;控制器为空走首次进入路径
|
||||
Future<void> startPlay({VideoModel? model, bool resetPos = false}) async {
|
||||
if (model != null) {
|
||||
_trackComplete();
|
||||
videoModel = model;
|
||||
}
|
||||
if (playerCtr == null) {
|
||||
@@ -619,7 +605,6 @@ class VideoLogic extends GetxController with GetSingleTickerProviderStateMixin {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
_trackComplete();
|
||||
currentEpisode = episode;
|
||||
isShowBuy.value = false;
|
||||
releasePlayer(rebuild: false);
|
||||
@@ -653,13 +638,12 @@ class VideoLogic extends GetxController with GetSingleTickerProviderStateMixin {
|
||||
playerCtr = null;
|
||||
}
|
||||
|
||||
/// 页面销毁清理:上报 VIDEO_COMPLETE → 取消事件订阅 → 非预览视频上报观看记录 → 释放播放器
|
||||
/// 页面销毁清理:取消事件订阅 → 非预览视频上报观看记录 → 释放播放器
|
||||
@override
|
||||
void onClose() {
|
||||
isDispose = true; // 第一时间置位,让所有异步回调(initialize/postFrame/Future.delayed)能尽早 return
|
||||
TimedPopupManager().cancel(TimedPopupType.freeWatchPay);
|
||||
TimedPopupManager().cancel(TimedPopupType.videoPayAhead);
|
||||
_trackComplete();
|
||||
|
||||
playerCtr?.pause();
|
||||
playerCtr?.removeListener(_onProgress);
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'package:jydj/assets_tool/images.dart';
|
||||
import '../../../hj_model/splash/ads_model.dart';
|
||||
import '../../../tools_base/banner/ads_banner.dart';
|
||||
import '../../../tools_base/global_store/store.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
|
||||
/// 播放前贴片广告(Banner + 倒计时关闭)。
|
||||
/// 倒计时完或 VIP 关闭走 [onFinish],未到时间的非 VIP 走 [onToVip] 引导开通
|
||||
@@ -91,7 +90,6 @@ class _VideoAdWidgetState extends State<VideoAdWidget> {
|
||||
height: 88,
|
||||
autoPlayMs: 2000,
|
||||
indicatorAlign: IndicatorAlign.bottomCenter,
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.videoPlay, adType: AdType.smallBanner),
|
||||
),
|
||||
_closeBtn(),
|
||||
if (widget.showBackArrow) _backBtn(),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:analytics_sdk/enum/video_event_enum.dart';
|
||||
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -17,7 +16,6 @@ import 'package:video_player/video_player.dart';
|
||||
|
||||
import '../../../alert/video/share_media_dialog.dart';
|
||||
import '../../../routers/jump_router.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
import '../../cartoon/cartoon_recommend_page.dart';
|
||||
|
||||
/// 视频播放页数据详情
|
||||
@@ -83,7 +81,6 @@ class _VideoDetailViewState extends State<VideoDetailView> with SingleTickerProv
|
||||
6,
|
||||
padding: EdgeInsets.only(left: 12, bottom: 18),
|
||||
autoStyle: true,
|
||||
exposureModel: AdExposureModel(pageType: TrackEventPageType.videoPlay),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(child: _buildTitleMenu()),
|
||||
@@ -209,9 +206,8 @@ class _VideoDetailViewState extends State<VideoDetailView> with SingleTickerProv
|
||||
);
|
||||
}
|
||||
|
||||
/// 分享:带播放器上报埋点(进度/时长),再弹分享面板
|
||||
/// 分享:弹分享面板
|
||||
void _onShare() {
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_SHARE, videoModel, widget.playCtr);
|
||||
Get.dialog(ShareMediaDialog(videoModel: videoModel));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ui' show ImageFilter;
|
||||
|
||||
import 'package:analytics_sdk/enum/video_event_enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -16,7 +15,6 @@ import '../../../hj_utils/buy_util.dart';
|
||||
import '../../../hj_utils/date_time_util.dart';
|
||||
import '../../../hj_utils/free_play_manager.dart';
|
||||
import '../../../tools_base/global_store/store.dart';
|
||||
import '../../../track_event_manager/track_manager.dart';
|
||||
import '../../pre_sale/pre_sale_provider.dart';
|
||||
import '../../short_video/view/video_progress_widget.dart';
|
||||
import 'long_video_status.dart';
|
||||
@@ -196,8 +194,6 @@ class _VideoMenuViewState extends State<VideoMenuView> {
|
||||
|
||||
void _setPlay(bool play) {
|
||||
_playing.value = play;
|
||||
TrackVideoManager.send(play ? VideoEventEnum.VIDEO_PLAY : VideoEventEnum.VIDEO_PAUSE, widget.videoModel, playCtr,
|
||||
isPreVideo: isPreview);
|
||||
play ? playCtr.play() : playCtr.pause();
|
||||
}
|
||||
|
||||
@@ -219,8 +215,6 @@ class _VideoMenuViewState extends State<VideoMenuView> {
|
||||
const step = Duration(seconds: 10);
|
||||
final pos = playCtr.value.position;
|
||||
playCtr.seekTo(_snapSeek(forward ? pos + step : pos - step));
|
||||
TrackVideoManager.send(forward ? VideoEventEnum.VIDEO_FORWARD : VideoEventEnum.VIDEO_REWIND, widget.videoModel, playCtr,
|
||||
isPreVideo: isPreview);
|
||||
}
|
||||
|
||||
void _onPlayerTick() {
|
||||
@@ -282,7 +276,6 @@ class _VideoMenuViewState extends State<VideoMenuView> {
|
||||
},
|
||||
onLongPressStart: (_) {
|
||||
showToast("长按不动,2X倍速播放", gravity: ToastGravity.top);
|
||||
TrackVideoManager.send(VideoEventEnum.VIDEO_FORWARD, widget.videoModel, playCtr, isPreVideo: isPreview);
|
||||
_isLongPress = true;
|
||||
_showSpeed = false;
|
||||
_showSeekText = false;
|
||||
|
||||
@@ -204,11 +204,12 @@ class CommonService {
|
||||
return result.isSuccess ? result.data : null;
|
||||
}
|
||||
|
||||
//广告点击统计 广告类型 0:应用 1:广告
|
||||
static Future<bool> adsClick(int? type) async {
|
||||
/// 广告点击日志:[id] 广告 id(后端必填,空就不报);type 固定传 0(普通广告)
|
||||
static Future<bool> adsClick(String? id) async {
|
||||
if (id == null || id.isEmpty) return false;
|
||||
final result = await httpManager.fetchResponseByPOST(
|
||||
'/ads/click/stat',
|
||||
param: {'type': type},
|
||||
'/ads/click',
|
||||
param: {'id': id, 'type': 0},
|
||||
);
|
||||
return result.isSuccess;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:jydj/tools_base/net/http_manager.dart';
|
||||
|
||||
/// 短剧接口。金币解锁已并入 PayManager/BuyService,这里只剩读操作 + 两个计数型写操作:
|
||||
/// 信息流翻页去重、分享互动计数,都必须带 `X-Request-ID`——同一次业务的重试要复用同一个 id,
|
||||
/// 换新 id 就会重复计数。播放埋点走现有 analytics SDK(TrackVideoManager),不另建短剧专用上报
|
||||
/// 换新 id 就会重复计数。
|
||||
class DramaService {
|
||||
static Options _idempotent(String requestId) => Options(headers: {'X-Request-ID': requestId});
|
||||
|
||||
|
||||
@@ -177,12 +177,6 @@ class MineService {
|
||||
return result.isSuccess ? result.data : null;
|
||||
}
|
||||
|
||||
/// 获取客服对接地址
|
||||
static Future<String?> fetchCustomService() async {
|
||||
final result = await httpManager.fetchResponseByGET('/customer/url', param: {});
|
||||
return result.isSuccess ? result.data : null;
|
||||
}
|
||||
|
||||
/// 积分兑换商品
|
||||
static Future<bool> integralExchange(String id, {String? name, String? tel, String? address}) async {
|
||||
final param = <String, dynamic>{"id": id, "name": name, "tel": tel, "address": address};
|
||||
|
||||
@@ -74,7 +74,7 @@ class ResolveResponse {
|
||||
final data = json['Question'];
|
||||
if (data == null) return null;
|
||||
if (data is List) {
|
||||
return (data as List)
|
||||
return data
|
||||
.map(
|
||||
(question) => _Question.fromJson(question as Map<String, dynamic>),
|
||||
)
|
||||
|
||||
@@ -342,8 +342,8 @@ class CacheServer {
|
||||
// 是否是预缓存的请求
|
||||
bool isPreCache = false;
|
||||
Map<String, String> queryParameters = {};
|
||||
queryParameters.addAll(localReq.uri.queryParameters ?? {});
|
||||
if (queryParameters.containsKey("isPreCache") ?? false) {
|
||||
queryParameters.addAll(localReq.uri.queryParameters);
|
||||
if (queryParameters.containsKey("isPreCache")) {
|
||||
queryParameters.remove("isPreCache");
|
||||
isPreCache = true;
|
||||
}
|
||||
@@ -432,7 +432,7 @@ class CacheServer {
|
||||
if (rangeStart <= 0) {
|
||||
resp.data?.headers.forEach((key, values) {
|
||||
if (HttpHeaders.contentLengthHeader == key) {
|
||||
var ct = int.parse(values[0] ?? "0");
|
||||
var ct = int.parse(values[0]);
|
||||
localReq.response.headers.add(key, ct > 0 ? (ct - 6) : ct);
|
||||
csPrint("resp header ct:$key ${ct > 0 ? (ct - 6) : ct}");
|
||||
} else {
|
||||
@@ -515,12 +515,6 @@ class CacheServer {
|
||||
/// 处理M3u8
|
||||
_handleM3u8(Uri remoteUri, HttpRequest localReq, Stream<FileResponse> s, BaseCacheManager cacheManager) async {
|
||||
final sc = s.listen((f) {
|
||||
if (null == f) {
|
||||
//l.e(local_server_tag, "handleM3u8()...$remoteUri 来了个null���鬼东西");
|
||||
_requestErr(localReq);
|
||||
return;
|
||||
}
|
||||
|
||||
if (f is FileInfo) {
|
||||
var len = localReq.response.headers.value(HttpHeaders.contentLengthHeader);
|
||||
if (null != len) {
|
||||
@@ -540,7 +534,7 @@ class CacheServer {
|
||||
);
|
||||
// csPrint("before source:$source");
|
||||
if (TextUtil.isNotEmpty(tsLine) && tsLine.startsWith("http")) {
|
||||
var domin = Uri.parse(tsLine ?? "").origin;
|
||||
var domin = Uri.parse(tsLine).origin;
|
||||
if (TextUtil.isNotEmpty(domin)) {
|
||||
csPrint("need replace m3u8 inner host:$domin");
|
||||
source = source.replaceAll(domin, "");
|
||||
@@ -581,17 +575,15 @@ class CacheServer {
|
||||
|
||||
/// 请求错误
|
||||
_requestErr(HttpRequest req, {StreamSubscription? sc}) async {
|
||||
if (null != req) {
|
||||
// if (null == req.response.statusCode) {
|
||||
try {
|
||||
req.response.statusCode = HttpStatus.badRequest;
|
||||
} catch (e) {
|
||||
//l.e(local_server_tag, "_requestErr()..." + req.response.toString());
|
||||
}
|
||||
// }
|
||||
await req.response.close();
|
||||
sc?.cancel();
|
||||
// if (null == req.response.statusCode) {
|
||||
try {
|
||||
req.response.statusCode = HttpStatus.badRequest;
|
||||
} catch (e) {
|
||||
//l.e(local_server_tag, "_requestErr()..." + req.response.toString());
|
||||
}
|
||||
// }
|
||||
await req.response.close();
|
||||
sc?.cancel();
|
||||
}
|
||||
|
||||
BaseCacheManager _getCacheManager(String url) {
|
||||
@@ -641,7 +633,6 @@ class CacheServer {
|
||||
// l.i(local_server_tag, "getCacheFile()...闲时缓存策略预测需要缓��的url:$remoteUrl");
|
||||
var cacheManager = _getCacheManager(remotePath);
|
||||
var fileInfo = cacheManager.getFileFromMemory(getCacheKey(remotePath));
|
||||
fileInfo ??= (await cacheManager.getFileFromCache(getCacheKey(remotePath))) as Future<FileInfo?>;
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
@@ -662,8 +653,7 @@ class CacheServer {
|
||||
// return "https://fs.lhexm.com/sp/8a/67/lf/mg/605635d590d11f0679a058dbc013bd53.mp4";
|
||||
// remotePath = "sp/r1/8p/mt/if/970dd3185c924ff29c273917615c844a.m3u8";
|
||||
if (TextUtil.isEmpty(remotePath)) return null;
|
||||
var remoteUri = Uri.parse(remotePath); //修正后的绝对��径
|
||||
if (null == remoteUri) return null;
|
||||
var remoteUri = Uri.parse(remotePath);
|
||||
final dot = remoteUri.path.lastIndexOf(".");
|
||||
if (dot <= 0 || dot >= remoteUri.path.length - 1) return null;
|
||||
final fileExtension = remoteUri.path.substring(dot);
|
||||
@@ -715,8 +705,7 @@ class CacheServer {
|
||||
// 兼容相对路径 sp/vid/xxxx.m3u8
|
||||
remotePath = reqFilter.pathPrefix + "/" + remotePath;
|
||||
}
|
||||
var uri = Uri.parse(remotePath); //修正后的绝对路径
|
||||
if (null == uri) return null;
|
||||
var uri = Uri.parse(remotePath);
|
||||
//这里替换远程
|
||||
final remoteUri = uri.replace(scheme: reqFilter.schema, host: reqFilter.host, port: reqFilter.port);
|
||||
return remoteUri.toString();
|
||||
@@ -725,6 +714,5 @@ class CacheServer {
|
||||
|
||||
/// url/绝对路径和相对路径
|
||||
String getCacheKey(String url) {
|
||||
assert(null != url);
|
||||
return FileUtil.getName(url);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user