using OrderSupportTicket.Models.Api;
using System;
using System.Globalization;
using WPFCommon.Models;
namespace OrderSupportTicket.ViewModels;
///
/// 历史工单列表中的单个工单摘要。
///
public sealed class WorkOrderSummaryViewModel : BindableBaseEx
{
private string _appId;
private string _wechatOrderId;
private string _status;
private string _statusText;
private DateTimeOffset _updatedAt;
private DateTimeOffset _lastMessageAt;
private DateTimeOffset? _lastReplyAt;
private string _lastSenderType;
private int _unreadCount;
private bool _hasNewMessage;
private string _version;
public WorkOrderSummaryViewModel(WorkOrderSummaryDto dto)
{
if (dto == null)
throw new ArgumentNullException(nameof(dto));
Apply(dto);
}
///
/// 订单所属店铺 APPID。
///
public string AppId
{
get => _appId;
private set => SetValue(ref _appId, value);
}
///
/// 微信订单号,也是客户端使用的工单号。
///
public string WechatOrderId
{
get => _wechatOrderId;
private set => SetValue(ref _wechatOrderId, value);
}
///
/// 工单状态编码。
///
public string Status
{
get => _status;
private set
{
if (SetValue(ref _status, value))
RaisePropertyChanged(nameof(IsCompleted));
}
}
///
/// 工单状态中文文本。
///
public string StatusText
{
get => _statusText;
private set => SetValue(ref _statusText, value);
}
///
/// 工单最后更新时间。
///
public DateTimeOffset UpdatedAt
{
get => _updatedAt;
private set
{
if (SetValue(ref _updatedAt, value))
RaisePropertyChanged(nameof(UpdatedAtText));
}
}
///
/// 最近一条公开留言的时间。
///
public DateTimeOffset LastMessageAt
{
get => _lastMessageAt;
private set => SetValue(ref _lastMessageAt, value);
}
///
/// 最近一次客服正式回复时间。
///
public DateTimeOffset? LastReplyAt
{
get => _lastReplyAt;
private set => SetValue(ref _lastReplyAt, value);
}
///
/// 最近一条留言的发送方类型。
///
public string LastSenderType
{
get => _lastSenderType;
private set
{
if (SetValue(ref _lastSenderType, value))
RaisePropertyChanged(nameof(PreviewText));
}
}
///
/// 当前工单的未读留言数量。
///
public int UnreadCount
{
get => _unreadCount;
private set => SetValue(ref _unreadCount, value);
}
///
/// 本次服务器刷新是否检测到比本地缓存更新的公开消息。
///
public bool HasNewMessage
{
get => _hasNewMessage;
private set
{
if (SetValue(ref _hasNewMessage, value))
RaisePropertyChanged(nameof(PreviewText));
}
}
///
/// 工单版本号字符串。
///
public string Version
{
get => _version;
private set => SetValue(ref _version, value);
}
///
/// 用于合并工单的 APPID 与订单号组合键。
///
public string Key => AppId + "|" + WechatOrderId;
///
/// 工单是否已完结。
///
public bool IsCompleted =>
string.Equals(Status, "completed", StringComparison.OrdinalIgnoreCase);
///
/// 适合列表展示的本地时间文本。
///
public string UpdatedAtText =>
UpdatedAt == default
? string.Empty
: UpdatedAt.ToLocalTime().ToString("MM-dd HH:mm", CultureInfo.CurrentCulture);
///
/// 不读取留言正文时使用的最近动态摘要。
///
public string PreviewText
{
get
{
if (HasNewMessage)
return "有新消息,点击查看";
if (string.Equals(
LastSenderType,
"customer",
StringComparison.OrdinalIgnoreCase))
{
return "客户最近有新留言";
}
if (LastReplyAt.HasValue)
return "客服最近已回复";
return "暂无公开留言";
}
}
public bool TryApply(WorkOrderSummaryDto dto)
{
if (dto == null || !string.Equals(Key, dto.AppId + "|" + dto.WechatOrderId,
StringComparison.Ordinal))
{
return false;
}
if (!IsAtLeastCurrentVersion(dto.Version))
return false;
Apply(dto);
return true;
}
public void ApplySendResult(string status, string version)
{
if (!string.IsNullOrWhiteSpace(status))
{
Status = status;
StatusText = GetStatusText(status);
}
if (!string.IsNullOrWhiteSpace(version))
Version = version;
UpdatedAt = DateTimeOffset.Now;
LastMessageAt = UpdatedAt;
LastSenderType = "customer";
HasNewMessage = false;
}
public void MarkRead()
{
UnreadCount = 0;
HasNewMessage = false;
}
///
/// 标记检测到新消息,并确保列表显示未读角标。
///
public void MarkHasNewMessage()
{
HasNewMessage = true;
if (UnreadCount <= 0)
UnreadCount = 1;
}
private void Apply(WorkOrderSummaryDto dto)
{
AppId = dto.AppId;
WechatOrderId = dto.WechatOrderId;
Status = dto.Status;
StatusText = string.IsNullOrWhiteSpace(dto.StatusText)
? GetStatusText(dto.Status)
: dto.StatusText;
UpdatedAt = ParseTimestamp(dto.UpdatedAt);
LastMessageAt = ParseTimestamp(dto.LastMessageAt);
LastReplyAt = ParseNullableTimestamp(dto.LastReplyAt);
LastSenderType = dto.LastSenderType;
UnreadCount = Math.Max(0, dto.UnreadCount);
Version = dto.Version;
}
private bool IsAtLeastCurrentVersion(string incomingVersion)
{
if (string.IsNullOrWhiteSpace(incomingVersion))
return true;
if (!long.TryParse(incomingVersion, out var incoming))
return true;
if (!long.TryParse(Version, out var current))
return true;
return incoming >= current;
}
private static DateTimeOffset ParseTimestamp(string value)
{
if (DateTimeOffset.TryParse(
value,
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal,
out var parsed))
{
return parsed;
}
return default;
}
private static DateTimeOffset? ParseNullableTimestamp(string value)
{
var parsed = ParseTimestamp(value);
return parsed == default ? (DateTimeOffset?)null : parsed;
}
private static string GetStatusText(string status)
{
if (string.Equals(status, "waiting_reply", StringComparison.OrdinalIgnoreCase))
return "待客服回复";
if (string.Equals(status, "replied", StringComparison.OrdinalIgnoreCase))
return "客服已回复";
if (string.Equals(status, "completed", StringComparison.OrdinalIgnoreCase))
return "已完结";
return string.IsNullOrWhiteSpace(status) ? "状态未知" : status;
}
}