Browse Source

Update 优化个人中心页面

Yue 5 days ago
parent
commit
c084aede49

+ 37 - 0
UI/CF.APP/chicken_farm/lib/pages/home/_profile/clear_cache_button.dart

@@ -0,0 +1,37 @@
+import 'package:chicken_farm/core/utils/storage.dart';
+import 'package:chicken_farm/core/utils/toast.dart';
+import 'package:chicken_farm/stores/config_store.dart';
+import 'package:chicken_farm/stores/dict_stroe.dart';
+import 'package:flutter/material.dart';
+
+class ClearCacheButton extends StatelessWidget {
+  const ClearCacheButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return SizedBox(
+      width: double.infinity,
+      child: ElevatedButton.icon(
+        onPressed: () {
+          ToastUtil.confirm('确定要清除所有缓存吗?', () async {
+            await StorageUtils.removeWithPrefix("vb_");
+            ConfigStore().clearAll();
+            DictStore().clearAll();
+            if (context.mounted) {
+              ToastUtil.success('缓存已清除');
+            }
+          });
+        },
+        icon: const Icon(Icons.cleaning_services),
+        label: const Text('清除缓存'),
+        style: ElevatedButton.styleFrom(
+          padding: const EdgeInsets.symmetric(
+            horizontal: 30,
+            vertical: 15,
+          ),
+          textStyle: const TextStyle(fontSize: 16),
+        ),
+      ),
+    );
+  }
+}

+ 35 - 0
UI/CF.APP/chicken_farm/lib/pages/home/_profile/config_button.dart

@@ -0,0 +1,35 @@
+import 'package:chicken_farm/core/utils/toast.dart';
+import 'package:chicken_farm/pages/account/config_dialog.dart';
+import 'package:flutter/material.dart';
+
+class ConfigButton extends StatelessWidget {
+  const ConfigButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return SizedBox(
+      width: double.infinity,
+      child: ElevatedButton.icon(
+        onPressed: () async {
+          final result = await showDialog(
+            context: context,
+            builder: (context) => const ConfigDialog(),
+          );
+          // 如果配置发生了变化,显示提示
+          if (result == true && context.mounted) {
+            ToastUtil.success('配置已保存');
+          }
+        },
+        icon: const Icon(Icons.settings),
+        label: const Text('服务配置'),
+        style: ElevatedButton.styleFrom(
+          padding: const EdgeInsets.symmetric(
+            horizontal: 30,
+            vertical: 15,
+          ),
+          textStyle: const TextStyle(fontSize: 16),
+        ),
+      ),
+    );
+  }
+}

+ 47 - 0
UI/CF.APP/chicken_farm/lib/pages/home/_profile/logout_button.dart

@@ -0,0 +1,47 @@
+import 'package:chicken_farm/core/services/connectivity_service.dart';
+import 'package:chicken_farm/core/utils/toast.dart';
+import 'package:chicken_farm/stores/auth_store.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+
+class LogoutButton extends ConsumerWidget {
+  const LogoutButton({super.key});
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final authStore = ref.read(authStoreProvider.notifier);
+    final isConnectedAsync = ref.watch(isConnectedProvider);
+
+    return SizedBox(
+      width: double.infinity,
+      child: ElevatedButton.icon(
+        onPressed: isConnectedAsync.when(
+          data: (isConnected) {
+            // 在线状态下允许退出登录,离线状态下禁用
+            return isConnected
+                ? () {
+                    ToastUtil.confirm(
+                      '确定要退出登录吗?',
+                      () => authStore.logout(),
+                    );
+                  }
+                : null;
+          },
+          loading: () => null,
+          error: (_, _) => null,
+        ),
+        icon: const Icon(Icons.logout),
+        label: const Text('退出登录'),
+        style: ElevatedButton.styleFrom(
+          // 保持背景色不变,只改变文字颜色为红色
+          foregroundColor: Colors.red,
+          padding: const EdgeInsets.symmetric(
+            horizontal: 30,
+            vertical: 15,
+          ),
+          textStyle: const TextStyle(fontSize: 16),
+        ),
+      ),
+    );
+  }
+}

+ 27 - 0
UI/CF.APP/chicken_farm/lib/pages/home/_profile/rfid_config_button.dart

