| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- import 'package:flutter/material.dart';
- import 'package:flutter_riverpod/flutter_riverpod.dart';
- import 'package:go_router/go_router.dart';
- import 'package:intl/intl.dart';
- import '../../../core/l10n/app_localizations.dart';
- import '../../../core/theme/app_colors.dart';
- import '../../../data/repositories/broker_repository.dart';
- // ── State ─────────────────────────────────────────────────
- class _TeamDetailState {
- final DateTime month;
- final String filter; // 'all' | 'month' | 'week' | 'day'
- _TeamDetailState({required this.month, required this.filter});
- _TeamDetailState copyWith({DateTime? month, String? filter}) =>
- _TeamDetailState(month: month ?? this.month, filter: filter ?? this.filter);
- }
- // ── Screen ───────────────────────────────────────────────
- class TeamDetailScreen extends ConsumerStatefulWidget {
- const TeamDetailScreen({super.key});
- @override
- ConsumerState<TeamDetailScreen> createState() => _TeamDetailScreenState();
- }
- class _TeamDetailScreenState extends ConsumerState<TeamDetailScreen> {
- _TeamDetailState _state = _TeamDetailState(month: DateTime.now(), filter: 'all');
- Map<String, dynamic> _data = {};
- bool _loading = false;
- String? _error;
- @override
- void initState() {
- super.initState();
- _load();
- }
- /// 对应安卓 requestAgentAwards(endDate) → GET agent/stat?endDate=
- Future<void> _load() async {
- setState(() { _loading = true; _error = null; });
- try {
- final endDate = _buildEndDate();
- final data = await ref.read(brokerRepositoryProvider).getTotalAward(endDate: endDate);
- if (mounted) setState(() { _data = data; _loading = false; });
- } catch (e) {
- if (mounted) setState(() { _error = e.toString(); _loading = false; });
- }
- }
- /// 对应安卓各个 load 方法传递的 endDate
- String? _buildEndDate() {
- final fmt = DateFormat('yyyy-MM-dd');
- final now = DateTime.now();
- switch (_state.filter) {
- case 'day': // loadToday
- return fmt.format(now);
- case 'week': // loadWeekBefore
- return fmt.format(now.subtract(const Duration(days: 7)));
- case 'month': // loadCurrentMonth → "${month}-01"
- return '${_state.month.year}-${_state.month.month.toString().padLeft(2, '0')}-01';
- default: // loadAllDate → null
- return null;
- }
- }
- Future<void> _pickMonth() async {
- final now = DateTime.now();
- final picked = await showDatePicker(
- context: context,
- initialDate: _state.month,
- firstDate: DateTime(now.year - 2),
- lastDate: now,
- initialDatePickerMode: DatePickerMode.year,
- );
- if (picked != null && mounted) {
- setState(() => _state = _state.copyWith(
- month: DateTime(picked.year, picked.month),
- filter: 'month',
- ));
- _load();
- }
- }
- void _setFilter(String f) {
- setState(() => _state = _state.copyWith(filter: f));
- _load();
- }
- @override
- Widget build(BuildContext context) {
- final cs = Theme.of(context).colorScheme;
- return Scaffold(
- backgroundColor: cs.surface,
- appBar: AppBar(
- backgroundColor: cs.surface,
- elevation: 0,
- leading: IconButton(
- icon: const Icon(Icons.arrow_back_ios, size: 18),
- onPressed: () => context.pop(),
- ),
- title: Text(AppLocalizations.of(context)!.teamDetail, style: TextStyle(color: cs.onSurface, fontSize: 17, fontWeight: FontWeight.w600)),
- centerTitle: true,
- ),
- body: Padding(
- padding: const EdgeInsets.all(16),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- // ── 筛选栏:三个独立带边框按钮 ───────────────
- Row(children: [
- // 月份选择
- Expanded(
- flex: 5,
- child: GestureDetector(
- onTap: _pickMonth,
- child: Container(
- height: 38,
- decoration: BoxDecoration(
- color: _state.filter == 'month' ? AppColors.brand : Colors.transparent,
- border: Border.all(color: AppColors.lightBorder, width: 1),
- borderRadius: BorderRadius.circular(6),
- ),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Text(
- '${_state.month.year}-${_state.month.month.toString().padLeft(2, '0')}',
- style: TextStyle(
- fontSize: 13,
- fontWeight: _state.filter == 'month' ? FontWeight.w600 : FontWeight.normal,
- color: _state.filter == 'month' ? Colors.black : cs.onSurface,
- ),
- ),
- const SizedBox(width: 2),
- Icon(Icons.arrow_drop_down, size: 18,
- color: _state.filter == 'month' ? Colors.black : cs.onSurface.withAlpha(160)),
- ],
- ),
- ),
- ),
- ),
- const SizedBox(width: 8),
- // 一周内
- Expanded(
- flex: 3,
- child: GestureDetector(
- onTap: () => _setFilter('week'),
- child: Container(
- height: 38,
- alignment: Alignment.center,
- decoration: BoxDecoration(
- color: _state.filter == 'week' ? AppColors.brand : Colors.transparent,
- border: Border.all(color: AppColors.lightBorder, width: 1),
- borderRadius: BorderRadius.circular(6),
- ),
- child: Text(
- AppLocalizations.of(context)!.withinOneWeek,
- style: TextStyle(
- fontSize: 13,
- fontWeight: _state.filter == 'week' ? FontWeight.w600 : FontWeight.normal,
- color: _state.filter == 'week' ? Colors.black : cs.onSurface,
- ),
- ),
- ),
- ),
- ),
- const SizedBox(width: 8),
- // 当日
- Expanded(
- flex: 3,
- child: GestureDetector(
- onTap: () => _setFilter('day'),
- child: Container(
- height: 38,
- alignment: Alignment.center,
- decoration: BoxDecoration(
- color: _state.filter == 'day' ? AppColors.brand : Colors.transparent,
- border: Border.all(color: AppColors.lightBorder, width: 1),
- borderRadius: BorderRadius.circular(6),
- ),
- child: Text(
- AppLocalizations.of(context)!.today,
- style: TextStyle(
- fontSize: 13,
- fontWeight: _state.filter == 'day' ? FontWeight.w600 : FontWeight.normal,
- color: _state.filter == 'day' ? Colors.black : cs.onSurface,
- ),
- ),
- ),
- ),
- ),
- ]),
- const SizedBox(height: 24),
- // ── 内容区 ────────────────────────────────
- if (_loading)
- const Center(child: CircularProgressIndicator())
- else if (_error != null)
- Center(child: Text('${AppLocalizations.of(context)!.loadFailed}: $_error', style: TextStyle(color: cs.error)))
- else ...[
- Text(AppLocalizations.of(context)!.teamTotalAssets, style: TextStyle(fontSize: 13, color: cs.onSurface.withAlpha(120))),
- const SizedBox(height: 8),
- Row(crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, children: [
- Text(
- _formatAmount(_data['totalBalance']),
- style: TextStyle(fontSize: 28, fontWeight: FontWeight.w700, color: cs.onSurface),
- ),
- const SizedBox(width: 6),
- Text('USDT', style: TextStyle(fontSize: 14, color: cs.onSurface.withAlpha(160))),
- ]),
- ],
- ],
- ),
- ),
- );
- }
- String _formatAmount(dynamic v) {
- if (v == null) return '0.00';
- final d = double.tryParse(v.toString()) ?? 0.0;
- if (d >= 1000) {
- final intPart = d.truncate().toString();
- final decPart = d.toStringAsFixed(2).split('.')[1];
- final buf = StringBuffer();
- for (int i = 0; i < intPart.length; i++) {
- if (i > 0 && (intPart.length - i) % 3 == 0) buf.write(',');
- buf.write(intPart[i]);
- }
- return '${buf.toString()}.$decPart';
- }
- return d.toStringAsFixed(2);
- }
- }
|