using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Net;
using System.Net.NetworkInformation;
///
/// 网络设置面板
/// 配置系统网络连接参数
///
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();
}
}
///
/// 显示静态网络状态(Android平台专用,避免Unity网络检查)
///
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: 配置模式";
}
}
///
/// 显示局域网配置状态(Android平台专用,适用于医疗设备局域网环境)
///
private void ShowLANConfigurationStatus()
{
if (NetworkStatusText != null)
{
NetworkStatusText.text = "局域网配置模式 (医疗设备专用)";
NetworkStatusText.color = Color.blue; // 蓝色表示局域网模式
}
if (ConnectionStatusIcon != null)
{
ConnectionStatusIcon.color = Color.blue; // 蓝色表示局域网模式
}
// 显示当前配置的IP信息(不检查连接状态)
UpdateIPConfigurationDisplay();
}
///
/// 更新IP配置显示(不进行网络连接检查)
///
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}");
}
}
}
///
/// 加载并显示当前DHCP获取的IP信息
///
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
///
/// 完成局域网配置验证(Android平台专用)
///
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);
}
///
/// 验证当前网络配置的有效性(不进行实际连接测试)
///
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();
// }
void OnDestroy()
{
CancelInvoke();
// 关闭自定义键盘(如果正在显示)
if (CustomKeyboardManager.Instance != null && CustomKeyboardManager.Instance.IsKeyboardShowing())
{
CustomKeyboardManager.Instance.HideKeyboard();
}
}
}