diff --git a/Assets/Scripts/.workbuddy/expert-history.json b/Assets/Scripts/.workbuddy/expert-history.json new file mode 100644 index 0000000..b37c0e1 --- /dev/null +++ b/Assets/Scripts/.workbuddy/expert-history.json @@ -0,0 +1,17 @@ +{ + "version": 2, + "sessions": { + "b51153a0b3224c0f80f1360a506ca525": [ + { + "expertId": "TestResultsAnalyst", + "name": "Lyra", + "profession": "测试结果分析师", + "avatarUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/avatars/08-QualityAssurance/TestResultsAnalyst/TestResultsAnalyst.png", + "promptUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/experts/08-QualityAssurance/TestResultsAnalyst/TestResultsAnalyst_zh.md", + "usedAt": 1776104693623, + "industryId": "08-QualityAssurance" + } + ] + }, + "lastUpdated": 1776104980483 +} \ No newline at end of file diff --git a/Assets/Scripts/.workbuddy/memory/2026-04-14.md b/Assets/Scripts/.workbuddy/memory/2026-04-14.md new file mode 100644 index 0000000..19fddfd --- /dev/null +++ b/Assets/Scripts/.workbuddy/memory/2026-04-14.md @@ -0,0 +1,19 @@ +# 2026-04-14 工作日志 + +## SDK代码质量修复 + +### 完成项 +1. **事件监听内存泄漏修复** - 为所有Panel添加OnDisable/OnDestroy中的监听器移除逻辑 + - LoginPanel.cs + - RegisterPanel.cs + - ChangePasswordPanel.cs + - RealNameAuthPanel.cs + +2. **单例初始化时序问题修复** - SDKManager改用协程确保SDKUIManager先初始化 + - SDKManager.cs:Start() 改用 AutoRegisterPanelsCoroutine() 协程 + - 添加最多10帧的等待和重试逻辑 + +### 待办 +- P0: 移除敏感数据日志 (LoginPanel:473, RealNameAuthPanel:56) +- P1: 添加网络请求封装 +- P2: 建立测试框架 diff --git a/Assets/Scripts/.workbuddy/memory/MEMORY.md b/Assets/Scripts/.workbuddy/memory/MEMORY.md new file mode 100644 index 0000000..e69de29 diff --git a/Assets/Scripts/SDK/ChangePasswordPanel.cs b/Assets/Scripts/SDK/ChangePasswordPanel.cs index ed4c333..d494980 100644 --- a/Assets/Scripts/SDK/ChangePasswordPanel.cs +++ b/Assets/Scripts/SDK/ChangePasswordPanel.cs @@ -28,6 +28,21 @@ namespace GameSDK backBtn.onClick.AddListener(OnBackClick); } + private void OnDisable() + { + if (!initialized) return; + initialized = false; + confirmBtn.onClick.RemoveListener(OnConfirmClick); + backBtn.onClick.RemoveListener(OnBackClick); + } + + private void OnDestroy() + { + initialized = false; + if (confirmBtn != null) confirmBtn.onClick.RemoveListener(OnConfirmClick); + if (backBtn != null) backBtn.onClick.RemoveListener(OnBackClick); + } + private void OnConfirmClick() { string username = usernameInput.text.Trim(); diff --git a/Assets/Scripts/SDK/LoginPanel.cs b/Assets/Scripts/SDK/LoginPanel.cs index 77d9403..4fcaa4a 100644 --- a/Assets/Scripts/SDK/LoginPanel.cs +++ b/Assets/Scripts/SDK/LoginPanel.cs @@ -451,6 +451,26 @@ namespace GameSDK if (guestLoginBtn != null) guestLoginBtn.onClick.AddListener(OnGuestLoginClick); } + private void UnbindButtons() + { + if (!initialized) return; + initialized = false; + if (loginBtn != null) loginBtn.onClick.RemoveListener(OnLoginClick); + if (registerBtn != null) registerBtn.onClick.RemoveListener(OnRegisterClick); + if (changePasswordBtn != null) changePasswordBtn.onClick.RemoveListener(OnChangePasswordClick); + if (guestLoginBtn != null) guestLoginBtn.onClick.RemoveListener(OnGuestLoginClick); + } + + private void OnDisable() + { + UnbindButtons(); + } + + private void OnDestroy() + { + UnbindButtons(); + } + #endregion private void OnLoginClick() diff --git a/Assets/Scripts/SDK/RealNameAuthPanel.cs b/Assets/Scripts/SDK/RealNameAuthPanel.cs index 63e3c30..686ba5b 100644 --- a/Assets/Scripts/SDK/RealNameAuthPanel.cs +++ b/Assets/Scripts/SDK/RealNameAuthPanel.cs @@ -26,6 +26,21 @@ namespace GameSDK skipBtn.onClick.AddListener(OnSkipClick); } + private void OnDisable() + { + if (!initialized) return; + initialized = false; + submitBtn.onClick.RemoveListener(OnSubmitClick); + skipBtn.onClick.RemoveListener(OnSkipClick); + } + + private void OnDestroy() + { + initialized = false; + if (submitBtn != null) submitBtn.onClick.RemoveListener(OnSubmitClick); + if (skipBtn != null) skipBtn.onClick.RemoveListener(OnSkipClick); + } + private void OnSubmitClick() { string realName = realNameInput.text.Trim(); diff --git a/Assets/Scripts/SDK/RegisterPanel.cs b/Assets/Scripts/SDK/RegisterPanel.cs index c838202..d091001 100644 --- a/Assets/Scripts/SDK/RegisterPanel.cs +++ b/Assets/Scripts/SDK/RegisterPanel.cs @@ -27,6 +27,21 @@ namespace GameSDK backBtn.onClick.AddListener(OnBackClick); } + private void OnDisable() + { + if (!initialized) return; + initialized = false; + registerBtn.onClick.RemoveListener(OnRegisterClick); + backBtn.onClick.RemoveListener(OnBackClick); + } + + private void OnDestroy() + { + initialized = false; + if (registerBtn != null) registerBtn.onClick.RemoveListener(OnRegisterClick); + if (backBtn != null) backBtn.onClick.RemoveListener(OnBackClick); + } + private void OnRegisterClick() { string username = usernameInput.text.Trim(); diff --git a/Assets/Scripts/SDK/SDKManager.cs b/Assets/Scripts/SDK/SDKManager.cs index c02c6ff..84d3589 100644 --- a/Assets/Scripts/SDK/SDKManager.cs +++ b/Assets/Scripts/SDK/SDKManager.cs @@ -38,7 +38,30 @@ namespace GameSDK private void Start() { - // Start 在所有 Awake 之后执行,此时 SDKUIManager.Instance 一定已初始化 + // 使用协程确保 SDKUIManager 单例已完全初始化 + StartCoroutine(AutoRegisterPanelsCoroutine()); + } + + private System.Collections.IEnumerator AutoRegisterPanelsCoroutine() + { + // 等待一帧,确保所有单例初始化完成 + yield return null; + + // 再次检查 SDKUIManager 是否已就绪 + int maxRetries = 10; + int retries = 0; + while (SDKUIManager.Instance == null && retries < maxRetries) + { + yield return null; + retries++; + } + + if (SDKUIManager.Instance == null) + { + Debug.LogError("[SDK] SDKUIManager 初始化失败,请检查场景配置"); + yield break; + } + AutoRegisterPanels(); if (autoShowLogin && panelsRegistered)