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);
Destroy(gameObject);
}
/// <summary>当前已打开的WiFi设置页实例(防连点重入)</summary>
private SetWifiPage currentWifiPage;
public void OnWifiButtonClick()
{
// WiFi模式下不支持设置WiFi
@ -117,18 +119,24 @@ namespace Kill.UI.Pages
ToastUI.Show("100293");
return;
}
SetWifiPage wifiPage=Instantiate(setWifiPage, transform);
wifiPage.gameObject.SetActive(true);
wifiPage.Init(WIfiCallback);
// 防连点:页面已打开时忽略重复触发
if (currentWifiPage != null) return;
currentWifiPage=Instantiate(setWifiPage, transform);
currentWifiPage.gameObject.SetActive(true);
currentWifiPage.Init(WIfiCallback);
}
public void WIfiCallback(string ssid)
{
infoTexts[5].text = ssid;
}
/// <summary>当前已打开的固件更新页实例(防连点重入)</summary>
private FirmwareUpdatePage currentFirmwareUpdatePage;
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");
return value;
}
/// <summary>当前已打开的RGB设置页实例(防连点重入)</summary>
private RGBlightSetting currentRgbSetting;
public void OpenRgbSetting()
{
RGBlightSetting settingPage = Instantiate(rGBlightSetting.gameObject, transform).GetComponent<RGBlightSetting>();
settingPage.gameObject.SetActive(true);
settingPage.Init(CloseRgbSetting, rGBControl);
// 防连点:页面已打开时忽略重复触发
if (currentRgbSetting != null) return;
currentRgbSetting = Instantiate(rGBlightSetting.gameObject, transform).GetComponent<RGBlightSetting>();
currentRgbSetting.gameObject.SetActive(true);
currentRgbSetting.Init(CloseRgbSetting, rGBControl);
}
public void CloseRgbSetting(RGBControl ct)
{
@ -272,22 +276,30 @@ namespace Kill.UI.Pages
rgbValue.text = GetOnOffValue(rGBControl.Enable);
UIManager.Instance.RegisterBackAction(Back);
}
/// <summary>当前已打开的LCD设置页实例(防连点重入)</summary>
private LCDSetting currentLcdSetting;
public void OpenLCDSetting()
{
LCDSetting settingPage = Instantiate(lcdSetting.gameObject, transform).GetComponent<LCDSetting>();
settingPage.gameObject.SetActive(true);
settingPage.Init(CloseLCDSetting);
// 防连点:页面已打开时忽略重复触发
if (currentLcdSetting != null) return;
currentLcdSetting = Instantiate(lcdSetting.gameObject, transform).GetComponent<LCDSetting>();
currentLcdSetting.gameObject.SetActive(true);
currentLcdSetting.Init(CloseLCDSetting);
}
public void CloseLCDSetting()
{
UIManager.Instance.RegisterBackAction(Back);
}
public RenamePage renamePage;
/// <summary>当前已打开的重命名页实例(防连点重入)</summary>
private RenamePage currentRenamePage;
public void OpenRenamePage()
{
RenamePage settingPage = Instantiate(renamePage.gameObject, transform).GetComponent<RenamePage>();
settingPage.gameObject.SetActive(true);
settingPage.Init(deviceInfo.device_name, CloseRenamePage);
// 防连点:页面已打开时忽略重复触发
if (currentRenamePage != null) return;
currentRenamePage = Instantiate(renamePage.gameObject, transform).GetComponent<RenamePage>();
currentRenamePage.gameObject.SetActive(true);
currentRenamePage.Init(deviceInfo.device_name, CloseRenamePage);
}
public void CloseRenamePage(string newName)
{
@ -297,11 +309,15 @@ namespace Kill.UI.Pages
DataManager.Instance.selectedDevice.device_name = newName;
}
public VideoAndSoundSetting videoAndSoundSetting;
/// <summary>当前已打开的音视频设置页实例(防连点重入)</summary>
private VideoAndSoundSetting currentVideoAndSoundSetting;
public void OpenVideoAndSoundSetting()
{
VideoAndSoundSetting settingPage = Instantiate(videoAndSoundSetting.gameObject, transform).GetComponent<VideoAndSoundSetting>();
settingPage.gameObject.SetActive(true);
settingPage.Init(CloseVideoAndSoundSetting);
// 防连点:页面已打开时忽略重复触发
if (currentVideoAndSoundSetting != null) return;
currentVideoAndSoundSetting = Instantiate(videoAndSoundSetting.gameObject, transform).GetComponent<VideoAndSoundSetting>();
currentVideoAndSoundSetting.gameObject.SetActive(true);
currentVideoAndSoundSetting.Init(CloseVideoAndSoundSetting);
}
public void CloseVideoAndSoundSetting()
{
@ -463,15 +479,23 @@ namespace Kill.UI.Pages
});
}
}
/// <summary>当前已打开的分享设备页实例(防连点重入)</summary>
private ShareDevicePage currentShareDevicePage;
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()
{
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()
{
@ -538,10 +562,14 @@ namespace Kill.UI.Pages
Debug.LogError("取消设备共享失败: " + ex.Message);
}
}
/// <summary>当前已打开的关于设备页实例(防连点重入)</summary>
private AboutDevicePage currentAboutDevicePage;
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()
{

View File

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

View File

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

View File

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