using System.Collections.ObjectModel; using System.Windows; using Prism.Commands; using Prism.Events; using YY.Admin.Core; using YY.Admin.Core.Entity; using YY.Admin.Core.Events; using YY.Admin.Core.Services; using YY.Admin.Views.Print; namespace YY.Admin.ViewModels.Print; /// 业务打印绑定列表(只读,本地缓存 + 同步) public class PrintBizTemplateBindListViewModel : BaseViewModel { private readonly IPrintBizTemplateBindService _bindService; private SubscriptionToken? _changeToken; private List _all = new(); public ObservableCollection Items { get; } = new(); private string _statusMessage = string.Empty; public string StatusMessage { get => _statusMessage; set => SetProperty(ref _statusMessage, value); } private string? _filterBizCode; public string? FilterBizCode { get => _filterBizCode; set => SetProperty(ref _filterBizCode, value); } private string? _filterBizName; public string? FilterBizName { get => _filterBizName; set => SetProperty(ref _filterBizName, value); } private string? _filterTemplateCode; public string? FilterTemplateCode { get => _filterTemplateCode; set => SetProperty(ref _filterTemplateCode, value); } public DelegateCommand SearchCommand { get; } public DelegateCommand ResetCommand { get; } public DelegateCommand DetailCommand { get; } public PrintBizTemplateBindListViewModel( IPrintBizTemplateBindService bindService, IContainerExtension container, IRegionManager regionManager) : base(container, regionManager) { _bindService = bindService; SearchCommand = new DelegateCommand(ApplyFilter); ResetCommand = new DelegateCommand(() => { FilterBizCode = null; FilterBizName = null; FilterTemplateCode = null; ApplyFilter(); }); DetailCommand = new DelegateCommand(OpenDetail); _changeToken = _eventAggregator .GetEvent() .Subscribe(_ => { RefreshSilentlyAsync().ConfigureAwait(false); }, ThreadOption.UIThread); ShowCached(); _ = RefreshSilentlyAsync(); } private void ShowCached() { var cached = _bindService.GetCached(); if (cached.Count == 0) return; _all = cached.ToList(); ApplyFilter(); UpdateStatus(); } private async Task RefreshSilentlyAsync() { try { var list = await _bindService.RefreshCacheAsync().ConfigureAwait(false); await Application.Current.Dispatcher.InvokeAsync(() => { _all = list.ToList(); ApplyFilter(); UpdateStatus(); }); } catch { var cached = _bindService.GetCached(); if (cached.Count > 0 && _all.Count == 0) { await Application.Current.Dispatcher.InvokeAsync(() => { _all = cached.ToList(); ApplyFilter(); UpdateStatus(); }); } } } private void ApplyFilter() { IEnumerable result = _all; if (!string.IsNullOrWhiteSpace(FilterBizCode)) result = result.Where(x => (x.BizCode ?? string.Empty) .Contains(FilterBizCode, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrWhiteSpace(FilterBizName)) result = result.Where(x => (x.BizName ?? string.Empty) .Contains(FilterBizName, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrWhiteSpace(FilterTemplateCode)) result = result.Where(x => (x.TemplateCode ?? string.Empty) .Contains(FilterTemplateCode, StringComparison.OrdinalIgnoreCase)); var filtered = result.ToList(); for (int i = Items.Count - 1; i >= 0; i--) { if (!filtered.Any(t => t.Id == Items[i].Id)) Items.RemoveAt(i); } for (int i = 0; i < filtered.Count; i++) { var item = filtered[i]; var existingIdx = -1; for (int j = 0; j < Items.Count; j++) { if (Items[j].Id == item.Id) { existingIdx = j; break; } } if (existingIdx < 0) Items.Insert(i, item); else { if (existingIdx != i) Items.Move(existingIdx, i); Items[i] = item; } } } private void UpdateStatus() { var hasFilter = !string.IsNullOrWhiteSpace(FilterBizCode) || !string.IsNullOrWhiteSpace(FilterBizName) || !string.IsNullOrWhiteSpace(FilterTemplateCode); StatusMessage = hasFilter ? $"筛选结果 {Items.Count} / {_all.Count} 条" : _all.Count > 0 ? $"共 {_all.Count} 条绑定(缓存于本地,可离线查看)" : "暂无数据(联网后将自动同步)"; } private async void OpenDetail(PrintBizTemplateBind? row) { if (row == null) return; PrintBizTemplateBind model = row; try { var fresh = await _bindService.GetByIdAsync(row.Id ?? "").ConfigureAwait(false); if (fresh != null) model = fresh; } catch { /* 使用列表行数据 */ } // 网络请求 continuation 可能在非 STA 线程,Window 必须在 UI 线程创建 var app = Application.Current; if (app?.Dispatcher == null) return; await app.Dispatcher.InvokeAsync(() => { var win = new PrintBizTemplateBindDetailWindow(model) { Owner = app.MainWindow }; win.ShowDialog(); }); } }