diff --git a/Assets/Res/language/language.json b/Assets/Res/language/language.json
index 180aa5d..b1539d0 100644
--- a/Assets/Res/language/language.json
+++ b/Assets/Res/language/language.json
@@ -199,6 +199,11 @@
"zh": "账号或密码错误,请重试",
"en": "Incorrect account or password. Please try again."
},
+ {
+ "key": "home_password_check_failed",
+ "zh": "密码错误或校验失败,请重试",
+ "en": "Password incorrect or verification failed. Please try again."
+ },
{
"key": "100041",
"zh": "该邮箱已绑定至其他账号,请更换邮箱",
diff --git a/Assets/Res/ui/homepage/homePage.prefab b/Assets/Res/ui/homepage/homePage.prefab
index 89138e5..44fa832 100644
--- a/Assets/Res/ui/homepage/homePage.prefab
+++ b/Assets/Res/ui/homepage/homePage.prefab
@@ -7955,6 +7955,7 @@ GameObject:
- component: {fileID: 6551506190466531803}
- component: {fileID: 3881773501436982883}
- component: {fileID: 6647875750186480783}
+ - component: {fileID: 2568189713370643574}
m_Layer: 5
m_Name: "\u65E0\u8BBE\u5907"
m_TagString: Untagged
@@ -8004,7 +8005,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
- m_RaycastTarget: 0
+ m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
@@ -8020,6 +8021,18 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
+--- !u!114 &2568189713370643574
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 3582556473535289502}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 432e8b6f5f7dd7a4f94d9c3b85c8b262, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
--- !u!1 &3686991546777705807
GameObject:
m_ObjectHideFlags: 0
@@ -15843,7 +15856,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 0}
- m_AnchoredPosition: {x: -9.000002, y: 10}
+ m_AnchoredPosition: {x: -9, y: 10}
m_SizeDelta: {x: -57.999992, y: 55}
m_Pivot: {x: 0.5, y: 0}
--- !u!222 &3186938245855593830
@@ -16935,6 +16948,8 @@ MonoBehaviour:
m_EditorClassIdentifier:
noDevicePage: {fileID: 3582556473535289502}
normalPage: {fileID: 8115864904787809625}
+ normalScrollRect: {fileID: 7398385099859628837}
+ pullTriggerDistance: 120
selectDeviceButton: {fileID: 1920078014523356616}
selectDevicePage: {fileID: 2340476075600265632}
selectCountryPage: {fileID: 1196293823344848224, guid: 90501a08c2cf82c4187b5f13c391291f,
@@ -17117,6 +17132,7 @@ GameObject:
- component: {fileID: 2697609740981075072}
- component: {fileID: 928882153762487195}
- component: {fileID: 7398385099859628837}
+ - component: {fileID: 5876146908749457361}
m_Layer: 5
m_Name: "\u6B63\u5E38"
m_TagString: Untagged
@@ -17225,6 +17241,18 @@ MonoBehaviour:
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []
+--- !u!114 &5876146908749457361
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 8115864904787809625}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 432e8b6f5f7dd7a4f94d9c3b85c8b262, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
--- !u!1 &8135258645254993493
GameObject:
m_ObjectHideFlags: 0
diff --git a/Assets/Scripts/UI/Components/HomePagePullRefreshTrigger.cs b/Assets/Scripts/UI/Components/HomePagePullRefreshTrigger.cs
new file mode 100644
index 0000000..c597bf1
--- /dev/null
+++ b/Assets/Scripts/UI/Components/HomePagePullRefreshTrigger.cs
@@ -0,0 +1,31 @@
+using UnityEngine;
+using UnityEngine.EventSystems;
+using Kill.UI.Pages;
+
+namespace Kill.UI.Components
+{
+ ///
+ /// 下拉刷新触发器:挂到主页 ScrollRect(带 Image 的 Graphic)上,接收 EventSystem
+ /// 拖拽事件并转发给 HomePageCtrl。这样在滚动区域内任意位置都可触发下拉刷新。
+ ///
+ public class HomePagePullRefreshTrigger : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
+ {
+ public void OnBeginDrag(PointerEventData eventData)
+ {
+ var ctrl = HomePageCtrl.Instance;
+ if (ctrl != null) ctrl.OnPullRefreshBeginDrag();
+ }
+
+ public void OnDrag(PointerEventData eventData)
+ {
+ var ctrl = HomePageCtrl.Instance;
+ if (ctrl != null) ctrl.OnPullRefreshDrag(eventData.delta.y);
+ }
+
+ public void OnEndDrag(PointerEventData eventData)
+ {
+ var ctrl = HomePageCtrl.Instance;
+ if (ctrl != null) ctrl.OnPullRefreshEndDrag();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/UI/Components/HomePagePullRefreshTrigger.cs.meta b/Assets/Scripts/UI/Components/HomePagePullRefreshTrigger.cs.meta
new file mode 100644
index 0000000..e820243
--- /dev/null
+++ b/Assets/Scripts/UI/Components/HomePagePullRefreshTrigger.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 432e8b6f5f7dd7a4f94d9c3b85c8b262
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/UI/Pages/HomePage/CheckPasswordPage.cs b/Assets/Scripts/UI/Pages/HomePage/CheckPasswordPage.cs
index e805d94..271e459 100644
--- a/Assets/Scripts/UI/Pages/HomePage/CheckPasswordPage.cs
+++ b/Assets/Scripts/UI/Pages/HomePage/CheckPasswordPage.cs
@@ -24,34 +24,45 @@ namespace Kill.UI.Pages
{
errorText.text="";
LoadingUI.Show();
- string password = passwordInput != null ? passwordInput.text : "";
- if (string.IsNullOrEmpty(password))
+ try
{
- errorText.text = LanguageManager.Instance.GetLanguage("100040");
+ string password = passwordInput != null ? passwordInput.text : "";
+ if (string.IsNullOrEmpty(password))
+ {
+ errorText.text = LanguageManager.Instance.GetLanguage("home_password_check_failed");
+ return;
+ }
+ PasswordRequest requestData=new PasswordRequest
+ {
+ password=passwordInput.text
+ };
+
+ var response = await NetworkCtrl.Instance.Post("/api/v1/auth/password/verify", requestData);
+
+ if (response != null && response.Data != null && response.Data.code == 200)
+ {
+ plane.SetActive(false);
+ gameObject.SetActive(false);
+ errorText.text="";
+ passwordInput.text="";
+ UIManager.Instance.isFirstTime=false;
+ }
+ else
+ {
+ errorText.text = LanguageManager.Instance.GetLanguage("home_password_check_failed");
+ passwordInput.text="";
+ }
+ }
+ catch (System.Exception ex)
+ {
+ Debug.LogError($"[CheckPasswordPage] 校验密码异常: {ex.Message}");
+ errorText.text = LanguageManager.Instance.GetLanguage("home_password_check_failed");
+ if (passwordInput != null) passwordInput.text = "";
+ }
+ finally
+ {
+ // 无论成功/失败/异常都关闭 Loading,避免一直挂着
LoadingUI.Hide();
- return;
- }
- PasswordRequest requestData=new PasswordRequest
- {
- password=passwordInput.text
- };
-
- var response = await NetworkCtrl.Instance.Post("/api/v1/auth/password/verify", requestData);
-
- LoadingUI.Hide();
-
- if (response.Data.code == 200)
- {
- plane.SetActive(false);
- gameObject.SetActive(false);
- errorText.text="";
- passwordInput.text="";
- UIManager.Instance.isFirstTime=false;
- }
- else
- {
- errorText.text = LanguageManager.Instance.GetLanguage("100040");
- passwordInput.text="";
}
}
diff --git a/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs b/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs
index dc23d38..831efcb 100644
--- a/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs
+++ b/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs
@@ -21,6 +21,13 @@ namespace Kill.UI.Pages
public GameObject noDevicePage;
public GameObject normalPage;
+ // 下拉刷新:滚动区域 ScrollRect(用于判断内容是否在最顶部);无设备页可不填
+ public ScrollRect normalScrollRect;
+ // 下拉刷新参数
+ [SerializeField] private float pullTriggerDistance = 120f; // 触发刷新的拖动距离(像素)
+ private float pullDistance; // 当前累积下拉距离
+ private bool isPullingAtTop; // 拖动开始时是否在内容顶部
+ private bool isRefreshing;
// 存储待执行的UI更新操作
private List pendingUIUpdates = new List();
public Button selectDeviceButton;
@@ -477,6 +484,7 @@ namespace Kill.UI.Pages
///
/// 网络断开:立刻把 WiFi 设备标离线并刷新 UI
+ /// 设备离线导致的 UI 重置由后台轮询触发,避免此处重复 Init
///
private void OnNetworkDisconnectedHandler(object sender, EventArgs e)
{
@@ -1878,11 +1886,14 @@ namespace Kill.UI.Pages
// WiFi和蓝牙都断开
if (wasOnline)
{
- Debug.Log("[HomePageCtrl] 设备WiFi离线");
+ Debug.Log("[HomePageCtrl] 设备WiFi离线,重新加载首页");
pendingUIUpdates.Add(() =>
{
deviceState?.UpdateDeviceState(hasBluetooth, hasWifi);
});
+ // 设备由在线变为离线且无蓝牙连接 → 直接重新加载首页
+ UIManager.Instance.OpenMainPage(UIManager.PageName.homePage);
+ return; // 旧页面即将销毁,结束轮询
}
else
{
@@ -1938,6 +1949,62 @@ namespace Kill.UI.Pages
pendingUIUpdates.Add(action);
}
+ #region 下拉刷新(由 HomePagePullRefreshTrigger 组件转发调用)
+
+ public void OnPullRefreshBeginDrag()
+ {
+ if (isRefreshing) return;
+ isPullingAtTop = IsContentAtTop();
+ pullDistance = 0f;
+ }
+
+ public void OnPullRefreshDrag(float deltaY)
+ {
+ if (isRefreshing || !isPullingAtTop) return;
+ if (deltaY < 0)
+ {
+ pullDistance += -deltaY;
+ }
+ }
+
+ public void OnPullRefreshEndDrag()
+ {
+ if (isRefreshing) return;
+ if (pullDistance >= pullTriggerDistance)
+ {
+ TriggerPullRefresh();
+ }
+ else
+ {
+ ResetPullRefreshUI();
+ }
+ isPullingAtTop = false;
+ }
+
+ ///
+ /// 判断 ScrollRect 内容是否已在顶部(无 ScrollRect 时视为可下拉)
+ ///
+ private bool IsContentAtTop()
+ {
+ if (normalScrollRect == null) return true;
+ return normalScrollRect.verticalNormalizedPosition >= 0.999f;
+ }
+
+ private void TriggerPullRefresh()
+ {
+ if (isRefreshing) return;
+ isRefreshing = true;
+ // 重新加载首页(销毁旧实例并实例化新实例,触发 Start/Init 重新跑)
+ UIManager.Instance.OpenMainPage(UIManager.PageName.homePage);
+ }
+
+ private void ResetPullRefreshUI()
+ {
+ pullDistance = 0f;
+ }
+
+ #endregion
+
///
/// 从WiFi刷新主页定时任务显示
///
diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset
index 4cb3683..7fcc8c2 100644
--- a/ProjectSettings/ProjectSettings.asset
+++ b/ProjectSettings/ProjectSettings.asset
@@ -173,7 +173,7 @@ PlayerSettings:
tvOS: 0
overrideDefaultApplicationIdentifier: 1
AndroidBundleVersionCode: 4
- AndroidMinSdkVersion: 33
+ AndroidMinSdkVersion: 31
AndroidTargetSdkVersion: 36
AndroidPreferredInstallLocation: 0
aotOptions: