Files
Ayay/SHH.CameraDashboard/ViewModels/CameraEditViewModel.cs
2026-01-01 22:40:32 +08:00

177 lines
6.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
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 System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace SHH.CameraDashboard
{
public class CameraEditViewModel : INotifyPropertyChanged
{
// 编辑中的数据副本
private CameraEditInfo _editingDto;
// 定义一个事件,通知 View 关闭窗口(或者 UserControl 所在的宿主)
public event Action<bool, CameraEditInfo> RequestClose;
public CameraEditInfo EditingDto
{
get => _editingDto;
set { _editingDto = value; OnPropertyChanged(); }
}
public ICommand SaveCommand { get; }
public ICommand CancelCommand { get; }
private bool _isAdd = false;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="sourceDto">如果是编辑模式,传入源对象;如果是新增,传入 null</param>
public CameraEditViewModel(CameraEditInfo sourceDto = null)
{
// 初始化枚举列表
InitBrandOptions();
if (sourceDto != null)
{
// 编辑模式:深拷贝数据,避免直接修改源对象
EditingDto = CloneDto(sourceDto);
}
else
{
// 新增模式:创建默认对象
EditingDto = new CameraEditInfo
{
Name = "新设备",
Port = 8000,
ChannelIndex = 1
};
}
if (EditingDto.Id == 0)
_isAdd = true;
SaveCommand = new RelayCommand(ExecuteSave, CanSave);
CancelCommand = new RelayCommand(ExecuteCancel);
}
private bool CanSave(object obj)
{
// 简单验证ID必须大于0IP不能为空
if (EditingDto == null) return false;
return EditingDto.Id > 0 && !string.IsNullOrWhiteSpace(EditingDto.IpAddress);
}
private bool IsSaving;
private async void ExecuteSave(object obj)
{
if (IsSaving) return;
try
{
IsSaving = true; // 开启 Loading
bool isSuccess = false;
if (_isAdd)
{
isSuccess = await ApiClient.Instance.Cameras.CreateCameraAsync(EditingDto, "摄像头-新增");
}
else
{
isSuccess = await ApiClient.Instance.Cameras.UpdateCameraAsync(EditingDto, "摄像头-编辑");
_isAdd = false;
}
// 1. 调用 Repository (ApiClient)
// 注意:这里调用的是我们刚才在 Repository 中定义的 UpdateCameraAsync
if (isSuccess)
{
// 2. 成功:通知外部关闭面板,并刷新列表
RequestClose?.Invoke(true, EditingDto);
}
else
{
// 3. 失败:弹窗提示
MessageBox.Show("保存失败,请检查服务节点日志。", "系统提示", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
MessageBox.Show($"保存过程中发生异常:\n{ex.Message}", "系统错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
IsSaving = false; // 关闭 Loading
}
}
private void ExecuteCancel(object obj)
{
// false 表示取消操作
RequestClose?.Invoke(false, null);
}
/// <summary>
/// 手动深拷贝 DTO防止引用传递导致界面未点保存就修改了列表
/// 生产环境建议用 AutoMapper 或 JSON 序列化实现
/// </summary>
private CameraEditInfo CloneDto(CameraEditInfo source)
{
return new CameraEditInfo
{
Id = source.Id,
Name = source.Name,
Brand = source.Brand,
Location = source.Location,
IpAddress = source.IpAddress,
Port = source.Port,
Username = source.Username,
Password = source.Password,
RenderHandle = source.RenderHandle,
ChannelIndex = source.ChannelIndex,
RtspPath = source.RtspPath,
MainboardIp = source.MainboardIp,
MainboardPort = source.MainboardPort,
StreamType = source.StreamType,
UseGrayscale = source.UseGrayscale,
EnhanceImage = source.EnhanceImage,
AllowCompress = source.AllowCompress,
AllowExpand = source.AllowExpand,
TargetResolution = source.TargetResolution
};
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
// 1. 定义一个简单的内部类或结构,用于 ComboBox 显示
public class BrandOption
{
public string Label { get; set; } // 显示的文本 (Description)
public int Value { get; set; } // 实际的值 (int)
}
// 2. 数据源属性
public List<BrandOption> BrandOptions { get; private set; }
private void InitBrandOptions()
{
// 遍历 DeviceBrand 枚举的所有值
BrandOptions = Enum.GetValues(typeof(DeviceBrand))
.Cast<DeviceBrand>()
.Select(e => new BrandOption
{
// 获取 Description ("海康威视")
Label = EnumHelper.GetDescription(e),
// 获取 int 值 (1)
Value = (int)e
})
.ToList();
}
}
}