import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:google_mlkit_barcode_scanning/google_mlkit_barcode_scanning.dart'; import 'package:provider/provider.dart'; import '../../providers/user_provider.dart'; class BindAccountPage extends StatefulWidget { const BindAccountPage({super.key}); @override State createState() => _BindAccountPageState(); } class _BindAccountPageState extends State { final TextEditingController _qrContentController = TextEditingController(); final ImagePicker _picker = ImagePicker(); bool _isProcessing = false; String? _statusMessage; File? _selectedImageFile; // 用户选择的原始二维码截图 // 条码扫描器 final BarcodeScanner _barcodeScanner = BarcodeScanner( formats: [BarcodeFormat.qrCode], ); @override void dispose() { _qrContentController.dispose(); _barcodeScanner.close(); super.dispose(); } // 1. 选择图片并识别二维码 Future _pickImageAndScan() async { try { final XFile? pickedFile = await _picker.pickImage(source: ImageSource.gallery); if (pickedFile == null) return; setState(() { _isProcessing = true; _statusMessage = "正在识别二维码..."; _selectedImageFile = File(pickedFile.path); }); final inputImage = InputImage.fromFilePath(pickedFile.path); final List barcodes = await _barcodeScanner.processImage(inputImage); setState(() { _isProcessing = false; }); if (barcodes.isNotEmpty && barcodes.first.rawValue != null) { final String code = barcodes.first.rawValue!; setState(() { _qrContentController.text = code; _statusMessage = "识别成功"; }); } else { setState(() { _statusMessage = "未识别到二维码,请手动输入"; }); } } catch (e) { setState(() { _isProcessing = false; _statusMessage = "识别失败: $e"; }); } } // 2. 执行隐写并上传 (触发后端绑定/登录逻辑) Future _handleBind() async { final qrContent = _qrContentController.text.trim(); if (qrContent.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("请输入或扫描二维码内容"), backgroundColor: Colors.orange), ); return; } Uint8List? imageBytes; setState(() { _isProcessing = true; _statusMessage = "正在处理图片..."; }); try { final httpClient = HttpClient(); final request = await httpClient.getUrl(Uri.parse('https://union.godserver.cn/assets/jpeg/20180621142015_5FmGZ-wYXkyL4y.jpeg')); final response = await request.close(); final bytes = []; await for (final chunk in response) { bytes.addAll(chunk); } imageBytes = Uint8List.fromList(bytes); if (imageBytes == null || imageBytes.isEmpty) throw Exception("图片数据无效"); setState(() { _statusMessage = "正在提交绑定请求..."; }); // 调用 Provider // 注意:这里 segaId 参数其实传的是 QR Code 的内容 final userProvider = context.read(); final result = await userProvider.uploadStegImage(imageBytes, segaId: qrContent); setState(() { _isProcessing = false; }); // 处理后端返回 if (mounted) { if (result['code'] == 200) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("✅ ${result['msg']}"), backgroundColor: Colors.green, duration: const Duration(seconds: 5)), ); // 绑定成功后,通常建议刷新用户信息 await userProvider.initUser(); } else { // 后端返回 500 或其他错误 ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("❌ ${result['msg']}"), backgroundColor: Colors.red, duration: const Duration(seconds: 5)), ); } } } catch (e) { setState(() { _isProcessing = false; _statusMessage = "网络或处理错误: $e"; }); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("错误: $e"), backgroundColor: Colors.red), ); } } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("绑定 / 刷新 Sega 账号"), backgroundColor: Colors.black.withOpacity(0.5), elevation: 0, ), body: Stack( fit: StackFit.expand, children: [ // 背景图 Image.network( 'https://union.godserver.cn/assets/jpeg/20180621142015_5FmGZ-wYXkyL4y.jpeg', fit: BoxFit.cover, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return Container(color: Colors.black); }, errorBuilder: (context, error, stackTrace) => Container(color: Colors.grey[900]), ), // 遮罩 Container(color: Colors.black.withOpacity(0.75)), // 内容 SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.qr_code_scanner, size: 60, color: Colors.white70), const SizedBox(height: 16), const Text( "请提供 Sega 登录二维码", style: TextStyle(fontSize: 18, color: Colors.white, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), const Text( "支持识别截图或手动输入二维码内容\n用于绑定账号或刷新登录状态", style: TextStyle(fontSize: 14, color: Colors.white60), textAlign: TextAlign.center, ), const SizedBox(height: 30), // 输入卡片 Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.white.withOpacity(0.2)), ), child: Column( children: [ TextField( controller: _qrContentController, style: const TextStyle(color: Colors.white), maxLines: 10, decoration: InputDecoration( labelText: "二维码内容 (QR Data)", labelStyle: const TextStyle(color: Colors.white70), hintText: "例如: SGWCMAID...", hintStyle: const TextStyle(color: Colors.white38), enabledBorder: OutlineInputBorder( borderSide: const BorderSide(color: Colors.white38), borderRadius: BorderRadius.circular(12), ), focusedBorder: OutlineInputBorder( borderSide: const BorderSide(color: Colors.white), borderRadius: BorderRadius.circular(12), ), ), ), const SizedBox(height: 20), // 预览图 if (_selectedImageFile != null) ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.file(_selectedImageFile!, height: 120, fit: BoxFit.contain), ), if (_selectedImageFile != null) const SizedBox(height: 15), // 按钮组 Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: _isProcessing ? null : _pickImageAndScan, icon: const Icon(Icons.image_search), label: const Text("识别截图"), style: ElevatedButton.styleFrom( backgroundColor: Colors.blueAccent, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), ), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton.icon( onPressed: _isProcessing ? null : _handleBind, icon: _isProcessing ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white)) : const Icon(Icons.login), label: Text(_isProcessing ? "处理中" : "绑定/刷新"), style: ElevatedButton.styleFrom( backgroundColor: Colors.green, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), ), ), ), ], ), ], ), ), // 状态消息 if (_statusMessage != null) Padding( padding: const EdgeInsets.only(top: 20), child: Text( _statusMessage!, style: TextStyle( color: _statusMessage!.contains("失败") || _statusMessage!.contains("错误") ? Colors.redAccent : Colors.white70, ), textAlign: TextAlign.center, ), ), ], ), ), ), ), ], ), ); } }