using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using AI.Models.Form; namespace AI.Models.SpecialMessages { /// /// 散点文件加载卡片的阶段 /// public enum XyzLoadPhase { SelectFile = 0, // 初始:等待用户选择文件 FileLoaded = 1, // 文件已加载,显示数据预览 + 列头匹配 Completed = 2, // 列头匹配已确认,摘要已提交 } /// /// 散点文件加载综合卡片:将「打开散点文件」「数据预览」「列头匹配」合并到一张卡片。 /// 整个业务流程由卡片本身驱动,不需要 AI 参与中间步骤; /// 用户确认列头匹配后,统一生成摘要发给 AI。 /// public class XyzLoadCardMessage : ISpecialMessage, INotifyPropertyChanged { private XyzLoadPhase _phase = XyzLoadPhase.SelectFile; private string _filePath = string.Empty; private string _matchButtonLabel = "确认匹配"; private TableDataMessage? _tablePreview; private bool _isLoading; private string _statusMessage = string.Empty; /// 消息唯一标识符 public string Id { get; set; } = Guid.NewGuid().ToString(); /// 类型名称(用于序列化路由) public string TypeName => "XyzLoadCard"; /// 不需要实时更新 public bool IsLive => false; // ── 阶段控制 ────────────────────────────────────────────────────────── public XyzLoadPhase Phase { get => _phase; set { if (SetProperty(ref _phase, value)) { OnPropertyChanged(nameof(IsFileInputEnabled)); OnPropertyChanged(nameof(ShowLoadButtons)); OnPropertyChanged(nameof(HasSubmittedFile)); OnPropertyChanged(nameof(ShowPreviewSection)); OnPropertyChanged(nameof(ShowMatchSection)); OnPropertyChanged(nameof(ShowMatchButton)); } } } // ── 加载状态 ────────────────────────────────────────────────────────── /// 是否正在执行加载(禁用按钮,显示 loading 提示) public bool IsLoading { get => _isLoading; set { if (SetProperty(ref _isLoading, value)) { OnPropertyChanged(nameof(ShowLoadButtons)); OnPropertyChanged(nameof(IsFileInputEnabled)); } } } /// 状态提示文案(加载中、错误信息等) public string StatusMessage { get => _statusMessage; set { SetProperty(ref _statusMessage, value ?? string.Empty); OnPropertyChanged(nameof(HasStatusMessage)); } } /// 是否有错误提示 public bool HasStatusMessage => !string.IsNullOrEmpty(_statusMessage); // ── 第一步:选择文件 ───────────────────────────────────────────────── /// 文件路径(双向绑定到输入框) public string FilePath { get => _filePath; set => SetProperty(ref _filePath, value ?? string.Empty); } /// 文件输入框是否可编辑(仅 SelectFile 且非加载中时) public bool IsFileInputEnabled => Phase == XyzLoadPhase.SelectFile && !IsLoading; /// 是否显示「选择文件」和「加载」按钮(SelectFile 且非加载中) public bool ShowLoadButtons => Phase == XyzLoadPhase.SelectFile && !IsLoading; /// 是否显示正在加载提示 public bool ShowLoadingHint => IsLoading; /// 文件已提交后显示「已加载」标记 public bool HasSubmittedFile => Phase != XyzLoadPhase.SelectFile; // ── 第二步:数据预览 ───────────────────────────────────────────────── /// CSV 数据预览(加载后填充) public TableDataMessage? TablePreview { get => _tablePreview; set { if (SetProperty(ref _tablePreview, value)) { OnPropertyChanged(nameof(ShowPreviewSection)); } } } /// 是否显示数据预览区 public bool ShowPreviewSection => _tablePreview != null && Phase != XyzLoadPhase.SelectFile; // ── 第三步:列头匹配 ───────────────────────────────────────────────── /// 列头匹配下拉字段(必需列 → 可用列 ComboBox) public ObservableCollection ColumnMatchFields { get; } = new(); /// 列头匹配表单定义(保存 title、submitTarget,用于构建摘要) public FormDefinition? ColumnMatchDefinition { get; set; } /// 确认匹配按钮文案 public string MatchButtonLabel { get => _matchButtonLabel; set => SetProperty(ref _matchButtonLabel, value); } /// 是否显示列头匹配区(FileLoaded 阶段且有匹配字段) public bool ShowMatchSection => Phase == XyzLoadPhase.FileLoaded; /// 是否显示「确认匹配」按钮(FileLoaded 阶段) public bool ShowMatchButton => Phase == XyzLoadPhase.FileLoaded; // ── INotifyPropertyChanged ─────────────────────────────────────────── public event PropertyChangedEventHandler? PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); protected bool SetProperty(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } } }