From 263f1ecf8ea1448928c19ea32853288b2fbd0430 Mon Sep 17 00:00:00 2001 From: hailin Date: Thu, 29 Jan 2026 11:08:56 -0800 Subject: [PATCH] =?UTF-8?q?feat(c2c):=20=E5=8D=96=E5=8D=95=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=8E=B7=E5=8F=96=E8=B4=A6=E6=88=B7ID=E5=92=8CKava?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=EF=BC=8C=E7=A7=BB=E9=99=A4=E6=89=8B=E5=8A=A8?= =?UTF-8?q?=E8=BE=93=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端创建卖单时自动从 identity-service 获取卖家 Kava 地址并存入订单, 前端发布页面自动展示 accountSequence(只读),不再需要手动输入1.0系统ID。 Co-Authored-By: Claude Opus 4.5 --- .../src/api/controllers/c2c.controller.ts | 2 + .../trading-service/src/api/dto/c2c.dto.ts | 2 + .../src/application/services/c2c.service.ts | 18 ++++---- .../repositories/c2c-order.repository.ts | 4 ++ .../remote/trading_remote_datasource.dart | 3 -- .../pages/c2c/c2c_publish_page.dart | 45 ++++++------------- .../presentation/providers/c2c_providers.dart | 2 - 7 files changed, 31 insertions(+), 45 deletions(-) diff --git a/backend/services/trading-service/src/api/controllers/c2c.controller.ts b/backend/services/trading-service/src/api/controllers/c2c.controller.ts index be7fd95f..295b60f2 100644 --- a/backend/services/trading-service/src/api/controllers/c2c.controller.ts +++ b/backend/services/trading-service/src/api/controllers/c2c.controller.ts @@ -57,6 +57,8 @@ export class C2cController { paymentAccount: order.paymentAccount || undefined, paymentQrCode: order.paymentQrCode || undefined, paymentRealName: order.paymentRealName || undefined, + // 卖家 Kava 地址 + sellerKavaAddress: order.sellerKavaAddress || undefined, // 超时信息 paymentTimeoutMinutes: order.paymentTimeoutMinutes, confirmTimeoutMinutes: order.confirmTimeoutMinutes, diff --git a/backend/services/trading-service/src/api/dto/c2c.dto.ts b/backend/services/trading-service/src/api/dto/c2c.dto.ts index b3097387..19f95a99 100644 --- a/backend/services/trading-service/src/api/dto/c2c.dto.ts +++ b/backend/services/trading-service/src/api/dto/c2c.dto.ts @@ -168,6 +168,8 @@ export class C2cOrderResponseDto { paymentAccount?: string; paymentQrCode?: string; paymentRealName?: string; + // 卖家 Kava 地址(绿积分转账地址) + sellerKavaAddress?: string; // 超时信息 paymentTimeoutMinutes: number; confirmTimeoutMinutes: number; diff --git a/backend/services/trading-service/src/application/services/c2c.service.ts b/backend/services/trading-service/src/application/services/c2c.service.ts index 86b21595..0eaf0e9c 100644 --- a/backend/services/trading-service/src/application/services/c2c.service.ts +++ b/backend/services/trading-service/src/application/services/c2c.service.ts @@ -3,6 +3,7 @@ import { C2cOrderRepository, C2cOrderEntity } from '../../infrastructure/persist import { TradingAccountRepository } from '../../infrastructure/persistence/repositories/trading-account.repository'; import { RedisService } from '../../infrastructure/redis/redis.service'; import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service'; +import { IdentityClient } from '../../infrastructure/identity/identity.client'; import { Money } from '../../domain/value-objects/money.vo'; import Decimal from 'decimal.js'; @@ -57,6 +58,7 @@ export class C2cService { private readonly tradingAccountRepository: TradingAccountRepository, private readonly redis: RedisService, private readonly prisma: PrismaService, + private readonly identityClient: IdentityClient, ) {} /** @@ -109,16 +111,12 @@ export class C2cService { throw new BadRequestException('数量必须大于0'); } - // 卖单必须提供收款信息 + // 卖单:自动获取卖家 Kava 地址(用于绿积分转账) + let sellerKavaAddress: string | null = null; if (type === C2C_ORDER_TYPE.SELL) { - if (!options?.paymentMethod) { - throw new BadRequestException('卖单必须提供收款方式'); - } - if (!options?.paymentAccount) { - throw new BadRequestException('卖单必须提供收款账号'); - } - if (!options?.paymentRealName) { - throw new BadRequestException('卖单必须提供收款人实名'); + sellerKavaAddress = await this.identityClient.getUserKavaAddress(accountSequence); + if (!sellerKavaAddress) { + throw new BadRequestException('未找到您的 Kava 钱包地址,请先绑定钱包'); } } @@ -169,6 +167,8 @@ export class C2cService { paymentAccount: options?.paymentAccount, paymentQrCode: options?.paymentQrCode, paymentRealName: options?.paymentRealName, + // 卖家 Kava 地址(卖单时自动获取) + sellerKavaAddress, remark: options?.remark, }); diff --git a/backend/services/trading-service/src/infrastructure/persistence/repositories/c2c-order.repository.ts b/backend/services/trading-service/src/infrastructure/persistence/repositories/c2c-order.repository.ts index 9cd4dec3..00fd43b6 100644 --- a/backend/services/trading-service/src/infrastructure/persistence/repositories/c2c-order.repository.ts +++ b/backend/services/trading-service/src/infrastructure/persistence/repositories/c2c-order.repository.ts @@ -111,6 +111,8 @@ export class C2cOrderRepository { paymentAccount?: string; paymentQrCode?: string; paymentRealName?: string; + // 卖家 Kava 地址 + sellerKavaAddress?: string | null; remark?: string; }): Promise { const record = await this.prisma.c2cOrder.create({ @@ -132,6 +134,8 @@ export class C2cOrderRepository { paymentAccount: data.paymentAccount, paymentQrCode: data.paymentQrCode, paymentRealName: data.paymentRealName, + // 卖家 Kava 地址 + sellerKavaAddress: data.sellerKavaAddress, remark: data.remark, }, }); diff --git a/frontend/mining-app/lib/data/datasources/remote/trading_remote_datasource.dart b/frontend/mining-app/lib/data/datasources/remote/trading_remote_datasource.dart index a1ff6695..824d3967 100644 --- a/frontend/mining-app/lib/data/datasources/remote/trading_remote_datasource.dart +++ b/frontend/mining-app/lib/data/datasources/remote/trading_remote_datasource.dart @@ -108,7 +108,6 @@ abstract class TradingRemoteDataSource { String? paymentAccount, String? paymentQrCode, String? paymentRealName, - String? systemId, // 1.0系统ID(绿积分支付必填) String? remark, }); @@ -467,7 +466,6 @@ class TradingRemoteDataSourceImpl implements TradingRemoteDataSource { String? paymentAccount, String? paymentQrCode, String? paymentRealName, - String? systemId, // 1.0系统ID(绿积分支付必填) String? remark, }) async { try { @@ -483,7 +481,6 @@ class TradingRemoteDataSourceImpl implements TradingRemoteDataSource { if (paymentAccount != null) data['paymentAccount'] = paymentAccount; if (paymentQrCode != null) data['paymentQrCode'] = paymentQrCode; if (paymentRealName != null) data['paymentRealName'] = paymentRealName; - if (systemId != null && systemId.isNotEmpty) data['systemId'] = systemId; if (remark != null && remark.isNotEmpty) data['remark'] = remark; final response = await client.post( diff --git a/frontend/mining-app/lib/presentation/pages/c2c/c2c_publish_page.dart b/frontend/mining-app/lib/presentation/pages/c2c/c2c_publish_page.dart index b48e5408..9ae6fd33 100644 --- a/frontend/mining-app/lib/presentation/pages/c2c/c2c_publish_page.dart +++ b/frontend/mining-app/lib/presentation/pages/c2c/c2c_publish_page.dart @@ -32,7 +32,6 @@ class _C2cPublishPageState extends ConsumerState { Set _selectedPaymentMethods = {'GREEN_POINTS'}; // 绿积分默认选中且不可取消 final _paymentAccountController = TextEditingController(); final _paymentRealNameController = TextEditingController(); - final _systemIdController = TextEditingController(); // 1.0系统ID @override void dispose() { @@ -41,7 +40,6 @@ class _C2cPublishPageState extends ConsumerState { _remarkController.dispose(); _paymentAccountController.dispose(); _paymentRealNameController.dispose(); - _systemIdController.dispose(); super.dispose(); } @@ -400,32 +398,27 @@ class _C2cPublishPageState extends ConsumerState { ), const SizedBox(height: 16), - // 1.0系统ID(绿积分必填) + // 账户ID(自动读取,只读) const Text( - '1.0系统ID', + '账户ID', style: TextStyle(fontSize: 14, color: _grayText), ), const SizedBox(height: 4), const Text( - '买家将通过此ID向您转账绿积分', + '买家将通过此账户向您转账绿积分', style: TextStyle(fontSize: 12, color: _grayText), ), const SizedBox(height: 8), - TextField( - controller: _systemIdController, - decoration: InputDecoration( - hintText: '请输入您的1.0系统ID', - hintStyle: const TextStyle(color: _grayText), - filled: true, - fillColor: _bgGray, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: BorderSide.none, - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - borderSide: const BorderSide(color: _orange, width: 2), - ), + Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + decoration: BoxDecoration( + color: _bgGray, + borderRadius: BorderRadius.circular(12), + ), + child: Text( + ref.watch(userNotifierProvider).accountSequence ?? '', + style: const TextStyle(fontSize: 15, color: _darkText), ), ), @@ -675,8 +668,6 @@ class _C2cPublishPageState extends ConsumerState { // 验证条件 bool isValid = price > 0 && quantity > 0; if (isSell) { - // 卖单必须填写1.0系统ID(因为绿积分是必选的) - isValid = isValid && _systemIdController.text.trim().isNotEmpty; // 如果选择了其他支付方式,还需要填写收款账号和姓名 if (_selectedPaymentMethods.any((m) => m != 'GREEN_POINTS')) { isValid = isValid && @@ -774,13 +765,6 @@ class _C2cPublishPageState extends ConsumerState { // 卖单验证收款信息 if (isSell) { - // 必须填写1.0系统ID(绿积分是必选的) - if (_systemIdController.text.trim().isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('请填写1.0系统ID'), backgroundColor: _red), - ); - return; - } // 如果选择了其他支付方式,需要填写收款账号和姓名 if (_selectedPaymentMethods.any((m) => m != 'GREEN_POINTS')) { if (_paymentAccountController.text.trim().isEmpty) { @@ -832,7 +816,7 @@ class _C2cPublishPageState extends ConsumerState { const SizedBox(height: 8), Text('收款方式: $paymentMethodTexts'), const SizedBox(height: 4), - Text('1.0系统ID: ${_systemIdController.text.trim()}'), + Text('账户ID: ${ref.read(userNotifierProvider).accountSequence ?? ''}'), if (_selectedPaymentMethods.any((m) => m != 'GREEN_POINTS')) ...[ const SizedBox(height: 4), Text('收款账号: ${_paymentAccountController.text.trim()}'), @@ -874,7 +858,6 @@ class _C2cPublishPageState extends ConsumerState { paymentMethod: isSell ? _selectedPaymentMethods.join(',') : null, paymentAccount: isSell ? _paymentAccountController.text.trim() : null, paymentRealName: isSell ? _paymentRealNameController.text.trim() : null, - systemId: isSell ? _systemIdController.text.trim() : null, remark: remark.isEmpty ? null : remark, ); diff --git a/frontend/mining-app/lib/presentation/providers/c2c_providers.dart b/frontend/mining-app/lib/presentation/providers/c2c_providers.dart index 37fd7af6..1d422f8e 100644 --- a/frontend/mining-app/lib/presentation/providers/c2c_providers.dart +++ b/frontend/mining-app/lib/presentation/providers/c2c_providers.dart @@ -87,7 +87,6 @@ class C2cTradingNotifier extends StateNotifier { String? paymentAccount, String? paymentQrCode, String? paymentRealName, - String? systemId, // 1.0系统ID(绿积分支付必填) String? remark, }) async { state = state.copyWith(isLoading: true, clearError: true); @@ -102,7 +101,6 @@ class C2cTradingNotifier extends StateNotifier { paymentAccount: paymentAccount, paymentQrCode: paymentQrCode, paymentRealName: paymentRealName, - systemId: systemId, remark: remark, ); state = state.copyWith(isLoading: false, lastOrder: order);