feat: 为多处UI交互添加防连点重入逻辑

1.  为WiFi配置、固件升级、设备信息页的多个设置页面添加防重复点击逻辑
2.  为定时任务、FOV/镜头/灯光/安全设置、消息页等主页功能添加防连点
3.  新增锁定指令、WiFi配置发送的状态标记避免重复触发
4.  所有页面打开时检查实例状态,避免重复创建页面实例
This commit is contained in:
“虞渠成” 2026-08-14 08:35:38 +08:00
parent c3910747dd
commit e11d67df32
5 changed files with 149 additions and 43 deletions

View File

@ -109,6 +109,8 @@ namespace Kill.UI.Pages
UIManager.Instance.RegisterBackAction(GetComponentInParent<DeviceInfoPage>().Back); UIManager.Instance.RegisterBackAction(GetComponentInParent<DeviceInfoPage>().Back);
Destroy(gameObject); Destroy(gameObject);
} }
/// <summary>当前已打开的WiFi设置页实例(防连点重入)</summary>
private SetWifiPage currentWifiPage;
public void OnWifiButtonClick() public void OnWifiButtonClick()
{ {
// WiFi模式下不支持设置WiFi // WiFi模式下不支持设置WiFi
@ -117,18 +119,24 @@ namespace Kill.UI.Pages
ToastUI.Show("100293"); ToastUI.Show("100293");
return; return;
} }
SetWifiPage wifiPage=Instantiate(setWifiPage, transform); // 防连点:页面已打开时忽略重复触发
wifiPage.gameObject.SetActive(true); if (currentWifiPage != null) return;
wifiPage.Init(WIfiCallback); currentWifiPage=Instantiate(setWifiPage, transform);
currentWifiPage.gameObject.SetActive(true);
currentWifiPage.Init(WIfiCallback);
} }
public void WIfiCallback(string ssid) public void WIfiCallback(string ssid)
{ {
infoTexts[5].text = ssid; infoTexts[5].text = ssid;
} }
/// <summary>当前已打开的固件更新页实例(防连点重入)</summary>
private FirmwareUpdatePage currentFirmwareUpdatePage;
public void OnFirmwareUpdateButtonClick() public void OnFirmwareUpdateButtonClick()
{ {
FirmwareUpdatePage page = Instantiate(firmwareUpdatePage, transform); // 防连点:页面已打开时忽略重复触发
page.gameObject.SetActive(true); if (currentFirmwareUpdatePage != null) return;
currentFirmwareUpdatePage = Instantiate(firmwareUpdatePage, transform);
currentFirmwareUpdatePage.gameObject.SetActive(true);
} }
} }

View File

