DCS/ruiyiweiUX/Assets/Scripts/Views/NetworkSettingPanel.cs

777 lines
28 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Net;
using System.Net.NetworkInformation;
/// <summary>
/// 网络设置面板
/// 配置系统网络连接参数
/// </summary>
public class NetworkSettingPanel : BasePanel
{
[Header("网络模式")]
public Toggle DhcpToggle;
public Toggle StaticToggle;
public ToggleGroup NetworkModeGroup;
[Header("静态IP设置")]
public TMP_InputField IPv4Input;
public TMP_InputField SubnetMaskInput;
public TMP_InputField GatewayInput;
public TMP_InputField DNS1Input;
public TMP_InputField DNS2Input;
[Header("网络状态")]
public TextMeshProUGUI NetworkStatusText;
public Button TestConnectionButton;
public Image ConnectionStatusIcon;
public TextMeshProUGUI CurrentIPText;
public Button ResetButton;
[Header("控制按钮")]
public Button HomeButton;
public Button ConfirmButton;
public Button BackButton;
private SettingsViewModel _vm;
private NetworkConfig _tempConfig;
public override void Init()
{
_vm = new SettingsViewModel();
_tempConfig = _vm.Network;
InitializeUI();
LoadCurrentSettings();
// 保留网络配置功能但完全禁用网络状态检查避免Unity底层网络错误
// 医疗设备通常在局域网环境中运行,无需互联网连接检查
#if UNITY_ANDROID && !UNITY_EDITOR
// Android平台显示局域网配置状态禁用互联网检查
Debug.Log("[NetworkSettingPanel] Android平台局域网配置模式 (禁用互联网检查)");
ShowLANConfigurationStatus();
#else
// PC平台也禁用网络检查避免"Network is unreachable"错误导致软件崩溃
Debug.Log("[NetworkSettingPanel] PC平台网络配置模式 (禁用网络检查防止崩溃)");
ShowStaticNetworkStatus();
// 完全禁用定期网络检查防止Unity底层网络异常
// InvokeRepeating(nameof(UpdateNetworkStatus), 1f, 5f); // 已禁用
#endif
}
private void InitializeUI()
{
// 设置网络模式切换
if (DhcpToggle != null && StaticToggle != null)
{
DhcpToggle.onValueChanged.AddListener(OnNetworkModeChanged);
StaticToggle.onValueChanged.AddListener((value) => OnNetworkModeChanged(!value));
}
// 输入字段验证
SetupInputFieldValidation();
if (ResetButton != null)
ResetButton.onClick.AddListener(ResetToDefaults);
if (HomeButton != null)
{
HomeButton.onClick.AddListener(() =>
{
ConfirmDialog.Show("确认", "是否返回主界面?", () =>
{
ReturnToHome();
});
});
}
if (ConfirmButton != null)
{
ConfirmButton.onClick.AddListener(ApplyAndBack);
}
if (BackButton != null)
{
BackButton.onClick.AddListener(() =>
ConfirmDialog.Show("确认", "是否返回设置界面?", () =>
{
ClosePanel();
ClosePanel();
})
);
}
}
private void LoadCurrentSettings()
{
var config = _vm.Network;
// 设置网络模式
bool isDhcp = config.Mode == NetworkMode.Dhcp;
if (DhcpToggle != null) DhcpToggle.isOn = isDhcp;
if (StaticToggle != null) StaticToggle.isOn = !isDhcp;
// 加载IP配置
if (isDhcp)
{
// DHCP模式显示当前获取的IP信息
LoadAndDisplayCurrentDhcpIP();
}
else
{
// 静态IP模式显示保存的配置
if (IPv4Input != null) IPv4Input.text = config.IPv4;
if (SubnetMaskInput != null) SubnetMaskInput.text = config.Mask;
if (GatewayInput != null) GatewayInput.text = config.Gateway;
if (DNS1Input != null) DNS1Input.text = config.Dns1;
if (DNS2Input != null) DNS2Input.text = config.Dns2;
}
// 设置静态IP字段的可用性
SetStaticFieldsInteractable(!isDhcp);
}
private void OnNetworkModeChanged(bool isDhcp)
{
_tempConfig.Mode = isDhcp ? NetworkMode.Dhcp : NetworkMode.Static;
SetStaticFieldsInteractable(!isDhcp);
UpdateNetworkModeDisplay(isDhcp);
// 模式切换时更新显示
if (isDhcp)
{
LoadAndDisplayCurrentDhcpIP();
}
else
{
// 切换到静态IP时清空或恢复到配置值
var config = _vm.Network;
if (IPv4Input != null) IPv4Input.text = config.IPv4;
if (SubnetMaskInput != null) SubnetMaskInput.text = config.Mask;
if (GatewayInput != null) GatewayInput.text = config.Gateway;
if (DNS1Input != null) DNS1Input.text = config.Dns1;
if (DNS2Input != null) DNS2Input.text = config.Dns2;
}
}
private void SetStaticFieldsInteractable(bool interactable)
{
if (IPv4Input != null) IPv4Input.interactable = interactable;
if (SubnetMaskInput != null) SubnetMaskInput.interactable = interactable;
if (GatewayInput != null) GatewayInput.interactable = interactable;
if (DNS1Input != null) DNS1Input.interactable = interactable;
if (DNS2Input != null) DNS2Input.interactable = interactable;
// 改变颜色以指示状态
// DHCP模式灰色半透明只读静态IP模式完全不透明可编辑
float alpha = interactable ? 1f : 0.5f;
SetInputFieldAlpha(IPv4Input, alpha);
SetInputFieldAlpha(SubnetMaskInput, alpha);
SetInputFieldAlpha(GatewayInput, alpha);
SetInputFieldAlpha(DNS1Input, alpha);
SetInputFieldAlpha(DNS2Input, alpha);
// DHCP模式下禁用编辑设置为只读提示
if (!interactable)
{
if (IPv4Input != null) IPv4Input.readOnly = true;
if (SubnetMaskInput != null) SubnetMaskInput.readOnly = true;
if (GatewayInput != null) GatewayInput.readOnly = true;
if (DNS1Input != null) DNS1Input.readOnly = true;
if (DNS2Input != null) DNS2Input.readOnly = true;
}
else
{
if (IPv4Input != null) IPv4Input.readOnly = false;
if (SubnetMaskInput != null) SubnetMaskInput.readOnly = false;
if (GatewayInput != null) GatewayInput.readOnly = false;
if (DNS1Input != null) DNS1Input.readOnly = false;
if (DNS2Input != null) DNS2Input.readOnly = false;
}
}
private void SetInputFieldAlpha(TMP_InputField inputField, float alpha)
{
if (inputField != null)
{
var colors = inputField.colors;
colors.normalColor = new Color(colors.normalColor.r, colors.normalColor.g, colors.normalColor.b, alpha);
inputField.colors = colors;
}
}
private void SetupInputFieldValidation()
{
// 设置自定义键盘IP 地址使用数字和点号)
if (IPv4Input != null)
{
IPv4Input.onEndEdit.AddListener(ValidateIPAddress);
IPv4Input.characterLimit = 15;
CustomKeyboardManager.SetupInputField(IPv4Input, KeyboardLayout.Numeric,
(newValue) =>
{
IPv4Input.text = newValue;
ValidateIPAddress(newValue);
},
clearOnFirstInput: true);
}
if (SubnetMaskInput != null)
{
SubnetMaskInput.onEndEdit.AddListener(ValidateSubnetMask);
SubnetMaskInput.characterLimit = 15;
CustomKeyboardManager.SetupInputField(SubnetMaskInput, KeyboardLayout.Numeric,
(newValue) =>
{
SubnetMaskInput.text = newValue;
ValidateSubnetMask(newValue);
},
clearOnFirstInput: true);
}
if (GatewayInput != null)
{
GatewayInput.onEndEdit.AddListener(ValidateIPAddress);
GatewayInput.characterLimit = 15;
CustomKeyboardManager.SetupInputField(GatewayInput, KeyboardLayout.Numeric,
(newValue) =>
{
GatewayInput.text = newValue;
ValidateIPAddress(newValue);
},
clearOnFirstInput: true);
}
if (DNS1Input != null)
{
DNS1Input.onEndEdit.AddListener(ValidateIPAddress);
DNS1Input.characterLimit = 15;
CustomKeyboardManager.SetupInputField(DNS1Input, KeyboardLayout.Numeric,
(newValue) =>
{
DNS1Input.text = newValue;
ValidateIPAddress(newValue);
},
clearOnFirstInput: true);
}
if (DNS2Input != null)
{
DNS2Input.onEndEdit.AddListener(ValidateIPAddress);
DNS2Input.characterLimit = 15;
CustomKeyboardManager.SetupInputField(DNS2Input, KeyboardLayout.Numeric,
(newValue) =>
{
DNS2Input.text = newValue;
ValidateIPAddress(newValue);
},
clearOnFirstInput: true);
}
}
private void ValidateIPAddress(string ip)
{
if (string.IsNullOrEmpty(ip)) return;
if (!IPAddress.TryParse(ip, out _))
{
Debug.LogWarning($"无效的IP地址格式: {ip}");
// 这里可以显示错误提示
}
}
private void ValidateSubnetMask(string mask)
{
if (string.IsNullOrEmpty(mask)) return;
// 验证子网掩码格式和有效性
if (!IPAddress.TryParse(mask, out IPAddress maskAddr))
{
Debug.LogWarning($"无效的子网掩码格式: {mask}");
return;
}
// 检查是否为有效的子网掩码
byte[] maskBytes = maskAddr.GetAddressBytes();
uint maskUint = (uint)(maskBytes[0] << 24 | maskBytes[1] << 16 | maskBytes[2] << 8 | maskBytes[3]);
// 检查掩码是否连续
uint inverted = ~maskUint;
if ((inverted & (inverted + 1)) != 0)
{
Debug.LogWarning($"无效的子网掩码: {mask}");
}
}
private void UpdateNetworkModeDisplay(bool isDhcp)
{
string mode = isDhcp ? "DHCP (自动获取)" : "静态IP";
StaticToggle.isOn = !isDhcp;
DhcpToggle.isOn = isDhcp;
Debug.Log($"网络模式: {mode}");
}
private void UpdateNetworkStatus()
{
try
{
#if UNITY_ANDROID && !UNITY_EDITOR
// Android平台避免Unity底层网络检查使用简化的状态显示
ShowStaticNetworkStatus();
#else
// 其他平台:保留原有网络检查逻辑
NetworkReachability reachability = Application.internetReachability;
bool isConnected = reachability != NetworkReachability.NotReachable;
string networkType = reachability.ToString();
if (NetworkStatusText != null)
{
string status = isConnected ? "网络已连接" : "网络未连接";
NetworkStatusText.text = $"{status} ({networkType})";
NetworkStatusText.color = isConnected ? Color.green : Color.red;
}
if (ConnectionStatusIcon != null)
{
ConnectionStatusIcon.color = isConnected ? Color.green : Color.red;
}
// 更新当前IP地址和网络信息
UpdateCurrentIPDisplay();
#endif
}
catch (System.Exception ex)
{
Debug.LogError($"更新网络状态失败: {ex.Message}");
// 异常时显示静态状态
ShowStaticNetworkStatus();
}
}
/// <summary>
/// 显示静态网络状态Android平台专用避免Unity网络检查
/// </summary>
private void ShowStaticNetworkStatus()
{
if (NetworkStatusText != null)
{
NetworkStatusText.text = "网络配置 (无在线检测)";
NetworkStatusText.color = Color.gray;
}
if (ConnectionStatusIcon != null)
{
ConnectionStatusIcon.color = Color.gray;
}
if (CurrentIPText != null)
{
CurrentIPText.text = "当前IP: 配置模式";
}
}
/// <summary>
/// 显示局域网配置状态Android平台专用适用于医疗设备局域网环境
/// </summary>
private void ShowLANConfigurationStatus()
{
if (NetworkStatusText != null)
{
NetworkStatusText.text = "局域网配置模式 (医疗设备专用)";
NetworkStatusText.color = Color.blue; // 蓝色表示局域网模式
}
if (ConnectionStatusIcon != null)
{
ConnectionStatusIcon.color = Color.blue; // 蓝色表示局域网模式
}
// 显示当前配置的IP信息不检查连接状态
UpdateIPConfigurationDisplay();
}
/// <summary>
/// 更新IP配置显示不进行网络连接检查
/// </summary>
private void UpdateIPConfigurationDisplay()
{
if (CurrentIPText != null)
{
try
{
var config = _vm.Network;
string displayText = "";
if (config.Mode == NetworkMode.Dhcp)
{
displayText = "网络模式: DHCP (自动获取)\n";
displayText += "适用于: 路由器环境\n";
displayText += "状态: 配置已保存";
}
else
{
displayText = "网络模式: 静态IP\n";
displayText += $"IP地址: {config.IPv4}\n";
displayText += $"子网掩码: {config.Mask}\n";
displayText += $"网关: {config.Gateway}\n";
if (!string.IsNullOrEmpty(config.Dns1)) displayText += $"DNS1: {config.Dns1}\n";
if (!string.IsNullOrEmpty(config.Dns2)) displayText += $"DNS2: {config.Dns2}\n";
displayText += "适用于: 监护仪局域网";
}
CurrentIPText.text = displayText;
}
catch (System.Exception ex)
{
CurrentIPText.text = "IP配置: 获取配置失败";
Debug.LogError($"获取IP配置显示失败: {ex.Message}");
}
}
}
/// <summary>
/// 加载并显示当前DHCP获取的IP信息
/// </summary>
private void LoadAndDisplayCurrentDhcpIP()
{
try
{
#if UNITY_ANDROID && !UNITY_EDITOR
// Android平台获取实际的DHCP分配的IP信息
var ipConfig = AndroidNetworkConfigurator.GetCurrentIPConfiguration();
if (ipConfig != null && ipConfig.ContainsKey("status") && ipConfig["status"] == "success")
{
string dhcpIp = ipConfig.ContainsKey("dhcp_ip") ? ipConfig["dhcp_ip"] : "获取中...";
string dhcpMask = ipConfig.ContainsKey("dhcp_mask") ? ipConfig["dhcp_mask"] : "获取中...";
string dhcpGateway = ipConfig.ContainsKey("dhcp_gateway") ? ipConfig["dhcp_gateway"] : "获取中...";
string dhcpDns1 = ipConfig.ContainsKey("dhcp_dns1") ? ipConfig["dhcp_dns1"] : "";
string dhcpDns2 = ipConfig.ContainsKey("dhcp_dns2") ? ipConfig["dhcp_dns2"] : "";
// 在输入字段中显示当前IP只读
if (IPv4Input != null) IPv4Input.text = dhcpIp;
if (SubnetMaskInput != null) SubnetMaskInput.text = dhcpMask;
if (GatewayInput != null) GatewayInput.text = dhcpGateway;
if (DNS1Input != null) DNS1Input.text = dhcpDns1;
if (DNS2Input != null) DNS2Input.text = dhcpDns2;
Debug.Log($"[DHCP] 已加载当前IP: {dhcpIp}");
}
else
{
// 获取失败时显示提示
if (IPv4Input != null) IPv4Input.text = "自动获取中...";
if (SubnetMaskInput != null) SubnetMaskInput.text = "";
if (GatewayInput != null) GatewayInput.text = "";
if (DNS1Input != null) DNS1Input.text = "";
if (DNS2Input != null) DNS2Input.text = "";
Debug.LogWarning("[DHCP] 获取IP配置失败");
}
#else
// PC平台尝试获取本地IP
try
{
System.Net.NetworkInformation.NetworkInterface[] interfaces =
System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
string localIP = "127.0.0.1";
string subnetMask = "255.255.255.0";
string gateway = "";
foreach (var ni in interfaces)
{
if (ni.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up &&
ni.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)
{
var ipProps = ni.GetIPProperties();
foreach (var addr in ipProps.UnicastAddresses)
{
if (addr.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
localIP = addr.Address.ToString();
subnetMask = addr.IPv4Mask.ToString();
break;
}
}
if (ipProps.GatewayAddresses.Count > 0)
{
gateway = ipProps.GatewayAddresses[0].Address.ToString();
}
break;
}
}
if (IPv4Input != null) IPv4Input.text = localIP;
if (SubnetMaskInput != null) SubnetMaskInput.text = subnetMask;
if (GatewayInput != null) GatewayInput.text = gateway;
if (DNS1Input != null) DNS1Input.text = "";
if (DNS2Input != null) DNS2Input.text = "";
Debug.Log($"[DHCP] 已加载当前IP: {localIP}");
}
catch (System.Exception ex)
{
Debug.LogWarning($"[DHCP] 获取PC IP失败: {ex.Message}");
if (IPv4Input != null) IPv4Input.text = "127.0.0.1";
}
#endif
}
catch (System.Exception ex)
{
Debug.LogError($"[DHCP] 加载IP配置异常: {ex.Message}");
if (IPv4Input != null) IPv4Input.text = "获取失败";
}
}
private void UpdateCurrentIPDisplay()
{
if (CurrentIPText != null)
{
try
{
#if UNITY_ANDROID && !UNITY_EDITOR
// Android平台显示配置模式避免网络检查
CurrentIPText.text = "当前IP: 配置模式 (避免网络检查)";
#else
// 其他平台保留IP获取逻辑
string currentIP = "127.0.0.1"; // 临时修复
CurrentIPText.text = $"当前IP: {currentIP}";
CurrentIPText.text += $"\n网络: 配置模式";
#endif
}
catch (System.Exception ex)
{
CurrentIPText.text = "当前IP: 获取失败";
Debug.LogError($"获取IP显示失败: {ex.Message}");
}
}
}
#if UNITY_ANDROID && !UNITY_EDITOR
private void UpdateAndroidPermissionStatus()
{
try
{
bool hasNetworkPermission = AndroidPermissionManager.HasNetworkStatePermission();
bool hasWifiPermission = AndroidPermissionManager.HasWifiStatePermission();
if (!hasNetworkPermission || !hasWifiPermission)
{
if (NetworkStatusText != null)
{
NetworkStatusText.text += "\n⚠ 权限受限";
NetworkStatusText.color = Color.yellow;
}
Debug.LogWarning("网络权限不足,功能可能受限");
}
}
catch (System.Exception ex)
{
Debug.LogError($"检查Android权限失败: {ex.Message}");
}
}
#endif
/// <summary>
/// 完成局域网配置验证Android平台专用
/// </summary>
private void CompleteLANConfigurationTest()
{
// 验证IP配置的有效性不进行实际网络连接
bool configValid = ValidateCurrentNetworkConfig();
if (NetworkStatusText != null)
{
if (configValid)
{
NetworkStatusText.text = "局域网配置有效";
NetworkStatusText.color = Color.green;
}
else
{
NetworkStatusText.text = "局域网配置需要检查";
NetworkStatusText.color = new Color(1f, 0.5f, 0f); // 橙色
}
}
Debug.Log($"局域网配置验证结果: {(configValid ? "" : "")}");
// 3秒后恢复局域网状态显示
Invoke(nameof(ShowLANConfigurationStatus), 3f);
}
/// <summary>
/// 验证当前网络配置的有效性(不进行实际连接测试)
/// </summary>
private bool ValidateCurrentNetworkConfig()
{
try
{
var config = _tempConfig;
// DHCP模式总是有效的
if (config.Mode == NetworkMode.Dhcp)
{
return true;
}
// 静态IP模式验证
if (config.Mode == NetworkMode.Static)
{
// 验证IP地址格式
if (string.IsNullOrEmpty(config.IPv4) || !System.Net.IPAddress.TryParse(config.IPv4, out _))
{
return false;
}
// 验证子网掩码格式
if (string.IsNullOrEmpty(config.Mask) || !System.Net.IPAddress.TryParse(config.Mask, out _))
{
return false;
}
// 验证网关格式(可选)
if (!string.IsNullOrEmpty(config.Gateway) && !System.Net.IPAddress.TryParse(config.Gateway, out _))
{
return false;
}
// 验证DNS格式可选
if (!string.IsNullOrEmpty(config.Dns1) && !System.Net.IPAddress.TryParse(config.Dns1, out _))
{
return false;
}
if (!string.IsNullOrEmpty(config.Dns2) && !System.Net.IPAddress.TryParse(config.Dns2, out _))
{
return false;
}
return true;
}
return false;
}
catch (System.Exception ex)
{
Debug.LogError($"验证网络配置时发生异常: {ex.Message}");
return false;
}
}
private void ResetToDefaults()
{
_tempConfig = new NetworkConfig
{
Mode = NetworkMode.Dhcp,
IPv4 = "",
Mask = "255.255.255.0",
Gateway = "",
Dns1 = "",
Dns2 = ""
};
LoadConfigToUI(_tempConfig);
Debug.Log("网络设置已重置为默认值");
}
private void LoadConfigToUI(NetworkConfig config)
{
bool isDhcp = config.Mode == NetworkMode.Dhcp;
if (DhcpToggle != null) DhcpToggle.isOn = isDhcp;
if (StaticToggle != null) StaticToggle.isOn = !isDhcp;
if (IPv4Input != null) IPv4Input.text = config.IPv4;
if (SubnetMaskInput != null) SubnetMaskInput.text = config.Mask;
if (GatewayInput != null) GatewayInput.text = config.Gateway;
if (DNS1Input != null) DNS1Input.text = config.Dns1;
if (DNS2Input != null) DNS2Input.text = config.Dns2;
SetStaticFieldsInteractable(!isDhcp);
}
private void ApplyAndBack()
{
// 收集当前UI的设置
_tempConfig.Mode = (DhcpToggle != null && DhcpToggle.isOn) ? NetworkMode.Dhcp : NetworkMode.Static;
if (_tempConfig.Mode == NetworkMode.Static)
{
if (IPv4Input != null) _tempConfig.IPv4 = IPv4Input.text;
if (SubnetMaskInput != null) _tempConfig.Mask = SubnetMaskInput.text;
if (GatewayInput != null) _tempConfig.Gateway = GatewayInput.text;
if (DNS1Input != null) _tempConfig.Dns1 = DNS1Input.text;
if (DNS2Input != null) _tempConfig.Dns2 = DNS2Input.text;
// 验证静态IP配置
if (!ValidateStaticConfig(_tempConfig))
{
Debug.LogWarning("静态IP配置无效请检查输入");
return;
}
}
else
{
_tempConfig.Dns1 = "";
_tempConfig.Dns2 = "";
}
// 应用设置
_vm.Network = _tempConfig;
Debug.Log($"网络设置已应用: {_tempConfig.Mode}, IP: {_tempConfig.IPv4}");
// DHCP模式下尝试立即刷新当前IP显示下发后可能有短暂延迟
if (_tempConfig.Mode == NetworkMode.Dhcp)
{
Invoke(nameof(UpdateCurrentIPDisplay), 1f);
}
else
{
UpdateCurrentIPDisplay();
}
ClosePanel();
}
private bool ValidateStaticConfig(NetworkConfig config)
{
if (config.Mode == NetworkMode.Static)
{
if (string.IsNullOrEmpty(config.IPv4) || !IPAddress.TryParse(config.IPv4, out _))
return false;
if (string.IsNullOrEmpty(config.Mask) || !IPAddress.TryParse(config.Mask, out _))
return false;
if (!string.IsNullOrEmpty(config.Gateway) && !IPAddress.TryParse(config.Gateway, out _))
return false;
if (!string.IsNullOrEmpty(config.Dns1) && !IPAddress.TryParse(config.Dns1, out _))
return false;
if (!string.IsNullOrEmpty(config.Dns2) && !IPAddress.TryParse(config.Dns2, out _))
return false;
}
return true;
}
// public void ClosePanel()
// {
// CancelInvoke(); // 停止定期更新
// UIManager.Instance.HidePanel<NetworkSettingPanel>();
// }
void OnDestroy()
{
CancelInvoke();
// 关闭自定义键盘(如果正在显示)
if (CustomKeyboardManager.Instance != null && CustomKeyboardManager.Instance.IsKeyboardShowing())
{
CustomKeyboardManager.Instance.HideKeyboard();
}
}
}