@@ -0,0 +1,27 @@
+import 'package:flutter/material.dart';
+import 'package:go_router/go_router.dart';
+
+class RfidConfigButton extends StatelessWidget {
+  const RfidConfigButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return SizedBox(
+      width: double.infinity,
+      child: ElevatedButton.icon(
+        onPressed: () {
+          context.push('/rfid-config');
+        },
+        icon: const Icon(Icons.settings_ethernet),
+        label: const Text('RFID参数配置'),
+        style: ElevatedButton.styleFrom(
+          padding: const EdgeInsets.symmetric(
+            horizontal: 30,
+            vertical: 15,
+          ),
+          textStyle: const TextStyle(fontSize: 16),
+        ),
+      ),
+    );
+  }
+}

+ 159 - 0
UI/CF.APP/chicken_farm/lib/pages/home/_profile/rfid_config_page.dart

@@ -0,0 +1,159 @@
+import 'package:flutter/material.dart';
+import 'package:chicken_farm/core/services/pda/rfid_channel.dart';
+
+class RfidConfigPage extends StatefulWidget {
+  const RfidConfigPage({super.key});
+
+  @override
+  State<RfidConfigPage> createState() => _RfidConfigPageState();
+}
+
+class _RfidConfigPageState extends State<RfidConfigPage> {
+  Map<String, dynamic>? _rfidParams;
+  bool _isLoading = true;
+  String? _error;
+
+  @override
+  void initState() {
+    super.initState();
+    _loadRfidParams();
+  }
+
+  Future<void> _loadRfidParams() async {
+    setState(() {
+      _isLoading = true;
+      _error = null;
+    });
+
+    try {
+      // 获取RFID参数
+      final params = await RfidChannel.getReaderParameter();
+      final power = await RfidChannel.getPower();
+      
+      setState(() {
+        _rfidParams = {
+          'power': power,
+          ...params,
+        };
+        _isLoading = false;
+      });
+    } catch (e) {
+      setState(() {
+        _error = e.toString();
+        _isLoading = false;
+      });
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: const Text('RFID参数配置'),
+        actions: [
+          IconButton(
+            icon: const Icon(Icons.refresh),
+            onPressed: _loadRfidParams,
+          ),
+        ],
+      ),
+      body: Padding(
+        padding: const EdgeInsets.all(16.0),
+        child: _isLoading
+            ? const Center(child: CircularProgressIndicator())
+            : _error != null
+                ? Center(
+                    child: Column(
+                      mainAxisAlignment: MainAxisAlignment.center,
+                      children: [
+                        Text('加载失败: $_error'),
+                        const SizedBox(height: 16),
+                        ElevatedButton(
+                          onPressed: _loadRfidParams,
+                          child: const Text('重试'),
+                        ),
+                      ],
+                    ),
+                  )
+                : _rfidParams != null
+                    ? Stack(
+                        children: [
+                          ListView(
+                            padding: const EdgeInsets.only(bottom: 80),
+                            children: [
+                              const Text(
+                                'RFID 参数信息',
+                                style: TextStyle(
+                                  fontSize: 20,
+                                  fontWeight: FontWeight.bold,
+                                ),
+                              ),
+                              const SizedBox(height: 16),
+                              _buildParamField('功率', _rfidParams!['power'].toString()),
+                              _buildParamField('Q值', _rfidParams!['QValue'].toString()),
+                              _buildParamField('会话', _rfidParams!['Session'].toString()),
+                              _buildParamField('扫描时间', _rfidParams!['ScanTime'].toString()),
+                              _buildParamField('TID长度', _rfidParams!['TidLen'].toString()),
+                              _buildParamField('TID指针', _rfidParams!['TidPtr'].toString()),
+                              _buildParamField('ASCII指针', _rfidParams!['AsciiPtr'].toString()),
+                              _buildParamField('间隔时间', _rfidParams!['Interval'].toString()),
+                            ],
+                          ),
+                          Positioned(
+                            bottom: 0,
+                            left: 0,
+                            right: 0,
+                            child: Padding(
+                              padding: const EdgeInsets.all(16.0),
+                              child: SizedBox(
+                                width: double.infinity,
+                                child: ElevatedButton(
+                                  onPressed: () {
+                                    Navigator.of(context).pop();
+                                  },
+                                  style: ElevatedButton.styleFrom(
+                                    backgroundColor: Colors.white,
+                                    foregroundColor: Colors.blue,
+                                    side: const BorderSide(color: Colors.blue),
+                                  ),
+                                  child: const Text('返回'),
+                                ),
+                              ),
+                            ),
+                          ),
+                        ],
+                      )
+                    : const Center(child: Text('暂无参数信息')),
+      ),
+    );
+  }
+
+  Widget _buildParamField(String label, String value) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 8.0),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Text(
+            label,
+            style: const TextStyle(
+              fontWeight: FontWeight.bold,
+              fontSize: 16,
+            ),
+          ),
+          const SizedBox(height: 4),
+          TextField(
+            enabled: false,
+            decoration: InputDecoration(
+              border: const OutlineInputBorder(),
+              hintText: value,
+              filled: true,
+              fillColor: Colors.grey[200],
+            ),
+            controller: TextEditingController(text: value),
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 161 - 0
UI/CF.APP/chicken_farm/lib/pages/home/_profile/scanner_light_button.dart

@@ -0,0 +1,161 @@
+// ignore_for_file: deprecated_member_use
+
+import 'package:chicken_farm/core/services/pda/scan_channel.dart';
+import 'package:chicken_farm/core/utils/storage.dart';
+import 'package:chicken_farm/core/utils/toast.dart';
+import 'package:flutter/material.dart';
+
+class ScannerLightButton extends StatefulWidget {
+  const ScannerLightButton({super.key});
+
+  @override
+  State<ScannerLightButton> createState() => _ScannerLightButtonState();
+}
+
+class _ScannerLightButtonState extends State<ScannerLightButton> {
+  late Future<int> _lightingModeFuture;
+
+  @override
+  void initState() {
+    super.initState();
+    _lightingModeFuture = _getSavedLightingMode();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return FutureBuilder<int>(
+      future: _lightingModeFuture,
+      builder: (context, snapshot) {
+        final mode = snapshot.data ?? 0;
+        return SizedBox(
+          width: double.infinity,
+          child: ElevatedButton.icon(
+            onPressed: () => _showLightingModeDialog(context, mode),
+            icon: const Icon(Icons.lightbulb),
+            label: Text('扫描头灯光(${_getModeText(mode)})'),
+            style: ElevatedButton.styleFrom(
+              padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 15),
+              textStyle: const TextStyle(fontSize: 16),
+            ),
+          ),
+        );
+      },
+    );
+  }
+
+  // 获取保存的灯光模式
+  Future<int> _getSavedLightingMode() async {
+    final modeStr = await StorageUtils.get('scanner_lighting_mode');
+    return modeStr != null ? int.parse(modeStr) : 0;
+  }
+
+  // 获取模式对应的文字描述
+  String _getModeText(int mode) {
+    switch (mode) {
+      case 0:
+        return '关闭';
+      case 1:
+        return '仅瞄准';
+      case 2:
+        return '仅照明';
+      case 3:
+        return '交替';
+      case 4:
+        return '瞄准+照明';
+      default:
+        return '未知';
+    }
+  }
+
+  // 显示灯光模式选择对话框
+  void _showLightingModeDialog(BuildContext context, int currentMode) {
+    int selectedMode = currentMode;
+
+    showDialog(
+      context: context,
+      builder: (BuildContext context) {
+        return StatefulBuilder(
+          builder: (context, setState) {
+            return AlertDialog(
+              title: const Text('选择扫描头灯光模式'),
+              content: SingleChildScrollView(
+                child: Column(
+                  mainAxisSize: MainAxisSize.min,
+                  children: [
+                    for (int i = 0; i <= 4; i++)
+                      RadioListTile<int>(
+                        title: Text(_getModeDescription(i)),
+                        value: i,
+                        groupValue: selectedMode,
+                        onChanged: (value) {
+                          if (value != null) {
+                            setState(() {
+                              selectedMode = value;
+                            });
+                          }
+                        },
+                      ),
+                  ],
+                ),
+              ),
+              actions: [
+                TextButton(
+                  onPressed: () => Navigator.of(context).pop(),
+                  child: const Text('取消'),
+                ),
+                TextButton(
+                  onPressed: () async {
+                    // 保存选择的模式到本地存储
+                    await StorageUtils.set(
+                      'scanner_lighting_mode',
+                      selectedMode.toString(),
+                    );
+
+                    // 设置灯光模式
+                    try {
+                      await ScanChannel.setLightingMode(selectedMode);
+                      if (context.mounted) {
+                        ToastUtil.success(
+                          '灯光模式已设置为${_getModeText(selectedMode)}',
+                        );
+                        Navigator.of(context).pop();
+
+                        // 更新按钮显示
+                        setState(() {
+                          _lightingModeFuture = Future.value(selectedMode);
+                        });
+                      }
+                    } catch (e) {
+                      if (context.mounted) {
+                        ToastUtil.error('设置灯光模式失败: $e');
+                      }
+                    }
+                  },
+                  child: const Text('确定'),
+                ),
+              ],
+            );
+          },
+        );
+      },
+    );
+  }
+
+  // 获取模式描述
+  String _getModeDescription(int mode) {
+    switch (mode) {
+      case 0:
+        return '0 - 关闭';
+      case 1:
+        return '1 - 仅瞄准';
+      case 2:
+        return '2 - 仅照明';
+      case 3:
+        return '3 - 交替';
+      case 4:
+        return '4 - 瞄准+照明';
+      default:
+        return '$mode - 未知';
+    }
+  }
+}

