ver1.00.00

update2
This commit is contained in:
spasolreisa
2026-04-21 01:28:53 +08:00
parent f5f62c828d
commit 603772bc81
11 changed files with 346 additions and 286 deletions

View File

@@ -1,10 +1,21 @@
import com.android.build.api.dsl.SigningConfig
import java.util.Properties
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
// 加载 key.properties 配置 👇
val keystoreProperties = Properties()
val keystoreFile = rootProject.file("key.properties")
if (keystoreFile.exists()) {
keystoreFile.inputStream().use { stream ->
keystoreProperties.load(stream)
}
}
android {
namespace = "org.ast.unionapp"
compileSdk = flutter.compileSdkVersion
@@ -20,21 +31,33 @@ android {
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "org.ast.unionapp"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
// 签名配置 👇
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
// 启用正式签名(替换原来的 debug
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}

View File

@@ -1,8 +1,24 @@
allprojects {
repositories {
// ✅ 阿里云 Maven 镜像(推荐,稳定快速)
maven { url = uri("https://maven.aliyun.com/repository/google") }
maven { url = uri("https://maven.aliyun.com/repository/public") }
maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
maven { url = uri("https://storage.googleapis.com/download.flutter.io") }
// ✅ 腾讯云 Maven 镜像(备用)
// maven { url = uri("https://mirrors.cloud.tencent.com/nexus/repository/maven-public/") }
// 官方源(放在最后作为备用)
google()
mavenCentral()
maven { url = uri("https://storage.googleapis.com/download.flutter.io") }
}
configurations.all {
resolutionStrategy {
force("androidx.work:work-runtime:2.8.1")
force("androidx.work:work-runtime-ktx:2.8.1")
}
}
}

View File

@@ -3,3 +3,4 @@ distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
org.gradle.java.home=/Users/spasolreisa/Library/Java/JavaVirtualMachines/jbr-17.0.14/Contents/Home

View File

@@ -2,8 +2,10 @@ 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 'package:zxing2/qrcode.dart';
import 'package:image/image.dart' as img;
import '../../providers/user_provider.dart';
@@ -22,19 +24,13 @@ class _BindAccountPageState extends State<BindAccountPage> {
String? _statusMessage;
File? _selectedImageFile; // 用户选择的原始二维码截图
// 条码扫描器
final BarcodeScanner _barcodeScanner = BarcodeScanner(
formats: [BarcodeFormat.qrCode],
);
@override
void dispose() {
_qrContentController.dispose();
_barcodeScanner.close();
super.dispose();
}
// 1. 选择图片并识别二维码
// 1. 选择图片并识别二维码 (使用 zxing2替代 ML Kit)
Future<void> _pickImageAndScan() async {
try {
final XFile? pickedFile = await _picker.pickImage(source: ImageSource.gallery);
@@ -42,33 +38,79 @@ class _BindAccountPageState extends State<BindAccountPage> {
setState(() {
_isProcessing = true;
_statusMessage = "正在识别二维码...";
_statusMessage = "正在加载图片...";
_selectedImageFile = File(pickedFile.path);
});
final inputImage = InputImage.fromFilePath(pickedFile.path);
final List<Barcode> barcodes = await _barcodeScanner.processImage(inputImage);
// 读取图片字节
final bytes = await pickedFile.readAsBytes();
// 使用 image 库解码图片为 RGB 数据
final img.Image? decodedImage = img.decodeImage(bytes);
if (decodedImage == null) {
throw Exception("无法解析图片格式");
}
setState(() {
_isProcessing = false;
_statusMessage = "正在解析二维码...";
});
if (barcodes.isNotEmpty && barcodes.first.rawValue != null) {
final String code = barcodes.first.rawValue!;
final reader = QRCodeReader();
try {
// 【修复点开始】
// 1. 获取 Uint8List (RGBA 格式)
final Uint8List rgbaBytes = decodedImage.getBytes(order: img.ChannelOrder.rgba);
// 2. 将 Uint8List 转换为 Int32List
// 注意:这需要底层字节序匹配。大多数现代移动设备是 Little Endian。
// Uint8List 的长度必须是 4 的倍数RGBA 每个像素4字节这通常成立。
final Int32List pixels = Int32List.view(rgbaBytes.buffer);
// 3. 创建 LuminanceSource
// ZXing 的 RGBLuminanceSource 期望 Int32List其中每个 int 代表一个像素 (0xAARRGGBB 或类似格式)
// 由于 image 库给出的是 RGBA (0xRR, 0xGG, 0xBB, 0xAA),直接转换可能导致颜色通道错位,
// 但 ZXing 主要关注亮度(灰度),通常 RGBA 直接转 Int32 也能被正确二值化识别,
// 如果识别失败,可能需要手动重排字节为 ARGB。
final source = RGBLuminanceSource(
decodedImage.width,
decodedImage.height,
pixels
);
// 【修复点结束】
final binarizer = HybridBinarizer(source);
final bitmap = BinaryBitmap(binarizer);
final result = reader.decode(bitmap);
if (result != null && result.text != null) {
setState(() {
_qrContentController.text = result.text!;
_statusMessage = "识别成功";
});
} else {
setState(() {
_statusMessage = "未识别到二维码,请手动输入";
});
}
} catch (e) {
// 捕获 zxing 内部的 NotFoundException 等
print("ZXing Error: $e"); // 调试用
setState(() {
_qrContentController.text = code;
_statusMessage = "识别成功";
});
} else {
setState(() {
_statusMessage = "未识别到二维码,请手动输入";
_statusMessage = "未在图中找到有效二维码";
});
}
} catch (e) {
setState(() {
_statusMessage = "识别出错: $e";
});
} finally {
setState(() {
_isProcessing = false;
_statusMessage = "识别失败: $e";
});
}
}
@@ -92,7 +134,9 @@ class _BindAccountPageState extends State<BindAccountPage> {
});
try {
// 下载背景图用于隐写
final httpClient = HttpClient();
// 建议在实际生产环境中添加 timeout
final request = await httpClient.getUrl(Uri.parse('https://union.godserver.cn/assets/jpeg/20180621142015_5FmGZ-wYXkyL4y.jpeg'));
final response = await request.close();
final bytes = <int>[];
@@ -101,6 +145,9 @@ class _BindAccountPageState extends State<BindAccountPage> {
}
imageBytes = Uint8List.fromList(bytes);
// 关闭 client 以释放资源
httpClient.close();
if (imageBytes == null || imageBytes.isEmpty) throw Exception("图片数据无效");
setState(() {
@@ -108,7 +155,6 @@ class _BindAccountPageState extends State<BindAccountPage> {
});
// 调用 Provider
// 注意:这里 segaId 参数其实传的是 QR Code 的内容
final userProvider = context.read<UserProvider>();
final result = await userProvider.uploadStegImage(imageBytes, segaId: qrContent);
@@ -122,10 +168,13 @@ class _BindAccountPageState extends State<BindAccountPage> {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("${result['msg']}"), backgroundColor: Colors.green, duration: const Duration(seconds: 5)),
);
// 绑定成功后,通常建议刷新用户信息
// 绑定成功后,刷新用户信息
await userProvider.initUser();
// 可选:清空输入或跳转
// _qrContentController.clear();
// Navigator.of(context).pop();
} else {
// 后端返回 500 或其他错误
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("${result['msg']}"), backgroundColor: Colors.red, duration: const Duration(seconds: 5)),
);
@@ -276,7 +325,7 @@ class _BindAccountPageState extends State<BindAccountPage> {
child: Text(
_statusMessage!,
style: TextStyle(
color: _statusMessage!.contains("失败") || _statusMessage!.contains("错误") ? Colors.redAccent : Colors.white70,
color: _statusMessage!.contains("失败") || _statusMessage!.contains("错误") || _statusMessage!.contains("未识别") ? Colors.redAccent : Colors.white70,
),
textAlign: TextAlign.center,
),

View File

@@ -77,6 +77,8 @@ class _LoginPageState extends State<LoginPage> {
final isDark = theme.brightness == Brightness.dark;
return Scaffold(
// 关键修复1resizeToAvoidBottomInset = false防止键盘弹出重绘崩溃
resizeToAvoidBottomInset: false,
backgroundColor: isDark ? Colors.black : Colors.white,
appBar: AppBar(
title: Text(isRegisterMode ? '创建账号' : '欢迎回来'),
@@ -96,215 +98,217 @@ class _LoginPageState extends State<LoginPage> {
),
alignment: Alignment.center,
padding: const EdgeInsets.all(24),
child: Transform.translate(
offset: const Offset(0, -30),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Card(
elevation: 8,
shadowColor: _pinkColor.withOpacity(0.3),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
color: isDark ? Colors.grey[850] : Colors.white,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 头像/图标区域 - 已修改为黑白粉主题
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: _pinkColor.withOpacity(0.15),
shape: BoxShape.circle,
),
child: Icon(
// 更换为更美观的人物头像类图标
isRegisterMode ? Icons.person_add_rounded : Icons.person_rounded,
size: 48,
color: _pinkColor,
),
),
const SizedBox(height: 24),
Text(
isRegisterMode ? '注册新账号' : '账号登录',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: isDark ? Colors.white : Colors.black87,
),
),
const SizedBox(height: 8),
Text(
isRegisterMode ? '请填写以下信息' : '请输入您的凭证以继续',
style: TextStyle(
fontSize: 14,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
if (errorMessage.isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.red.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.red.withOpacity(0.3)),
child: SingleChildScrollView(
// 关键修复2让滚动视图正常工作
physics: const AlwaysScrollableScrollPhysics(),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height - 100,
),
child: Center(
child: Transform.translate(
offset: const Offset(0, -30),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Card(
elevation: 8, shadowColor: _pinkColor.withOpacity(0.3),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
color: isDark ? Colors.grey[850] : Colors.white,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: _pinkColor.withOpacity(0.15),
shape: BoxShape.circle,
),
child: Icon(
isRegisterMode ? Icons.person_add_rounded : Icons.person_rounded,
size: 48,
color: _pinkColor,
),
),
child: Row(
children: [
const Icon(Icons.error_outline, color: Colors.red, size: 20),
const SizedBox(width: 8),
Expanded(
child: Text(
errorMessage,
style: const TextStyle(color: Colors.red, fontSize: 13),
const SizedBox(height: 24),
Text(
isRegisterMode ? '注册新账号' : '账号登录',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: isDark ? Colors.white : Colors.black87,
),
),
const SizedBox(height: 8),
Text(
isRegisterMode ? '请填写以下信息' : '请输入您的凭证以继续',
style: TextStyle(
fontSize: 14,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
if (errorMessage.isNotEmpty)
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.red.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.red.withOpacity(0.3)),
),
child: Row(
children: [
const Icon(Icons.error_outline, color: Colors.red, size: 20),
const SizedBox(width: 8),
Expanded(
child: Text(
errorMessage,
style: const TextStyle(color: Colors.red, fontSize: 13),
),
),
],
),
),
TextField(
controller: usernameController,
enabled: !isLoading,
decoration: InputDecoration(
labelText: '用户名',
prefixIcon: const Icon(Icons.person_outline, color: _pinkColor),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: _pinkColor.withOpacity(0.5)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor, width: 2),
),
filled: true,
fillColor: isDark ? Colors.grey[800] : Colors.grey[50],
),
),
const SizedBox(height: 16),
TextField(
controller: passwordController,
obscureText: true,
enabled: !isLoading,
decoration: InputDecoration(
labelText: isRegisterMode ? '设置密码' : '密码 / TOTP验证码',
prefixIcon: const Icon(Icons.lock_outline, color: _pinkColor),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: _pinkColor.withOpacity(0.5)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor, width: 2),
),
filled: true,
fillColor: isDark ? Colors.grey[800] : Colors.grey[50],
),
),
if (isRegisterMode) ...[
const SizedBox(height: 16),
TextField(
controller: inviterController,
enabled: !isLoading,
decoration: InputDecoration(
labelText: '邀请人 ID (可选)',
prefixIcon: const Icon(Icons.card_giftcard_outlined, color: _pinkColor),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: _pinkColor.withOpacity(0.5)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor, width: 2),
),
filled: true,
fillColor: isDark ? Colors.grey[800] : Colors.grey[50],
),
),
],
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
onPressed: isLoading ? null : submit,
style: ElevatedButton.styleFrom(
backgroundColor: _pinkColor,
foregroundColor: Colors.black,
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
],
child: isLoading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.black),
),
)
: Text(
isRegisterMode ? '立即注册' : '登录',
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
),
),
// 用户名输入框
TextField(
controller: usernameController,
enabled: !isLoading,
decoration: InputDecoration(
labelText: '用户名',
prefixIcon: const Icon(Icons.person_outline, color: _pinkColor),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor),
const SizedBox(height: 16),
TextButton(
onPressed: isLoading
? null
: () {
setState(() {
isRegisterMode = !isRegisterMode;
errorMessage = '';
});
},
child: Text(
isRegisterMode
? '已有账号?去登录'
: '没有账号?去注册',
style: const TextStyle(
color: _pinkColor,
fontWeight: FontWeight.w500,
fontSize: 14,
),
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: _pinkColor.withOpacity(0.5)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor, width: 2),
),
filled: true,
fillColor: isDark ? Colors.grey[800] : Colors.grey[50],
),
],
),
const SizedBox(height: 16),
// 密码输入框
TextField(
controller: passwordController,
obscureText: true,
enabled: !isLoading,
decoration: InputDecoration(
labelText: isRegisterMode ? '设置密码' : '密码 / TOTP验证码',
prefixIcon: const Icon(Icons.lock_outline, color: _pinkColor),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: _pinkColor.withOpacity(0.5)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor, width: 2),
),
filled: true,
fillColor: isDark ? Colors.grey[800] : Colors.grey[50],
),
),
if (isRegisterMode) ...[
const SizedBox(height: 16),
TextField(
controller: inviterController,
enabled: !isLoading,
decoration: InputDecoration(
labelText: '邀请人 ID (可选)',
prefixIcon: const Icon(Icons.card_giftcard_outlined, color: _pinkColor),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: _pinkColor.withOpacity(0.5)),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: _pinkColor, width: 2),
),
filled: true,
fillColor: isDark ? Colors.grey[800] : Colors.grey[50],
),
),
],
const SizedBox(height: 24),
// 登录/注册按钮
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
onPressed: isLoading ? null : submit,
style: ElevatedButton.styleFrom(
backgroundColor: _pinkColor,
foregroundColor: Colors.black,
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: isLoading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.black),
),
)
: Text(
isRegisterMode ? '立即注册' : '登录',
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
),
const SizedBox(height: 16),
// 切换登录/注册
TextButton(
onPressed: isLoading
? null
: () {
setState(() {
isRegisterMode = !isRegisterMode;
errorMessage = '';
});
},
child: Text(
isRegisterMode
? '已有账号?去登录'
: '没有账号?去注册',
style: const TextStyle(
color: _pinkColor,
fontWeight: FontWeight.w500,
fontSize: 14,
),
),
),
],
),
),
),
),

