using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; namespace AntDesign { public partial class Rate : AntDomComponentBase { [Parameter] public RenderFragment ChildContent { get; set; } /// /// 是否允许再次点击后清除 /// [Parameter] public bool AllowClear { get; set; } = true; /// /// 是否允许半选 /// [Parameter] public bool AllowHalf { get; set; } = false; /// /// 是否禁止用户交互 /// [Parameter] public bool Disabled { get; set; } = false; /// /// 是否可获得输入焦点 /// [Parameter] public bool AutoFocus { get; set; } = true; /// /// 自定义字符,星星可以被自定义字符替代 /// [Parameter] public RenderFragment Character { get; set; } /// /// 组件要呈现的星星数目 /// [Parameter] public int Count { get; set; } = 5; /// /// 当前值--被选中的星星数量 /// [Parameter] public decimal Value { get { return _currentValue; } set { if (_currentValue != value) { this._currentValue = value; this._hasHalf = !(_currentValue == (int)_currentValue); this._hoverValue = (int)Math.Ceiling(value); ValueChanged.InvokeAsync(value); } } } [Parameter] public EventCallback ValueChanged { get; set; } /// /// 默认当前被选中的星星数量,如果被设置为小数位不为0的,则组件默认含有半星并且允许半星 /// [Parameter] public decimal DefaultValue { get; set; } /// /// 自定义每项的提示信息(存储每个子元素的提醒框内容文本) /// [Parameter] public string[] Tooltips { get; set; } [Parameter] public EventCallback OnBlur { get; set; } [Parameter] public EventCallback OnFocus { get; set; } private IEnumerable RateMetaDatas { get; set; } /// /// 是否允许半选 /// private bool _hasHalf = false; /// /// 鼠标悬停时从最左到光标位置的星星数。 /// private int _hoverValue = 0; /// /// 当前被选中的星星数量 /// private decimal _currentValue; /// /// 是否获取的输入焦点 /// private bool _isFocused = false; private void Blur(FocusEventArgs e) { this._isFocused = false; OnBlur.InvokeAsync(e); } private void Focus(FocusEventArgs e) { this._isFocused = true; OnFocus.InvokeAsync(e); } private void KeyDown(KeyboardEventArgs e) { decimal oldVal = this.Value; if (e.Key == "ArrowRight" && this.Value < Count) { this.Value += this.AllowHalf ? 0.5M : 1M; } else if (e.Key == "ArrowLeft" && this.Value > 0) { this.Value -= this.AllowHalf ? 0.5M : 1M; } if (oldVal != this.Value) { this._hasHalf = !(this.Value == (int)this.Value); this._hoverValue = (int)Math.Ceiling(this.Value); } } private void MouseLeave() { this._hasHalf = !(this.Value == (int)this.Value); this._hoverValue = (int)Math.Ceiling(this.Value); } private void ItemHoverChange(int index, bool isHalf) { if (this.Disabled || (this._hoverValue == index + 1 && isHalf == _hasHalf)) return; this._hoverValue = index + 1; this._hasHalf = isHalf; } private void ItemClick(int index, bool isHalf) { if (this.Disabled) return; this._hoverValue = index + 1; decimal actualValue = isHalf ? index + 0.5M : index + 1; if (this.Value == actualValue) { if (this.AllowClear) { this.Value = 0; this._hoverValue = 0; } } else { this.Value = actualValue; } } protected override void OnInitialized() { if (DefaultValue > 0) { this.Value = DefaultValue; } SetClass(); RateMetaDatas = Enumerable.Range(1, Count).Select(c => new RateMetaData() { SerialNumber = c - 1, ToolTipText = this.Tooltips?[c - 1] }); base.OnInitialized(); } protected override void OnParametersSet() { if (RateMetaDatas == null) RateMetaDatas = Enumerable.Range(1, Count).Select(c => new RateMetaData() { SerialNumber = c - 1, ToolTipText = this.Tooltips?[c - 1] }); SetClass(); base.OnParametersSet(); } protected void SetClass() { var clsPrefix = "ant-rate"; ClassMapper.Clear() .Add(clsPrefix) .If($"{clsPrefix}-disabled", () => Disabled) .If($"{clsPrefix}-rtl", () => RTL); } } public class RateMetaData { public int SerialNumber { get; set; } public string ToolTipText { get; set; } } public class RateItemRenderContext { /// /// 'AntIcon' | 'Text' /// public string Type { get; set; } public RenderFragment DefaultRender { get; set; } } }