+ 50 - 0
UI/CF.APP/chicken_farm/lib/pages/home/_profile/upload_data_button.dart

@@ -0,0 +1,50 @@
+import 'package:chicken_farm/core/services/offline_storage_service.dart';
+import 'package:chicken_farm/core/services/sync_service.dart';
+import 'package:chicken_farm/core/utils/toast.dart';
+import 'package:flutter/material.dart';
+
+class UploadDataButton extends StatelessWidget {
+  const UploadDataButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return FutureBuilder<List<OfflineOperation>>(
+      future: OfflineStorageService().getPendingOperations(),
+      builder: (context, snapshot) {
+        if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
+          final pendingCount = snapshot.data!.length;
+          return SizedBox(
+            width: double.infinity,
+            child: ElevatedButton.icon(
+              onPressed: pendingCount > 0
+                  ? () async {
+                      ToastUtil.show(
+                        '正在上传 $pendingCount 条数据...',
+                      );
+                      final syncService = SyncService();
+                      await syncService.syncPendingOperations();
+                      ToastUtil.success('数据上传完成');
+                      // 刷新按钮状态
+                      (context as Element).markNeedsBuild();
+                    }
+                  : null, // 禁用按钮
+              icon: const Icon(Icons.upload),
+              label: Text('上传数据 ($pendingCount条待上传)'),
+              style: ElevatedButton.styleFrom(
+                padding: const EdgeInsets.symmetric(
+                  horizontal: 30,
+                  vertical: 15,
+                ),
+                textStyle: const TextStyle(fontSize: 16),
+              ),
+            ),
+          );
+        }
+        return const SizedBox(
+          width: double.infinity,
+          child: Center(child: CircularProgressIndicator()),
+        );
+      },
+    );
+  }
+}

