версия 2.0.7: надёжный автоапдейт (CDN) + кнопка проверки + без лимита листания
- UpdateService: проверка через публичный CDN latest.json (тот же хост, что и установщик — надёжнее поддомена git), fallback на Gitea, лог в %TEMP%\elfisa-update.log - Настройки: кнопка «Проверить обновления» (ручной триггер + видимый результат) - Прайс-лист: убран лимит показа (300 → весь прайс/все совпадения одним запросом) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
23f34cc769
commit
4e341f76c3
@ -3,7 +3,7 @@
|
||||
|
||||
#define MyAppName "Электронная Фармация"
|
||||
#define MyAppBrand "ЭльФиСА"
|
||||
#define MyAppVersion "2.0.6"
|
||||
#define MyAppVersion "2.0.7"
|
||||
#define MyAppPublisher "PharmData"
|
||||
#define MyAppURL "https://cdn.24pharmdata.ru"
|
||||
#define MyAppSupportURL "https://24pharmdata.ru"
|
||||
|
||||
@ -5,9 +5,9 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
<Version>2.0.6</Version>
|
||||
<AssemblyVersion>2.0.6.0</AssemblyVersion>
|
||||
<FileVersion>2.0.6.0</FileVersion>
|
||||
<Version>2.0.7</Version>
|
||||
<AssemblyVersion>2.0.7.0</AssemblyVersion>
|
||||
<FileVersion>2.0.7.0</FileVersion>
|
||||
<Product>ЭльФиСА — Электронная Фармация</Product>
|
||||
<Company>PharmData</Company>
|
||||
<!-- Кросс-платформенная публикация задаётся флагами CLI (RID + self-contained). -->
|
||||
|
||||
@ -128,7 +128,9 @@ public partial class PriceListViewModel : ViewModelBase
|
||||
try
|
||||
{
|
||||
Busy = true;
|
||||
var resp = await _api.GetPriceSummaryAsync(Search, limit: 300, priceListId: SelectedPriceList?.PriceListId);
|
||||
// Без лимита показа: тянем весь прайс/все совпадения одним запросом (сервер
|
||||
// при одном большом запросе прогоняет дедупликацию один раз, без COUNT).
|
||||
var resp = await _api.GetPriceSummaryAsync(Search, limit: 500000, priceListId: SelectedPriceList?.PriceListId);
|
||||
RebuildIndex(resp.Summary ?? new());
|
||||
Total = resp.TotalDrugs;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
xmlns:vm="using:Elfisa.Avalonia.ViewModels"
|
||||
x:Class="Elfisa.Avalonia.Views.SettingsWindow"
|
||||
x:DataType="vm:SettingsViewModel"
|
||||
Width="460" Height="360" CanResize="False"
|
||||
Width="460" Height="440" CanResize="False"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Background="{DynamicResource Bg}"
|
||||
Title="Настройки">
|
||||
@ -26,6 +26,15 @@
|
||||
<ComboBox ItemsSource="{Binding Locations}" SelectedItem="{Binding SelectedLocation}" HorizontalAlignment="Stretch"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock Text="Обновления" Classes="label"/>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<Button Content="Проверить обновления" Click="OnCheckUpdate"/>
|
||||
<TextBlock x:Name="UpdateStatus" VerticalAlignment="Center" TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource Muted}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="10" Margin="0,8,0,0">
|
||||
<Button Content="Отмена" Click="OnCancel" Padding="18,9"/>
|
||||
<Button Classes="primary" Content="Сохранить" Click="OnSave"/>
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
@ -12,6 +14,28 @@ public partial class SettingsWindow : Window
|
||||
{
|
||||
public SettingsWindow() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
private async void OnCheckUpdate(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var status = this.FindControl<TextBlock>("UpdateStatus");
|
||||
var current = Assembly.GetEntryAssembly()?.GetName().Version ?? new Version(0, 0, 0, 0);
|
||||
if (status is not null) status.Text = "Проверяем…";
|
||||
var info = await UpdateService.CheckAsync(current);
|
||||
if (info is null)
|
||||
{
|
||||
if (status is not null) status.Text = "Не удалось проверить (нет сети).";
|
||||
return;
|
||||
}
|
||||
if (!info.Available)
|
||||
{
|
||||
if (status is not null) status.Text = $"У вас последняя версия ({info.CurrentVersion}).";
|
||||
return;
|
||||
}
|
||||
if (status is not null) status.Text = $"Доступна {info.LatestVersion} — открываю…";
|
||||
var win = new UpdateWindow();
|
||||
win.DataContext = new UpdateViewModel(info, win.Close);
|
||||
await win.ShowDialog(this);
|
||||
}
|
||||
|
||||
private void OnSave(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is SettingsViewModel vm)
|
||||
|
||||
@ -20,6 +20,9 @@ public sealed class UpdateInfo
|
||||
/// </summary>
|
||||
public static class UpdateService
|
||||
{
|
||||
// Первичный источник — публичный CDN (тот же хост, откуда качается установщик;
|
||||
// надёжнее приватных API и отдельных поддоменов). Fallback — Gitea Releases.
|
||||
private const string LatestJsonUrl = "https://cdn.24pharmdata.ru/latest.json";
|
||||
private const string ReleasesLatest =
|
||||
"https://git.24pharmdata.ru/api/v1/repos/pharmdata/elfisa-pharmacy/releases/latest";
|
||||
|
||||
@ -28,6 +31,41 @@ public static class UpdateService
|
||||
|
||||
/// <summary>Проверяет наличие новой версии. Возвращает null при офлайне/ошибке (не мешаем работе).</summary>
|
||||
public static async Task<UpdateInfo?> CheckAsync(Version current)
|
||||
{
|
||||
var info = await TryCdnAsync(current).ConfigureAwait(false)
|
||||
?? await TryGiteaAsync(current).ConfigureAwait(false);
|
||||
Log(info is null
|
||||
? $"current={current}: проверка не удалась (нет ответа CDN и Gitea)"
|
||||
: $"current={current} latest={info.LatestVersion} available={info.Available}");
|
||||
return info;
|
||||
}
|
||||
|
||||
// CDN latest.json: {"version":"2.0.7","setup":"https://cdn.24pharmdata.ru/ElfisaPharmacy-Setup.exe"}
|
||||
private static async Task<UpdateInfo?> TryCdnAsync(Version current)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(8) };
|
||||
var json = await http.GetStringAsync(LatestJsonUrl).ConfigureAwait(false);
|
||||
using var doc = JsonDocument.Parse(json);
|
||||
var root = doc.RootElement;
|
||||
var ver = root.TryGetProperty("version", out var v) ? v.GetString() : null;
|
||||
var latest = ParseVersion(ver);
|
||||
if (latest is null) return null;
|
||||
var setup = root.TryGetProperty("setup", out var s) ? s.GetString() : null;
|
||||
return new UpdateInfo
|
||||
{
|
||||
Available = latest > current,
|
||||
CurrentVersion = current.ToString(),
|
||||
LatestVersion = latest.ToString(),
|
||||
ReleaseUrl = "",
|
||||
SetupUrl = string.IsNullOrWhiteSpace(setup) ? SetupUrl : setup!,
|
||||
};
|
||||
}
|
||||
catch (Exception ex) { Log("CDN latest.json недоступен: " + ex.Message); return null; }
|
||||
}
|
||||
|
||||
private static async Task<UpdateInfo?> TryGiteaAsync(Version current)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -49,10 +87,18 @@ public static class UpdateService
|
||||
SetupUrl = SetupUrl,
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
catch (Exception ex) { Log("Gitea releases/latest недоступен: " + ex.Message); return null; }
|
||||
}
|
||||
|
||||
/// <summary>Лог проверки в %TEMP%\elfisa-update.log — для диагностики на машине клиента.</summary>
|
||||
private static void Log(string msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = Path.Combine(Path.GetTempPath(), "elfisa-update.log");
|
||||
File.AppendAllText(path, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {msg}{Environment.NewLine}");
|
||||
}
|
||||
catch { /* лог не критичен */ }
|
||||
}
|
||||
|
||||
/// <summary>Скачивает установщик с CDN во временный файл. Возвращает путь.</summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user