View File

@@ -6,18 +6,6 @@
#include "generated_plugin_registrant.h"
#include <file_selector_linux/file_selector_plugin.h>
#include <open_file_linux/open_file_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) open_file_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "OpenFileLinuxPlugin");
open_file_linux_plugin_register_with_registrar(open_file_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
}

View File

@@ -3,13 +3,9 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
file_selector_linux
open_file_linux
url_launcher_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
)
set(PLUGIN_BUNDLED_LIBRARIES)

View File

@@ -49,6 +49,14 @@ packages:
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "1.4.1"
charcode:
dependency: transitive
description:
name: charcode
sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "1.4.0"
clock:
dependency: transitive
description:
@@ -376,22 +384,6 @@ packages:
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "2.1.3"
google_mlkit_barcode_scanning:
dependency: "direct dev"
description:
name: google_mlkit_barcode_scanning
sha256: "965183a8cd5cef8477ceea5dbdf29c34a739cf0cfbf1bdad54cd3f9f1807afe5"
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "0.10.0"
google_mlkit_commons:
dependency: transitive
description:
name: google_mlkit_commons
sha256: "046586b381cdd139f7f6a05ad6998f7e339d061bd70158249907358394b5f496"
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "0.6.1"
gsettings:
dependency: transitive
description:
@@ -1181,6 +1173,14 @@ packages:
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "3.1.3"
zxing2:
dependency: "direct dev"
description:
name: zxing2
sha256: "2677c49a3b9ca9457cb1d294fd4bd5041cac6aab8cdb07b216ba4e98945c684f"
url: "https://mirrors.tuna.tsinghua.edu.cn/dart-pub/"
source: hosted
version: "0.2.4"
sdks:
dart: ">=3.11.3 <4.0.0"
flutter: ">=3.38.4"

View File

@@ -58,8 +58,8 @@ dev_dependencies:
open_file: ^3.3.2
webview_flutter: ^4.8.0
image: ^4.0.17
google_mlkit_barcode_scanning: ^0.10.0 # 用于识别二维码/条形码
image_picker: ^1.0.4
zxing2: ^0.2.3 # 新增:用于二维码识别
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

View File

@@ -6,18 +6,6 @@
#include "generated_plugin_registrant.h"
#include <file_selector_windows/file_selector_windows.h>
#include <geolocator_windows/geolocator_windows.h>
#include <share_plus/share_plus_windows_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
GeolocatorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("GeolocatorWindows"));
SharePlusWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}

View File

@@ -3,14 +3,9 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
file_selector_windows
geolocator_windows
share_plus
url_launcher_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
)
set(PLUGIN_BUNDLED_LIBRARIES)