feat(mining-app): 二维码扫描支持从相册选择图片识别

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-31 07:21:56 -08:00
parent 286b82c63b
commit c5126187d2
3 changed files with 96 additions and 9 deletions

View File

@ -815,7 +815,17 @@
"WebFetch(domain:oneuptime.com)",
"Bash(gradlew.bat assembleDebug:*)",
"Bash(cmd /c \"gradlew.bat assembleDebug --no-daemon\")",
"Bash(./build-install-debug.bat)"
"Bash(./build-install-debug.bat)",
"Bash(dir /s /b \"backend\\\\mpc-system\\\\services\\\\service-party-android\\\\*.kt\")",
"Bash(set DATABASE_URL=postgresql://postgres:password@localhost:5432/trading_db?schema=public)",
"Bash(ssh -o ProxyJump=ceshi@103.39.231.231 -o StrictHostKeyChecking=no ceshi@192.168.1.111 \"curl -s ''http://localhost:3000/api/v2/trading/asset/account/D25122700015'' | jq .\")",
"Bash(ssh -o ProxyJump=ceshi@103.39.231.231 -o StrictHostKeyChecking=no ceshi@192.168.1.111 \"curl -s ''http://localhost:3000/api/v2/trading/trading/orders?accountSequence=D25122700015'' | jq .\")",
"Bash(docker stop:*)",
"Bash(ssh-add:*)",
"Bash(ls -la \"c:\\\\Users\\\\dong\\\\Desktop\\\\rwadurian\\\\backend\\\\services\\\\auth-service\\\\src\"\" 2>/dev/null || echo \"Source directory structure: \")",
"Bash($env:DATABASE_URL=\"postgresql://postgres:postgres@localhost:5432/rwa_auth\")",
"Bash(DATABASE_URL=\"postgresql://postgres:postgres@localhost:5432/rwa_auth\" npx prisma migrate dev:*)",
"Bash(ssh -J ceshi@103.39.231.231 ceshi@192.168.1.111:*)"
],
"deny": [],
"ask": []

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
///
@ -31,6 +32,7 @@ class _QrScannerSheetState extends State<QrScannerSheet> {
);
bool _hasScanned = false;
bool _isPickingImage = false;
@override
void dispose() {
@ -51,6 +53,53 @@ class _QrScannerSheetState extends State<QrScannerSheet> {
Navigator.of(context).pop(code);
}
///
Future<void> _pickImageAndScan() async {
if (_isPickingImage || _hasScanned) return;
setState(() => _isPickingImage = true);
try {
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.gallery);
if (image == null) {
setState(() => _isPickingImage = false);
return;
}
final BarcodeCapture? capture = await _controller.analyzeImage(image.path);
if (capture != null && capture.barcodes.isNotEmpty) {
final code = capture.barcodes.first.rawValue;
if (code != null && code.isNotEmpty && !_hasScanned) {
_hasScanned = true;
if (mounted) Navigator.of(context).pop(code);
return;
}
}
//
if (mounted) {
setState(() => _isPickingImage = false);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('未在图片中识别到二维码'),
backgroundColor: Colors.red,
),
);
}
} catch (e) {
debugPrint('[QR_SCAN] pickImage error: $e');
if (mounted) {
setState(() => _isPickingImage = false);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('图片识别失败,请重试'),
backgroundColor: Colors.red,
),
);
}
}
}
@override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
@ -200,15 +249,42 @@ class _QrScannerSheetState extends State<QrScannerSheet> {
),
),
//
// +
Padding(
padding: const EdgeInsets.all(24),
child: Text(
'将二维码放入框内,即可自动扫描',
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Column(
children: [
Text(
'将二维码放入框内,即可自动扫描',
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
const SizedBox(height: 12),
GestureDetector(
onTap: _isPickingImage ? null : _pickImageAndScan,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.photo_library_outlined,
size: 18,
color: _isPickingImage ? Colors.grey : _orange,
),
const SizedBox(width: 6),
Text(
_isPickingImage ? '识别中...' : '从相册选择',
style: TextStyle(
fontSize: 14,
color: _isPickingImage ? Colors.grey : _orange,
fontWeight: FontWeight.w500,
),
),
],
),
),
],
),
),
],

View File

@ -39,6 +39,7 @@ dependencies:
shimmer: ^3.0.0
qr_flutter: ^4.1.0
mobile_scanner: ^5.1.1
image_picker: ^1.0.4
# 图表
fl_chart: ^0.64.0