Explorar o código

[fit]1.对keyboard_manage拆分

云天逵 hai 7 meses
pai
achega
0bbd287afa

+ 6 - 4
lib/di/network_module.dart

@@ -32,10 +32,12 @@ abstract class NetworkModule {
   @singleton
   @Named("fileDio")
   Dio createFileDio() {
-    Dio dio = Dio(BaseOptions(
-      sendTimeout: const Duration(seconds: 15),
-      receiveTimeout: const Duration(seconds: 15),
-    ));
+    Dio dio = Dio(
+      BaseOptions(
+        sendTimeout: const Duration(seconds: 15),
+        receiveTimeout: const Duration(seconds: 15),
+      ),
+    );
     dio.interceptors.add(
       PrettyDioLogger(
         requestHeader: true,

+ 159 - 417
lib/module/keyboard_manage/keyboard_manage_controller.dart

@@ -1,4 +1,3 @@
-import 'package:collection/collection.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 import 'package:injectable/injectable.dart';
@@ -11,21 +10,18 @@ import 'package:keyboard/dialog/character_add_dialog.dart';
 import 'package:keyboard/dialog/custom_character/custom_character_add_dialog.dart';
 import 'package:keyboard/dialog/login/login_dialog.dart';
 import 'package:keyboard/handler/event_handler.dart';
-import 'package:keyboard/module/character/content/character_group_content_controller.dart';
 import 'package:keyboard/resource/string.gen.dart';
 import 'package:keyboard/utils/atmob_log.dart';
 import 'package:keyboard/utils/toast_util.dart';
 
 import '../../data/bean/keyboard_info.dart';
-import '../../data/consts/error_code.dart';
-import '../../data/repository/characters_repository.dart';
-import '../../plugins/keyboard_android_platform.dart';
-import '../../utils/error_handler.dart';
-import '../../utils/http_handler.dart';
+import 'keyboard_type_controller.dart';
+
+
 
 enum KeyboardType {
-  system, //通用键盘
-  custom, //自定义键盘
+  system, // 通用键盘
+  custom, // 自定义键盘
 }
 
 @injectable
@@ -34,81 +30,24 @@ class KeyboardManageController extends BaseController
   final String tag = 'KeyboardManageController';
 
   final AccountRepository accountRepository;
-
   final KeyboardRepository keyboardRepository;
 
+  // 登录状态
   RxBool get isLogin => accountRepository.isLogin;
 
+  // 键盘列表
   RxList<KeyboardInfo> get customKeyboardInfoList =>
       keyboardRepository.customKeyboardInfoList;
-
-  // 当前自定义键盘
-  final Rx<KeyboardInfo> _currentCustomKeyboardInfo = KeyboardInfo().obs;
-
-  KeyboardInfo get currentCustomKeyboardInfo =>
-      _currentCustomKeyboardInfo.value;
-
-  //当前自定义键盘人设列表
-  final RxList<CharacterInfo> _currentCustomKeyboardCharacterList = RxList();
-
-  RxList<CharacterInfo> get currentCustomKeyboardCharacterList =>
-      _currentCustomKeyboardCharacterList;
-
-  // 当前自定义键盘亲密度
-  final RxInt _currentCustomIntimacy = 0.obs;
-
-  int get currentCustomIntimacy => _currentCustomIntimacy.value;
-
-  // 当前定制亲密度是否有变化
-  final RxBool _customIntimacyChanged = false.obs;
-
-  bool get customIntimacyChanged => _customIntimacyChanged.value;
-
-  final RxBool _customKeyboardCharacterListChanged = false.obs;
-
-  bool get customKeyboardCharacterListChanged =>
-      _customKeyboardCharacterListChanged.value;
-
-  // 存储排序前的定制人设列表,用于比较是否有变化
-  List<CharacterInfo> _oldCustomCharacterList = [];
-
   RxList<KeyboardInfo> get generalKeyboardInfoList =>
       keyboardRepository.generalKeyboardInfoList;
 
-  // 当前通用键盘
-  final Rx<KeyboardInfo> _currentGeneralKeyboardInfo = KeyboardInfo().obs;
-
-  KeyboardInfo get currentGeneralKeyboardInfo =>
-      _currentGeneralKeyboardInfo.value;
+  // 子控制器
+  late KeyboardTypeController customKeyboardController;
+  late KeyboardTypeController generalKeyboardController;
 
-  // 当前通用键盘人设列表
-  final RxList<CharacterInfo> _currentGeneralKeyboardCharacterList = RxList();
-
-  List<CharacterInfo> get currentGeneralKeyboardCharacterList =>
-      _currentGeneralKeyboardCharacterList;
-
-  // 当前通用键盘亲密度
-  final RxInt _currentGeneralIntimacy = 0.obs;
-
-  int get currentGeneralIntimacy => _currentGeneralIntimacy.value;
-
-  // 当前通用亲密度是否有变化
-  final RxBool _generalIntimacyChanged = false.obs;
-
-  RxBool get generalIntimacyChanged => _generalIntimacyChanged;
-
-  final RxBool _generalKeyboardCharacterListChanged = false.obs;
-
-  bool get generalKeyboardCharacterListChanged =>
-      _generalKeyboardCharacterListChanged.value;
-
-  // 存储排序前的通用人设列表,用于比较是否有变化
-  late List<CharacterInfo> _oldGeneralCharacterList;
-
-  late Worker _customKeyboardInfoListWorker;
-
-  // 最小人设数量
-  final _minCount = 9;
+  // UI控制器
+  late TabController tabController;
+  late PageController pageController;
 
   // 键盘管理类型
   List<String> keyboardManageType = [
@@ -116,37 +55,49 @@ class KeyboardManageController extends BaseController
     StringName.generalKeyboard,
   ];
 
-  // 键盘管理页面的tabController,用于控制通用键盘和自定义键盘的切换
-  late TabController tabController;
-
-  // 键盘管理页面的pageController,用于控制通用键盘和自定义键盘的切换
-  late PageController pageController;
+  // worker
+  late Worker _keyboardInfoListWorker;
 
   // 首次加载数据标志
   final isFirstLoad = true.obs;
 
-  KeyboardManageController(this.keyboardRepository, this.accountRepository);
+  KeyboardManageController(this.keyboardRepository, this.accountRepository) {
+    // 初始化子控制器
+    customKeyboardController = KeyboardTypeController(
+      tag: '$tag-Custom',
+      keyboardRepository: keyboardRepository,
+      isCustom: true,
+    );
+
+    generalKeyboardController = KeyboardTypeController(
+      tag: '$tag-General',
+      keyboardRepository: keyboardRepository,
+      isCustom: false,
+    );
+  }
 
   @override
   void onInit() async {
     super.onInit();
 
+    // 处理传入的自定义键盘信息
     final args = Get.arguments;
     if (args is Map && args["customKeyboardInfo"] is KeyboardInfo) {
-      _currentCustomKeyboardInfo.value = args["customKeyboardInfo"];
+      customKeyboardController.keyboardInfo.value = args["customKeyboardInfo"];
     }
 
-    await _dataLoad();
+    await _initializeControllers();
   }
 
-  _dataLoad() async {
-    getCustomKeyboard();
-    getGeneralKeyboard();
+  // 初始化控制器
+  Future<void> _initializeControllers() async {
+    // 初始化Tab控制器
     tabController = TabController(
       length: keyboardManageType.length,
       vsync: this,
       initialIndex: customKeyboardInfoList.isEmpty ? 1 : 0,
     );
+
     tabController.addListener(() {
       if (tabController.indexIsChanging) {
         switchTabKeyboardType(tabController.index);
@@ -158,170 +109,64 @@ class KeyboardManageController extends BaseController
       }
     });
 
+    // 初始化Page控制器
     pageController = PageController(
       initialPage: customKeyboardInfoList.isEmpty ? 1 : 0,
     );
 
-    _customKeyboardInfoListWorker = everAll(
-      [customKeyboardInfoList, generalKeyboardInfoList],
-      (_) {
-
-
-          if (customKeyboardInfoList.isNotEmpty) {
-            _currentCustomKeyboardInfo.value = customKeyboardInfoList.firstWhere(
-                  (element) => element.isChoose == true,
-              orElse: () => customKeyboardInfoList.first,
-            );
-          getCustomKeyboard();
-          }else
-            {
-              _oldCustomCharacterList = [];
-              _currentCustomKeyboardInfo.value = KeyboardInfo();
-              _currentCustomKeyboardCharacterList.clear();
-            }
-
-
-        if (generalKeyboardInfoList.isNotEmpty) {
-          _currentGeneralKeyboardInfo.value = generalKeyboardInfoList.first;
-          getGeneralKeyboard();
-        }
-
-      },
-    );
-  }
-
-  clickBack() {
-    AtmobLog.i(tag, 'clickBack');
-    Get.back();
-  }
+    // 监听键盘列表变化
+    _keyboardInfoListWorker = everAll([
+      customKeyboardInfoList,
+      generalKeyboardInfoList,
+    ], (_) => _loadKeyboardData());
 
-  @override
-  void onReady() {
-    super.onReady();
+    // 首次加载数据
+    _loadKeyboardData();
   }
 
-  //   获取定制键盘
-  Future<void> getCustomKeyboard() async {
-    AtmobLog.i(tag, 'getCustomKeyboard');
+  // 加载键盘数据
+  void _loadKeyboardData() {
+    // 加载自定义键盘数据
     if (customKeyboardInfoList.isNotEmpty) {
-      AtmobLog.i(
-        tag,
-        'customKeyboardInfoList: ${customKeyboardInfoList.length}',
-      );
-      if (_currentCustomKeyboardInfo.value.id == null) {
-        _currentCustomKeyboardInfo.value = customKeyboardInfoList.firstWhere(
-          (element) => element.isChoose == true,
+      KeyboardInfo keyboard;
+
+      // 如果已有选择的键盘,就用它
+      if (customKeyboardController.keyboardInfo.value.id != null) {
+        keyboard = customKeyboardController.keyboardInfo.value;
+      } else {
+        // 否则选择默认选中的或第一个键盘
+        keyboard = customKeyboardInfoList.firstWhere(
+              (element) => element.isChoose == true,
           orElse: () => customKeyboardInfoList.first,
         );
       }
-      _currentCustomIntimacy.value =
-          _currentCustomKeyboardInfo.value.intimacy ?? 0;
-      _currentCustomIntimacy.listen((intimacy) {
-        _customIntimacyChanged.value =
-            _currentCustomKeyboardInfo.value.intimacy != intimacy;
-        AtmobLog.d(tag, 'intimacyChanged: $_customIntimacyChanged');
-      });
-
-      String? id = _currentCustomKeyboardInfo.value.id;
-      if (id != null) {
-        getKeyboardCharacterList(keyboardId: id, isCustom: true);
-      }
-    }
-  }
 
-  //   获取通用键盘
-  void getGeneralKeyboard() {
-    _currentGeneralKeyboardInfo.value = generalKeyboardInfoList.first;
-    _currentGeneralIntimacy.value =
-        _currentGeneralKeyboardInfo.value.intimacy ?? 0;
-    _currentGeneralIntimacy.listen((intimacy) {
-      _generalIntimacyChanged.value =
-          _currentGeneralKeyboardInfo.value.intimacy != intimacy;
-      AtmobLog.d(tag, 'intimacyChanged: $_generalIntimacyChanged');
-    });
-    String? id = _currentGeneralKeyboardInfo.value.id;
-    if (id != null) {
-      AtmobLog.i(tag, 'getGeneralKeyboard id: $id');
-      getKeyboardCharacterList(keyboardId: id, isCustom: false);
+      customKeyboardController.loadKeyboard(keyboard);
+    } else {
+      customKeyboardController.characterList.clear();
+      customKeyboardController.oldCharacterList = [];
+      customKeyboardController.keyboardInfo.value = KeyboardInfo();
     }
-  }
 
-  // 获取当前键盘人设列表
-  void getKeyboardCharacterList({
-    required String keyboardId,
-    required bool isCustom,
-  }) {
-    if (isCustom) {
-      keyboardRepository.getKeyboardCharacterList(keyboardId: keyboardId).then((
-        keyboardCharacterListResponse,
-      ) {
-        AtmobLog.i(
-          tag,
-          'keyboardCharacterListResponse: ${keyboardCharacterListResponse.characterInfos.toString()}',
-        );
-        _currentCustomKeyboardCharacterList.assignAll(
-          keyboardCharacterListResponse.characterInfos,
-        );
-        _oldCustomCharacterList = List<CharacterInfo>.from(
-          _currentCustomKeyboardCharacterList,
-        );
-        _customKeyboardCharacterListChanged.value = false;
-        _currentCustomKeyboardCharacterList.listen((event) {
-          _customKeyboardCharacterListChanged.value =
-              !ListEquality().equals(_oldCustomCharacterList, event);
-          AtmobLog.d(
-            tag,
-            '_customKeyboardCharacterListChanged: $_customKeyboardCharacterListChanged',
-          );
-        });
-      });
-    } else {
-      keyboardRepository.getKeyboardCharacterList(keyboardId: keyboardId).then((
-        keyboardCharacterListResponse,
-      ) {
-        AtmobLog.i(
-          tag,
-          'keyboardCharacterListResponse: ${keyboardCharacterListResponse.characterInfos.toString()}',
-        );
-        if (_currentGeneralKeyboardInfo.value.id == keyboardId) {
-          _currentGeneralKeyboardCharacterList.value =
-              keyboardCharacterListResponse.characterInfos;
-          _oldGeneralCharacterList = List<CharacterInfo>.from(
-            _currentGeneralKeyboardCharacterList,
-          );
-          _generalKeyboardCharacterListChanged.value = false;
-          _currentGeneralKeyboardCharacterList.listen((event) {
-            _generalKeyboardCharacterListChanged.value =
-                !ListEquality().equals(_oldGeneralCharacterList, event);
-            AtmobLog.d(
-              tag,
-              '_generalKeyboardCharacterListChanged: $_generalKeyboardCharacterListChanged',
-            );
-          });
-        }
-        if (_currentCustomKeyboardInfo.value.id == keyboardId) {
-          _currentCustomKeyboardCharacterList.value =
-              keyboardCharacterListResponse.characterInfos;
-        }
-      });
+    // 加载通用键盘数据
+    if (generalKeyboardInfoList.isNotEmpty) {
+      generalKeyboardController.loadKeyboard(generalKeyboardInfoList.first);
     }
   }
 
-  //   切换当前定制键盘
+  // 切换自定义键盘
   void switchCustomKeyboard(String? keyboardName) {
-    _currentCustomKeyboardInfo.value = customKeyboardInfoList.firstWhere(
-      (element) => element.name == keyboardName,
+    if (keyboardName == null) return;
+
+    KeyboardInfo keyboard = customKeyboardInfoList.firstWhere(
+          (element) => element.name == keyboardName,
       orElse: () => customKeyboardInfoList.first,
     );
-    String? keyboardId = _currentCustomKeyboardInfo.value.id;
-    _currentCustomIntimacy.value =
-        _currentCustomKeyboardInfo.value.intimacy ?? 0;
-    if (keyboardId != null) {
-      getKeyboardCharacterList(keyboardId: keyboardId, isCustom: true);
-    }
+
+    customKeyboardController.loadKeyboard(keyboard);
   }
 
-  // tab切换
+  // Tab切换
   void switchTabKeyboardType(int index) {
     pageController.animateToPage(
       index,
@@ -330,245 +175,142 @@ class KeyboardManageController extends BaseController
     );
   }
 
-  // page切换
+  // Page切换
   void switchPageKeyboardType(int index) {
-    // AtmobLog.i(tag, 'onPageChanged: $index');
-
     tabController.animateTo(index, duration: const Duration(milliseconds: 300));
 
     if (index == 0) {
-      _currentGeneralIntimacy.value =
-          _currentGeneralKeyboardInfo.value.intimacy ?? 0;
-      _currentGeneralKeyboardCharacterList.value = _oldGeneralCharacterList;
-      _generalIntimacyChanged.value = false;
-      _generalKeyboardCharacterListChanged.value = false;
-      getCustomKeyboard();
+      // 切换到自定义键盘,重置通用键盘状态
+      generalKeyboardController.intimacy.value =
+          generalKeyboardController.keyboardInfo.value.intimacy ?? 0;
+      generalKeyboardController.characterList.value =
+          generalKeyboardController.oldCharacterList;
+      generalKeyboardController.intimacyChanged.value = false;
+      generalKeyboardController.characterListChanged.value = false;
+
+      // 刷新自定义键盘数据
+      if (customKeyboardController.keyboardInfo.value.id != null) {
+        customKeyboardController.getKeyboardCharacterList(
+          keyboardId: customKeyboardController.keyboardInfo.value.id!,
+        );
+      }
     } else {
-      _currentCustomIntimacy.value =
-          _currentCustomKeyboardInfo.value.intimacy ?? 0;
+      // 切换到通用键盘,重置自定义键盘状态
+      customKeyboardController.intimacy.value =
+          customKeyboardController.keyboardInfo.value.intimacy ?? 0;
 
-      if (_oldCustomCharacterList.isNotEmpty) {
-        _currentCustomKeyboardCharacterList.value = _oldCustomCharacterList;
+      if (customKeyboardController.oldCharacterList.isNotEmpty) {
+        customKeyboardController.characterList.value =
+            customKeyboardController.oldCharacterList;
       }
 
-      _customIntimacyChanged.value = false;
-      _customKeyboardCharacterListChanged.value = false;
-      getGeneralKeyboard();
+      customKeyboardController.intimacyChanged.value = false;
+      customKeyboardController.characterListChanged.value = false;
+
+      // 刷新通用键盘数据
+      if (generalKeyboardController.keyboardInfo.value.id != null) {
+        generalKeyboardController.getKeyboardCharacterList(
+          keyboardId: generalKeyboardController.keyboardInfo.value.id!,
+        );
+      }
     }
   }
 
+  // 点击返回
+  void clickBack() {
+    AtmobLog.i(tag, 'clickBack');
+    Get.back();
+  }
+
   // 更新亲密度
   void updateIntimacy(int intimacy, bool isCustom) {
     if (isCustom) {
-      _currentCustomIntimacy.value = intimacy;
+      customKeyboardController.updateIntimacy(intimacy);
     } else {
-      _currentGeneralIntimacy.value = intimacy;
+      generalKeyboardController.updateIntimacy(intimacy);
     }
   }
 
   // 排序
   void onReorder(int oldIndex, int newIndex, bool isCustom) {
     if (isCustom) {
-      reorderList(_currentCustomKeyboardCharacterList, oldIndex, newIndex);
+      customKeyboardController.reorderCharacters(oldIndex, newIndex);
     } else {
-      reorderList(_currentGeneralKeyboardCharacterList, oldIndex, newIndex);
+      generalKeyboardController.reorderCharacters(oldIndex, newIndex);
     }
   }
 
-  // 排序
-  void reorderList<T>(RxList<T> list, int oldIndex, int newIndex) {
-    AtmobLog.d(tag, 'reorderList: $oldIndex, $newIndex');
-    final item = list.removeAt(oldIndex);
-    list.insert(newIndex, item);
-  }
-
+  // 保存
   void clickSave(bool isCustom) {
-    isCustom
-        ? saveCustomKeyboardCharacterList()
-        : saveGeneralKeyboardCharacterList();
-  }
-
-  void saveCustomKeyboardCharacterList() {
-
-    EventHandler.report(EventId.event_13002);
-
-    _saveKeyboardInfo(
-      intimacyChanged: _customIntimacyChanged,
-      currentIntimacy: currentCustomIntimacy,
-      currentKeyboardInfo: _currentCustomKeyboardInfo,
-      characterListChanged: _customKeyboardCharacterListChanged,
-      currentCharacterList: _currentCustomKeyboardCharacterList,
-      onUpdateSuccess: () {
-        _oldCustomCharacterList = List<CharacterInfo>.from(
-          _currentCustomKeyboardCharacterList,
-        );
-
-        // 更具键盘组刷新对应的数据
-        CharactersRepository.getInstance().characterGroupList.forEach((e) {
-          final tag = "CharacterGroupContentController${_currentCustomKeyboardInfo.value.id}${e.id}";
-
-          if (Get.isRegistered<CharacterGroupContentController>(tag: tag)) {
-
-            var controller = Get.find<CharacterGroupContentController>(tag: tag);
-            controller.refreshData();
-          }
-        });
-        // 通知键盘,刷新人设列表
-        KeyboardAndroidPlatform.refreshCharacterList();
-        saveSuccessGetBack();
-      },
-    );
-  }
-
-  void saveGeneralKeyboardCharacterList() {
-    EventHandler.report(EventId.event_13004);
-    _saveKeyboardInfo(
-      intimacyChanged: _generalIntimacyChanged,
-      currentIntimacy: currentGeneralIntimacy,
-      currentKeyboardInfo: _currentGeneralKeyboardInfo,
-      characterListChanged: _generalKeyboardCharacterListChanged,
-      currentCharacterList: _currentGeneralKeyboardCharacterList,
-      onUpdateSuccess: () {
-        _oldGeneralCharacterList = List<CharacterInfo>.from(
-          _currentGeneralKeyboardCharacterList,
-        );
+    final controller =
+    isCustom ? customKeyboardController : generalKeyboardController;
+    final eventId = isCustom ? EventId.event_13002 : EventId.event_13004;
 
-        // 每次保存对应键盘都刷一次数据,一瞬间刷新8次
-        CharactersRepository.getInstance().characterGroupList.forEach((e) {
-          final tag = "CharacterGroupContentController${_currentGeneralKeyboardInfo.value.id}${e.id}";
+    EventHandler.report(eventId);
 
-          if (Get.isRegistered<CharacterGroupContentController>(tag: tag)) {
-
-            var controller = Get.find<CharacterGroupContentController>(tag: tag);
-            controller.refreshData();
-          }
-        });
-        // 通知键盘,刷新人设列表
-        KeyboardAndroidPlatform.refreshCharacterList();
+    controller.saveKeyboardInfo(
+      onSuccess: () {
+        if (isCustom) {
+          saveSuccessGetBack();
+        }
       },
     );
   }
 
-  void _saveKeyboardInfo({
-    required RxBool intimacyChanged,
-    required int currentIntimacy,
-    required Rx<KeyboardInfo> currentKeyboardInfo,
-    required RxBool characterListChanged,
-    required List<CharacterInfo> currentCharacterList,
-    required VoidCallback onUpdateSuccess,
-  }) {
-    String? keyboardId = currentKeyboardInfo.value.id;
-
-    if (intimacyChanged.value && keyboardId != null) {
-      AtmobLog.i(tag, 'clickSave intimacyChanged');
-      currentKeyboardInfo.value.intimacy = currentIntimacy;
-      keyboardRepository
-          .updateKeyboardInfo(keyboardId: keyboardId, intimacy: currentIntimacy)
-          .then((_) async {
-            ToastUtil.show(StringName.keyboardSaveSuccess);
-            await keyboardRepository.refreshData();
-          })
-          .catchError((error) {
-            if (error is ServerErrorException) {
-              ErrorHandler.toastError(error);
-              if (error.code == ErrorCode.noLoginError) {
-                LoginDialog.show();
-              }
-            } else {
-              ToastUtil.show(StringName.keyboardSaveFailed);
-            }
-          })
-          .whenComplete(() => intimacyChanged.value = false);
-    }
-
-    if (characterListChanged.value && keyboardId != null) {
-      AtmobLog.i(tag, 'clickSave keyboardChanged');
-      List<String> characterIds =
-          currentCharacterList.map((e) => e.id).cast<String>().toList();
-      keyboardRepository
-          .keyboardCharacterUpdate(
-            keyboardId: keyboardId,
-            characterIds: characterIds,
-          )
-          .then((_) async {
-            onUpdateSuccess();
-            ToastUtil.show(StringName.keyboardSaveSuccess);
-            await keyboardRepository.refreshData();
-          })
-          .catchError((error) {
-            if (error is ServerErrorException) {
-              ErrorHandler.toastError(error);
-              if (error.code == ErrorCode.noLoginError) {
-                LoginDialog.show();
-              }
-            } else {
-              ToastUtil.show(StringName.keyboardSaveFailed);
-            }
-          })
-          .whenComplete(() => characterListChanged.value = false);
-    }
-  }
-
+  // 移除人设
   void clickRemoveCharacter(CharacterInfo characterInfo, bool isCustom) {
-    if (isCustom) {
-      if (_currentCustomKeyboardCharacterList.length <= _minCount) {
-        ToastUtil.show("最少需要保持$_minCount个人设");
-        return;
-      }
-      AtmobLog.i(tag, 'clickRemoveCharacter');
-      _currentCustomKeyboardCharacterList.remove(characterInfo);
-    } else {
-      if (_currentGeneralKeyboardCharacterList.length <= _minCount) {
-        ToastUtil.show("最少需要保持$_minCount个人设");
-        return;
-      }
-      AtmobLog.i(tag, 'clickRemoveCharacter');
-
-      _currentGeneralKeyboardCharacterList.remove(characterInfo);
-    }
+    final controller =
+    isCustom ? customKeyboardController : generalKeyboardController;
+    controller.removeCharacter(characterInfo);
   }
 
-  clickAddCharacter({required bool isCustom}) {
+  // 添加人设
+  void clickAddCharacter({required bool isCustom}) {
     if (!isLogin.value) {
       ToastUtil.show("请先登录");
       LoginDialog.show();
       return;
     }
-    if (isCustom) {
-      CharacterAddDialog.show(
-        currentKeyboardInfo: _currentCustomKeyboardInfo.value,
-        clickCallback: () {
-          getKeyboardCharacterList(
-            keyboardId: _currentCustomKeyboardInfo.value.id ?? "",
-            isCustom: true,
-          );
 
-        },
-      );
-    } else {
-      CharacterAddDialog.show(
-        currentKeyboardInfo: currentGeneralKeyboardInfo,
-        clickCallback: () {
-          getGeneralKeyboard();
-        },
-      );
-    }
+    final KeyboardInfo currentKeyboard =
+    isCustom
+        ? customKeyboardController.keyboardInfo.value
+        : generalKeyboardController.keyboardInfo.value;
+
+    CharacterAddDialog.show(
+      currentKeyboardInfo: currentKeyboard,
+      clickCallback: () {
+        if (isCustom) {
+          customKeyboardController.getKeyboardCharacterList(
+            keyboardId: customKeyboardController.keyboardInfo.value.id ?? "",
+          );
+        } else {
+          generalKeyboardController.getKeyboardCharacterList(
+            keyboardId: generalKeyboardController.keyboardInfo.value.id ?? "",
+          );
+        }
+      },
+    );
   }
 
-  clickCustomCharacter() {
+  // 自定义人设
+  void clickCustomCharacter() {
     if (!isLogin.value) {
       ToastUtil.show("请先登录");
       LoginDialog.show();
       return;
     }
+
     AtmobLog.i(tag, 'clickCustomCharacter');
     CustomCharacterAddDialog.show(
-      currentKeyboardInfo: _currentCustomKeyboardInfo.value,
+      currentKeyboardInfo: customKeyboardController.keyboardInfo.value,
       clickCallback: () {
-        getKeyboardCharacterList(
-          keyboardId: _currentCustomKeyboardInfo.value.id ?? "",
-          isCustom: true,
-        );
+        String? keyboardId = customKeyboardController.keyboardInfo.value.id;
+        if (keyboardId != null) {
+          customKeyboardController.getKeyboardCharacterList(
+            keyboardId: keyboardId,
+          );
+        }
       },
     );
   }
@@ -577,11 +319,11 @@ class KeyboardManageController extends BaseController
   void onClose() {
     tabController.dispose();
     pageController.dispose();
-    _customKeyboardInfoListWorker.dispose();
+    _keyboardInfoListWorker.dispose();
     super.onClose();
   }
 
   void saveSuccessGetBack() {
-    Get.back(result: _currentCustomKeyboardCharacterList);
+    Get.back(result: customKeyboardController.characterList);
   }
 }

+ 48 - 54
lib/module/keyboard_manage/keyboard_manage_page.dart

@@ -91,12 +91,11 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
           ),
           Expanded(
             child: TabBar(
-              // onTap: controller.switchTabKeyboardType,
               controller: controller.tabController,
               tabs:
-                  controller.keyboardManageType
-                      .map((e) => Tab(text: e))
-                      .toList(),
+              controller.keyboardManageType
+                  .map((e) => Tab(text: e))
+                  .toList(),
               dividerHeight: 0,
               indicator: TabCustomGradientIndicator(),
               labelStyle: TextStyle(
@@ -139,6 +138,9 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
   }
 
   Widget _buildDropdownButton() {
+    // 获取当前使用的子控制器
+    final typeController = controller.customKeyboardController;
+
     return Obx(() {
       return Padding(
         padding: EdgeInsets.only(left: 16.w, top: 24.h, right: 16.w),
@@ -159,7 +161,7 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
               customButton: Row(
                 children: [
                   Text(
-                    controller.currentCustomKeyboardInfo.name ?? "",
+                    typeController.currentKeyboardInfo.name ?? "",
                     style: TextStyle(
                       color: Colors.black.withAlpha(204),
                       fontSize: 16.sp,
@@ -180,14 +182,10 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
                   child: Divider(height: 1, color: Color(0xFFF6F6F6)),
                 ),
               ),
-              // 选项改变回调
-              onChanged: (String? newValue) {
-                controller.switchCustomKeyboard(newValue);
-              },
-              // 生成下拉菜单项
+              onChanged: controller.switchCustomKeyboard,
               items: List.generate(controller.customKeyboardInfoList.length, (
-                index,
-              ) {
+                  index,
+                  ) {
                 String? value = controller.customKeyboardInfoList[index].name;
                 return DropdownItem<String>(
                   value: value,
@@ -227,8 +225,13 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
   }
 
   Widget _buildIntimacySlider({required bool isCustom}) {
-    return // 亲密度模块
-    Container(
+    // 获取当前使用的子控制器
+    final typeController =
+    isCustom
+        ? controller.customKeyboardController
+        : controller.generalKeyboardController;
+
+    return Container(
       margin: EdgeInsets.only(left: 16.w, top: 24.h, right: 16.w),
       padding: EdgeInsets.only(
         left: 16.w,
@@ -270,9 +273,7 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
                 ),
                 child: Obx(() {
                   return Text(
-                    isCustom
-                        ? '${StringName.intimacy}${controller.currentCustomIntimacy}%'
-                        : '${StringName.intimacy}${controller.currentGeneralIntimacy}%',
+                    '${StringName.intimacy}${typeController.currentIntimacy}%',
                     textAlign: TextAlign.right,
                     style: TextStyle(
                       color: Colors.black.withAlpha(204),
@@ -299,11 +300,7 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
                 ),
                 child: Obx(() {
                   return Slider(
-                    value:
-                        isCustom
-                            ? controller.currentCustomIntimacy.toDouble()
-                            : controller.currentGeneralIntimacy.toDouble(),
-
+                    value: typeController.currentIntimacy.toDouble(),
                     divisions: 100,
                     min: 0,
                     max: 100,
@@ -322,6 +319,12 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
 
   // 键盘人设列表
   Widget _buildKeyboardCharacter({required bool isCustom}) {
+    // 获取当前使用的子控制器
+    final typeController =
+    isCustom
+        ? controller.customKeyboardController
+        : controller.generalKeyboardController;
+
     return Column(
       mainAxisAlignment: MainAxisAlignment.start,
       crossAxisAlignment: CrossAxisAlignment.start,
@@ -363,36 +366,22 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
                   controller.clickAddCharacter(isCustom: isCustom);
                 },
               ),
-              _buildFooterItem(
-                image: Assets.images.iconKeyboardManageCustom.image(
-                  width: 18.w,
-                  height: 18.w,
+              if (isCustom) // 仅在自定义键盘模式显示自定义人设选项
+                _buildFooterItem(
+                  image: Assets.images.iconKeyboardManageCustom.image(
+                    width: 18.w,
+                    height: 18.w,
+                  ),
+                  name: StringName.customCharacter,
+                  onTap: controller.clickCustomCharacter,
                 ),
-                name: StringName.customCharacter,
-                onTap: () {
-                  controller.clickCustomCharacter();
-                },
-              ),
             ],
-
             children:
-                isCustom
-                    ? controller.currentCustomKeyboardCharacterList
-                        .map(
-                          (e) => _buildKeyboardCharacterItem(
-                            e,
-                            isCustom: isCustom,
-                          ),
-                        )
-                        .toList()
-                    : controller.currentGeneralKeyboardCharacterList
-                        .map(
-                          (e) => _buildKeyboardCharacterItem(
-                            e,
-                            isCustom: isCustom,
-                          ),
-                        )
-                        .toList(),
+            typeController.characterList
+                .map(
+                  (e) => _buildKeyboardCharacterItem(e, isCustom: isCustom),
+            )
+                .toList(),
           );
         }),
       ],
@@ -503,13 +492,18 @@ class KeyboardManagePage extends BasePage<KeyboardManageController> {
 
   //   保存按钮
   Widget _buildSaveButton({required bool isCustom}) {
+    // 获取当前使用的子控制器
+    final typeController =
+    isCustom
+        ? controller.customKeyboardController
+        : controller.generalKeyboardController;
+
     return Obx(() {
+      // 检查是否有变化
       bool hasChanges =
-          isCustom
-              ? (controller.customKeyboardCharacterListChanged ||
-                  controller.customIntimacyChanged)
-              : (controller.generalKeyboardCharacterListChanged ||
-                  controller.generalIntimacyChanged.value);
+          typeController.intimacyChanged.value ||
+              typeController.characterListChanged.value;
+
       return GestureDetector(
         onTap: () {
           controller.clickSave(isCustom);

+ 228 - 0
lib/module/keyboard_manage/keyboard_type_controller.dart

@@ -0,0 +1,228 @@
+import 'dart:ui';
+
+import 'package:collection/collection.dart';
+import 'package:get/get.dart';
+
+import '../../data/bean/character_info.dart';
+import '../../data/bean/keyboard_info.dart';
+import '../../data/consts/error_code.dart';
+import '../../data/repository/characters_repository.dart';
+import '../../data/repository/keyboard_repository.dart';
+import '../../dialog/login/login_dialog.dart';
+import '../../plugins/keyboard_android_platform.dart';
+import '../../resource/string.gen.dart';
+import '../../utils/atmob_log.dart';
+import '../../utils/error_handler.dart';
+import '../../utils/http_handler.dart';
+import '../../utils/toast_util.dart';
+import '../character/content/character_group_content_controller.dart';
+
+enum KeyboardState { loading, loaded, saving, error }
+
+/// 键盘类型基础控制器 - 管理单个键盘类型的状态和操作
+class KeyboardTypeController {
+  final String tag;
+  final KeyboardRepository keyboardRepository;
+  final bool isCustom;
+  final int minCharacterCount = 9;
+
+  // 键盘信息
+  final Rx<KeyboardInfo> keyboardInfo = KeyboardInfo().obs;
+
+  KeyboardInfo get currentKeyboardInfo => keyboardInfo.value;
+
+  // 人设列表
+  final RxList<CharacterInfo> characterList = RxList();
+
+  List<CharacterInfo> get currentCharacterList => characterList;
+  List<CharacterInfo> oldCharacterList = [];
+
+  // 亲密度相关
+  final RxInt intimacy = 0.obs;
+
+  int get currentIntimacy => intimacy.value;
+
+  // 状态管理
+  final RxBool intimacyChanged = false.obs;
+  final RxBool characterListChanged = false.obs;
+  final Rx<KeyboardState> state = KeyboardState.loading.obs;
+
+  // 构造函数
+  KeyboardTypeController({
+    required this.tag,
+    required this.keyboardRepository,
+    required this.isCustom,
+  }) {
+    // 亲密度变更监听
+    intimacy.listen((_) {
+      intimacyChanged.value = keyboardInfo.value.intimacy != intimacy.value;
+      AtmobLog.d(tag, 'intimacyChanged: $intimacyChanged');
+    });
+
+    // 人设列表变更监听
+    characterList.listen((_) {
+      characterListChanged.value =
+          !ListEquality().equals(oldCharacterList, characterList);
+      AtmobLog.d(tag, 'characterListChanged: $characterListChanged');
+    });
+  }
+
+  // 加载键盘数据
+  void loadKeyboard(KeyboardInfo info) {
+    keyboardInfo.value = info;
+    intimacy.value = info.intimacy ?? 0;
+    String? id = info.id;
+    if (id != null) {
+      getKeyboardCharacterList(keyboardId: id);
+    }
+  }
+
+  // 获取键盘人设列表
+  void getKeyboardCharacterList({required String keyboardId}) {
+    state.value = KeyboardState.loading;
+
+    keyboardRepository
+        .getKeyboardCharacterList(keyboardId: keyboardId)
+        .then((response) {
+          AtmobLog.i(
+            tag,
+            'keyboardCharacterListResponse: ${response.characterInfos}',
+          );
+
+          if (keyboardInfo.value.id == keyboardId) {
+            characterList.assignAll(response.characterInfos);
+            oldCharacterList = List<CharacterInfo>.from(characterList);
+            intimacyChanged.value = false;
+            characterListChanged.value = false;
+            state.value = KeyboardState.loaded;
+          }
+        })
+        .catchError((error) {
+          state.value = KeyboardState.error;
+          if (error is ServerErrorException) {
+            ErrorHandler.toastError(error);
+          } else {
+            ToastUtil.show(StringName.keyboardSaveFailed);
+          }
+        });
+  }
+
+  // 更新亲密度
+  void updateIntimacy(int value) {
+    intimacy.value = value;
+  }
+
+  // 重新排序人设列表
+  void reorderCharacters(int oldIndex, int newIndex) {
+    AtmobLog.d(tag, 'reorderList: $oldIndex, $newIndex');
+    final item = characterList.removeAt(oldIndex);
+    characterList.insert(newIndex, item);
+  }
+
+  // 移除人设
+  bool removeCharacter(CharacterInfo characterInfo) {
+    if (characterList.length <= minCharacterCount) {
+      ToastUtil.show("最少需要保持$minCharacterCount个人设");
+      return false;
+    }
+
+    characterList.remove(characterInfo);
+    return true;
+  }
+
+  // 保存键盘信息
+  Future<bool> saveKeyboardInfo({required VoidCallback onSuccess}) async {
+    final String? keyboardId = keyboardInfo.value.id;
+    bool hasChanges = false;
+
+    if (keyboardId == null) {
+      return false;
+    }
+
+    state.value = KeyboardState.saving;
+
+    // 保存亲密度变更
+    if (intimacyChanged.value) {
+      AtmobLog.i(tag, 'Saving intimacy changes');
+      keyboardInfo.value.intimacy = currentIntimacy;
+
+      try {
+        await keyboardRepository.updateKeyboardInfo(
+          keyboardId: keyboardId,
+          intimacy: currentIntimacy,
+        );
+        await keyboardRepository.refreshData();
+        intimacyChanged.value = false;
+        hasChanges = true;
+      } catch (error) {
+        _handleError(error);
+        state.value = KeyboardState.error;
+        return false;
+      }
+    }
+
+    // 保存人设列表变更
+    if (characterListChanged.value) {
+      AtmobLog.i(tag, 'Saving character list changes');
+      List<String> characterIds =
+          characterList.map((e) => e.id).cast<String>().toList();
+
+      try {
+        await keyboardRepository.keyboardCharacterUpdate(
+          keyboardId: keyboardId,
+          characterIds: characterIds,
+        );
+        await keyboardRepository.refreshData();
+        oldCharacterList = List<CharacterInfo>.from(characterList);
+        characterListChanged.value = false;
+        hasChanges = true;
+      } catch (error) {
+        _handleError(error);
+        state.value = KeyboardState.error;
+        return false;
+      }
+    }
+
+    if (hasChanges) {
+      onSuccess();
+      ToastUtil.show(StringName.keyboardSaveSuccess);
+      refreshKeyboardData();
+    }
+
+    state.value = KeyboardState.loaded;
+    return hasChanges;
+  }
+
+  // 刷新键盘数据
+  void refreshKeyboardData() {
+    // 刷新所有人设组的数据
+    CharactersRepository.getInstance().characterGroupList.forEach((group) {
+      final controllerTag =
+          "CharacterGroupContentController${keyboardInfo.value.id}${group.id}";
+
+      if (Get.isRegistered<CharacterGroupContentController>(
+        tag: controllerTag,
+      )) {
+        var controller = Get.find<CharacterGroupContentController>(
+          tag: controllerTag,
+        );
+        controller.refreshData();
+      }
+    });
+
+    // 通知键盘,刷新人设列表
+    KeyboardAndroidPlatform.refreshCharacterList();
+  }
+
+  // 错误处理
+  void _handleError(dynamic error) {
+    if (error is ServerErrorException) {
+      ErrorHandler.toastError(error);
+      if (error.code == ErrorCode.noLoginError) {
+        LoginDialog.show();
+      }
+    } else {
+      ToastUtil.show(StringName.keyboardSaveFailed);
+    }
+  }
+}