Переглянути джерело

Update API接口调试优化

Yue 1 місяць тому
батько
коміт
582bc21280
24 змінених файлів з 178 додано та 392 видалено
  1. 7 2
      UI/CF.APP/chicken_farm/lib/apis/_login.dart
  2. 2 2
      UI/CF.APP/chicken_farm/lib/apis/breeding/_query.dart
  3. 4 6
      UI/CF.APP/chicken_farm/lib/apis/breeding/_submit.dart
  4. 13 7
      UI/CF.APP/chicken_farm/lib/components/vb_search_select.dart
  5. 15 9
      UI/CF.APP/chicken_farm/lib/core/db/sqlite_manager.dart
  6. 4 5
      UI/CF.APP/chicken_farm/lib/core/permissions/permission_keys.dart
  7. 62 41
      UI/CF.APP/chicken_farm/lib/core/utils/toast.dart
  8. 1 1
      UI/CF.APP/chicken_farm/lib/modes/breeding/family.dart
  9. 1 1
      UI/CF.APP/chicken_farm/lib/modes/breeding/family.g.dart
  10. 6 2
      UI/CF.APP/chicken_farm/lib/pages/account/login_page.dart
  11. 9 25
      UI/CF.APP/chicken_farm/lib/pages/breeding/batch_create_page.dart
  12. 2 13
      UI/CF.APP/chicken_farm/lib/pages/breeding/batch_create_page_win.dart
  13. 2 16
      UI/CF.APP/chicken_farm/lib/pages/breeding/batch_culling_page.dart
  14. 2 18
      UI/CF.APP/chicken_farm/lib/pages/breeding/batch_culling_page_win.dart
  15. 2 172
      UI/CF.APP/chicken_farm/lib/pages/breeding/cage_change_page.dart
  16. 2 16
      UI/CF.APP/chicken_farm/lib/pages/breeding/individual_culling_page.dart
  17. 4 17
      UI/CF.APP/chicken_farm/lib/pages/breeding/individual_weighing_page.dart
  18. 0 1
      UI/CF.APP/chicken_farm/lib/pages/home/home_page.dart
  19. 30 28
      UI/CF.APP/chicken_farm/lib/pages/home/profile.dart
  20. 2 0
      UI/CF.APP/chicken_farm/lib/pages/serial/serial_setting_page.dart
  21. 3 3
      UI/CF.APP/chicken_farm/lib/stores/auth_store.dart
  22. 4 4
      UI/CF.APP/chicken_farm/lib/stores/menu_store.dart
  23. 0 2
      UI/CF.APP/chicken_farm/macos/Flutter/GeneratedPluginRegistrant.swift
  24. 1 1
      UI/CF.APP/chicken_farm/pubspec.yaml

+ 7 - 2
UI/CF.APP/chicken_farm/lib/apis/_login.dart

@@ -1,3 +1,4 @@
+import 'package:chicken_farm/core/api/api_option.dart';
 import 'package:chicken_farm/core/api/api_service.dart';
 import 'package:chicken_farm/modes/auth/auth_model.dart';
 import 'package:chicken_farm/modes/auth/login_model.dart';
