Files
Ayay/SHH.CameraDashboard/ViewModels/CameraImageSubscriptionViewModels.cs

254 lines
8.5 KiB
C#
Raw Normal View History

2026-01-01 22:40:32 +08:00
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace SHH.CameraDashboard
{
public class CameraImageSubscriptionViewModels : INotifyPropertyChanged
{
private readonly WebApiCameraModel _camera;
public event Action RequestClose;
// 用于绑定 ComboBox 的类型列表
public Dictionary<int, string> SubscriptionTypes { get; } = new Dictionary<int, string>
{
{ 0, "仅取流" },
{ 1, "本地窗口预览" },
{ 2, "本地录像" },
{ 3, "句柄渲染 (嵌入)" },
{ 4, "网络转发 (TCP/UDP)" },
{ 5, "Web 推流" }
2026-01-01 22:40:32 +08:00
};
// --- 数据源 ---
public ObservableCollection<SubscriptionDto> Subscriptions { get; set; } = new ObservableCollection<SubscriptionDto>();
// --- 编辑表单属性 ---
private string _editAppId;
public string EditAppId
{
get => _editAppId;
set { _editAppId = value; OnPropertyChanged(); }
}
private int _editType;
public int EditType
{
get => _editType;
set
{
_editType = value;
OnPropertyChanged();
// 切换类型时,控制 UI 上 IP/Port 输入框的显示
OnPropertyChanged(nameof(IsNetworkType));
OnPropertyChanged(nameof(IsRecordType));
}
}
private int _editFps = 25;
public int EditFps
{
get => _editFps;
set { _editFps = value; OnPropertyChanged(); }
}
private string _editMemo;
public string EditMemo
{
get => _editMemo;
set { _editMemo = value; OnPropertyChanged(); }
}
// 网络参数
private string _editTargetIp = "127.0.0.1";
public string EditTargetIp
{
get => _editTargetIp;
set { _editTargetIp = value; OnPropertyChanged(); }
}
private int _editTargetPort = 8080;
public int EditTargetPort
{
get => _editTargetPort;
set { _editTargetPort = value; OnPropertyChanged(); }
}
// --- 界面显隐控制 ---
// 只有类型是 3或4 时显示网络设置
public bool IsNetworkType => EditType == 3 || EditType == 4;
// 只有类型是 1 时显示录像设置 (这里简化,暂时只演示网络显隐)
public bool IsRecordType => EditType == 1;
// --- 命令 ---
public ICommand LoadCommand { get; }
public ICommand SaveCommand { get; }
public ICommand DeleteCommand { get; }
public ICommand ClearFormCommand { get; }
public CameraImageSubscriptionViewModels(WebApiCameraModel camera)
{
_camera = camera;
LoadCommand = new RelayCommand(ExecuteLoad);
SaveCommand = new RelayCommand(ExecuteSave);
DeleteCommand = new RelayCommand(ExecuteDelete);
ClearFormCommand = new RelayCommand(obj => ResetForm());
// 初始化加载
ExecuteLoad(null);
}
private async void ExecuteLoad(object obj)
{
var list = await ApiClient.Instance.Cameras.GetSubscriptionsAsync(_camera.Id);
Subscriptions.Clear();
foreach (var item in list)
{
Subscriptions.Add(item);
}
}
private async void ExecuteSave(object obj)
{
// 1. 基础校验
if (string.IsNullOrWhiteSpace(EditAppId))
{
MessageBox.Show("AppId 不能为空", "提示");
return;
}
// 2. 构建 DTO
// 注意:这里需要根据你 DTO 的定义进行类型转换和默认值处理
var dto = new SubscriptionDto
{
AppId = EditAppId,
// ★★★ 修改:直接赋值 int不需要强转枚举 ★★★
Type = EditType,
DisplayFps = EditFps,
Memo = EditMemo ?? string.Empty,
// ... 网络参数 ...
TargetIp = IsNetworkType ? (EditTargetIp ?? string.Empty) : string.Empty,
TargetPort = IsNetworkType ? EditTargetPort : 0,
// ★★★ 修改:直接赋值 int ★★★
Protocol = 0, // 0 代表 TCP
// ... 其他参数 ...
Handle = string.Empty,
SavePath = ((SubscriptionType)EditType == SubscriptionType.LocalRecord) ? @"C:\Temp\Video" : string.Empty,
RecordDuration = 0
};
// 3. 发送请求
bool success = await ApiClient.Instance.Cameras.UpdateSubscriptionAsync(_camera.Id, dto);
if (success)
{
MessageBox.Show("保存成功", "提示");
ExecuteLoad(null); // 刷新列表
// ResetForm(); // 可选:保存后清空表单
}
else
{
MessageBox.Show("保存失败,请检查网络或参数。", "错误");
}
}
private async void ExecuteDelete(object parameter)
{
// 支持两种方式删除:
// 1. 传入 parameter (点击列表中的删除按钮)
// 2. 根据当前表单的 AppId (如果在编辑模式)
string appIdToDelete = parameter as string;
if (string.IsNullOrEmpty(appIdToDelete)) return;
if (MessageBox.Show($"确定要停止并注销 [{appIdToDelete}] 吗?", "确认", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
return;
// 构造删除请求:关键是 DisplayFps = 0
var dto = new SubscriptionDto
{
AppId = appIdToDelete,
Type = 0,
DisplayFps = 0, // <--- 核心0 代表注销
Memo = "User Deleted"
};
bool success = await ApiClient.Instance.Cameras.UpdateSubscriptionAsync(_camera.Id, dto);
if (success)
{
ExecuteLoad(null);
}
}
private void ResetForm()
{
// 生成一个随机 AppId 方便测试
EditAppId = $"Client_{DateTime.Now:HHmmss}";
EditType = 0;
EditFps = 25;
EditMemo = "";
EditTargetIp = "127.0.0.1";
EditTargetPort = 8080;
}
// --- INotifyPropertyChanged 实现 (略,使用你的基类或标准实现) ---
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
// 1. 添加一个字段
private SubscriptionDto _selectedSubscription;
// 2. 添加 SelectedSubscription 属性
public SubscriptionDto SelectedSubscription
{
get => _selectedSubscription;
set
{
// 如果两次选中同一个,不做处理
if (_selectedSubscription == value) return;
_selectedSubscription = value;
OnPropertyChanged();
// ★★★ 核心逻辑:一旦选中项发生变化,就填充表单 ★★★
if (_selectedSubscription != null)
{
FillForm(_selectedSubscription);
}
}
}
// 3. 编写填充表单的辅助方法
private void FillForm(SubscriptionDto dto)
{
// 这里我们将 DTO 的值“复制”到编辑属性中
// 这样做的好处是:修改下方文本框时,不会立即改变列表里的显示,只有点击“保存”后才刷新
EditAppId = dto.AppId;
EditType = dto.Type; // 之前改成了 int直接赋值即可
EditFps = dto.DisplayFps; // 注意:后端返回可能是 targetFps前端 DTO 映射已修复
EditMemo = dto.Memo;
// 网络参数回显
EditTargetIp = dto.TargetIp;
EditTargetPort = dto.TargetPort;
// 触发一下 UI 状态刷新(比如网络参数的显隐)
OnPropertyChanged(nameof(IsNetworkType));
}
}
}