具备界面基础功能
This commit is contained in:
188
SHH.CameraDashboard/ViewModels/WizardClientsVewModel.cs
Normal file
188
SHH.CameraDashboard/ViewModels/WizardClientsVewModel.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace SHH.CameraDashboard
|
||||
{
|
||||
/// <summary>
|
||||
/// 客户端配置向导的 ViewModel
|
||||
/// 实现了 <see cref="IOverlayClosable"/> 接口,用于与父窗口的蒙板交互。
|
||||
/// </summary>
|
||||
public class WizardClientsViewModel : INotifyPropertyChanged, IOverlayClosable
|
||||
{
|
||||
/// <summary>
|
||||
/// 绑定到 ListView 的数据源
|
||||
/// </summary>
|
||||
public static ObservableCollection<ServiceNodeModel> ServiceNodes
|
||||
=> AppGlobal.ServiceNodes;
|
||||
|
||||
#region --- 业务数据属性 ---
|
||||
|
||||
private string _statusText = "准备就绪";
|
||||
/// <summary>
|
||||
/// 获取或设置向导的当前状态文本。
|
||||
/// </summary>
|
||||
public string StatusText
|
||||
{
|
||||
get => _statusText;
|
||||
set { _statusText = value; OnPropertyChanged(); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- 命令属性 ---
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于确认操作的命令。
|
||||
/// </summary>
|
||||
public ICommand ConfirmCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于取消操作的命令。
|
||||
/// </summary>
|
||||
public ICommand CancelCommand { get; }
|
||||
|
||||
// 新增一行的命令
|
||||
public ICommand AddNodeCommand { get; }
|
||||
|
||||
public ICommand DeleteNodeCommand { get; }
|
||||
|
||||
public ICommand CheckCommand { get; }
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- 构造函数 ---
|
||||
|
||||
/// <summary>
|
||||
/// 初始化 <see cref="WizardClientsViewModel"/> 类的新实例。
|
||||
/// </summary>
|
||||
public WizardClientsViewModel()
|
||||
{
|
||||
// 实现新增逻辑
|
||||
AddNodeCommand = new RelayCommand<object>(_ =>
|
||||
{
|
||||
// 创建新行对象并添加到集合
|
||||
var newNode = new ServiceNodeModel
|
||||
{
|
||||
ServiceNodeName = "新节点",
|
||||
ServiceNodeIp = "0.0.0.0",
|
||||
ServiceNodePort = "5000",
|
||||
Status = "未检测"
|
||||
};
|
||||
ServiceNodes.Add(newNode);
|
||||
});
|
||||
|
||||
// 删除逻辑实现
|
||||
DeleteNodeCommand = new RelayCommand<ServiceNodeModel>(node =>
|
||||
{
|
||||
if (node != null && ServiceNodes.Contains(node))
|
||||
{
|
||||
ServiceNodes.Remove(node);
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化确认命令
|
||||
ConfirmCommand = new RelayCommand<object>(async _ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 2. 【核心代码】调用通用存储服务
|
||||
// 泛型 T 自动推断为 ObservableCollection<ServiceNodeModel>
|
||||
await LocalStorageService.SaveAsync(
|
||||
AppPaths.ServiceNodesConfig, // 路径:Configs/service_nodes.json
|
||||
ServiceNodes // 数据:当前的列表对象
|
||||
);
|
||||
|
||||
// 4. 关闭当前弹窗
|
||||
RequestClose?.Invoke();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"保存失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
});
|
||||
|
||||
CheckCommand = new RelayCommand<object>(async _ => await ExecuteCheckAsync());
|
||||
|
||||
// 初始化取消命令
|
||||
CancelCommand = new RelayCommand<object>(_ =>
|
||||
{
|
||||
// 直接触发关闭请求事件,取消并关闭向导
|
||||
RequestClose?.Invoke();
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- IOverlayClosable 接口实现 ---
|
||||
|
||||
/// <summary>
|
||||
/// 当需要关闭蒙板时发生。
|
||||
/// </summary>
|
||||
public event Action? RequestClose;
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- INotifyPropertyChanged 接口实现 ---
|
||||
|
||||
/// <summary>
|
||||
/// 当属性值更改时发生。
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 引发 <see cref="PropertyChanged"/> 事件。
|
||||
/// </summary>
|
||||
/// <param name="name">更改的属性名称。</param>
|
||||
protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string name = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task ExecuteCheckAsync()
|
||||
{
|
||||
foreach (var node in ServiceNodes)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(node.ServiceNodeIp) || string.IsNullOrWhiteSpace(node.ServiceNodePort))
|
||||
continue;
|
||||
|
||||
node.Status = "正在获取信息...";
|
||||
|
||||
// 1. 调用 ApiClient 获取列表 (代码不需要变,因为 Repository 已经封装好了)
|
||||
var cameras = await ApiClient.Instance.Cameras.GetListByAddressAsync(
|
||||
node.ServiceNodeIp,
|
||||
node.ServiceNodePort,
|
||||
"向导页面"
|
||||
);
|
||||
|
||||
// 2. 根据返回的详细数据,生成更智能的状态描述
|
||||
if (cameras.Count > 0)
|
||||
{
|
||||
// 统计在线的摄像头数量
|
||||
int onlineCount = 0;
|
||||
// 统计主要品牌 (例如: HikVision)
|
||||
string firstBrand = cameras[0].Brand;
|
||||
|
||||
foreach (var cam in cameras)
|
||||
{
|
||||
if (cam.IsOnline) onlineCount++;
|
||||
}
|
||||
|
||||
// 状态显示示例:只能是在线,其它的影响界面上色
|
||||
node.Status = $"在线";
|
||||
}
|
||||
else
|
||||
{
|
||||
// 列表为空,或者是网络不通导致 Repository 返回了空列表
|
||||
// 为了区分是“无数据”还是“网络不通”,其实 Repository 可以优化返回 null 或抛异常,
|
||||
// 但目前的架构返回空列表最安全。
|
||||
node.Status = "离线或无设备";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user