From 30de9a71ceec20dbc4b4c0ce25e2f1d41676ca4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=96=8C?= <259278618@qq.com> Date: Fri, 31 Jul 2026 16:11:08 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20web=20=E7=AB=AF=E4=BC=9A=E5=91=98?= =?UTF-8?q?=E9=A1=B5=E5=B4=A9=E6=BA=83=EF=BC=88dart:io=20=E4=B8=8D?= =?UTF-8?q?=E5=8F=AF=E7=94=A8=EF=BC=89+=20=E5=B5=8C=E5=A5=97=20AppBar=20?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E9=87=8D=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - member_center_page 改用 kIsWeb + defaultTargetPlatform 判断 iOS, 删 dart:io 依赖(web 访问 Platform 抛异常导致页面灰屏) - HomePage 移除外层 AppBar,4 个 tab 页各自持有单一标题栏 Co-Authored-By: Claude Opus 4.7 --- lib/features/home/home_page.dart | 3 - lib/features/member/member_center_page.dart | 189 ++++++++++---------- 2 files changed, 97 insertions(+), 95 deletions(-) diff --git a/lib/features/home/home_page.dart b/lib/features/home/home_page.dart index 92d461f..9f16a6f 100644 --- a/lib/features/home/home_page.dart +++ b/lib/features/home/home_page.dart @@ -21,8 +21,6 @@ class _HomePageState extends ConsumerState { int _index = 0; bool _splashShown = false; - static const _titles = ['我的形象', '我的衣橱', '穿搭方案', '会员中心']; - @override void initState() { super.initState(); @@ -44,7 +42,6 @@ class _HomePageState extends ConsumerState { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text(_titles[_index])), body: IndexedStack( index: _index, children: const [ diff --git a/lib/features/member/member_center_page.dart b/lib/features/member/member_center_page.dart index f4d08f4..f508eed 100644 --- a/lib/features/member/member_center_page.dart +++ b/lib/features/member/member_center_page.dart @@ -1,5 +1,4 @@ -import 'dart:io'; - +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -69,7 +68,9 @@ class _MemberCenterPageState extends ConsumerState { int? _typeFilter; bool _rewarding = false; - bool get _isIOS => Platform.isIOS; + // web 上无 Platform(dart:io 不可用),且 web 端默认走系统浏览器收银台 + bool get _isIOS => + !kIsWeb && defaultTargetPlatform == TargetPlatform.iOS; Future _openPlans() async { final plans = await showModalBottomSheet( @@ -121,101 +122,105 @@ class _MemberCenterPageState extends ConsumerState { final member = ref.watch(memberProvider); final stores = ref.watch(storeProvider); final scheme = Theme.of(context).colorScheme; - return ListView( - padding: const EdgeInsets.all(16), - children: [ - _MemberCard( - member: member, - isIOS: _isIOS, - onOpenPlans: _openPlans, - ), - const SizedBox(height: 12), - const _RecentDealsCard(), - if (member.value?.isVip == false) ...[ - const SizedBox(height: 12), - _AdsRewardCard( - rewarding: _rewarding, - onClaim: (adType, msg) => _claimReward(adType, msg), + return Scaffold( + appBar: AppBar(title: const Text('会员中心')), + body: ListView( + padding: const EdgeInsets.all(16), + children: [ + _MemberCard( + member: member, + isIOS: _isIOS, + onOpenPlans: _openPlans, ), - ], - const SizedBox(height: 16), - Row( - children: [ - Text('合作门店', - style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold)), - const Spacer(), - ChoiceChip( - label: const Text('全部'), - selected: _typeFilter == null, - onSelected: (_) => setState(() => _typeFilter = null), + const SizedBox(height: 12), + const _RecentDealsCard(), + if (member.value?.isVip == false) ...[ + const SizedBox(height: 12), + _AdsRewardCard( + rewarding: _rewarding, + onClaim: (adType, msg) => _claimReward(adType, msg), ), - const SizedBox(width: 8), - for (final entry in _storeTypeLabels.entries) ...[ + ], + const SizedBox(height: 16), + Row( + children: [ + Text('合作门店', + style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold)), + const Spacer(), ChoiceChip( - label: Text(entry.value), - selected: _typeFilter == entry.key, - onSelected: (_) => setState(() => _typeFilter = entry.key), + label: const Text('全部'), + selected: _typeFilter == null, + onSelected: (_) => setState(() => _typeFilter = null), ), const SizedBox(width: 8), - ], - ], - ), - const SizedBox(height: 8), - stores.when( - loading: () => const Padding( - padding: EdgeInsets.only(top: 32), child: LoadingView(text: '加载门店...')), - error: (e, _) => Padding( - padding: const EdgeInsets.only(top: 32), - child: ErrorView( - message: e.toString().replaceFirst('Exception: ', ''), - onRetry: () => ref.read(storeProvider.notifier).refresh(), - ), - ), - data: (list) { - final shown = _typeFilter == null - ? list - : list.where((s) => s.type == _typeFilter).toList(); - if (shown.isEmpty) { - return const Padding( - padding: EdgeInsets.only(top: 32), - child: Center( - child: Text('附近暂无可合作门店', - style: TextStyle(color: Colors.grey))), - ); - } - return Column( - children: [ - for (final s in shown) ...[ - Card( - child: ListTile( - leading: CircleAvatar( - backgroundColor: scheme.primaryContainer, - child: Icon( - s.type == 1 ? Icons.content_cut : Icons.checkroom), - ), - title: Text(s.name), - subtitle: Text('${s.address}\n${s.commissionPolicy}'), - isThreeLine: true, - trailing: member.value?.isVip == true - ? const Chip( - label: Text('会员价'), - labelStyle: TextStyle( - color: Colors.white, fontSize: 10), - backgroundColor: Colors.amber, - visualDensity: VisualDensity.compact, - padding: EdgeInsets.zero, - ) - : const Icon(Icons.chevron_right, - color: Colors.grey), - ), - ), - const SizedBox(height: 8), - ], + for (final entry in _storeTypeLabels.entries) ...[ + ChoiceChip( + label: Text(entry.value), + selected: _typeFilter == entry.key, + onSelected: (_) => setState(() => _typeFilter = entry.key), + ), + const SizedBox(width: 8), ], - ); - }, - ), - ], + ], + ), + const SizedBox(height: 8), + stores.when( + loading: () => const Padding( + padding: EdgeInsets.only(top: 32), + child: LoadingView(text: '加载门店...')), + error: (e, _) => Padding( + padding: const EdgeInsets.only(top: 32), + child: ErrorView( + message: e.toString().replaceFirst('Exception: ', ''), + onRetry: () => ref.read(storeProvider.notifier).refresh(), + ), + ), + data: (list) { + final shown = _typeFilter == null + ? list + : list.where((s) => s.type == _typeFilter).toList(); + if (shown.isEmpty) { + return const Padding( + padding: EdgeInsets.only(top: 32), + child: Center( + child: Text('附近暂无可合作门店', + style: TextStyle(color: Colors.grey))), + ); + } + return Column( + children: [ + for (final s in shown) ...[ + Card( + child: ListTile( + leading: CircleAvatar( + backgroundColor: scheme.primaryContainer, + child: Icon( + s.type == 1 ? Icons.content_cut : Icons.checkroom), + ), + title: Text(s.name), + subtitle: Text('${s.address}\n${s.commissionPolicy}'), + isThreeLine: true, + trailing: member.value?.isVip == true + ? const Chip( + label: Text('会员价'), + labelStyle: TextStyle( + color: Colors.white, fontSize: 10), + backgroundColor: Colors.amber, + visualDensity: VisualDensity.compact, + padding: EdgeInsets.zero, + ) + : const Icon(Icons.chevron_right, + color: Colors.grey), + ), + ), + const SizedBox(height: 8), + ], + ], + ); + }, + ), + ], + ), ); } }