@@ -11,7 +12,11 @@ class LoginApi {
   LoginApi._internal();
 
   Future<AuthResultModel> login(LoginModel data) async {
-    final result = await ApiService().post('/auth/login', data: data);
+    final result = await ApiService().post(
+      '/auth/login',
+      data: data,
+      apiOption: ApiOption.noAlert(),
+    );
     if (result.success && result.data != null) {
       return AuthResultModel.fromJson(result.data);
     } else {
@@ -41,6 +46,6 @@ class LoginApi {
   }
 
   Future<void> logout() async {
-    ApiService().post('/auth/logout');
+    ApiService().post('/auth/logout', apiOption: ApiOption.noAlert());
   }
 }

+ 2 - 2
UI/CF.APP/chicken_farm/lib/apis/breeding/_query.dart

@@ -14,7 +14,7 @@ class BreedQueryApi {
 
   Future<PageResultModel<BatchModel>> queryPageBatchs(dynamic query) async {
     final result = await ApiService().get(
-      '$apiPrefix/listBatch/${query['keyword']}',
+      '$apiPrefix/listBatch',
       queryParameters: query,
     );
     if (result.success) {
@@ -31,7 +31,7 @@ class BreedQueryApi {
 
   Future<PageResultModel<FamilyModel>> queryPageFamilys(dynamic query) async {
     final result = await ApiService().get(
-      '$apiPrefix/listFamily/${query['keyword']}',
+      '$apiPrefix/listFamily',
       queryParameters: query,
     );
     if (result.success) {

+ 4 - 6
UI/CF.APP/chicken_farm/lib/apis/breeding/_submit.dart

@@ -17,7 +17,7 @@ class BreedSubmitApi {
 
   final String bindChickenUrl = '$apiPrefix/batchAddChicken';
   final String cageChangeUrl = '$apiPrefix/batchChangeCage';
-  final String weightUrl = '$apiPrefix/chickenWeight';
+  final String weightUrl = '$apiPrefix/batchChickenWeight';
   final String cullUrl = '$apiPrefix/batchCullChicken';
 
   Future<ResultModel> bindChicken(dynamic data) async {
@@ -97,20 +97,18 @@ class BreedSubmitApi {
         'recordDate': data['date'],
         'isExport': 0,
       };
+      List<Map<String, dynamic>> list = [weightData].toList();
       ResultModel result = ResultModel.offline();
       if (!AppConfig.isOffline &&
           await _breedingDataService.queryCount(TableConfig.chicken) == 0) {
         result = await ApiService().post(
           weightUrl,
-          data: weightData,
+          data: list,
           apiOption: ApiOption.noAlert(),
         );
       }
       if (result.isOffline == true || result.isNetError == true) {
-        return await _breedingDataService.insert(
-          TableConfig.weight,
-          weightData,
-        );
+        return await _breedingDataService.batchInsert(TableConfig.weight, list);
       } else {
         return result;
       }

+ 13 - 7
UI/CF.APP/chicken_farm/lib/components/vb_search_select.dart

@@ -206,7 +206,10 @@ class _VberSearchSelectState<T> extends State<VberSearchSelect<T>> {
       dropdownItems.add(
         DropdownMenuItem<String>(
           value: _selectedOption!.value,
-          child: Text(_selectedOption!.label),
+          child: Text(
+            _selectedOption!.label,
+            style: TextStyle(color: Colors.black),
+          ),
         ),
       );
     }
@@ -313,7 +316,7 @@ class _SearchDialogState<T> extends State<_SearchDialog<T>> {
     // WidgetsBinding.instance.addPostFrameCallback((_) {
     //   widget.searchFocusNode.requestFocus();
     // });
-    
+
     _scrollController.addListener(_scrollListener);
   }
 
@@ -408,9 +411,7 @@ class _SearchDialogState<T> extends State<_SearchDialog<T>> {
       'pageNum': pageNum,
     };
 
-    if (keyword != null && keyword.isNotEmpty) {
-      queryParams['keyword'] = keyword;
-    }
+    queryParams['keyword'] = keyword ?? "";
 
     if (widget.extraParams != null) {
       queryParams.addAll(widget.extraParams!);
@@ -441,7 +442,7 @@ class _SearchDialogState<T> extends State<_SearchDialog<T>> {
     return AlertDialog(
       title: Text('查询${widget.hint ?? ""}'),
       content: SizedBox(
-        width: MediaQuery.of(context).size.width * 0.8,
+        width: MediaQuery.of(context).size.width * 0.9,
         height: MediaQuery.of(context).size.height * 0.6,
         child: Column(
           children: [
@@ -492,7 +493,12 @@ class _SearchDialogState<T> extends State<_SearchDialog<T>> {
                       if (index == _items.length) {
                         // 显示加载更多指示器
                         return Padding(
-                          padding: const EdgeInsets.all(12.0),
+                          padding: const EdgeInsets.fromLTRB(
+                            5.0,
+                            5.0,
+                            5.0,
+                            5.0,
+                          ),
                           child: Center(
                             child: _isLoading
                                 ? CircularProgressIndicator()

+ 15 - 9
UI/CF.APP/chicken_farm/lib/core/db/sqlite_manager.dart

@@ -4,10 +4,9 @@ import 'package:chicken_farm/core/db/table_config.dart';
 import 'package:chicken_farm/core/utils/datetime_util.dart';
 import 'package:chicken_farm/core/utils/logger.dart';
 import 'package:path/path.dart';
-import 'package:sqflite/sqflite.dart';
 import 'package:path_provider/path_provider.dart';
 
-// 为桌面平台添加 ffi 支持
+// 为所有平台添加 ffi 支持
 import 'package:sqflite_common_ffi/sqflite_ffi.dart';
 
 class SqliteManager {
@@ -31,13 +30,11 @@ class SqliteManager {
   /// [dbName] 数据库名称
   /// [version] 数据库版本(默认1)
   Future<void> init({required String dbName, int version = 1}) async {
-    // 在桌面平台上初始化 ffi 数据库工厂
-    if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
-      // 初始化 FFI 数据库工厂
-      sqfliteFfiInit();
-      // 设置数据库工厂为 FFI 工厂
-      databaseFactory = databaseFactoryFfi;
-    }
+    // 在所有平台上初始化 ffi 数据库工厂
+    // 初始化 FFI 数据库工厂
+    sqfliteFfiInit();
+    // 设置数据库工厂为 FFI 工厂
+    databaseFactory = databaseFactoryFfi;
 
     _dbName = dbName;
     _dbVersion = version;
@@ -78,6 +75,15 @@ class SqliteManager {
         logger.d('已创建 db 文件夹:$dbFolderPath');
       }
     } else if (Platform.isIOS) {
+      // iOS 使用文档目录
+      Directory documentsDir = await getApplicationDocumentsDirectory();
+      dbFolderPath = join(documentsDir.path, 'db');
+      // 检查并创建 db 文件夹(不存在则创建)
+      Directory dbFolder = Directory(dbFolderPath);
+      if (!await dbFolder.exists()) {
+        await dbFolder.create(recursive: true);
+        logger.d('已创建 db 文件夹:$dbFolderPath');
+      }
     } else if (Platform.isMacOS || Platform.isLinux) {
       // macOS 和 Linux 使用文档目录
       Directory documentsDir = await getApplicationDocumentsDirectory();

+ 4 - 5
UI/CF.APP/chicken_farm/lib/core/permissions/permission_keys.dart

@@ -1,11 +1,10 @@
 // 权限标识
 class PermissionKeys {
   // 养殖相关权限
-  static const String bindChicken = 'breeding:bind:chicken';
-  static const String cageChange = 'breeding:cage:change';
-  static const String individualWeighing = 'breeding:individual:weighing';
-  static const String individualCulling = 'breeding:individual:culling';
-  static const String batchCulling = 'breeding:batch:culling';
+  static const String bindChicken = 'app:breeding:addChicken';
+  static const String cageChange = 'app:breeding:changeCage';
+  static const String chickenWeighing = 'app:breeding:chickenWeight';
+  static const String chickenCulling = 'app:breeding:cullChicken';
 
   // 实验相关权限
   static const String sampleQuery = 'experiment:sample:query';

+ 62 - 41
UI/CF.APP/chicken_farm/lib/core/utils/toast.dart

@@ -1,4 +1,5 @@
 import 'package:chicken_farm/core/services/navigation_service.dart';
+import 'package:chicken_farm/core/utils/logger.dart';
 import 'package:flutter/material.dart';
 
 class ToastUtil {
@@ -27,51 +28,65 @@ class ToastUtil {
     String message, {
     Color? bgColor = Colors.lightBlue,
     double duration = 2.0,
-    String position = "center",
+    String position = "bottom",
     Color? textColor = Colors.white,
     double? fontSize = 16.0,
   }) {
     final BuildContext? context = NavigationService.navigatorKey.currentContext;
     if (context == null) return;
-
-    // 确保在WidgetsBinding.instance调度器中执行
-    WidgetsBinding.instance.addPostFrameCallback((_) {
-      final scaffoldMessenger = ScaffoldMessenger.of(context);
-
-      // 先清除之前的snackbars
-      scaffoldMessenger.clearSnackBars();
-
-      // 计算显示时长
-      final Duration displayDuration = Duration(
-        milliseconds: (duration * 1000).toInt(),
-      );
-      bool isBottomPosition = position == "bottom";
-      bool isCenterPosition = !isBottomPosition;
-
-      // 显示新的snackbar
-      scaffoldMessenger.showSnackBar(
-        SnackBar(
-          content: Text(
-            message,
-            textAlign: isCenterPosition ? TextAlign.center : TextAlign.left,
-            style: TextStyle(color: textColor, fontSize: fontSize),
-          ),
-          backgroundColor: bgColor,
-          duration: displayDuration,
-          behavior: isCenterPosition
-              ? SnackBarBehavior.floating
-              : SnackBarBehavior.fixed,
-          shape: isCenterPosition
-              ? RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))
-              : null,
-          margin: isCenterPosition
-              ? _calculateCenterMargin(message, textColor, fontSize, context)
-              : null,
-          padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
-          showCloseIcon: duration == 0,
-        ),
-      );
-    });
+    try {
+      // 确保在WidgetsBinding.instance调度器中执行
+      WidgetsBinding.instance.addPostFrameCallback((_) {
+        try {
+          final scaffoldMessenger = ScaffoldMessenger.of(context);
+          // 先清除之前的snackbars
+          scaffoldMessenger.clearSnackBars();
+          // 计算显示时长
+          final Duration displayDuration = Duration(
+            milliseconds: (duration * 1000).toInt(),
+          );
+          bool isBottomPosition = position == "bottom";
+          bool isCenterPosition = !isBottomPosition;
+          // 显示新的snackbar
+          scaffoldMessenger.showSnackBar(
+            SnackBar(
+              content: Text(
+                message,
+                textAlign: isCenterPosition ? TextAlign.center : TextAlign.left,
+                style: TextStyle(color: textColor, fontSize: fontSize),
+              ),
+              backgroundColor: bgColor,
+              duration: displayDuration,
+              behavior: isCenterPosition
+                  ? SnackBarBehavior.floating
+                  : SnackBarBehavior.fixed,
+              shape: isCenterPosition
+                  ? RoundedRectangleBorder(
+                      borderRadius: BorderRadius.circular(10),
+                    )
+                  : null,
+              margin: isCenterPosition
+                  ? _calculateCenterMargin(
+                      message,
+                      textColor,
+                      fontSize,
+                      context,
+                    )
+                  : null,
+              padding: const EdgeInsets.symmetric(
+                horizontal: 16.0,
+                vertical: 12.0,
+              ),
+              showCloseIcon: duration == 0,
+            ),
+          );
+        } catch (e) {
+          logger.e("弹窗出错=>", e);
+        }
+      });
+    } catch (e) {
+      logger.e("弹窗出错:", e);
+    }
   }
 
   /// 计算center位置的margin
@@ -97,9 +112,15 @@ class ToastUtil {
     final screenWidth = MediaQuery.of(context).size.width;
     final horizontalMargin = (screenWidth - actualWidth) / 2;
 
+    // 结合viewInsets来计算垂直边距,考虑键盘等影响因素
+    final mediaQueryData = MediaQuery.of(context);
+    final screenHeight = mediaQueryData.size.height;
+    final viewInsets = mediaQueryData.viewInsets;
+    final verticalMargin = (screenHeight - viewInsets.bottom) * 0.4;
+
     return EdgeInsets.symmetric(
       horizontal: horizontalMargin > 0 ? horizontalMargin : 20,
-      vertical: MediaQuery.of(context).size.height * 0.4,
+      vertical: verticalMargin > 0 ? verticalMargin : 20,
     );
   }
 

+ 1 - 1
UI/CF.APP/chicken_farm/lib/modes/breeding/family.dart

@@ -10,7 +10,7 @@ class FamilyModel {
   String? maleBatchNum;
   int? femaleChickenId;
   String? femaleBatchNum;
-  int? breedDate;
+  String? breedDate;
   int? status;
 
   FamilyModel({

+ 1 - 1
UI/CF.APP/chicken_farm/lib/modes/breeding/family.g.dart

@@ -13,7 +13,7 @@ FamilyModel _$FamilyModelFromJson(Map<String, dynamic> json) => FamilyModel(
   maleBatchNum: json['maleBatchNum'] as String?,
   femaleChickenId: (json['femaleChickenId'] as num?)?.toInt(),
   femaleBatchNum: json['femaleBatchNum'] as String?,
-  breedDate: (json['breedDate'] as num?)?.toInt(),
+  breedDate: json['breedDate'] as String?,
   status: (json['status'] as num?)?.toInt(),
 );
 

+ 6 - 2
UI/CF.APP/chicken_farm/lib/pages/account/login_page.dart

@@ -98,7 +98,8 @@ class _LoginPageState extends ConsumerState<LoginPage> {
                                 filled: true,
                                 fillColor: Colors.grey[50],
                               ),
-                              validator: (v) => v!.length < 6 ? '密码不能少于6位' : null,
+                              validator: (v) =>
+                                  v!.length < 6 ? '密码不能少于6位' : null,
                             ),
                             const SizedBox(height: 24),
                             SizedBox(
@@ -109,6 +110,9 @@ class _LoginPageState extends ConsumerState<LoginPage> {
                                     ? null
                                     : () {
                                         if (_formKey.currentState!.validate()) {
+                                          // 关闭当前焦点上的键盘
+                                          FocusManager.instance.primaryFocus
+                                              ?.unfocus();
                                           authStore
                                               .login(
                                                 LoginModel(
@@ -188,4 +192,4 @@ class _LoginPageState extends ConsumerState<LoginPage> {
       ),
     );
   }
-}
+}

+ 9 - 25
UI/CF.APP/chicken_farm/lib/pages/breeding/batch_create_page.dart

@@ -209,7 +209,7 @@ class _BatchCreatePageState extends State<BatchCreatePage> {
             },
             converter: (BatchModel data) {
               return SelectOption(
-                label: '${data.batchNum}(${data.batchName})',
+                label: '批次号:${data.batchNum}',
                 value: data.batchNum,
                 extra: data,
               );
@@ -222,12 +222,6 @@ class _BatchCreatePageState extends State<BatchCreatePage> {
                 // 当切换批次时,重置后续选项和数据
                 _familyNum = null;
               });
-
-              // // 获取翅号数据
-              // if (value != null) {
-              //   // 使用Future.microtask确保在下一个微任务中加载数据,避免在构建过程中修改状态
-              //   Future.microtask(() => _loadWingTags(value));
-              // }
             },
             hideUnderline: true,
           ),
@@ -237,6 +231,8 @@ class _BatchCreatePageState extends State<BatchCreatePage> {
   }
 
   Widget _buildFamilySearchSelect() {
+    final bool isFamilySelectEnabled = _batchNum != null;
+
     return Column(
       crossAxisAlignment: CrossAxisAlignment.start,
       children: [
@@ -250,6 +246,7 @@ class _BatchCreatePageState extends State<BatchCreatePage> {
           ),
           child: VberSearchSelect<FamilyModel>(
             searchApi: ({required dynamic queryParams}) async {
+              queryParams['batchNum'] = _batchNum;
               final result = await apis.breeding.queryApi.queryPageFamilys(
                 queryParams,
               );
@@ -257,13 +254,14 @@ class _BatchCreatePageState extends State<BatchCreatePage> {
             },
             converter: (FamilyModel data) {
               return SelectOption(
-                label: data.familyNum,
-                value: data.id.toString(),
+                label: '家系号:${data.familyNum}',
+                value: data.familyNum,
                 extra: data,
               );
             },
             value: _familyNum,
             hint: '家系号',
+            enabled: isFamilySelectEnabled,
             onChanged: (String? value) {
               setState(() {
                 _familyNum = value;
@@ -350,29 +348,15 @@ class _BatchCreatePageState extends State<BatchCreatePage> {
     };
     apis.breeding.submitApi.bindChicken(data).then((res) {
       if (res.success) {
-        if (res.message.isNotEmpty) {
-          ToastUtil.success(res.message);
-        }
+        ToastUtil.success(res.message.isEmpty ? '批量绑定个体成功' : res.message);
         if (mounted) {
-          ScaffoldMessenger.of(context).showSnackBar(
-            const SnackBar(
-              content: Text('批量绑定个体成功'),
-              backgroundColor: Colors.green,
-            ),
-          );
           // 提交后重置表单
           setState(() {
             _electronicIds.clear();
           });
         }
       } else {
-        ToastUtil.error('批量绑定个体失败');
-        if (mounted && res.message.isNotEmpty) {
-          logger.e(res.message);
-          ScaffoldMessenger.of(context).showSnackBar(
-            SnackBar(content: Text(res.message), backgroundColor: Colors.red),
-          );
-        }
+        ToastUtil.errorAlert(res.message.isNotEmpty ? res.message : '批量绑定个体失败');
       }
     });
   }

+ 2 - 13
UI/CF.APP/chicken_farm/lib/pages/breeding/batch_create_page_win.dart

@@ -238,14 +238,9 @@ class _BatchCreatePageWinState extends State<BatchCreatePageWin> {
         'date': DateTimeUtil.format(DateTime.now()),
       };
     }).toList();
-    apis.breeding.submitApi.bindChicken(data);
-    apis.breeding.submitApi.bindChicken(data);
-    apis.breeding.submitApi.bindChicken(data);
     apis.breeding.submitApi.bindChicken(data).then((res) {
       if (res.success) {
-        if (res.message.isNotEmpty) {
-          ToastUtil.success(res.message);
-        }
+        ToastUtil.success(res.message.isEmpty ? '批量绑定个体成功' : res.message);
         if (mounted) {
           ScaffoldMessenger.of(context).showSnackBar(
             const SnackBar(
@@ -259,13 +254,7 @@ class _BatchCreatePageWinState extends State<BatchCreatePageWin> {
           });
         }
       } else {
-        ToastUtil.error('批量绑定个体失败');
-        if (mounted && res.message.isNotEmpty) {
-          logger.e(res.message);
-          ScaffoldMessenger.of(context).showSnackBar(
-            SnackBar(content: Text(res.message), backgroundColor: Colors.red),
-          );
-        }
+        ToastUtil.errorAlert(res.message.isNotEmpty ? res.message : '批量绑定个体失败');
       }
     });
   }

+ 2 - 16
UI/CF.APP/chicken_farm/lib/pages/breeding/batch_culling_page.dart

@@ -238,16 +238,8 @@ class _BatchCullingPageState extends State<BatchCullingPage> {
     };
     apis.breeding.submitApi.weight(data).then((res) {
       if (res.success) {
-        if (res.message.isNotEmpty) {
-          ToastUtil.success(res.message);
-        }
+        ToastUtil.success(res.message.isNotEmpty ? res.message : '批量淘汰提交成功');
         if (mounted) {
-          ScaffoldMessenger.of(context).showSnackBar(
-            const SnackBar(
-              content: Text('批量淘汰提交成功'),
-              backgroundColor: Colors.green,
-            ),
-          );
           // 提交后重置表单
           setState(() {
             _electronicIds.clear();
@@ -256,13 +248,7 @@ class _BatchCullingPageState extends State<BatchCullingPage> {
           });
         }
       } else {
-        ToastUtil.error('批量淘汰提交失败');
-        if (mounted && res.message.isNotEmpty) {
-          logger.e(res.message);
-          ScaffoldMessenger.of(context).showSnackBar(
-            SnackBar(content: Text(res.message), backgroundColor: Colors.red),
-          );
-        }
+        ToastUtil.errorAlert(res.message.isNotEmpty ? res.message : '批量淘汰提交失败');
       }
     });
   }

+ 2 - 18
UI/CF.APP/chicken_farm/lib/pages/breeding/batch_culling_page_win.dart

@@ -209,31 +209,15 @@ class _BatchCullingPageWinState extends State<BatchCullingPageWin> {
     };
     apis.breeding.submitApi.weight(data).then((res) {
       if (res.success) {
-        if (res.message.isNotEmpty) {
-          ToastUtil.success(res.message);
-        }
+        ToastUtil.success(res.message.isNotEmpty ? res.message : '批量淘汰提交成功');
         if (mounted) {
-          ScaffoldMessenger.of(context).showSnackBar(
-            const SnackBar(
-              content: Text('批量淘汰提交成功'),
-              backgroundColor: Colors.green,
-            ),
-          );
           // 提交后重置表单
           setState(() {
             _electronicIds.clear();
-            // _cullReason = null;
-            // _disposalMethod = null;
           });
         }
       } else {
-        ToastUtil.error('批量淘汰提交失败');
-        if (mounted && res.message.isNotEmpty) {
-          logger.e(res.message);
-          ScaffoldMessenger.of(context).showSnackBar(
-            SnackBar(content: Text(res.message), backgroundColor: Colors.red),
-          );
-        }
+        ToastUtil.errorAlert(res.message.isNotEmpty ? res.message : '批量淘汰提交失败');
       }
     });
   }

+ 2 - 172
UI/CF.APP/chicken_farm/lib/pages/breeding/cage_change_page.dart

@@ -18,43 +18,17 @@ class CageChangePage extends StatefulWidget {
 class _CageChangePageState extends State<CageChangePage> {
   final List<String> _electronicIds = [];
 
-  // 添加TextEditingControllers用于控制输入框
-  // final TextEditingController _sourceCageController = TextEditingController();
-  // final TextEditingController _targetCageController = TextEditingController();
   final TextEditingController _cageController = TextEditingController();
 
-  // 添加FocusNode用于控制焦点
-  // final FocusNode _sourceCageFocusNode = FocusNode();
-  // final FocusNode _targetCageFocusNode = FocusNode();
-
-  // 扫描状态
-  // bool _isScanningSource = false;
-  // bool _isScanningTarget = false;
-  // int _scanTag = 1;
   bool _isScanningCode = false;
 
   @override
   void initState() {
     super.initState();
 
-    // _sourceCageController.clear();
-    // _targetCageController.clear();
-    // 监听焦点变化以更新_scanTag值
-    // _sourceCageFocusNode.addListener(() {
-    //   if (_sourceCageFocusNode.hasFocus) {
-    //     _scanTag = 1;
-    //   }
-    // });
-
-    // _targetCageFocusNode.addListener(() {
-    //   if (_targetCageFocusNode.hasFocus) {
-    //     _scanTag = 2;
-    //   }
-    // });
     _isScanningCode = false;
     _cageController.clear();
 
-    // 延迟到下一帧执行,确保页面构建完成后再打开扫描头
     WidgetsBinding.instance.addPostFrameCallback((_) {
       ScanChannel.openScanHead().then((success) {
         if (success) {
@@ -123,8 +97,6 @@ class _CageChangePageState extends State<CageChangePage> {
         },
       );
     });
-
-    // _scanTag = 1;
   }
 
   @override
@@ -270,94 +242,6 @@ class _CageChangePageState extends State<CageChangePage> {
     );
   }
 
-  // Widget _buildCageSection(int tag) {
-  //   String title = '源笼号';
-  //   TextEditingController controller = _sourceCageController;
-  //   FocusNode focusNode = _sourceCageFocusNode;
-  //   bool isScanning = _isScanningSource;
-  //   if (tag != 1) {
-  //     tag = 2;
-  //     title = '目标笼号';
-  //     controller = _targetCageController;
-  //     focusNode = _targetCageFocusNode;
-  //     isScanning = _isScanningTarget;
-  //   }
-  //   // 确保光标在文本末尾
-  //   if (controller.text.isNotEmpty) {
-  //     controller.selection = TextSelection.fromPosition(
-  //       TextPosition(offset: controller.text.length),
-  //     );
-  //   }
-  //   return Column(
-  //     crossAxisAlignment: CrossAxisAlignment.start,
-  //     children: [
-  //       Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),
-  //       const SizedBox(height: 10),
-  //       Container(
-  //         padding: const EdgeInsets.fromLTRB(16, 2, 16, 2),
-  //         decoration: BoxDecoration(
-  //           border: Border.all(color: Colors.grey),
-  //           borderRadius: BorderRadius.circular(8),
-  //         ),
-  //         child: Row(
-  //           children: [
-  //             Expanded(
-  //               // 将Text替换为TextField
-  //               child: TextField(
-  //                 focusNode: focusNode,
-  //                 controller: controller,
-  //                 enabled: controller.text.isEmpty,
-  //                 decoration: InputDecoration(
-  //                   border: InputBorder.none,
-  //                   hintText: controller.text.isNotEmpty ? null : '未扫描',
-  //                   hintStyle: TextStyle(
-  //                     color: controller.text.isNotEmpty
-  //                         ? Colors.black
-  //                         : Colors.grey,
-  //                     fontSize: 16,
-  //                   ),
-  //                 ),
-  //                 style: TextStyle(
-  //                   color: controller.text.isNotEmpty
-  //                       ? Colors.black
-  //                       : Colors.grey,
-  //                   fontSize: 16,
-  //                 ),
-  //                 onChanged: (text) {
-  //                   setState(() {
-  //                     // 文本更改由controller自动处理
-  //                   });
-  //                 },
-  //               ),
-  //             ),
-  //             if (controller.text.isNotEmpty) ...[
-  //               IconButton(
-  //                 icon: const Icon(Icons.refresh, size: 20),
-  //                 onPressed: () {
-  //                   _handleChangeCageCode(tag);
-  //                 },
-  //               ),
-  //             ] else ...[
-  //               IconButton(
-  //                 icon: isScanning
-  //                     ? const SizedBox(
-  //                         width: 20,
-  //                         height: 20,
-  //                         child: CircularProgressIndicator(strokeWidth: 2),
-  //                       )
-  //                     : const Icon(Icons.qr_code_scanner, size: 20),
-  //                 onPressed: () {
-  //                   _handleScanCageCode(tag);
-  //                 },
-  //               ),
-  //             ],
-  //           ],
-  //         ),
-  //       ),
-  //     ],
-  //   );
-  // }
-
   Widget _buildCageSection() {
     // 确保光标在文本末尾
     if (_cageController.text.isNotEmpty) {
@@ -469,45 +353,6 @@ class _CageChangePageState extends State<CageChangePage> {
     );
   }
 
-  // void _dealyScanCode(int scanTag, {int? dealy}) async {
-  //   dealy ??= 800;
-  //   _scanTag = scanTag;
-  //   logger.d("开始扫码: $_scanTag");
-  //   await Future.delayed(Duration(milliseconds: dealy));
-  //   bool success = await ScanChannel.startScan();
-  //   if (!success) {
-  //     ToastUtil.error("扫码失败");
-  //   }
-  // }
-
-  // void _handleScanCageCode(int tag) async {
-  //   if (_isScanningTarget || _isScanningSource) return;
-  //   setState(() {
-  //     if (tag == 1) {
-  //       _isScanningSource = true;
-  //     } else if (tag == 2) {
-  //       _isScanningTarget = true;
-  //     }
-  //   });
-  //   _scanTag = tag;
-  //   logger.d("开始扫码: $_scanTag");
-  //   bool success = await ScanChannel.startScan();
-  //   if (!success) {
-  //     ToastUtil.error("扫码失败");
-  //   }
-  // }
-
-  // void _handleChangeCageCode(int tag) {
-  //   setState(() {
-  //     if (tag == 1) {
-  //       _sourceCageController.clear();
-  //     } else {
-  //       _targetCageController.clear();
-  //     }
-  //   });
-  //   _dealyScanCode(tag);
-  // }
-
   void _handleScanCageCode() async {
     if (_isScanningCode) return;
     setState(() {
@@ -568,31 +413,16 @@ class _CageChangePageState extends State<CageChangePage> {
     apis.breeding.submitApi.cageChange(data).then((res) {
       if (res.success) {
         if (res.message.isNotEmpty) {
-          ToastUtil.success(res.message);
+          ToastUtil.success(res.message.isEmpty ? '换笼成功' : res.message);
         }
         if (mounted) {
-          ScaffoldMessenger.of(context).showSnackBar(
-            const SnackBar(
-              content: Text('换笼提交成功'),
-              backgroundColor: Colors.green,
-            ),
-          );
           // 提交后重置表单
           setState(() {
-            // _sourceCageController.clear();
-            // _targetCageController.clear();
-            _cageController.clear();
             _electronicIds.clear();
           });
         }
       } else {
-        ToastUtil.error('换笼提交失败');
-        if (mounted && res.message.isNotEmpty) {
-          logger.e(res.message);
-          ScaffoldMessenger.of(context).showSnackBar(
-            SnackBar(content: Text(res.message), backgroundColor: Colors.red),
-          );
-        }
+        ToastUtil.errorAlert(res.message.isEmpty ? '换笼提交失败' : res.message);
       }
     });
   }

+ 2 - 16
UI/CF.APP/chicken_farm/lib/pages/breeding/individual_culling_page.dart

@@ -160,16 +160,8 @@ class _IndividualCullingPageState extends State<IndividualCullingPage> {
     };
     apis.breeding.submitApi.cull(data).then((res) {
       if (res.success) {
-        if (res.message.isNotEmpty) {
-          ToastUtil.success(res.message);
-        }
+        ToastUtil.success(res.message.isNotEmpty ? res.message : '淘汰提交成功');
         if (mounted) {
-          ScaffoldMessenger.of(context).showSnackBar(
-            const SnackBar(
-              content: Text('淘汰提交成功'),
-              backgroundColor: Colors.green,
-            ),
-          );
           // 提交后重置表单
           setState(() {
             _electronicId = null;
@@ -178,13 +170,7 @@ class _IndividualCullingPageState extends State<IndividualCullingPage> {
           });
         }
       } else {
-        ToastUtil.error('淘汰提交失败');
-        if (mounted && res.message.isNotEmpty) {
-          logger.e(res.message);
-          ScaffoldMessenger.of(context).showSnackBar(
-            SnackBar(content: Text(res.message), backgroundColor: Colors.red),
-          );
-        }
+        ToastUtil.errorAlert(res.message.isNotEmpty ? res.message : '淘汰提交失败');
       }
     });
   }

+ 4 - 17
UI/CF.APP/chicken_farm/lib/pages/breeding/individual_weighing_page.dart

@@ -128,6 +128,8 @@ class _IndividualWeighingPageState extends State<IndividualWeighingPage> {
                   focusNode: _weightFocusNode,
                   controller: _weightController,
                   enabled: _weight == null,
+                  // 修改键盘类型为none以防止键盘弹出,同时保持可编辑性
+                  keyboardType: TextInputType.none,
                   decoration: InputDecoration(
                     border: InputBorder.none,
                     hintText: _weight != null
@@ -148,7 +150,6 @@ class _IndividualWeighingPageState extends State<IndividualWeighingPage> {
                     color: _weight != null ? Colors.black : Colors.grey,
                     fontSize: 16,
                   ),
-                  keyboardType: TextInputType.numberWithOptions(decimal: true),
                   onChanged: (text) {
                     // 取消之前的定时器
                     _inputDebounceTimer?.cancel();
@@ -245,16 +246,8 @@ class _IndividualWeighingPageState extends State<IndividualWeighingPage> {
     };
     apis.breeding.submitApi.weight(data).then((res) {
       if (res.success) {
-        if (res.message.isNotEmpty) {
-          ToastUtil.success(res.message);
-        }
+        ToastUtil.success(res.message.isNotEmpty ? res.message : '称重提交成功');
         if (mounted) {
-          ScaffoldMessenger.of(context).showSnackBar(
-            const SnackBar(
-              content: Text('称重提交成功'),
-              backgroundColor: Colors.green,
-            ),
-          );
           // 提交后重置表单
           setState(() {
             _electronicId = null;
@@ -263,13 +256,7 @@ class _IndividualWeighingPageState extends State<IndividualWeighingPage> {
           });
         }
       } else {
-        ToastUtil.error('称重提交失败');
-        if (mounted && res.message.isNotEmpty) {
-          logger.e(res.message);
-          ScaffoldMessenger.of(context).showSnackBar(
-            SnackBar(content: Text(res.message), backgroundColor: Colors.red),
-          );
-        }
+        ToastUtil.errorAlert(res.message.isNotEmpty ? res.message : '称重提交失败');
       }
     });
   }

+ 0 - 1
UI/CF.APP/chicken_farm/lib/pages/home/home_page.dart

@@ -1,7 +1,6 @@
 import 'package:chicken_farm/components/vb_app_bar.dart';
 import 'package:chicken_farm/core/config/app_config.dart';
 import 'package:chicken_farm/core/services/breeding_data_service.dart';
-import 'package:chicken_farm/core/services/offline_storage_service.dart';
 import 'package:chicken_farm/core/utils/logger.dart';
 import 'package:chicken_farm/core/utils/service_checker.dart';
 import 'package:chicken_farm/core/utils/toast.dart';

+ 30 - 28
UI/CF.APP/chicken_farm/lib/pages/home/profile.dart

@@ -67,37 +67,39 @@ class ProfilePage extends ConsumerWidget {
               crossAxisAlignment: CrossAxisAlignment.center,
               mainAxisAlignment: MainAxisAlignment.center,
               children: [
-                if (AppConfig.isOffline) ...[
-                  GestureDetector(
-                    onTap: handleUserCardTap,
-                    child: UserInfoCard(user: authState.user!),
-                  ),
-                  const SizedBox(height: 20),
-                  if (showDictConfig) ...[
-                    const DictConfigButton(),
+                if (authState.state == AuthState.authenticated) ...[
+                  if (AppConfig.isOffline) ...[
+                    GestureDetector(
+                      onTap: handleUserCardTap,
+                      child: UserInfoCard(user: authState.user!),
+                    ),
                     const SizedBox(height: 20),
-                  ],
-                  const ClearCacheButton(),
-                  const SizedBox(height: 20),
-                  const ExportDataButton(),
-                  const SizedBox(height: 20),
-                ] else ...[
-                  UserInfoCard(user: authState.user!),
-                  const SizedBox(height: 20),
-                  if (AppConfig.isPda) ...[
-                    const UploadDataButton(),
+                    if (showDictConfig) ...[
+                      const DictConfigButton(),
+                      const SizedBox(height: 20),
+                    ],
+                    const ClearCacheButton(),
+                    const SizedBox(height: 20),
+                    const ExportDataButton(),
+                    const SizedBox(height: 20),
+                  ] else ...[
+                    UserInfoCard(user: authState.user!),
+                    const SizedBox(height: 20),
+                    if (AppConfig.isPda) ...[
+                      const UploadDataButton(),
+                      const SizedBox(height: 20),
+                    ],
+                    const ClearCacheButton(),
+                    const SizedBox(height: 20),
+                    const ConfigButton(),
+                    const SizedBox(height: 20),
+                    // const RfidConfigButton(),
+                    // const SizedBox(height: 20),
+                    // const ScannerLightButton(),
+                    // const SizedBox(height: 20),
+                    const LogoutButton(),
                     const SizedBox(height: 20),
                   ],
-                  const ClearCacheButton(),
-                  const SizedBox(height: 20),
-                  const ConfigButton(),
-                  const SizedBox(height: 20),
-                  // const RfidConfigButton(),
-                  // const SizedBox(height: 20),
-                  // const ScannerLightButton(),
-                  // const SizedBox(height: 20),
-                  const LogoutButton(),
-                  const SizedBox(height: 20),
                 ],
               ],
             ),

+ 2 - 0
UI/CF.APP/chicken_farm/lib/pages/serial/serial_setting_page.dart

@@ -1,3 +1,5 @@
+// ignore_for_file: unused_import, unused_field, prefer_final_fields
+
 import 'dart:typed_data';
 import 'package:chicken_farm/components/vb_app_bar.dart';
 import 'package:chicken_farm/core/utils/toast.dart';

+ 3 - 3
UI/CF.APP/chicken_farm/lib/stores/auth_store.dart

@@ -104,9 +104,9 @@ class AuthStore extends StateNotifier<AuthInfo> {
         final breedingPermissions = [
           PermissionKeys.bindChicken,
           PermissionKeys.cageChange,
-          PermissionKeys.individualWeighing,
-          PermissionKeys.individualCulling,
-          PermissionKeys.batchCulling,
+          PermissionKeys.chickenWeighing,
+          PermissionKeys.chickenCulling,
+          PermissionKeys.chickenCulling,
         ];
 
         state = AuthInfo.authenticated(

+ 4 - 4
UI/CF.APP/chicken_farm/lib/stores/menu_store.dart

@@ -28,21 +28,21 @@ class MenuStore {
       name: '个体称重',
       routeName: AppRouteNames.individualWeighing,
       icon: Icons.scale,
-      permission: PermissionKeys.individualWeighing,
+      permission: PermissionKeys.chickenWeighing,
       platform: 1,
     ),
     MenuItem(
       name: '个体淘汰',
       routeName: AppRouteNames.individualCulling,
       icon: Icons.person_remove,
-      permission: PermissionKeys.individualCulling,
+      permission: PermissionKeys.chickenCulling,
       platform: 1,
     ),
     MenuItem(
       name: '批量淘汰',
       routeName: AppRouteNames.batchCulling,
       icon: Icons.group_remove,
-      permission: PermissionKeys.batchCulling,
+      permission: PermissionKeys.chickenCulling,
       platform: 1,
     ),
     MenuItem(
@@ -73,7 +73,7 @@ class MenuStore {
       name: '批量淘汰',
       routeName: AppRouteNames.batchCullingWin,
       icon: Icons.group_remove,
-      permission: PermissionKeys.batchCulling,
+      permission: PermissionKeys.chickenCulling,
       isPda: false,
       platform: 2,
     ),

+ 0 - 2
UI/CF.APP/chicken_farm/macos/Flutter/GeneratedPluginRegistrant.swift

@@ -13,7 +13,6 @@ import flutter_image_compress_macos
 import mobile_scanner
 import path_provider_foundation
 import shared_preferences_foundation
-import sqflite_darwin
 
 func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
   AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
@@ -24,5 +23,4 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
   MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
   PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
   SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
-  SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
 }

+ 1 - 1
UI/CF.APP/chicken_farm/pubspec.yaml

@@ -58,7 +58,6 @@ dependencies:
   flutter_image_compress: ^2.3.0
   connectivity_plus: ^5.0.1
   uuid: ^4.2.1
-  sqflite: ^2.3.0
   path: ^1.8.0
   excel: ^4.0.0
   open_filex: ^4.3.2
@@ -66,6 +65,7 @@ dependencies:
   permission_handler: ^11.3.1
   device_info_plus: ^12.3.0
   media_scanner: ^2.2.0
+  sqflite_common_ffi: ^2.4.0+1
   
 
 dev_dependencies: