From c02eca2999cb780147ce6c439fd6151f995afe3a Mon Sep 17 00:00:00 2001 From: sion Date: Wed, 25 Mar 2026 00:47:37 +0800 Subject: [PATCH] 111 --- flutter_monisuo/lib/main.dart | 64 ++----------------- .../lib/ui/pages/asset/asset_page.dart | 21 ++++-- .../lib/ui/pages/auth/login_page.dart | 6 +- .../monisuo/controller/AdminController.java | 5 ++ .../rattan/monisuo/service/AssetService.java | 48 ++++++++++++-- .../rattan/monisuo/service/CoinService.java | 5 ++ 6 files changed, 74 insertions(+), 75 deletions(-) diff --git a/flutter_monisuo/lib/main.dart b/flutter_monisuo/lib/main.dart index 2a9b6d5..47f81fc 100644 --- a/flutter_monisuo/lib/main.dart +++ b/flutter_monisuo/lib/main.dart @@ -62,13 +62,11 @@ class MyApp extends StatelessWidget { providers: _buildProviders(), child: Consumer( builder: (context, themeProvider, _) { - return AuthNavigator( - child: ShadApp.custom( - themeMode: themeProvider.themeMode, - theme: createLightShadTheme(), - darkTheme: createDarkShadTheme(), - appBuilder: _buildMaterialApp, - ), + return ShadApp.custom( + themeMode: themeProvider.themeMode, + theme: createLightShadTheme(), + darkTheme: createDarkShadTheme(), + appBuilder: _buildMaterialApp, ); }, ), @@ -134,55 +132,3 @@ class MyApp extends StatelessWidget { ); } } - -/// 认证路由守卫 - 监听认证状态并自动导航 -class AuthNavigator extends StatefulWidget { - final Widget child; - - const AuthNavigator({super.key, required this.child}); - - @override - State createState() => _AuthNavigatorState(); -} - -class _AuthNavigatorState extends State { - bool? _wasLoggedIn; - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - final isLoggedIn = context.watch().isLoggedIn; - - if (_wasLoggedIn == null) { - _wasLoggedIn = isLoggedIn; - return; - } - - if (_wasLoggedIn != isLoggedIn) { - _wasLoggedIn = isLoggedIn; - _navigateToAuthPage(isLoggedIn); - } - } - - void _navigateToAuthPage(bool isLoggedIn) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (!mounted) return; - - // 退出登录时重置其他 Provider 的状态 - if (!isLoggedIn) { - context.read().resetLoadState(); - context.read().resetLoadState(); - } - - Navigator.of(context).pushAndRemoveUntil( - MaterialPageRoute( - builder: (_) => isLoggedIn ? const MainPage() : const LoginPage(), - ), - (route) => false, - ); - }); - } - - @override - Widget build(BuildContext context) => widget.child; -} diff --git a/flutter_monisuo/lib/ui/pages/asset/asset_page.dart b/flutter_monisuo/lib/ui/pages/asset/asset_page.dart index 26544b2..67a46be 100644 --- a/flutter_monisuo/lib/ui/pages/asset/asset_page.dart +++ b/flutter_monisuo/lib/ui/pages/asset/asset_page.dart @@ -389,7 +389,7 @@ class _AssetCard extends StatelessWidget { } } -/// 代币列表 +/// 资产列表 class _TokenList extends StatelessWidget { final List holdings; @@ -399,11 +399,22 @@ class _TokenList extends StatelessWidget { Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; + // 对持仓进行排序:USDT 放在最上面 + final sortedHoldings = List.from(holdings); + sortedHoldings.sort((a, b) { + final codeA = (a.coinCode ?? a['coinCode'] ?? '').toString().toUpperCase(); + final codeB = (b.coinCode ?? b['coinCode'] ?? '').toString().toUpperCase(); + // USDT 排在最前面 + if (codeA == 'USDT') return -1; + if (codeB == 'USDT') return 1; + return 0; + }); + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '代币列表', + '资产列表', style: GoogleFonts.spaceGrotesk( fontSize: 16, fontWeight: FontWeight.bold, @@ -411,18 +422,18 @@ class _TokenList extends StatelessWidget { ), ), SizedBox(height: AppSpacing.md), - if (holdings.isEmpty) + if (sortedHoldings.isEmpty) _EmptyState(icon: LucideIcons.wallet, message: '暂无持仓') else ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - itemCount: holdings.length, + itemCount: sortedHoldings.length, separatorBuilder: (_, __) => Divider( height: 1, color: colorScheme.outlineVariant.withOpacity(0.2), ), - itemBuilder: (context, index) => _TokenItem(holding: holdings[index]), + itemBuilder: (context, index) => _TokenItem(holding: sortedHoldings[index]), ), ], ); diff --git a/flutter_monisuo/lib/ui/pages/auth/login_page.dart b/flutter_monisuo/lib/ui/pages/auth/login_page.dart index cc2aa68..2790043 100644 --- a/flutter_monisuo/lib/ui/pages/auth/login_page.dart +++ b/flutter_monisuo/lib/ui/pages/auth/login_page.dart @@ -176,10 +176,8 @@ class _LoginPageState extends State { } void _navigateToMainPage() { - Navigator.of(context).pushAndRemoveUntil( - MaterialPageRoute(builder: (_) => const MainPage()), - (route) => false, - ); + // 不使用 Navigator,让 main.dart 中的 Consumer 自动处理页面切换 + // 登录成功后,auth.isLoggedIn 会变为 true,Consumer 会自动显示 MainPage } void _navigateToRegister() { diff --git a/src/main/java/com/it/rattan/monisuo/controller/AdminController.java b/src/main/java/com/it/rattan/monisuo/controller/AdminController.java index 9d5ecad..f772380 100644 --- a/src/main/java/com/it/rattan/monisuo/controller/AdminController.java +++ b/src/main/java/com/it/rattan/monisuo/controller/AdminController.java @@ -201,6 +201,11 @@ public class AdminController { String code = (String) params.get("code"); BigDecimal price = new BigDecimal(params.get("price").toString()); + // USDT价格固定为1,不允许修改 + if ("USDT".equalsIgnoreCase(code)) { + return Result.fail("USDT价格固定为1,不可修改"); + } + Coin coin = coinService.getCoinByCode(code); if (coin == null) { return Result.fail("币种不存在"); diff --git a/src/main/java/com/it/rattan/monisuo/service/AssetService.java b/src/main/java/com/it/rattan/monisuo/service/AssetService.java index b8b706e..13e34fe 100644 --- a/src/main/java/com/it/rattan/monisuo/service/AssetService.java +++ b/src/main/java/com/it/rattan/monisuo/service/AssetService.java @@ -153,16 +153,35 @@ public class AssetService { // 获取交易账户USDT持仓 AccountTrade tradeUsdt = getOrCreateTradeAccount(userId, "USDT"); + LocalDateTime now = LocalDateTime.now(); + if (direction == 1) { // 资金账户 -> 交易账户 if (fund.getBalance().compareTo(amount) < 0) { throw new RuntimeException("资金账户余额不足"); } + BigDecimal fundBalanceBefore = fund.getBalance(); + BigDecimal tradeBalanceBefore = tradeUsdt.getQuantity(); + fund.setBalance(fund.getBalance().subtract(amount)); tradeUsdt.setQuantity(tradeUsdt.getQuantity().add(amount)); + // 使用 LambdaUpdateWrapper 显式更新资金账户 + LambdaUpdateWrapper fundUpdateWrapper = new LambdaUpdateWrapper<>(); + fundUpdateWrapper.eq(AccountFund::getId, fund.getId()) + .set(AccountFund::getBalance, fund.getBalance()) + .set(AccountFund::getUpdateTime, now); + accountFundMapper.update(null, fundUpdateWrapper); + + // 使用 LambdaUpdateWrapper 显式更新交易账户 + LambdaUpdateWrapper tradeUpdateWrapper = new LambdaUpdateWrapper<>(); + tradeUpdateWrapper.eq(AccountTrade::getId, tradeUsdt.getId()) + .set(AccountTrade::getQuantity, tradeUsdt.getQuantity()) + .set(AccountTrade::getUpdateTime, now); + accountTradeMapper.update(null, tradeUpdateWrapper); + // 记录流水 - createFlow(userId, 4, amount.negate(), fund.getBalance().add(amount), + createFlow(userId, 4, amount.negate(), fundBalanceBefore, fund.getBalance(), "USDT", null, "划转至交易账户"); } else if (direction == 2) { @@ -170,22 +189,37 @@ public class AssetService { if (tradeUsdt.getQuantity().compareTo(amount) < 0) { throw new RuntimeException("交易账户USDT余额不足"); } + BigDecimal fundBalanceBefore = fund.getBalance(); + BigDecimal tradeBalanceBefore = tradeUsdt.getQuantity(); + tradeUsdt.setQuantity(tradeUsdt.getQuantity().subtract(amount)); fund.setBalance(fund.getBalance().add(amount)); + // 使用 LambdaUpdateWrapper 显式更新资金账户 + LambdaUpdateWrapper fundUpdateWrapper = new LambdaUpdateWrapper<>(); + fundUpdateWrapper.eq(AccountFund::getId, fund.getId()) + .set(AccountFund::getBalance, fund.getBalance()) + .set(AccountFund::getUpdateTime, now); + accountFundMapper.update(null, fundUpdateWrapper); + + // 使用 LambdaUpdateWrapper 显式更新交易账户 + LambdaUpdateWrapper tradeUpdateWrapper = new LambdaUpdateWrapper<>(); + tradeUpdateWrapper.eq(AccountTrade::getId, tradeUsdt.getId()) + .set(AccountTrade::getQuantity, tradeUsdt.getQuantity()) + .set(AccountTrade::getUpdateTime, now); + accountTradeMapper.update(null, tradeUpdateWrapper); + // 记录流水 - createFlow(userId, 3, amount, fund.getBalance().subtract(amount), + createFlow(userId, 3, amount, fundBalanceBefore, fund.getBalance(), "USDT", null, "划转至资金账户"); } else { throw new RuntimeException("无效的划转方向"); } - fund.setUpdateTime(LocalDateTime.now()); - accountFundMapper.updateById(fund); - - tradeUsdt.setUpdateTime(LocalDateTime.now()); - accountTradeMapper.updateById(tradeUsdt); + System.out.println("[划转成功] 用户ID=" + userId + ", 方向=" + (direction == 1 ? "资金→交易" : "交易→资金") + + ", 金额=" + amount + " USDT, 资金账户余额=" + fund.getBalance() + + ", 交易账户USDT=" + tradeUsdt.getQuantity()); } /** diff --git a/src/main/java/com/it/rattan/monisuo/service/CoinService.java b/src/main/java/com/it/rattan/monisuo/service/CoinService.java index 76bc1dc..d3f1b32 100644 --- a/src/main/java/com/it/rattan/monisuo/service/CoinService.java +++ b/src/main/java/com/it/rattan/monisuo/service/CoinService.java @@ -36,8 +36,13 @@ public class CoinService extends ServiceImpl { /** * 更新币种价格 + * 注意:USDT价格固定为1,不允许修改 */ public void updatePrice(String code, BigDecimal price) { + // USDT价格固定为1,不允许修改 + if ("USDT".equalsIgnoreCase(code)) { + return; + } Coin coin = getCoinByCode(code); if (coin != null) { coin.setPrice(price);