调换tab顺序

This commit is contained in:
谢宇宁
2026-09-22 15:13:29 +07:00
parent f6a91760f3
commit 220018715c
5 changed files with 30 additions and 18 deletions
+19 -3
View File
@@ -44,12 +44,16 @@ class HomeMainLogic extends GetxController {
int get selectedTabIndex => tabCtr?.index ?? _initIndex; int get selectedTabIndex => tabCtr?.index ?? _initIndex;
/// 主页固定注入的「热门短剧」tab(从短剧频道挪过来),不走后端模块
static const hotDramaTabId = '-120';
//服务端下发的原始顺序(抽屉「恢复默认」用) //服务端下发的原始顺序(抽屉「恢复默认」用)
List<ModuleData> get defaultList { List<ModuleData> get defaultList {
if (isDarkStyle) return Config.plateModule?.deepWeb ?? []; if (isDarkStyle) return Config.plateModule?.deepWeb ?? [];
// 固定最新模块 // 固定最新 + 热门短剧模块,热门短剧排第二个
return [ return [
ModuleData(id: "-110", moduleName: "最新", type: 1, showType: 1), ModuleData(id: "-110", moduleName: "最新", type: 1, showType: 1),
ModuleData(id: hotDramaTabId, moduleName: "热门短剧"),
...?Config.plateModule?.homePage, ...?Config.plateModule?.homePage,
]; ];
} }
@@ -74,6 +78,7 @@ class HomeMainLogic extends GetxController {
/// 应用抽屉里的新排序:顺序没变只切 tab,变了就落盘并换 key 重建 TabView /// 应用抽屉里的新排序:顺序没变只切 tab,变了就落盘并换 key 重建 TabView
Future<void> resortTabs(List<ModuleData> dataArr, ModuleData? tagData) async { Future<void> resortTabs(List<ModuleData> dataArr, ModuleData? tagData) async {
final curTagData = tagData ?? tabs[selectedTabIndex]; final curTagData = tagData ?? tabs[selectedTabIndex];
dataArr = _pinHotDrama(dataArr);
bool isSameArr = true; bool isSameArr = true;
int selectIndex = 0; int selectIndex = 0;
//抽屉只重排不增删,长度必然一致;逐项比名字,顺带定位选中项的新位置 //抽屉只重排不增删,长度必然一致;逐项比名字,顺带定位选中项的新位置
@@ -102,13 +107,15 @@ class HomeMainLogic extends GetxController {
serverTabs: defaultList, serverTabs: defaultList,
key: _sortKey, key: _sortKey,
); );
if (!isDarkStyle) tabs = _pinHotDrama(tabs);
if (darkDefaultId?.isNotEmpty == true) { if (darkDefaultId?.isNotEmpty == true) {
// 初始化指定模块(一般暗网模块用) // 初始化指定模块(一般暗网模块用)
final index = tabs.indexWhere((e) => e.id == darkDefaultId); final index = tabs.indexWhere((e) => e.id == darkDefaultId);
if (index >= 0) _initIndex = index; if (index >= 0) _initIndex = index;
} else if (!isDarkStyle) { } else if (!isDarkStyle) {
//默认不显示最新模块,选中「热门」(index 1);但 tab 不足 2 个时回退到 0,避免越界 //默认选中「热门短剧」
_initIndex = (tabs.first.moduleName == "最新" && tabs.length > 1) ? 1 : 0; final index = tabs.indexWhere((e) => e.id == hotDramaTabId);
_initIndex = index >= 0 ? index : 0;
} }
} catch (e) { } catch (e) {
debugLog(e); debugLog(e);
@@ -117,6 +124,15 @@ class HomeMainLogic extends GetxController {
update(); update();
} }
/// 「热门短剧」固定排第二个:本地排序里新 tab 会被追加到末尾,抽屉里也可能被拖走,这里统一挪回来
List<ModuleData> _pinHotDrama(List<ModuleData> list) {
final index = list.indexWhere((e) => e.id == hotDramaTabId);
if (index < 0 || index == 1 || list.length < 2) return list;
final result = [...list];
result.insert(1, result.removeAt(index));
return result;
}
/// 首页弹窗链:预售 → 支付分层 → VIP 引导。 /// 首页弹窗链:预售 → 支付分层 → VIP 引导。
/// 逐个 await 串行弹,每次启动只跑一次。 /// 逐个 await 串行弹,每次启动只跑一次。
/// 广告类弹窗(九宫格/图片公告/文字公告)不在这里:它们跟着启动落地页弹,见 MainPageLogic.onReady /// 广告类弹窗(九宫格/图片公告/文字公告)不在这里:它们跟着启动落地页弹,见 MainPageLogic.onReady
+4
View File
@@ -11,6 +11,7 @@ import 'package:tgdj/tools_base/widget/keep_alive_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../cartoon/cartoon_sub_detail_page.dart'; import '../cartoon/cartoon_sub_detail_page.dart';
import '../drama/drama_list_page.dart';
import '../main_page/provider/bottom_bar_provider.dart'; import '../main_page/provider/bottom_bar_provider.dart';
import 'activity_float/home_float_widget.dart'; import 'activity_float/home_float_widget.dart';
import 'home_drawer.dart'; import 'home_drawer.dart';
@@ -203,6 +204,9 @@ class _HomeTabViewState extends State<HomeTabView>
/// 按 module type/showType/isACG 分发到对应子页,统一 keepAlive /// 按 module type/showType/isACG 分发到对应子页,统一 keepAlive
Widget _tabPage(int index) { Widget _tabPage(int index) {
final module = logic.tabs[index]; final module = logic.tabs[index];
if (module.id == HomeMainLogic.hotDramaTabId) {
return const DramaListPage().keepAlive;
}
if (module.type == 1 || module.type == 3) { if (module.type == 1 || module.type == 3) {
//showType==2 走分区聚合页,其余走排序列表页 //showType==2 走分区聚合页,其余走排序列表页
return module.showType == 2 return module.showType == 2
@@ -1,12 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
//短剧频道的二级 tab:写死这 4 个,顺序与 ShortVideoMainPage 的 TabBarView children 一一对应 //短剧频道的二级 tab:写死这 3 个,顺序与 ShortVideoMainPage 的 TabBarView children 一一对应
const kDramaTabs = ["直播", "抖音", "AI短剧", "热门短剧"]; const kDramaTabs = ["直播", "抖音", "AI短剧"]; //热门短剧已挪到主页 tab
//默认打开 AI短剧 //默认打开 AI短剧
const kDramaDefaultTab = 2; const kDramaDefaultTab = 2;
const kDramaHotTab = 3;
/// 短剧频道的 tab 调度。被 MainPageLogic.skipToLive 和 ShortTopMenu 按类型 Get.find, /// 短剧频道的 tab 调度。被 MainPageLogic.skipToLive 和 ShortTopMenu 按类型 Get.find,
/// 所以必须保持全局注册、不能加 tag /// 所以必须保持全局注册、不能加 tag
@@ -7,10 +7,9 @@ import 'package:tgdj/hj_page/short_video/view/short_top_menu.dart';
import 'package:tgdj/tools_base/widget/keep_alive_widget.dart'; import 'package:tgdj/tools_base/widget/keep_alive_widget.dart';
import '../drama/drama_feed_page.dart'; import '../drama/drama_feed_page.dart';
import '../drama/drama_list_page.dart';
import '../live/live_main_page.dart'; import '../live/live_main_page.dart';
/// 短剧频道:直播 / 抖音 / AI短剧 / 热门短剧 /// 短剧频道:直播 / 抖音 / AI短剧
class ShortVideoMainPage extends StatelessWidget { class ShortVideoMainPage extends StatelessWidget {
/// 指定初始 tab;<0(默认) 表示用 [kDramaDefaultTab] /// 指定初始 tab;<0(默认) 表示用 [kDramaDefaultTab]
final int index; final int index;
@@ -30,9 +29,7 @@ class ShortVideoMainPage extends StatelessWidget {
() => logic.tabIndex.value == 0 () => logic.tabIndex.value == 0
? Image.asset('live_main_bg2.webp'.livePath, ? Image.asset('live_main_bg2.webp'.livePath,
alignment: Alignment.topCenter, fit: BoxFit.cover) alignment: Alignment.topCenter, fit: BoxFit.cover)
: logic.tabIndex.value == kDramaHotTab : const SizedBox.shrink(),
? const ColoredBox(color: Color(0xFF05000E))
: const SizedBox.shrink(),
), ),
), ),
SafeArea( SafeArea(
@@ -44,7 +41,7 @@ class ShortVideoMainPage extends StatelessWidget {
child: TabBarView( child: TabBarView(
controller: logic.tabCtr, controller: logic.tabCtr,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
//顺序必须与 kDramaTabs 一致。直播/热门短剧是普通页面,要给顶部菜单让位;两个信息流页自己铺满 //顺序必须与 kDramaTabs 一致。直播是普通页面,要给顶部菜单让位;两个信息流页自己铺满
children: [ children: [
const Padding( const Padding(
padding: EdgeInsets.only(top: 44), padding: EdgeInsets.only(top: 44),
@@ -56,10 +53,6 @@ class ShortVideoMainPage extends StatelessWidget {
.keepAlive, .keepAlive,
DramaFeedPage(tabIndex: 2, superTabCtr: logic.tabCtr) DramaFeedPage(tabIndex: 2, superTabCtr: logic.tabCtr)
.keepAlive, .keepAlive,
const Padding(
padding: EdgeInsets.only(top: 44),
child: DramaListPage())
.keepAlive,
], ],
), ),
), ),
@@ -16,7 +16,7 @@ class ShortTopMenu extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// 选中态、下划线位移全交给 TabBar 自己按 tabCtr 动画,不用 Obx 整条重建 // 选中态、下划线位移全交给 TabBar 自己按 tabCtr 动画,不用 Obx 整条重建
//高度 48 与 ShortVideoMainPage 里两个普通 tab 的 Padding(top: 44) 对应,改一处要同步 //高度 48 与 ShortVideoMainPage 里直播 tab 的 Padding(top: 44) 对应,改一处要同步
return Container( return Container(
height: 48, height: 48,
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
@@ -65,7 +65,7 @@ class ShortTopMenu extends StatelessWidget {
/// 单个 tab:只画文字(直播原来是图标,改版后统一成文字)。 /// 单个 tab:只画文字(直播原来是图标,改版后统一成文字)。
/// 底部留 7 = 与文字间距 3 + 指示器高 4,腾给贴底绘制的 CustomIndicator /// 底部留 7 = 与文字间距 3 + 指示器高 4,腾给贴底绘制的 CustomIndicator
Widget _menuItem(String title) => Container( Widget _menuItem(String title) => Container(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 7), padding: const EdgeInsets.fromLTRB(20, 0, 20, 7),
child: Text(title), child: Text(title),
); );
} }