From 1953e43ca4deb760058d68c1eab4cd0c11a68633 Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Sun, 23 Nov 2025 23:07:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=A1=86=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/utils/convert_utils.dart | 9 ++ lib/utils/file_utils.dart | 50 ++++++++ lib/utils/minio_utils.dart | 58 +++++++++ lib/utils/toast_util.dart | 48 +++++++ lib/widget/chart.dart | 228 +++++++++++++++++++++++---------- lib/widget/common_widget.dart | 6 + lib/widget/dialog_widget.dart | 100 +++++++++++++++ lib/widget/loading_widget.dart | 52 ++++++++ lib/widget/year_selector.dart | 51 +++++--- pubspec.lock | 154 +++++++++++++++++++++- pubspec.yaml | 6 + 11 files changed, 669 insertions(+), 93 deletions(-) create mode 100644 lib/utils/file_utils.dart create mode 100644 lib/utils/minio_utils.dart create mode 100644 lib/utils/toast_util.dart create mode 100644 lib/widget/dialog_widget.dart create mode 100644 lib/widget/loading_widget.dart diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index 494b766..1a71e11 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -12,6 +12,15 @@ List convertList( ); } +List convertStringList(dynamic data) { + if (data is List) { + return data.map((item) => item.toString()).toList(); + } + throw FormatException( + 'Expected a list of items for conversion, but got ${data.runtimeType}', + ); +} + PageResult convertPage( dynamic data, T Function(Map) fromJson, diff --git a/lib/utils/file_utils.dart b/lib/utils/file_utils.dart new file mode 100644 index 0000000..e8cfd93 --- /dev/null +++ b/lib/utils/file_utils.dart @@ -0,0 +1,50 @@ +import 'dart:io'; +import 'package:crypto/crypto.dart'; +import 'package:flutter_image_compress/flutter_image_compress.dart'; + +import 'log_utils.dart'; + +String getFileExtension(String fileName) { + if (fileName.contains('.')) { + return '.${fileName.split('.').last.toLowerCase()}'; + } + return ''; +} + +Future generateMD5HashName(String filePath) async { + final file = File(filePath); + final bytes = await file.readAsBytes(); + final hash = md5.convert(bytes); + return hash.toString(); +} + +// 图片压缩方法 +Future compressImage(File file) async { + try { + // 获取压缩后的文件路径 + final result = await FlutterImageCompress.compressAndGetFile( + file.absolute.path, + '${file.parent.path}/compressed_${DateTime.now().millisecondsSinceEpoch}.jpg', + minWidth: 800, + minHeight: 600, + quality: 70, + format: CompressFormat.jpeg, + ); + + if (result == null) { + throw Exception('图片压缩失败'); + } + + return File(result.path); + } catch (e) { + logger.e('图片压缩失败,使用原文件: $e'); + return file; + } +} + +// 检查是否为图片文件 +bool isImageFile(String fileName) { + final imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']; + final extension = fileName.toLowerCase().substring(fileName.lastIndexOf('.')); + return imageExtensions.contains(extension); +} diff --git a/lib/utils/minio_utils.dart b/lib/utils/minio_utils.dart new file mode 100644 index 0000000..ea3192a --- /dev/null +++ b/lib/utils/minio_utils.dart @@ -0,0 +1,58 @@ +import 'dart:io'; + +import 'package:file_picker/file_picker.dart'; +import 'package:minio/io.dart'; +import 'package:minio/minio.dart'; + +import 'file_utils.dart'; + +class MinIOHelper { + static final MinIOHelper _instance = MinIOHelper._internal(); + + factory MinIOHelper() => _instance; + + final String ip = '14.103.235.151'; + final String fileUrl = 'http://14.103.235.151:9100'; + + MinIOHelper._internal() { + _minio = Minio( + endPoint: ip, + port: 9100, + accessKey: "tHSFfcDW8qpCzKa2Xg6Y", + secretKey: "oq79EeYJ4jdczRp2IHUMCnbKtSw58NgDlG3sOkvX", + useSSL: false, + ); + } + + late Minio _minio; + + Future uploadFile({ + required PlatformFile file, + required String bucketName, + Function(double)? onProgress, + }) async { + try { + if (isImageFile(file.name)) { + // 压缩图片 + final compressedFile = await compressImage(File(file.path!)); + + String hashName = await generateMD5HashName(compressedFile.path); + String fileName = '$hashName${getFileExtension(file.name)}'; + + await _minio.fPutObject(bucketName, fileName, compressedFile.path); + await compressedFile.delete(); + + return fileName; + } else { + String hashName = await generateMD5HashName(file.path!); + String fileName = '$hashName${getFileExtension(file.name)}'; + + await _minio.fPutObject(bucketName, fileName, file.path!); + + return fileName; + } + } catch (e) { + throw Exception('文件上传失败: $e'); + } + } +} diff --git a/lib/utils/toast_util.dart b/lib/utils/toast_util.dart new file mode 100644 index 0000000..d471e03 --- /dev/null +++ b/lib/utils/toast_util.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +class ToastUtil { + static void success(String message) { + Fluttertoast.showToast( + msg: message, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.TOP, + backgroundColor: Colors.green, + textColor: Colors.white, + fontSize: 16.0, + ); + } + + static void error(String message) { + Fluttertoast.showToast( + msg: message, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.TOP, + backgroundColor: Colors.red, + textColor: Colors.white, + fontSize: 16.0, + ); + } + + static void warning(String message) { + Fluttertoast.showToast( + msg: message, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.TOP, + backgroundColor: Colors.orange, + textColor: Colors.white, + fontSize: 16.0, + ); + } + + static void info(String message) { + Fluttertoast.showToast( + msg: message, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.TOP, + backgroundColor: Colors.blue, + textColor: Colors.white, + fontSize: 16.0, + ); + } +} \ No newline at end of file diff --git a/lib/widget/chart.dart b/lib/widget/chart.dart index 0cc154c..a0b2916 100644 --- a/lib/widget/chart.dart +++ b/lib/widget/chart.dart @@ -2,6 +2,83 @@ import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; import '../models/common_model.dart'; +import 'common_widget.dart'; + +class StatsCard extends StatelessWidget { + final String title; + final String value; + final String unit; + final IconData icon; + + const StatsCard( + {super.key, + required this.title, + required this.value, + required this.unit, + required this.icon}); + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + + return CommonCard( + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colors.primary.withAlpha(50), + shape: BoxShape.circle, + ), + child: Icon(icon, size: 26, color: colors.primary), + ), + SizedBox(width: 6), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + title, + style: TextStyle( + fontSize: 16, + color: Colors.grey.shade600, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 6), + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + value, + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: colors.primary, + height: 1.0, + ), + ), + const SizedBox(width: 4), + Text( + unit, + style: TextStyle( + fontSize: 14, + color: Colors.grey.shade600, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ], + ), + ), + ], + ), + ); + } +} class LineChart extends StatelessWidget { final String title; @@ -168,6 +245,7 @@ class BarChart extends StatelessWidget { } class DoubleBarChart extends StatelessWidget { + final String title; final String xAxisName; final String yAxisName; final String unit; @@ -178,6 +256,7 @@ class DoubleBarChart extends StatelessWidget { const DoubleBarChart( {super.key, + required this.title, required this.xAxisName, required this.yAxisName, required this.unit, @@ -190,81 +269,88 @@ class DoubleBarChart extends StatelessWidget { Widget build(BuildContext context) { final colors = Theme.of(context).colorScheme; - return SfCartesianChart( - // X轴配置(类别轴) - primaryXAxis: - CategoryAxis(majorGridLines: const MajorGridLines(width: 0)), + return Column(children: [ + _buildChartTitle(context, title, Icons.bar_chart), + const SizedBox(height: 3), + _buildChartDivider(context), + const SizedBox(height: 3), + Expanded( + child: SfCartesianChart( + // X轴配置(类别轴) + primaryXAxis: + CategoryAxis(majorGridLines: const MajorGridLines(width: 0)), - // Y轴配置(数值轴) - // primaryYAxis: NumericAxis(title: AxisTitle(text: '$yAxisName($unit)')), + // Y轴配置(数值轴) + // primaryYAxis: NumericAxis(title: AxisTitle(text: '$yAxisName($unit)')), - // 图例配置 - legend: Legend( - isVisible: true, - position: LegendPosition.top, - overflowMode: LegendItemOverflowMode.wrap, - ), - - // 启用交互提示 - tooltipBehavior: TooltipBehavior( - enable: true, - format: 'series.name: point.y $unit', - ), - - // 双柱状图数据系列 - series: >[ - ColumnSeries( - dataSource: data1, - // X轴数据映射 - xValueMapper: (ChartData chart, _) => chart.name, - // Y轴数据映射 - yValueMapper: (ChartData chart, _) => chart.value, - // 系列名称 - name: series1Name, - // 柱子颜色 - color: colors.primary, - // 柱子宽度 - width: 0.3, - // 柱子边框 - borderWidth: 1, - borderColor: Colors.black12, - // 数据标签 - dataLabelSettings: const DataLabelSettings( - isVisible: true, - color: Colors.white, - opacity: 0, - alignment: ChartAlignment.center, - ), - // 动画效果 - animationDuration: 2000, + // 图例配置 + legend: Legend( + isVisible: true, + position: LegendPosition.top, + overflowMode: LegendItemOverflowMode.wrap, ), - ColumnSeries( - dataSource: data2, - // X轴数据映射 - xValueMapper: (ChartData chart, _) => chart.name, - // Y轴数据映射 - yValueMapper: (ChartData chart, _) => chart.value, - // 系列名称 - name: series2Name, - // 柱子颜色 - color: colors.inversePrimary, - // 柱子宽度 - width: 0.3, - // 柱子边框 - borderWidth: 1, - borderColor: Colors.black12, - // 数据标签 - dataLabelSettings: const DataLabelSettings( - isVisible: true, - color: Colors.white, - opacity: 0, - alignment: ChartAlignment.center, - ), - // 动画效果 - animationDuration: 2000, + + // 启用交互提示 + tooltipBehavior: TooltipBehavior( + enable: true, + format: 'series.name: point.y $unit', ), - ], - ); + + // 双柱状图数据系列 + series: >[ + ColumnSeries( + dataSource: data1, + // X轴数据映射 + xValueMapper: (ChartData chart, _) => chart.name, + // Y轴数据映射 + yValueMapper: (ChartData chart, _) => chart.value, + // 系列名称 + name: series1Name, + // 柱子颜色 + color: colors.primary, + // 柱子宽度 + width: 0.3, + // 柱子边框 + borderWidth: 1, + borderColor: Colors.black12, + // 数据标签 + dataLabelSettings: const DataLabelSettings( + isVisible: true, + color: Colors.white, + opacity: 0, + alignment: ChartAlignment.center, + ), + // 动画效果 + animationDuration: 2000, + ), + ColumnSeries( + dataSource: data2, + // X轴数据映射 + xValueMapper: (ChartData chart, _) => chart.name, + // Y轴数据映射 + yValueMapper: (ChartData chart, _) => chart.value, + // 系列名称 + name: series2Name, + // 柱子颜色 + color: colors.inversePrimary, + // 柱子宽度 + width: 0.3, + // 柱子边框 + borderWidth: 1, + borderColor: Colors.black12, + // 数据标签 + dataLabelSettings: const DataLabelSettings( + isVisible: true, + color: Colors.white, + opacity: 0, + alignment: ChartAlignment.center, + ), + // 动画效果 + animationDuration: 2000, + ), + ], + )) + ]); } } diff --git a/lib/widget/common_widget.dart b/lib/widget/common_widget.dart index 0f320ea..8aeb267 100644 --- a/lib/widget/common_widget.dart +++ b/lib/widget/common_widget.dart @@ -64,3 +64,9 @@ Widget buildErrorInfo({ Widget buildLoadingIndicator() { return Center(child: CircularProgressIndicator()); } + +Widget buildEmptyData() { + return Center( + child: Text('暂无数据', style: TextStyle(fontSize: 16, color: Colors.grey)), + ); +} diff --git a/lib/widget/dialog_widget.dart b/lib/widget/dialog_widget.dart new file mode 100644 index 0000000..f2bc34c --- /dev/null +++ b/lib/widget/dialog_widget.dart @@ -0,0 +1,100 @@ +import 'package:awesome_dialog/awesome_dialog.dart'; +import 'package:flutter/material.dart'; + +void showAwesomeDialog({ + required BuildContext context, + required Widget body, + required VoidCallback onOk, + required VoidCallback onCancel, +}) { + AwesomeDialog( + context: context, + dialogType: DialogType.noHeader, + animType: AnimType.scale, + body: body, + dialogBackgroundColor: Theme.of(context).colorScheme.surfaceContainer, + btnOkText: "确认", + btnCancelText: "取消", + btnOkColor: Colors.orange, + btnCancelColor: Colors.grey, + buttonsBorderRadius: BorderRadius.circular(10), + headerAnimationLoop: false, + dismissOnTouchOutside: false, + dismissOnBackKeyPress: true, + btnOk: ElevatedButton( + onPressed: onOk, + style: ElevatedButton.styleFrom( + elevation: 0, + backgroundColor: Theme.of(context).colorScheme.primary, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 6), + textStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + fontFamily: 'CustomFont'), + ), + child: Text("确认"), + ), + btnCancelOnPress: onCancel, + ).show(); +} + +// 显示成功提示 +void showSuccessTip(BuildContext context, String message) { + AwesomeDialog( + context: context, + dialogType: DialogType.success, + animType: AnimType.scale, + title: message, + btnOkText: "好的", + btnOkColor: Colors.green, + btnOkOnPress: () {}, + autoHide: Duration(seconds: 2), + ).show(); +} + +// 显示失败提示 +void showErrorTip(BuildContext context, String message) { + AwesomeDialog( + context: context, + dialogType: DialogType.error, + animType: AnimType.scale, + title: message, + btnOkText: "好的", + btnOkColor: Colors.red, + btnOkOnPress: () {}, + autoHide: Duration(seconds: 2), + ).show(); +} + +// 确认对话框 +Future showConfirmDialog(BuildContext context, String text) async { + final colors = Theme.of(context).colorScheme; + + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('确认'), + backgroundColor: colors.surfaceContainer, + content: Text(text), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: Text( + '取消', + style: TextStyle(color: colors.secondary.withAlpha(150)), + ), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text('确认', style: TextStyle(color: colors.primary)), + ), + ], + ); + }, + ); +} diff --git a/lib/widget/loading_widget.dart b/lib/widget/loading_widget.dart new file mode 100644 index 0000000..b4c81d6 --- /dev/null +++ b/lib/widget/loading_widget.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +class LoadingDialog { + static void show(BuildContext context, {String? message}) { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return PopScope( + canPop: false, + child: AlertDialog( + backgroundColor: Colors.transparent, + elevation: 0, + content: _buildLoadingContent(context, message), + ), + ); + }, + ); + } + + static void hide(BuildContext context) { + Navigator.of(context, rootNavigator: true).pop(); + } + + static Widget _buildLoadingContent(BuildContext context, String? message) { + final colors = Theme.of(context).colorScheme; + + return Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(colors.primary), + strokeWidth: 3, + ), + if (message != null) ...[ + SizedBox(height: 16), + Text( + message, + style: TextStyle(fontSize: 14, color: Colors.grey[600]), + ), + ], + ], + ), + ); + } +} diff --git a/lib/widget/year_selector.dart b/lib/widget/year_selector.dart index 1b94842..338e842 100644 --- a/lib/widget/year_selector.dart +++ b/lib/widget/year_selector.dart @@ -3,26 +3,21 @@ import 'package:flutter/material.dart'; import 'common_widget.dart'; class YearSelector extends StatefulWidget { - final int initialYear; - final int? minYear; - final int? maxYear; + final int currentYear; final Function(int) onYearChanged; - const YearSelector({ - super.key, - required this.initialYear, - required this.onYearChanged, - this.minYear, - this.maxYear, - }); + const YearSelector( + {super.key, required this.currentYear, required this.onYearChanged}); @override State createState() => _YearSelectorState(); } -// SingleTickerProviderStateMixin 动画控制器 class _YearSelectorState extends State with SingleTickerProviderStateMixin { + final int minYear = 2000; + final int maxYear = 2100; + late int _currentYear; // 用于动画效果 @@ -32,7 +27,8 @@ class _YearSelectorState extends State @override void initState() { super.initState(); - _currentYear = widget.initialYear; + + _currentYear = widget.currentYear; // 初始化动画控制器 _animationController = AnimationController( @@ -46,6 +42,17 @@ class _YearSelectorState extends State ); } + @override + void didUpdateWidget(YearSelector oldWidget) { + super.didUpdateWidget(oldWidget); + + if (oldWidget.currentYear != widget.currentYear) { + setState(() { + _currentYear = widget.currentYear; + }); + } + } + @override void dispose() { _animationController.dispose(); @@ -54,24 +61,26 @@ class _YearSelectorState extends State /// 切换到上一年 void _previousYear() { - if (widget.minYear == null || _currentYear > widget.minYear!) { + if (_currentYear > minYear) { _animateYearChange(() { + final newYear = _currentYear - 1; setState(() { - _currentYear--; + _currentYear = newYear; }); - widget.onYearChanged(_currentYear); + widget.onYearChanged(newYear); }); } } /// 切换到下一年 void _nextYear() { - if (widget.maxYear == null || _currentYear < widget.maxYear!) { + if (_currentYear < maxYear) { _animateYearChange(() { + final newYear = _currentYear + 1; setState(() { - _currentYear++; + _currentYear = newYear; }); - widget.onYearChanged(_currentYear); + widget.onYearChanged(newYear); }); } } @@ -91,7 +100,7 @@ class _YearSelectorState extends State children: [ CircleIconButton( icon: Icons.chevron_left, - onPressed: () => _previousYear(), + onPressed: _previousYear, ), AnimatedBuilder( animation: _scaleAnimation, @@ -109,8 +118,8 @@ class _YearSelectorState extends State ), CircleIconButton( icon: Icons.chevron_right, - onPressed: () => _nextYear(), - ) + onPressed: _nextYear, + ), ], ); } diff --git a/pubspec.lock b/pubspec.lock index febc81c..a6f9b08 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -33,6 +33,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.12.0" + awesome_dialog: + dependency: "direct main" + description: + name: awesome_dialog + sha256: "4c5821a0a637ceee022084e78c1b8237dd4b8bfca4dd24ac2484662a56707338" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.3.0" boolean_selector: dependency: transitive description: @@ -41,6 +49,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" + buffer: + dependency: transitive + description: + name: buffer + sha256: "389da2ec2c16283c8787e0adaede82b1842102f8c8aae2f49003a766c5c6b3d1" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.3" build: dependency: transitive description: @@ -153,8 +169,16 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.1.2" - crypto: + cross_file: dependency: transitive + description: + name: cross_file + sha256: "942a4791cd385a68ccb3b32c71c427aba508a1bb949b86dff2adbe4049f16239" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.5" + crypto: + dependency: "direct main" description: name: crypto sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf @@ -177,6 +201,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.1.1" + dbus: + dependency: transitive + description: + name: dbus + sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.11" dio: dependency: "direct main" description: @@ -217,6 +249,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "7.0.1" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: "7872545770c277236fd32b022767576c562ba28366204ff1a5628853cf8f2200" + url: "https://pub.flutter-io.cn" + source: hosted + version: "10.3.7" fixnum: dependency: transitive description: @@ -230,6 +270,54 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_image_compress: + dependency: "direct main" + description: + name: flutter_image_compress + sha256: "51d23be39efc2185e72e290042a0da41aed70b14ef97db362a6b5368d0523b27" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.4.0" + flutter_image_compress_common: + dependency: transitive + description: + name: flutter_image_compress_common + sha256: c5c5d50c15e97dd7dc72ff96bd7077b9f791932f2076c5c5b6c43f2c88607bfb + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.6" + flutter_image_compress_macos: + dependency: transitive + description: + name: flutter_image_compress_macos + sha256: "20019719b71b743aba0ef874ed29c50747461e5e8438980dfa5c2031898f7337" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.3" + flutter_image_compress_ohos: + dependency: transitive + description: + name: flutter_image_compress_ohos + sha256: e76b92bbc830ee08f5b05962fc78a532011fcd2041f620b5400a593e96da3f51 + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.3" + flutter_image_compress_platform_interface: + dependency: transitive + description: + name: flutter_image_compress_platform_interface + sha256: "579cb3947fd4309103afe6442a01ca01e1e6f93dc53bb4cbd090e8ce34a41889" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.5" + flutter_image_compress_web: + dependency: transitive + description: + name: flutter_image_compress_web + sha256: b9b141ac7c686a2ce7bb9a98176321e1182c9074650e47bb140741a44b6f5a96 + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.5" flutter_lints: dependency: "direct dev" description: @@ -238,6 +326,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "5.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: c2fe1001710127dfa7da89977a08d591398370d099aacdaa6d44da7eb14b8476 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.31" flutter_test: dependency: "direct dev" description: flutter @@ -248,6 +344,14 @@ packages: description: flutter source: sdk version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "90778fe0497fe3a09166e8cf2e0867310ff434b794526589e77ec03cf08ba8e8" + url: "https://pub.flutter-io.cn" + source: hosted + version: "8.2.14" frontend_server_client: dependency: transitive description: @@ -416,6 +520,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" + minio: + dependency: "direct main" + description: + name: minio + sha256: ee2ce47766e46c7d164f960f2f5ed6a9a82844d877f6b82574f6876ec50c56d1 + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.5.8" nested: dependency: transitive description: @@ -464,6 +576,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.3.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.1.0" platform: dependency: transitive description: @@ -512,6 +632,22 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.5.0" + rive: + dependency: transitive + description: + name: rive + sha256: fc0abf65d03d1c9afaeb35be9e71c7cf04d2d1f76e94e69d2af1b3ba413cddf9 + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.14.0-dev.14" + rive_native: + dependency: transitive + description: + name: rive_native + sha256: e9c7d36f19eb6d32f563825d4e9d5032b19a36d3ca3341641431035bca022d19 + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.17" shared_preferences: dependency: "direct main" description: @@ -741,6 +877,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.0.3" + win32: + dependency: transitive + description: + name: win32 + sha256: "329edf97fdd893e0f1e3b9e88d6a0e627128cc17cc316a8d67fda8f1451178ba" + url: "https://pub.flutter-io.cn" + source: hosted + version: "5.13.0" xdg_directories: dependency: transitive description: @@ -749,6 +893,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.5.0" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 705749a..457bac4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,6 +18,12 @@ dependencies: dio: ^5.7.0 logger: ^2.6.0 json_annotation: ^4.9.0 + minio: ^3.5.8 + crypto: ^3.0.7 + file_picker: ^10.3.3 + fluttertoast: ^8.2.2 + flutter_image_compress: ^2.4.0 + awesome_dialog: ^3.3.0 dev_dependencies: flutter_test: