From 11413df3db7d2d80482e044aeba8a3f022941b94 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Sat, 4 Jul 2026 20:55:31 +0800 Subject: [PATCH] =?UTF-8?q?fix(client):=20=E5=BA=95=E9=83=A8=20sheet=20?= =?UTF-8?q?=E6=89=93=E5=BC=80=E6=97=B6=E6=A8=AA=E6=BB=91=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E5=85=B3=20sheet=EF=BC=8C=E4=B8=8D=E5=86=8D=E5=88=87=20tab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - showMSheet 登记「打开中 sheet」关闭器栈(任何方式关闭都注销) - 壳层横滑手势先查栈:有 sheet 开着 → 从左往右滑关顶层 sheet, 任何方向都不切 tab / 不退二级屏;无 sheet 才走原 tab 切换/返回逻辑 Co-Authored-By: Claude Fable 5 --- client/lib/screens/shell/app_shell.dart | 7 ++++++ client/lib/widgets/ds/m_sheet.dart | 33 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/client/lib/screens/shell/app_shell.dart b/client/lib/screens/shell/app_shell.dart index 9baa0dc..4dcbecd 100644 --- a/client/lib/screens/shell/app_shell.dart +++ b/client/lib/screens/shell/app_shell.dart @@ -25,6 +25,7 @@ import '../../widgets/notification_bell.dart'; import '../../widgets/app_status_bar.dart'; import '../../widgets/ds/ds_atoms.dart'; import '../../widgets/ds/ds_toast.dart'; +import '../../widgets/ds/m_sheet.dart'; import '../../widgets/ds/m_tab_bar.dart'; import '../../widgets/theme_sheet.dart'; @@ -282,6 +283,12 @@ class _AppShellState extends ConsumerState onHorizontalDragEnd: (d) { final v = d.primaryVelocity ?? 0; if (v.abs() < 200) return; // 轻微拖动不触发 + // 有底部 sheet(详情/筛选等「抽屉」)开着:从左往右滑关掉顶层 + // sheet,任何方向都不切 tab / 不退屏。 + if (hasOpenMSheet) { + if (v > 0) closeTopMSheet(); + return; + } if (isTabRoot) { final pos = _tabForBranch(widget.navigationShell.currentIndex); final next = v < 0 ? pos + 1 : pos - 1; // 向左滑→下一个 tab diff --git a/client/lib/widgets/ds/m_sheet.dart b/client/lib/widgets/ds/m_sheet.dart index ba8ba63..a12ec70 100644 --- a/client/lib/widgets/ds/m_sheet.dart +++ b/client/lib/widgets/ds/m_sheet.dart @@ -10,6 +10,14 @@ import '../../core/theme/app_dims.g.dart'; import '../../core/theme/context_tokens.dart'; import '../../core/utils/dialog_util.dart'; +/// 打开中的移动 sheet 关闭器栈:壳层横滑手势据此判定——有 sheet 开着时 +/// 「从左往右滑」关顶层 sheet,而不是切 tab / 退二级屏(2026-07-04 拍板)。 +final List _openSheetClosers = []; +bool get hasOpenMSheet => _openSheetClosers.isNotEmpty; +void closeTopMSheet() { + if (_openSheetClosers.isNotEmpty) _openSheetClosers.last(); +} + /// 打开移动底部 sheet(对齐原型 mobile-shell openSheet)。 /// - [title] 为 null 时只渲染 grip,内容自带头部(详情抽屉复用场景)。 /// - [scrollable] true:内容包 SingleChildScrollView;false:内容自管布局 @@ -22,6 +30,31 @@ Future showMSheet( bool scrollable = true, double maxHeightFactor = 0.86, List? actions, +}) { + // 登记关闭器(壳层手势用);sheet 结束(任何方式关闭)时注销。 + final nav = Navigator.of(context); + void closer() { + if (nav.canPop()) nav.pop(); + } + + _openSheetClosers.add(closer); + return _showMSheetInner( + context, + title: title, + builder: builder, + scrollable: scrollable, + maxHeightFactor: maxHeightFactor, + actions: actions, + ).whenComplete(() => _openSheetClosers.remove(closer)); +} + +Future _showMSheetInner( + BuildContext context, { + String? title, + required WidgetBuilder builder, + bool scrollable = true, + double maxHeightFactor = 0.86, + List? actions, }) { return showModalBottomSheet( context: context,