+ 78 - 0
UI/CF.APP/chicken_farm/lib/pages/home/_profile/user_info_card.dart

@@ -0,0 +1,78 @@
+import 'package:chicken_farm/modes/user/user_model.dart';
+import 'package:flutter/material.dart';
+
+class UserInfoCard extends StatelessWidget {
+  final UserModel user;
+
+  const UserInfoCard({super.key, required this.user});
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      child: Padding(
+        padding: const EdgeInsets.all(16.0),
+        child: Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            ListTile(
+              leading: const CircleAvatar(
+                radius: 30,
+                child: Icon(Icons.person, size: 30),
+              ),
+              title: Text(
+                user.nickName ?? '未设置昵称',
+                style: const TextStyle(
+                  fontSize: 20,
+                  fontWeight: FontWeight.bold,
+                ),
+              ),
+              subtitle: Text(
+                '用户名: ${user.userName}',
+              ),
+            ),
+            const Divider(),
+            const Text(
+              '基本信息',
+              style: TextStyle(fontWeight: FontWeight.bold),
+            ),
+            const SizedBox(height: 10),
+            _buildInfoRow(
+              '手机号码',
+              user.phonenumber ?? '未填写',
+            ),
+            _buildInfoRow(
+              '邮箱地址',
+              user.email ?? '未填写',
+            ),
+            _buildInfoRow(
+              '部门',
+              user.orgName ?? '未分配',
+            ),
+            _buildInfoRow(
+              '角色',
+              (user.roles?.map((r) => r.roleName).join(', ')) ?? '未分配',
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget _buildInfoRow(String label, String value) {
+    return Padding(
+      padding: const EdgeInsets.symmetric(vertical: 4.0),
+      child: Row(
+        children: [
+          SizedBox(
+            width: 80,
+            child: Text(
+              '$label:',
+              style: const TextStyle(fontWeight: FontWeight.w500),
+            ),
+          ),
+          Expanded(child: Text(value)),
+        ],
+      ),
+    );
+  }
+}

+ 34 - 21
UI/CF.APP/chicken_farm/lib/pages/home/menu_buttons.dart

@@ -21,26 +21,39 @@ class MenuButtons extends ConsumerWidget {
       return authState.permissions?.contains(item.permission) ?? false;
     }).toList();
 
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        for (var i = 0; i < visibleMenuItems.length; i++) ...[
-          SizedBox(
-            width: 200,
-            height: 50,
-            child: ElevatedButton.icon(
-              onPressed: () {
-                context.pushNamed(visibleMenuItems[i].routeName);
-              },
-              icon: visibleMenuItems[i].icon != null
-                  ? Icon(visibleMenuItems[i].icon)
-                  : const SizedBox.shrink(),
-              label: Text(visibleMenuItems[i].name),
-            ),
-          ),
-          if (i < visibleMenuItems.length - 1) const SizedBox(height: 20),
-        ],
-      ],
+    final screenWidth = MediaQuery.of(context).size.width;
+    final buttonWidth = screenWidth * 0.8;
+
+    return SingleChildScrollView(
+      child: Center(
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: [
+            for (var i = 0; i < visibleMenuItems.length; i++) ...[
+              SizedBox(
+                width: buttonWidth,
+                height: 50,
+                child: ElevatedButton.icon(
+                  onPressed: () {
+                    // 立即给予按钮按下反馈
+                    Future.delayed(const Duration(milliseconds: 100), () {
+                      // 检查context是否仍然有效
+                      if (context.mounted) {
+                        context.pushNamed(visibleMenuItems[i].routeName);
+                      }
+                    });
+                  },
+                  icon: visibleMenuItems[i].icon != null
+                      ? Icon(visibleMenuItems[i].icon)
+                      : const SizedBox.shrink(),
+                  label: Text(visibleMenuItems[i].name),
+                ),
+              ),
+              if (i < visibleMenuItems.length - 1) const SizedBox(height: 20),
+            ],
+          ],
+        ),
+      ),
     );
   }
-}
+}

+ 17 - 205
UI/CF.APP/chicken_farm/lib/pages/home/profile.dart

@@ -1,14 +1,13 @@
-import 'package:chicken_farm/core/services/offline_storage_service.dart';
-import 'package:chicken_farm/core/services/sync_service.dart';
-import 'package:chicken_farm/core/utils/storage.dart';
-import 'package:chicken_farm/core/utils/toast.dart';
 import 'package:chicken_farm/stores/auth_store.dart';
-import 'package:chicken_farm/stores/config_store.dart';
-import 'package:chicken_farm/stores/dict_stroe.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:chicken_farm/core/services/connectivity_service.dart';
-import 'package:chicken_farm/pages/account/config_dialog.dart';
+import 'package:chicken_farm/pages/home/_profile/user_info_card.dart';
+import 'package:chicken_farm/pages/home/_profile/upload_data_button.dart';
+import 'package:chicken_farm/pages/home/_profile/clear_cache_button.dart';
+import 'package:chicken_farm/pages/home/_profile/config_button.dart';
+import 'package:chicken_farm/pages/home/_profile/rfid_config_button.dart';
+// import 'package:chicken_farm/pages/home/_profile/scanner_light_button.dart';
+import 'package:chicken_farm/pages/home/_profile/logout_button.dart';
 
 class ProfilePage extends ConsumerWidget {
   const ProfilePage({super.key});
@@ -16,7 +15,6 @@ class ProfilePage extends ConsumerWidget {
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final authState = ref.watch(authStoreProvider);
-    final authStore = ref.read(authStoreProvider.notifier);
 
     return Scaffold(
       body: Padding(
@@ -32,191 +30,23 @@ class ProfilePage extends ConsumerWidget {
                   child: Column(
                     crossAxisAlignment: CrossAxisAlignment.start,
                     children: [
-                      Card(
-                        child: Padding(
-                          padding: const EdgeInsets.all(16.0),
-                          child: Column(
-                            crossAxisAlignment: CrossAxisAlignment.start,
-                            children: [
-                              ListTile(
-                                leading: const CircleAvatar(
-                                  radius: 30,
-                                  child: Icon(Icons.person, size: 30),
-                                ),
-                                title: Text(
-                                  authState.user!.nickName ?? '未设置昵称',
-                                  style: const TextStyle(
-                                    fontSize: 20,
-                                    fontWeight: FontWeight.bold,
-                                  ),
-                                ),
-                                subtitle: Text(
-                                  '用户名: ${authState.user!.userName}',
-                                ),
-                              ),
-                              const Divider(),
-                              const Text(
-                                '基本信息',
-                                style: TextStyle(fontWeight: FontWeight.bold),
-                              ),
-                              const SizedBox(height: 10),
-                              _buildInfoRow(
-                                '手机号码',
-                                authState.user!.phonenumber ?? '未填写',
-                              ),
-                              _buildInfoRow(
-                                '邮箱地址',
-                                authState.user!.email ?? '未填写',
-                              ),
-                              _buildInfoRow(
-                                '部门',
-                                authState.user!.orgName ?? '未分配',
-                              ),
-                              _buildInfoRow(
-                                '角色',
-                                (authState.user!.roles
-                                        ?.map((r) => r.roleName)
-                                        .join(', ')) ??
-                                    '未分配',
-                              ),
-                            ],
-                          ),
-                        ),
-                      ),
+                      UserInfoCard(user: authState.user!),
                       const SizedBox(height: 20),
-                      // 显示待上传数据数量的按钮
-                      FutureBuilder<List<OfflineOperation>>(
-                        future: OfflineStorageService().getPendingOperations(),
-                        builder: (context, snapshot) {
-                          if (snapshot.connectionState ==
-                                  ConnectionState.done &&
-                              snapshot.hasData) {
-                            final pendingCount = snapshot.data!.length;
-                            return SizedBox(
-                              width: double.infinity,
-                              child: ElevatedButton.icon(
-                                onPressed: pendingCount > 0
-                                    ? () async {
-                                        ToastUtil.show(
-                                          '正在上传 $pendingCount 条数据...',
-                                        );
-                                        final syncService = SyncService();
-                                        await syncService
-                                            .syncPendingOperations();
-                                        ToastUtil.success('数据上传完成');
-                                        // 刷新按钮状态
-                                        (context as Element).markNeedsBuild();
-                                      }
-                                    : null, // 禁用按钮
-                                icon: const Icon(Icons.upload),
-                                label: Text('上传数据 ($pendingCount条待上传)'),
-                                style: ElevatedButton.styleFrom(
-                                  padding: const EdgeInsets.symmetric(
-                                    horizontal: 30,
-                                    vertical: 15,
-                                  ),
-                                  textStyle: const TextStyle(fontSize: 16),
-                                ),
-                              ),
-                            );
-                          }
-                          return const SizedBox(
-                            width: double.infinity,
-                            child: Center(child: CircularProgressIndicator()),
-                          );
-                        },
-                      ),
+                      const UploadDataButton(),
                       const SizedBox(height: 20),
-                      SizedBox(
-                        width: double.infinity,
-                        child: ElevatedButton.icon(
-                          onPressed: () {
-                            ToastUtil.confirm('确定要清除所有缓存吗?', () async {
-                              await StorageUtils.removeWithPrefix("vb_");
-                              ConfigStore().clearAll();
-                              DictStore().clearAll();
-                              if (context.mounted) {
-                                ToastUtil.success('缓存已清除');
-                              }
-                            });
-                          },
-                          icon: const Icon(Icons.cleaning_services),
-                          label: const Text('清除缓存'),
-                          style: ElevatedButton.styleFrom(
-                            padding: const EdgeInsets.symmetric(
-                              horizontal: 30,
-                              vertical: 15,
-                            ),
-                            textStyle: const TextStyle(fontSize: 16),
-                          ),
-                        ),
-                      ),
+                      const ClearCacheButton(),
                       const SizedBox(height: 20),
-                      SizedBox(
-                        width: double.infinity,
-                        child: ElevatedButton.icon(
-                          onPressed: () async {
-                            final result = await showDialog(
-                              context: context,
-                              builder: (context) => const ConfigDialog(),
-                            );
-                            // 如果配置发生了变化,显示提示
-                            if (result == true && context.mounted) {
-                              ToastUtil.success('配置已保存');
-                            }
-                          },
-                          icon: const Icon(Icons.settings),
-                          label: const Text('服务配置'),
-                          style: ElevatedButton.styleFrom(
-                            padding: const EdgeInsets.symmetric(
-                              horizontal: 30,
-                              vertical: 15,
-                            ),
-                            textStyle: const TextStyle(fontSize: 16),
-                          ),
-                        ),
-                      ),
+                      const ConfigButton(),
+                      const SizedBox(height: 20),
+                      const RfidConfigButton(),
+                      const SizedBox(height: 20),
+                      // const ScannerLightButton(),
+                      // const SizedBox(height: 20),
+                      const LogoutButton(),
                     ],
                   ),
                 ),
               ),
-              // 网络状态感知的退出登录按钮
-              Consumer(
-                builder: (context, ref, child) {
-                  final isConnectedAsync = ref.watch(isConnectedProvider);
-                  return SizedBox(
-                    width: double.infinity,
-                    child: ElevatedButton.icon(
-                      onPressed: isConnectedAsync.when(
-                        data: (isConnected) {
-                          // 在线状态下允许退出登录,离线状态下禁用
-                          return isConnected
-                              ? () {
-                                  ToastUtil.confirm(
-                                    '确定要退出登录吗?',
-                                    () => authStore.logout(),
-                                  );
-                                }
-                              : null;
-                        },
-                        loading: () => null,
-                        error: (_, _) => null,
-                      ),
-                      icon: const Icon(Icons.logout),
-                      label: const Text('退出登录'),
-                      style: ElevatedButton.styleFrom(
-                        // 保持背景色不变,只改变文字颜色为红色
-                        foregroundColor: Colors.red,
-                        padding: const EdgeInsets.symmetric(
-                          horizontal: 30,
-                          vertical: 15,
-                        ),
-                        textStyle: const TextStyle(fontSize: 16),
-                      ),
-                    ),
-                  );
-                },
-              ),
             ] else ...[
               const Center(child: Text('加载中...')),
             ],
@@ -225,22 +55,4 @@ class ProfilePage extends ConsumerWidget {
       ),
     );
   }
