- 主框架收敛为「穿搭」「我的」两个 tab:
- 穿搭 = 造型方案制作向导:个人信息完整性检查(4 类照片 +
身形参数,缺失引导去完善)+ 任务参数(日期范围/地点)+ 已有方案
- 我的 = 个人信息管理入口:用户卡片(昵称/会员状态)+ 我的形象 /
我的衣橱 / 会员中心入口 + 退出登录
- profile_page 移除退出登录(归「我的」页)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
138 lines
3.7 KiB
Dart
138 lines
3.7 KiB
Dart
import 'dart:async';
|
||
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
|
||
import '../../core/ads/ads_service.dart';
|
||
import '../mine/mine_page.dart';
|
||
import '../outfit/outfit_page.dart';
|
||
|
||
/// 主框架:2 Tab(穿搭 = 造型方案制作向导 / 我的 = 个人信息管理入口)
|
||
class HomePage extends ConsumerStatefulWidget {
|
||
const HomePage({super.key});
|
||
|
||
@override
|
||
ConsumerState<HomePage> createState() => _HomePageState();
|
||
}
|
||
|
||
class _HomePageState extends ConsumerState<HomePage> {
|
||
int _index = 0;
|
||
bool _splashShown = false;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
// 开屏广告:仅广告开通时展示一次(P0 Mock 下 pangleAppId 为空 → 跳过)
|
||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||
if (_splashShown) return;
|
||
if (!ref.read(adsServiceProvider).enabled) return;
|
||
_splashShown = true;
|
||
showDialog<void>(
|
||
context: context,
|
||
barrierDismissible: false,
|
||
builder: (_) => _SplashAdOverlay(
|
||
onSkip: () => Navigator.of(context).pop(),
|
||
),
|
||
);
|
||
});
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
body: IndexedStack(
|
||
index: _index,
|
||
children: const [
|
||
OutfitPage(),
|
||
MinePage(),
|
||
],
|
||
),
|
||
bottomNavigationBar: NavigationBar(
|
||
selectedIndex: _index,
|
||
onDestinationSelected: (i) => setState(() => _index = i),
|
||
destinations: const [
|
||
NavigationDestination(
|
||
icon: Icon(Icons.auto_awesome_outlined),
|
||
selectedIcon: Icon(Icons.auto_awesome),
|
||
label: '穿搭'),
|
||
NavigationDestination(
|
||
icon: Icon(Icons.person_outline),
|
||
selectedIcon: Icon(Icons.person),
|
||
label: '我的'),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 开屏广告:3 秒倒计时后自动关闭,右上角可手动跳过
|
||
class _SplashAdOverlay extends StatefulWidget {
|
||
final VoidCallback onSkip;
|
||
|
||
const _SplashAdOverlay({required this.onSkip});
|
||
|
||
@override
|
||
State<_SplashAdOverlay> createState() => _SplashAdOverlayState();
|
||
}
|
||
|
||
class _SplashAdOverlayState extends State<_SplashAdOverlay> {
|
||
Timer? _timer;
|
||
int _seconds = 3;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_timer = Timer.periodic(const Duration(seconds: 1), (_) {
|
||
if (_seconds <= 1) {
|
||
_timer?.cancel();
|
||
if (mounted) widget.onSkip();
|
||
return;
|
||
}
|
||
setState(() => _seconds -= 1);
|
||
});
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_timer?.cancel();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return PopScope(
|
||
canPop: false,
|
||
child: ColoredBox(
|
||
color: Theme.of(context).colorScheme.primaryContainer,
|
||
child: Stack(
|
||
children: [
|
||
const Center(
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Icon(Icons.campaign_outlined, size: 64),
|
||
SizedBox(height: 12),
|
||
Text('开屏广告位',
|
||
style:
|
||
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||
SizedBox(height: 4),
|
||
Text('P1 接入穿山甲开屏广告',
|
||
style: TextStyle(fontSize: 12, color: Colors.grey)),
|
||
],
|
||
),
|
||
),
|
||
Positioned(
|
||
top: 24,
|
||
right: 24,
|
||
child: OutlinedButton(
|
||
onPressed: widget.onSkip,
|
||
child: Text('跳过($_seconds)'),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|