config_dialog.dart 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import 'package:chicken_farm/core/api/api_client.dart';
  2. import 'package:chicken_farm/core/config/app_config.dart';
  3. import 'package:chicken_farm/core/utils/toast.dart';
  4. import 'package:flutter/material.dart';
  5. class ConfigDialog extends StatefulWidget {
  6. const ConfigDialog({super.key});
  7. @override
  8. State<ConfigDialog> createState() => _ConfigDialogState();
  9. }
  10. class _ConfigDialogState extends State<ConfigDialog> {
  11. final _formKey = GlobalKey<FormState>();
  12. late TextEditingController _baseUrlController;
  13. late TextEditingController _clientIdController;
  14. bool _isSaving = false; // 添加保存状态标识
  15. @override
  16. void initState() {
  17. super.initState();
  18. _baseUrlController = TextEditingController(text: AppConfig.baseUrl);
  19. _clientIdController = TextEditingController(text: AppConfig.clientId);
  20. }
  21. @override
  22. void dispose() {
  23. _baseUrlController.dispose();
  24. _clientIdController.dispose();
  25. super.dispose();
  26. }
  27. @override
  28. Widget build(BuildContext context) {
  29. return AlertDialog(
  30. title: const Text('配置服务器'),
  31. content: SizedBox(
  32. width: MediaQuery.of(context).size.width * 0.8,
  33. child: Form(
  34. key: _formKey,
  35. child: Column(
  36. mainAxisSize: MainAxisSize.min,
  37. children: [
  38. TextFormField(
  39. controller: _baseUrlController,
  40. decoration: const InputDecoration(
  41. labelText: 'Base URL',
  42. hintText: '例如: http://localhost:8080',
  43. border: OutlineInputBorder(),
  44. ),
  45. validator: (value) {
  46. if (value == null || value.isEmpty) {
  47. return '请输入Base URL';
  48. }
  49. if (!value.startsWith('http')) {
  50. return '请输入有效的URL地址';
  51. }
  52. return null;
  53. },
  54. ),
  55. const SizedBox(height: 16),
  56. TextFormField(
  57. controller: _clientIdController,
  58. decoration: const InputDecoration(
  59. labelText: 'Client ID',
  60. border: OutlineInputBorder(),
  61. ),
  62. validator: (value) {
  63. if (value == null || value.isEmpty) {
  64. return '请输入Client ID';
  65. }
  66. return null;
  67. },
  68. ),
  69. ],
  70. ),
  71. ),
  72. ),
  73. actions: [
  74. TextButton(
  75. onPressed: _isSaving ? null : () {
  76. // 保存过程中禁用取消按钮
  77. Navigator.of(context).pop();
  78. },
  79. child: const Text('取消'),
  80. ),
  81. ElevatedButton(
  82. onPressed: _isSaving ? null : () async {
  83. // 保存过程中禁用保存按钮
  84. if (_formKey.currentState!.validate()) {
  85. // 保存前取消当前焦点,避免输入法相关问题
  86. FocusManager.instance.primaryFocus?.unfocus();
  87. setState(() {
  88. _isSaving = true;
  89. });
  90. try {
  91. // 稍微延迟一下确保焦点完全失去
  92. await Future.delayed(const Duration(milliseconds: 50));
  93. // 保存配置
  94. await AppConfig.save(
  95. _baseUrlController.text.trim(),
  96. _clientIdController.text.trim(),
  97. );
  98. // 重新初始化API客户端
  99. ApiClient.clearDio();
  100. if (context.mounted) {
  101. Navigator.of(context).pop(true);
  102. ToastUtil.success('配置保存成功');
  103. }
  104. } catch (e) {
  105. // 发生错误时显示提示
  106. if (context.mounted) {
  107. ToastUtil.error('保存配置失败: ${e.toString()}');
  108. }
  109. setState(() {
  110. _isSaving = false;
  111. });
  112. }
  113. }
  114. },
  115. child: _isSaving
  116. ? const SizedBox(
  117. width: 20,
  118. height: 20,
  119. child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white),
  120. )
  121. : const Text('保存'),
  122. ),
  123. ],
  124. );
  125. }
  126. }