-
-  Widget _buildInfoRow(String label, String value) {
-    return Padding(
-      padding: const EdgeInsets.symmetric(vertical: 4.0),
-      child: Row(
-        children: [
-          SizedBox(
-            width: 80,
-            child: Text(
-              '$label:',
-              style: const TextStyle(fontWeight: FontWeight.w500),
-            ),
-          ),
-          Expanded(child: Text(value)),
-        ],
-      ),
-    );
-  }
 }

+ 7 - 0
UI/CF.APP/chicken_farm/lib/routes/app_routes.dart

@@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:go_router/go_router.dart';
 import '../pages/account/login_page.dart';
 import '../pages/home/home_page.dart';
+import '../pages/home/_profile/rfid_config_page.dart';
 import '../pages/checkin/checkin_page.dart';
 import '../pages/checkin/checkin_record_page.dart';
 import '../pages/sample/sample_query_page.dart';
@@ -27,6 +28,7 @@ class AppRouteNames {
   static const String batchCulling = '/batch_culling';
   static const String sample = '/sample';
   static const String sampleDetail = '/sample/detail';
+  static const String rfidConfig = '/rfid-config';
 }
 
 class AppRoutes {
@@ -96,6 +98,11 @@ class AppRoutes {
       name: AppRouteNames.batchCulling,
       builder: (context, state) => const BatchCullingPage(),
     ),
+    GoRoute(
+      path: AppRouteNames.rfidConfig,
+      name: AppRouteNames.rfidConfig,
+      builder: (context, state) => const RfidConfigPage(),
+    ),
   ];
 }