You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/AI/Models/SpecialMessages/FormRequestMessage.cs

127 lines
5.2 KiB
C#

1 month ago
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
{
/// <summary>
/// 表单请求特殊消息 - 在聊天流中显示可填写的表单
/// </summary>
public class FormRequestMessage : ISpecialMessage, INotifyPropertyChanged
{
private string _submitLabel = "提交";
/// <summary>消息唯一标识符</summary>
public string Id { get; set; } = Guid.NewGuid().ToString();
/// <summary>类型名称</summary>
public string TypeName => "Form";
/// <summary>不需要实时更新</summary>
public bool IsLive => false;
/// <summary>表单定义(只读)</summary>
public FormDefinition Definition { get; }
/// <summary>带当前值的字段列表,用于绑定与提交</summary>
public ObservableCollection<FormFieldEntry> FieldsWithValues { get; } = new ObservableCollection<FormFieldEntry>();
/// <summary>提交按钮文案(可从 Definition 覆盖)</summary>
public string SubmitLabel
{
get => _submitLabel;
set => SetProperty(ref _submitLabel, value);
}
public FormRequestMessage(FormDefinition definition)
{
Definition = definition ?? throw new ArgumentNullException(nameof(definition));
_submitLabel = definition.SubmitLabel;
foreach (var f in definition.Fields)
{
var entry = new FormFieldEntry
{
Id = f.Id,
Label = f.Label,
Description = f.Description,
Type = f.Type,
Required = f.Required,
DefaultValue = f.DefaultValue,
Options = f.Options,
Min = f.Min,
Max = f.Max,
Step = f.Step,
MaxLength = f.MaxLength,
Placeholder = f.Placeholder,
DefaultValues = f.DefaultValues != null ? new List<string>(f.DefaultValues) : null,
CurrentValue = f.DefaultValue?.ToString() ?? string.Empty,
};
if (f.Type == FormFieldType.MultiSelect)
{
if (f.DefaultValues != null && f.DefaultValues.Count > 0)
{
foreach (var v in f.DefaultValues)
entry.SelectedValues.Add(v);
}
else if (f.DefaultValue is System.Collections.IEnumerable en && f.DefaultValue is not string)
{
foreach (var v in en)
entry.SelectedValues.Add(v?.ToString() ?? string.Empty);
}
else if (f.DefaultValue is string defStr && !string.IsNullOrEmpty(defStr))
{
foreach (var v in defStr.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
entry.SelectedValues.Add(v);
}
if (f.Options != null)
{
foreach (var opt in f.Options)
entry.MultiSelectOptions.Add(new MultiSelectOptionItem(entry, opt, entry.SelectedValues.Contains(opt)));
}
}
FieldsWithValues.Add(entry);
}
}
/// <summary>收集当前值用于提交。Key 为字段 IdValue 为对象(按 Type 转换)</summary>
public Dictionary<string, object> GetValues()
{
var dict = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
foreach (var entry in FieldsWithValues)
{
var raw = entry.CurrentValue?.Trim() ?? string.Empty;
object value = entry.Type switch
{
FormFieldType.Number => double.TryParse(raw, out var n) ? n : 0d,
FormFieldType.Boolean => raw is "1" or "true" or "True" or "yes" or "是",
FormFieldType.Json => raw,
FormFieldType.MultiSelect => entry.SelectedValues.Count > 0
? new List<string>(entry.SelectedValues)
: (object)raw.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList(),
_ => raw,
};
dict[entry.Id] = value;
}
return dict;
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
}