Files
monisuo/flutter_monisuo/lib/ui/pages/main/main_page.dart
sion c3f196ded4 feat: 添加业务分析后端接口
新增 AnalysisController 提供 6 个分析接口:
- /admin/analysis/profit - 盈利分析(交易手续费/充提手续费/资金利差)
- /admin/analysis/cash-flow - 资金流动趋势(按月统计充值/提现/净流入)
- /admin/analysis/trade - 交易分析(买入/卖出统计+趋势)
- /admin/analysis/coin-distribution - 币种交易分布
- /admin/analysis/user-growth - 用户增长分析(新增/活跃用户)
- /admin/analysis/risk - 风险指标(大额交易/异常提现/KYC/冻结账户)
- /admin/analysis/health - 综合健康度评分

更新 Mapper 添加分析查询方法:
- OrderFundMapper: 手续费统计、时间范围查询、大额交易、异常提现
- OrderTradeMapper: 交易金额统计、活跃用户、币种分布

前端 API 对接:
- 新增 6 个分析相关 Query hooks
- 更新 analytics.vue 使用真实数据
- 动态决策建议基于实际数据
2026-03-22 04:50:19 +08:00

142 lines
4.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import '../home/home_page.dart';
import '../market/market_page.dart';
import '../trade/trade_page.dart';
import '../asset/asset_page.dart';
import '../mine/mine_page.dart';
/// 主页面(使用 shadcn_ui 风格)
class MainPage extends StatefulWidget {
const MainPage({super.key});
@override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int _currentIndex = 0;
final List<Widget> _pages = [
const HomePage(),
const MarketPage(),
const TradePage(),
const AssetPage(),
const MinePage(),
];
final List<_TabItem> _tabs = [
_TabItem('首页', LucideIcons.house, LucideIcons.house),
_TabItem('行情', LucideIcons.trendingUp, LucideIcons.trendingUp),
_TabItem('交易', LucideIcons.arrowLeftRight, LucideIcons.arrowLeftRight),
_TabItem('资产', LucideIcons.wallet, LucideIcons.wallet),
_TabItem('我的', LucideIcons.user, LucideIcons.user),
];
@override
Widget build(BuildContext context) {
final theme = ShadTheme.of(context);
return Scaffold(
body: IndexedStack(
index: _currentIndex,
children: _pages,
),
bottomNavigationBar: Container(
decoration: BoxDecoration(
color: theme.colorScheme.background,
border: Border(
top: BorderSide(color: theme.colorScheme.border),
),
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: _tabs.asMap().entries.map((entry) {
final index = entry.key;
final tab = entry.value;
final isSelected = index == _currentIndex;
return GestureDetector(
onTap: () => setState(() => _currentIndex = index),
behavior: HitTestBehavior.opaque,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
tab.icon,
color: isSelected
? theme.colorScheme.primary
: theme.colorScheme.mutedForeground,
size: 24,
),
const SizedBox(height: 4),
Text(
tab.label,
style: TextStyle(
fontSize: 12,
color: isSelected
? theme.colorScheme.primary
: theme.colorScheme.mutedForeground,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
),
),
],
),
),
);
}).toList(),
),
),
),
),
);
}
}
class _TabItem {
final String label;
final IconData icon;
final IconData selectedIcon;
_TabItem(this.label, this.icon, this.selectedIcon);
}
/// IndexedStack 用于保持页面状态
class IndexedStack extends StatefulWidget {
final int index;
final List<Widget> children;
const IndexedStack({
super.key,
required this.index,
required this.children,
});
@override
State<IndexedStack> createState() => _IndexedStackState();
}
class _IndexedStackState extends State<IndexedStack> {
@override
Widget build(BuildContext context) {
return Stack(
children: widget.children.asMap().entries.map((entry) {
return Positioned.fill(
child: Offstage(
offstage: entry.key != widget.index,
child: TickerMode(
enabled: entry.key == widget.index,
child: entry.value,
),
),
);
}).toList(),
);
}
}