������� �� Avalonia 2.0 (�����-���������, ����������, �������� ��������) #1
@ -123,8 +123,8 @@
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
</Style>
|
||||
<Style Selector="ListBox.topnav ListBoxItem">
|
||||
<Setter Property="Padding" Value="10,7"/>
|
||||
<Setter Property="Margin" Value="3,0"/>
|
||||
<Setter Property="Padding" Value="6,7"/>
|
||||
<Setter Property="Margin" Value="2,0"/>
|
||||
<Setter Property="CornerRadius" Value="10"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
</Style>
|
||||
|
||||
78
src/Elfisa.Avalonia/ViewModels/LoadPriceViewModel.cs
Normal file
78
src/Elfisa.Avalonia/ViewModels/LoadPriceViewModel.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Elfisa.Core;
|
||||
|
||||
namespace Elfisa.Avalonia.ViewModels;
|
||||
|
||||
/// <summary>«Загрузить» — скачивание актуального прайса с сервера в память.</summary>
|
||||
public partial class LoadPriceViewModel : ViewModelBase
|
||||
{
|
||||
private readonly ApiClient _api = new();
|
||||
|
||||
[ObservableProperty] private bool _busy;
|
||||
[ObservableProperty] private double _progress; // 0..100
|
||||
[ObservableProperty] private string _progressText = "";
|
||||
[ObservableProperty] private string? _result;
|
||||
|
||||
public string LastLoaded =>
|
||||
PriceCache.LoadedAt is { } dt
|
||||
? $"Последняя загрузка: {dt:dd.MM.yyyy HH:mm} — {PriceCache.Items.Count} позиций"
|
||||
: "Прайс ещё не загружался в этой сессии.";
|
||||
|
||||
public LoadPriceViewModel()
|
||||
{
|
||||
_api.SetToken(Session.Current.Token);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task LoadAsync()
|
||||
{
|
||||
Result = null;
|
||||
try
|
||||
{
|
||||
Busy = true;
|
||||
Progress = 0;
|
||||
ProgressText = "Соединение с сервером…";
|
||||
|
||||
var all = new List<PriceItem>();
|
||||
const int page = 500;
|
||||
int offset = 0, total = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
var resp = await _api.GetPriceSummaryAsync(null, limit: page, offset: offset);
|
||||
var batch = resp.Summary ?? new();
|
||||
if (resp.TotalDrugs > 0) total = resp.TotalDrugs;
|
||||
all.AddRange(batch);
|
||||
|
||||
Progress = total > 0 ? Math.Min(100.0, all.Count * 100.0 / total) : 0;
|
||||
ProgressText = total > 0
|
||||
? $"Загружено {all.Count} из {total} позиций…"
|
||||
: $"Загружено {all.Count} позиций…";
|
||||
|
||||
offset += batch.Count;
|
||||
if (batch.Count < page || (total > 0 && all.Count >= total) || offset > 30000)
|
||||
break;
|
||||
}
|
||||
|
||||
PriceCache.Items = all;
|
||||
PriceCache.LoadedAt = DateTime.Now;
|
||||
Progress = 100;
|
||||
ProgressText = "Готово.";
|
||||
|
||||
var suppliers = all.Select(x => x.SupplierName).Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().Count();
|
||||
Result = $"Прайс загружен: {all.Count} позиций от {suppliers} поставщик(ов).";
|
||||
OnPropertyChanged(nameof(LastLoaded));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Result = "Ошибка загрузки: " + ex.Message;
|
||||
ProgressText = "";
|
||||
}
|
||||
finally { Busy = false; }
|
||||
}
|
||||
}
|
||||
@ -46,6 +46,7 @@ public partial class ShellViewModel : ViewModelBase
|
||||
new("Заказы", "🛒", () => new OrdersViewModel()),
|
||||
new("Накладные", "📄", () => new InvoicesViewModel()),
|
||||
new("Отчёты", "📊", () => new ReportsViewModel()),
|
||||
new("Загрузить", "📥", () => new LoadPriceViewModel()),
|
||||
new("Отправить", "📤", () => new SendOrderViewModel()),
|
||||
new("Отказы", "⛔", () => new PlaceholderPageViewModel("Отказы",
|
||||
"Отказные позиции по заказам. Нужен серверный эндпоинт: данные (RefuseItemsCount) сейчас есть только в локальной БД WinForms-клиента.")),
|
||||
|
||||
39
src/Elfisa.Avalonia/Views/LoadPriceView.axaml
Normal file
39
src/Elfisa.Avalonia/Views/LoadPriceView.axaml
Normal file
@ -0,0 +1,39 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:Elfisa.Avalonia.ViewModels"
|
||||
xmlns:conv="using:Avalonia.Data.Converters"
|
||||
x:Class="Elfisa.Avalonia.Views.LoadPriceView"
|
||||
x:DataType="vm:LoadPriceViewModel">
|
||||
|
||||
<Grid Margin="24" RowDefinitions="Auto,*">
|
||||
<StackPanel Grid.Row="0" Spacing="2">
|
||||
<TextBlock Text="Загрузить" Classes="h1"/>
|
||||
<TextBlock Text="Скачать актуальный прайс с сервера" Classes="muted"/>
|
||||
</StackPanel>
|
||||
|
||||
<Border Grid.Row="1" Classes="card" MaxWidth="560" Padding="30"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<StackPanel Spacing="18" HorizontalAlignment="Center">
|
||||
<Border Width="60" Height="60" CornerRadius="30" Background="{DynamicResource AccentSoft}">
|
||||
<TextBlock Text="📥" FontSize="26" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
|
||||
<TextBlock Text="{Binding LastLoaded}" Classes="muted" HorizontalAlignment="Center" TextAlignment="Center"/>
|
||||
|
||||
<Button Classes="primary" Content="Загрузить прайс" HorizontalAlignment="Center"
|
||||
Padding="28,12" Command="{Binding LoadCommand}" IsEnabled="{Binding !Busy}"/>
|
||||
|
||||
<StackPanel Spacing="6" IsVisible="{Binding Busy}">
|
||||
<ProgressBar Minimum="0" Maximum="100" Value="{Binding Progress}" Height="8" Width="360"/>
|
||||
<TextBlock Text="{Binding ProgressText}" Classes="muted" HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<Border Background="{DynamicResource AccentSoft}" CornerRadius="8" Padding="14,10"
|
||||
IsVisible="{Binding Result, Converter={x:Static conv:ObjectConverters.IsNotNull}}">
|
||||
<TextBlock Text="{Binding Result}" Foreground="{DynamicResource AccentPressed}"
|
||||
TextWrapping="Wrap" TextAlignment="Center"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
9
src/Elfisa.Avalonia/Views/LoadPriceView.axaml.cs
Normal file
9
src/Elfisa.Avalonia/Views/LoadPriceView.axaml.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Elfisa.Avalonia.Views;
|
||||
|
||||
public partial class LoadPriceView : UserControl
|
||||
{
|
||||
public LoadPriceView() => AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
@ -11,9 +11,9 @@
|
||||
<Grid ColumnDefinitions="Auto,*,Auto" Margin="18,0">
|
||||
|
||||
<!-- Логотип -->
|
||||
<StackPanel Grid.Column="0" VerticalAlignment="Center" Margin="0,0,22,0">
|
||||
<TextBlock Text="ЭльФиСА" FontSize="19" FontWeight="Bold" Foreground="White"/>
|
||||
<TextBlock Text="Электронная Фармация" Foreground="{DynamicResource SidebarText}" FontSize="10.5"/>
|
||||
<StackPanel Grid.Column="0" VerticalAlignment="Center" Margin="0,0,14,0">
|
||||
<TextBlock Text="ЭльФиСА" FontSize="18" FontWeight="Bold" Foreground="White"/>
|
||||
<TextBlock Text="Электронная Фармация" Foreground="{DynamicResource SidebarText}" FontSize="10"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Навигация -->
|
||||
@ -26,10 +26,10 @@
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:NavItem">
|
||||
<StackPanel Orientation="Vertical" Width="76" Spacing="3">
|
||||
<TextBlock Text="{Binding Icon}" FontSize="17" HorizontalAlignment="Center"/>
|
||||
<StackPanel Orientation="Vertical" Width="66" Spacing="2">
|
||||
<TextBlock Text="{Binding Icon}" FontSize="16" HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding Title}" Foreground="{DynamicResource SidebarText}"
|
||||
FontSize="11.5" HorizontalAlignment="Center"
|
||||
FontSize="11" HorizontalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
@ -37,7 +37,7 @@
|
||||
</ListBox>
|
||||
|
||||
<!-- Пользователь + выход -->
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="14" VerticalAlignment="Center" Margin="18,0,0,0">
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="12" VerticalAlignment="Center" Margin="8,0,0,0">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding UserName}" Foreground="White" FontSize="12" FontWeight="SemiBold"
|
||||
HorizontalAlignment="Right" TextTrimming="CharacterEllipsis"/>
|
||||
|
||||
9
src/Elfisa.Core/PriceCache.cs
Normal file
9
src/Elfisa.Core/PriceCache.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Elfisa.Core;
|
||||
|
||||
/// <summary>Загруженный прайс в памяти (наполняется разделом «Загрузить»).</summary>
|
||||
public static class PriceCache
|
||||
{
|
||||
public static List<PriceItem> Items { get; set; } = new();
|
||||
public static DateTime? LoadedAt { get; set; }
|
||||
public static bool HasData => Items.Count > 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user