修复工单Bug

This commit is contained in:
chfei committed 2026-10-19 14:35:25 +08:00
1 parent 7982f7e348
commit 8e0cc20649
12 files changed
+602 -236

No files matched your search

@@ -1,6 +1,5 @@
using AllBase.Helper;
using AllBase.Model.DBModel;
using NaiBa.Util.Helper;
using OrderSupportTicket.Models;
using OrderSupportTicket.Models.Api;
using OrderSupportTicket.Services;
@@ -9,7 +8,6 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
@@ -32,9 +30,8 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
/// </summary>
public const string OrderParameterKey = "order";
private const string SavedListConfigName = "ordersupportticket";
private readonly ITicketApiService _api;
private readonly ITicketRealtimeService _realtime;
private readonly TicketService _ticketService;
private readonly WorkOrderCacheService _cacheService = new WorkOrderCacheService();
private readonly Dispatcher _dispatcher;
private readonly AsyncDelegateCommand<WorkOrderSummaryViewModel> _selectTicketCommand;
private readonly AsyncDelegateCommand _createTicketCommand;
@@ -52,7 +49,6 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
private bool _configured;
private bool _initialized;
private bool _disposed;
private readonly bool _ownsRealtime;
private string _pendingOpenKey;
private WorkOrderSummaryViewModel _selectedTicket;
private TicketOrderOption _selectedOrder;
@@ -82,14 +78,11 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
private int _selectionVersion;
public OrderSupportTicketViewModel(
ITicketApiService api,
ITicketRealtimeService realtime,
TicketClientOptions options = null,
bool ownsRealtime = true)
TicketService ticketService,
TicketClientOptions options = null)
{
_api = api ?? throw new ArgumentNullException(nameof(api));
_realtime = realtime ?? throw new ArgumentNullException(nameof(realtime));
_ownsRealtime = ownsRealtime;
_ticketService = ticketService
?? throw new ArgumentNullException(nameof(ticketService));
_dispatcher = System.Windows.Application.Current?.Dispatcher
?? Dispatcher.CurrentDispatcher;
@@ -112,10 +105,10 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
_retryRealtimeCommand = new AsyncDelegateCommand(
RestartRealtimeAsync,
() => !IsBusy && _configured);
_realtime.NotificationReceived += OnNotificationReceived;
_realtime.StateChanged += OnRealtimeStateChanged;
SseState = TicketRealtimeState.Disconnected;
SseStatusText = "实时推送:未连接";
_ticketService.NotificationReceived += OnNotificationReceived;
_ticketService.StateChanged += OnRealtimeStateChanged;
SseState = _ticketService.RealtimeState;
SseStatusText = GetRealtimeStatusText(SseState);
if (options != null)
Configure(options);
@@ -636,17 +629,16 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
if (_disposed)
throw new ObjectDisposedException(nameof(OrderSupportTicketViewModel));
if (_ownsRealtime)
if (_ticketService.OwnsRealtime)
{
_ = _realtime.StopAsync();
_ = _ticketService.StopRealtimeAsync();
SseState = TicketRealtimeState.Disconnected;
SseStatusText = GetRealtimeStatusText(SseState);
}
else
{
SseState = _realtime.State;
SseStatusText = GetRealtimeStatusText(SseState);
SseState = _ticketService.RealtimeState;
}
SseStatusText = GetRealtimeStatusText(SseState);
_configured = false;
_initialized = false;
_pendingOpenKey = null;
@@ -680,7 +672,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
{
try
{
TicketApiService.ValidateOptions(_options);
_ticketService.ValidateOptions(_options);
if (_options.AppIds == null || _options.AppIds.Count == 0)
throw new ArgumentException("appIds 至少需要一个 APPID。");
_configured = true;
@@ -718,11 +710,11 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
var started = false;
// 共享连接由宿主统一维护,页面首次打开时不能因为 _initialized=false 重启连接。
var shouldStartRealtime =
_realtime.State == TicketRealtimeState.Disconnected
|| (_ownsRealtime && !_initialized);
_ticketService.RealtimeState == TicketRealtimeState.Disconnected
|| (_ticketService.OwnsRealtime && !_initialized);
if (shouldStartRealtime)
{
_realtime.Start(_options);
_ticketService.StartRealtime(_options);
started = true;
}
@@ -743,8 +735,8 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
public async Task DeactivateAsync()
{
SaveWorkOrderList();
if (_ownsRealtime)
await _realtime.StopAsync();
if (_ticketService.OwnsRealtime)
await _ticketService.StopRealtimeAsync();
}
public void OpenNewTicket(TicketOrderOption order)
@@ -834,10 +826,9 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
return;
SaveWorkOrderList();
_disposed = true;
_realtime.NotificationReceived -= OnNotificationReceived;
_realtime.StateChanged -= OnRealtimeStateChanged;
if (_ownsRealtime)
_realtime.Dispose();
_ticketService.NotificationReceived -= OnNotificationReceived;
_ticketService.StateChanged -= OnRealtimeStateChanged;
_ticketService.Dispose();
}
private void OpenNewDraft()
@@ -938,7 +929,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
ClearNotice();
try
{
var result = await _api.CreateWorkOrderAsync(
var result = await _ticketService.CreateWorkOrderAsync(
_options,
SelectedOrder,
description,
@@ -1010,7 +1001,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
ClearNotice();
try
{
var result = await _api.SendMessageAsync(
var result = await _ticketService.SendMessageAsync(
_options,
ToSummaryDto(ticket),
text,
@@ -1068,7 +1059,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
IsBusy = true;
try
{
var response = await _api.GetMessagesAsync(
var response = await _ticketService.GetMessagesAsync(
_options,
ticket.AppId,
ticket.WechatOrderId,
@@ -1096,8 +1087,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
IsBusy = true;
try
{
await _realtime.StopAsync();
_realtime.Start(_options);
await _ticketService.RestartRealtimeAsync(_options);
await RefreshAllWorkOrdersAsync(loadSelectedMessages: false);
if (SelectedTicket != null && !IsDraft)
await LoadMessagesAsync(SelectedTicket, replace: true);
@@ -1121,7 +1111,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
IsLoadingMessages = true;
try
{
var response = await _api.GetMessagesAsync(
var response = await _ticketService.GetMessagesAsync(
_options,
ticket.AppId,
ticket.WechatOrderId,
@@ -1168,7 +1158,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
var page = 0;
do
{
var response = await _api.GetWorkOrdersAsync(
var response = await _ticketService.GetWorkOrdersAsync(
_options,
limit: 100,
cursor: cursor);
@@ -1240,7 +1230,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
var options = CloneOptions(_options);
options.AppIds = new List<string> { appId };
var response = await _api.GetWorkOrdersAsync(
var response = await _ticketService.GetWorkOrdersAsync(
options,
wechatOrderId,
limit: 1);
@@ -1338,7 +1328,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
try
{
await _api.MarkReadAsync(
await _ticketService.MarkReadAsync(
_options,
ticket.AppId,
ticket.WechatOrderId,
@@ -1671,21 +1661,8 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
if (string.IsNullOrWhiteSpace(_options?.UserName))
return;
if (!File.Exists(ConfigHelper.GetConfigUserPath(SavedListConfigName)))
return;
WorkOrderListCache cache;
try
{
cache = ConfigHelper.LoadConfig<WorkOrderListCache>(SavedListConfigName);
}
catch
{
return;
}
if (cache?.Items == null
|| !string.Equals(cache.UserName, _options.UserName, StringComparison.Ordinal))
var cache = _cacheService.Load(_options.UserName);
if (cache?.Items == null)
return;
foreach (var saved in cache.Items)
@@ -1735,7 +1712,7 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
try
{
ConfigHelper.SaveConfig(SavedListConfigName, cache);
_cacheService.Save(cache);
_hasSavedCache = true;
}
catch
@@ -1751,7 +1728,8 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
if (!_savedWorkOrders.TryGetValue(dto.WechatOrderId, out var saved))
return _hasSavedCache;
return ParseTimestamp(dto.LastMessageAt) > saved.LastMessageAt;
return WorkOrderCacheService.ParseTimestamp(dto.LastMessageAt)
> saved.LastMessageAt;
}
private static WorkOrderListCacheItem ToCacheItem(
@@ -1767,18 +1745,6 @@ public sealed class OrderSupportTicketViewModel : BindableBaseEx, IDialogAware,
};
}
private static DateTimeOffset ParseTimestamp(string value)
{
if (DateTimeOffset.TryParse(
value,
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal,
out var parsed))
{
return parsed;
}
return default;
}
private static string NewOperationId(string prefix)
{