@ -260,11 +260,15 @@ namespace Kill.UI.Pages
string value = ison ? LanguageManager.Instance.GetLanguage("100099") : LanguageManager.Instance.GetLanguage("100100"); string value = ison ? LanguageManager.Instance.GetLanguage("100099") : LanguageManager.Instance.GetLanguage("100100");
return value; return value;
} }
/// <summary>当前已打开的RGB设置页实例(防连点重入)</summary>
private RGBlightSetting currentRgbSetting;
public void OpenRgbSetting() public void OpenRgbSetting()
{ {
RGBlightSetting settingPage = Instantiate(rGBlightSetting.gameObject, transform).GetComponent<RGBlightSetting>(); // 防连点:页面已打开时忽略重复触发
settingPage.gameObject.SetActive(true); if (currentRgbSetting != null) return;
settingPage.Init(CloseRgbSetting, rGBControl); currentRgbSetting = Instantiate(rGBlightSetting.gameObject, transform).GetComponent<RGBlightSetting>();
currentRgbSetting.gameObject.SetActive(true);
currentRgbSetting.Init(CloseRgbSetting, rGBControl);
} }
public void CloseRgbSetting(RGBControl ct) public void CloseRgbSetting(RGBControl ct)
{ {
@ -272,22 +276,30 @@ namespace Kill.UI.Pages
rgbValue.text = GetOnOffValue(rGBControl.Enable); rgbValue.text = GetOnOffValue(rGBControl.Enable);
UIManager.Instance.RegisterBackAction(Back); UIManager.Instance.RegisterBackAction(Back);
} }
/// <summary>当前已打开的LCD设置页实例(防连点重入)</summary>
private LCDSetting currentLcdSetting;
public void OpenLCDSetting() public void OpenLCDSetting()
{ {
LCDSetting settingPage = Instantiate(lcdSetting.gameObject, transform).GetComponent<LCDSetting>(); // 防连点:页面已打开时忽略重复触发
settingPage.gameObject.SetActive(true); if (currentLcdSetting != null) return;
settingPage.Init(CloseLCDSetting); currentLcdSetting = Instantiate(lcdSetting.gameObject, transform).GetComponent<LCDSetting>();
currentLcdSetting.gameObject.SetActive(true);
currentLcdSetting.Init(CloseLCDSetting);
} }
public void CloseLCDSetting() public void CloseLCDSetting()
{ {
UIManager.Instance.RegisterBackAction(Back); UIManager.Instance.RegisterBackAction(Back);
} }
public RenamePage renamePage; public RenamePage renamePage;
/// <summary>当前已打开的重命名页实例(防连点重入)</summary>
private RenamePage currentRenamePage;
public void OpenRenamePage() public void OpenRenamePage()
{ {
RenamePage settingPage = Instantiate(renamePage.gameObject, transform).GetComponent<RenamePage>(); // 防连点:页面已打开时忽略重复触发
settingPage.gameObject.SetActive(true); if (currentRenamePage != null) return;
settingPage.Init(deviceInfo.device_name, CloseRenamePage); currentRenamePage = Instantiate(renamePage.gameObject, transform).GetComponent<RenamePage>();
currentRenamePage.gameObject.SetActive(true);
currentRenamePage.Init(deviceInfo.device_name, CloseRenamePage);
} }
public void CloseRenamePage(string newName) public void CloseRenamePage(string newName)
{ {
@ -297,11 +309,15 @@ namespace Kill.UI.Pages
DataManager.Instance.selectedDevice.device_name = newName; DataManager.Instance.selectedDevice.device_name = newName;
} }
public VideoAndSoundSetting videoAndSoundSetting; public VideoAndSoundSetting videoAndSoundSetting;
/// <summary>当前已打开的音视频设置页实例(防连点重入)</summary>
private VideoAndSoundSetting currentVideoAndSoundSetting;
public void OpenVideoAndSoundSetting() public void OpenVideoAndSoundSetting()
{ {
VideoAndSoundSetting settingPage = Instantiate(videoAndSoundSetting.gameObject, transform).GetComponent<VideoAndSoundSetting>(); // 防连点:页面已打开时忽略重复触发
settingPage.gameObject.SetActive(true); if (currentVideoAndSoundSetting != null) return;
settingPage.Init(CloseVideoAndSoundSetting); currentVideoAndSoundSetting = Instantiate(videoAndSoundSetting.gameObject, transform).GetComponent<VideoAndSoundSetting>();
currentVideoAndSoundSetting.gameObject.SetActive(true);
currentVideoAndSoundSetting.Init(CloseVideoAndSoundSetting);
} }
public void CloseVideoAndSoundSetting() public void CloseVideoAndSoundSetting()
{ {
@ -463,15 +479,23 @@ namespace Kill.UI.Pages
}); });
} }
} }
/// <summary>当前已打开的分享设备页实例(防连点重入)</summary>
private ShareDevicePage currentShareDevicePage;
public void OpenShareDevicePage() public void OpenShareDevicePage()
{ {
ShareDevicePage settingPage = Instantiate(shareDevicePage.gameObject, transform).GetComponent<ShareDevicePage>(); // 防连点:页面已打开时忽略重复触发
settingPage.gameObject.SetActive(true); if (currentShareDevicePage != null) return;
currentShareDevicePage = Instantiate(shareDevicePage.gameObject, transform).GetComponent<ShareDevicePage>();
currentShareDevicePage.gameObject.SetActive(true);
} }
/// <summary>当前已打开的共享用户页实例(防连点重入)</summary>
private DeviceSharedUserPage currentDeviceSharedUserPage;
public void OpenDeviceSharedUserPage() public void OpenDeviceSharedUserPage()
{ {
DeviceSharedUserPage settingPage = Instantiate(deviceSharedUserPage.gameObject, transform).GetComponent<DeviceSharedUserPage>(); // 防连点:页面已打开时忽略重复触发
settingPage.gameObject.SetActive(true); if (currentDeviceSharedUserPage != null) return;
currentDeviceSharedUserPage = Instantiate(deviceSharedUserPage.gameObject, transform).GetComponent<DeviceSharedUserPage>();
currentDeviceSharedUserPage.gameObject.SetActive(true);
} }
public void CancelShareBySharedUser() public void CancelShareBySharedUser()
{ {
@ -538,10 +562,14 @@ namespace Kill.UI.Pages
Debug.LogError("取消设备共享失败: " + ex.Message); Debug.LogError("取消设备共享失败: " + ex.Message);
} }
} }
/// <summary>当前已打开的关于设备页实例(防连点重入)</summary>
private AboutDevicePage currentAboutDevicePage;
public void OpenAboutDevicePage() public void OpenAboutDevicePage()
{ {
AboutDevicePage settingPage = Instantiate(aboutDevicePage.gameObject, transform).GetComponent<AboutDevicePage>(); // 防连点:页面已打开时忽略重复触发
settingPage.gameObject.SetActive(true); if (currentAboutDevicePage != null) return;
currentAboutDevicePage = Instantiate(aboutDevicePage.gameObject, transform).GetComponent<AboutDevicePage>();
currentAboutDevicePage.gameObject.SetActive(true);
} }
public IEnumerator BackToHomePage() public IEnumerator BackToHomePage()
{ {

View File

@ -95,12 +95,18 @@ namespace Kill.UI.Pages
Destroy(gameObject); Destroy(gameObject);
Screen.sleepTimeout = SleepTimeout.SystemSetting; Screen.sleepTimeout = SleepTimeout.SystemSetting;
} }
private bool isUpdating; // OTA升级进行中(防连点重入)
public async void OnUpdateButtonClick() public async void OnUpdateButtonClick()
{ {
// 防连点升级流程进行中忽略重复触发避免并发启动两个OTA
if (isUpdating) return;
isUpdating = true;
Screen.sleepTimeout = SleepTimeout.NeverSleep; Screen.sleepTimeout = SleepTimeout.NeverSleep;
// WiFi 模式:直接 push OTA 指令,设备自行下载固件 // WiFi 模式:直接 push OTA 指令,设备自行下载固件
if (DataManager.Instance.hasWifi) if (DataManager.Instance.hasWifi)
{
try
{ {
var pushRequest = new OTAPushRequest var pushRequest = new OTAPushRequest
{ {
@ -120,6 +126,15 @@ namespace Kill.UI.Pages
Debug.LogError($"WiFi OTA push 失败: {message}"); Debug.LogError($"WiFi OTA push 失败: {message}");
} }
); );
}
catch (System.Exception ex)
{
Debug.LogError($"WiFi OTA push 异常: {ex.Message}");
}
finally
{
isUpdating = false;
}
UIManager.Instance.OpenMainPage(UIManager.PageName.homePage); UIManager.Instance.OpenMainPage(UIManager.PageName.homePage);
return; return;
} }
@ -133,6 +148,7 @@ namespace Kill.UI.Pages
if (!downloadResult.IsSuccess) if (!downloadResult.IsSuccess)
{ {
ToastUI.Show("100224"); ToastUI.Show("100224");
isUpdating = false;
return; return;
} }
string md5 = NetworkCtrl.Instance.CalculateMD5(savePath); string md5 = NetworkCtrl.Instance.CalculateMD5(savePath);
@ -141,9 +157,15 @@ namespace Kill.UI.Pages
ToastUI.Show("100223"); ToastUI.Show("100223");
Debug.LogError("下载的文件MD5校验失败"); Debug.LogError("下载的文件MD5校验失败");
File.Delete(savePath); File.Delete(savePath);
isUpdating = false;
return; return;
} }
LoadFirmwareFile(savePath); LoadFirmwareFile(savePath);
if (_selectedFirmwareData == null)
{
isUpdating = false;
return;
}
ToastUI.Show("100225"); ToastUI.Show("100225");
UpdateLoadingUI.Instance.SetPrecent(0); UpdateLoadingUI.Instance.SetPrecent(0);
@ -154,6 +176,7 @@ namespace Kill.UI.Pages
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
isUpdating = false;
if (success) if (success)
{ {
ToastUI.Show("100226"); ToastUI.Show("100226");

View File

@ -70,6 +70,7 @@ namespace Kill.UI.Pages
confirmButton.gameObject.SetActive(true); confirmButton.gameObject.SetActive(true);
} }
} }
private bool isSending; // WiFi配置发送中(防连点重入)
/// <summary> /// <summary>
/// 确认配置 WiFi /// 确认配置 WiFi
/// </summary> /// </summary>
@ -91,6 +92,10 @@ namespace Kill.UI.Pages
return; return;
} }
// 防连点:配置发送中忽略重复触发,避免重复写入
if (isSending) return;
isSending = true;
// 创建 WiFi 配置 // 创建 WiFi 配置
var wifiControl = new Bluetooth.Protocol.WIFIControl var wifiControl = new Bluetooth.Protocol.WIFIControl
{ {
@ -106,6 +111,7 @@ namespace Kill.UI.Pages
{ {
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
isSending = false;
LoadingUI.Hide(); LoadingUI.Hide();
if (success) if (success)
{ {

View File

@ -40,6 +40,8 @@ namespace Kill.UI.Pages
public HomePageSchedule deviceSchedule; public HomePageSchedule deviceSchedule;
public Button scheduleSettingButton; public Button scheduleSettingButton;
public GameObject scheduleSettingPrefab; public GameObject scheduleSettingPrefab;
/// <summary>当前已打开的定时任务页实例(防连点重入)</summary>
private GameObject currentScheduleSettingPage;
/// <summary> /// <summary>
/// 触发密码验证按钮 /// 触发密码验证按钮
/// </summary> /// </summary>
@ -83,6 +85,7 @@ namespace Kill.UI.Pages
float waitLockTime=0; float waitLockTime=0;
private bool isLockSending; // 锁定/解锁指令发送中(防连点重入)
void FixedUpdate() void FixedUpdate()
{ {
if(!LockButtonPlane.activeSelf) if(!LockButtonPlane.activeSelf)
@ -1041,6 +1044,8 @@ namespace Kill.UI.Pages
public void ShowDeviceList() public void ShowDeviceList()
{ {
// 设备列表已打开时忽略重复触发
if (selectDevicePage.activeSelf) return;
selectDevicePage.SetActive(true); selectDevicePage.SetActive(true);
selectDevicePage.GetComponent<HomePageDevicePage>().InitDeviceList(OwnedDevices, SharedDevices, selectedDevice); selectDevicePage.GetComponent<HomePageDevicePage>().InitDeviceList(OwnedDevices, SharedDevices, selectedDevice);
UIManager.Instance.RegisterBackAction(() => UIManager.Instance.RegisterBackAction(() =>
@ -1049,6 +1054,8 @@ namespace Kill.UI.Pages
}); });
} }
public GameObject fovSettingPagePrefab; public GameObject fovSettingPagePrefab;
/// <summary>当前已打开的FOV设置页实例(防连点重入)</summary>
private GameObject currentFovSettingPage;
public void ShowFovSettingPage() public void ShowFovSettingPage()
{ {
waitLockTime=0; waitLockTime=0;
@ -1057,7 +1064,9 @@ namespace Kill.UI.Pages
Debug.LogError("[HomePageCtrl] 未设置FOV设置页面预制体"); Debug.LogError("[HomePageCtrl] 未设置FOV设置页面预制体");
return; return;
} }
if (currentFovSettingPage != null) return;
GameObject fovSettingPage = Instantiate(fovSettingPagePrefab, transform); GameObject fovSettingPage = Instantiate(fovSettingPagePrefab, transform);
currentFovSettingPage = fovSettingPage;
fovSettingPage.SetActive(true); fovSettingPage.SetActive(true);
UIManager.Instance.RegisterBackAction(() => UIManager.Instance.RegisterBackAction(() =>
{ {
@ -1065,6 +1074,8 @@ namespace Kill.UI.Pages
}); });
} }
public GameObject lensSettingPagePrefab; public GameObject lensSettingPagePrefab;
/// <summary>当前已打开的镜头设置页实例(防连点重入)</summary>
private GameObject currentLensSettingPage;
public void ShowLensSettingPage() public void ShowLensSettingPage()
{ {
waitLockTime=0; waitLockTime=0;
@ -1073,7 +1084,9 @@ namespace Kill.UI.Pages
Debug.LogError("[HomePageCtrl] 未设置lens设置页面预制体"); Debug.LogError("[HomePageCtrl] 未设置lens设置页面预制体");
return; return;
} }
if (currentLensSettingPage != null) return;
GameObject lensSettingPage = Instantiate(lensSettingPagePrefab, transform); GameObject lensSettingPage = Instantiate(lensSettingPagePrefab, transform);
currentLensSettingPage = lensSettingPage;
lensSettingPage.SetActive(true); lensSettingPage.SetActive(true);
UIManager.Instance.RegisterBackAction(() => UIManager.Instance.RegisterBackAction(() =>
{ {
@ -1081,6 +1094,8 @@ namespace Kill.UI.Pages
}); });
} }
public GameObject lightSettingPagePrefab; public GameObject lightSettingPagePrefab;
/// <summary>当前已打开的灯光设置页实例(防连点重入)</summary>
private GameObject currentLightSettingPage;
public void ShowLightSettingPage() public void ShowLightSettingPage()
{ {
waitLockTime=0; waitLockTime=0;
@ -1089,7 +1104,9 @@ namespace Kill.UI.Pages
Debug.LogError("[HomePageCtrl] 未设置light设置页面预制体"); Debug.LogError("[HomePageCtrl] 未设置light设置页面预制体");
return; return;
} }
if (currentLightSettingPage != null) return;
GameObject lightSettingPage = Instantiate(lightSettingPagePrefab, transform); GameObject lightSettingPage = Instantiate(lightSettingPagePrefab, transform);
currentLightSettingPage = lightSettingPage;
lightSettingPage.SetActive(true); lightSettingPage.SetActive(true);
UIManager.Instance.RegisterBackAction(() => UIManager.Instance.RegisterBackAction(() =>
{ {
@ -1097,6 +1114,8 @@ namespace Kill.UI.Pages
}); });
} }
public GameObject safetySettingPagePrefab; public GameObject safetySettingPagePrefab;
/// <summary>当前已打开的安全设置页实例(防连点重入)</summary>
private GameObject currentSafetySettingPage;
public void ShowSafetySettingPage() public void ShowSafetySettingPage()
{ {
waitLockTime=0; waitLockTime=0;
@ -1105,7 +1124,9 @@ namespace Kill.UI.Pages
Debug.LogError("[HomePageCtrl] 未设置safetySettingPage预制体"); Debug.LogError("[HomePageCtrl] 未设置safetySettingPage预制体");
return; return;
} }
if (currentSafetySettingPage != null) return;
GameObject safetySettingPage = Instantiate(safetySettingPagePrefab, transform); GameObject safetySettingPage = Instantiate(safetySettingPagePrefab, transform);
currentSafetySettingPage = safetySettingPage;
safetySettingPage.SetActive(true); safetySettingPage.SetActive(true);
UIManager.Instance.RegisterBackAction(() => UIManager.Instance.RegisterBackAction(() =>
{ {
@ -1121,7 +1142,9 @@ namespace Kill.UI.Pages
Debug.LogError("[HomePageCtrl] 未设置scheduleSettingPage预制体"); Debug.LogError("[HomePageCtrl] 未设置scheduleSettingPage预制体");
return; return;
} }
if (currentScheduleSettingPage != null) return;
GameObject scheduleSettingPage = Instantiate(scheduleSettingPrefab, transform); GameObject scheduleSettingPage = Instantiate(scheduleSettingPrefab, transform);
currentScheduleSettingPage = scheduleSettingPage;
scheduleSettingPage.SetActive(true); scheduleSettingPage.SetActive(true);
// 注册页面关闭回调,更新主页定时任务显示 // 注册页面关闭回调,更新主页定时任务显示
@ -1163,10 +1186,13 @@ namespace Kill.UI.Pages
UIManager.Instance.OpenPage(UIManager.PageName.selfPage); UIManager.Instance.OpenPage(UIManager.PageName.selfPage);
} }
public MessageTypeListPage messagePagePrefab; public MessageTypeListPage messagePagePrefab;
/// <summary>当前已打开的消息页实例(防连点重入)</summary>
private MessageTypeListPage currentMessagePage;
public void EnterMessagePage() public void EnterMessagePage()
{ {
waitLockTime=0; waitLockTime=0;
Instantiate(messagePagePrefab,transform); if (currentMessagePage != null) return;
currentMessagePage = Instantiate(messagePagePrefab,transform);
} }
public void EnterVideoPage() public void EnterVideoPage()
{ {
@ -1176,6 +1202,9 @@ namespace Kill.UI.Pages
public async void SetLock(bool ison) public async void SetLock(bool ison)
{ {
waitLockTime=0; waitLockTime=0;
// 防连点:指令发送中忽略重复触发
if (isLockSending) return;
isLockSending = true;
if (hasBluetooth) if (hasBluetooth)
{ {
BLECommunicationManager.Instance.WriteDeviceLockControl(!ison, (success) => BLECommunicationManager.Instance.WriteDeviceLockControl(!ison, (success) =>
@ -1183,6 +1212,7 @@ namespace Kill.UI.Pages
Loom.QueueOnMainThread(() => Loom.QueueOnMainThread(() =>
{ {
isLockSending = false;
if (ison) if (ison)
{ {
DeviceLockControl deviceLockControl = new DeviceLockControl(); DeviceLockControl deviceLockControl = new DeviceLockControl();
@ -1237,12 +1267,14 @@ namespace Kill.UI.Pages
finally finally
{ {
LoadingUI.Hide(); LoadingUI.Hide();
isLockSending = false;
} }
} }
else else
{ {
LoadingUI.Hide(); LoadingUI.Hide();
ToastUI.Show("100081"); ToastUI.Show("100081");
isLockSending = false;
} }
} }
@ -1845,6 +1877,10 @@ namespace Kill.UI.Pages
} }
public SetWifiPage setWifiPage; public SetWifiPage setWifiPage;
/// <summary>
/// 当前已打开的WiFi设置页实例用于防连点重入
/// </summary>
private SetWifiPage currentWifiPage;
public void EnterWifiPage() public void EnterWifiPage()
{ {
// WiFi模式下不支持设置WiFi // WiFi模式下不支持设置WiFi
@ -1853,9 +1889,14 @@ namespace Kill.UI.Pages
ToastUI.Show("100293"); ToastUI.Show("100293");
return; return;
} }
SetWifiPage wifiPage=Instantiate(setWifiPage, transform); // 防连点:页面已打开时忽略重复触发,避免连续实例化导致页面叠放/重复请求权限/重复注册返回键
wifiPage.gameObject.SetActive(true); if (currentWifiPage != null)
wifiPage.Init(null,1); {
return;
}
currentWifiPage=Instantiate(setWifiPage, transform);
currentWifiPage.gameObject.SetActive(true);
currentWifiPage.Init(null,1);
} }
} }