From a1c3657390793cfcfedfa279cf9d848b4c1260fd Mon Sep 17 00:00:00 2001 From: hailin Date: Sat, 31 Jan 2026 21:16:53 -0800 Subject: [PATCH] =?UTF-8?q?fix(c2c):=20=E4=BF=AE=E5=A4=8D=E4=BB=98?= =?UTF-8?q?=E6=AC=BE=E6=B0=B4=E5=8D=95=E5=9B=BE=E7=89=87=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 后端: proofs 图片端点添加 @Public() 装饰器, Image.network 无法携带 JWT token 2. 前端: paymentProofUrl 是相对路径,拼接 baseUrl 构建完整 URL 供 Image.network 加载 Co-Authored-By: Claude Opus 4.5 --- .../src/api/controllers/c2c.controller.ts | 2 ++ .../presentation/pages/c2c/c2c_order_detail_page.dart | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 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 485b3538..544f0df8 100644 --- a/backend/services/trading-service/src/api/controllers/c2c.controller.ts +++ b/backend/services/trading-service/src/api/controllers/c2c.controller.ts @@ -25,6 +25,7 @@ import { } from '@nestjs/swagger'; import * as path from 'path'; import * as fs from 'fs'; +import { Public } from '../../shared/guards/jwt-auth.guard'; import { C2cService } from '../../application/services/c2c.service'; import { CreateC2cOrderDto, @@ -295,6 +296,7 @@ export class C2cController { return this.toResponseDto(order); } + @Public() @Get('proofs/:filename') @ApiOperation({ summary: '获取付款水单图片' }) @ApiParam({ name: 'filename', description: '文件名' }) diff --git a/frontend/mining-app/lib/presentation/pages/c2c/c2c_order_detail_page.dart b/frontend/mining-app/lib/presentation/pages/c2c/c2c_order_detail_page.dart index 9553ccdc..e91b81fd 100644 --- a/frontend/mining-app/lib/presentation/pages/c2c/c2c_order_detail_page.dart +++ b/frontend/mining-app/lib/presentation/pages/c2c/c2c_order_detail_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:image_picker/image_picker.dart'; +import '../../../core/constants/app_constants.dart'; import '../../../core/utils/format_utils.dart'; import '../../../data/models/c2c_order_model.dart'; import '../../providers/c2c_providers.dart'; @@ -881,6 +882,12 @@ class _C2cOrderDetailPageState extends ConsumerState { ); } + /// 将后端返回的相对路径转为完整图片 URL + String _buildProofImageUrl(String relativePath) { + if (relativePath.startsWith('http')) return relativePath; + return '${AppConstants.baseUrl}$relativePath'; + } + Widget _buildPaymentProofCard(C2cOrderModel order, bool isBuyer) { final hasProof = order.paymentProofUrl != null && order.paymentProofUrl!.isNotEmpty; @@ -934,11 +941,11 @@ class _C2cOrderDetailPageState extends ConsumerState { const SizedBox(height: 16), if (hasProof) GestureDetector( - onTap: () => _showProofFullScreen(order.paymentProofUrl!), + onTap: () => _showProofFullScreen(_buildProofImageUrl(order.paymentProofUrl!)), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.network( - order.paymentProofUrl!, + _buildProofImageUrl(order.paymentProofUrl!), height: 200, width: double.infinity, fit: BoxFit.cover,