using AllBase; using AllBase.Model.DBModel; using System; using System.Collections.Generic; using System.Configuration; using System.Globalization; using System.Linq; namespace OrderSupportTicket.Models; /// /// 工单页运行参数。APPID 与拍单账号由宿主程序注入,页面内不硬编码账号。 /// public sealed class TicketClientOptions { public TicketClientOptions() { AppIds = new List(); Orders = new List(); } /// /// 当前拍单账号,对应接口字段 purchaseAccount。 /// public string UserName { get; set; } /// /// 当前账号需要订阅和查询的店铺 APPID 集合,最多 50 个。 /// public IList AppIds { get; set; } /// /// 可关联到新工单的本地订单集合。 /// public IList Orders { get; set; } /// /// 创建参数副本,避免宿主与页面共享可变集合。 /// public TicketClientOptions Clone() { return new TicketClientOptions { UserName = UserName, AppIds = (AppIds ?? Enumerable.Empty()) .Where(appId => !string.IsNullOrWhiteSpace(appId)) .Select(appId => appId.Trim()) .Distinct(StringComparer.Ordinal) .ToList(), Orders = (Orders ?? Enumerable.Empty()) .Where(order => order != null) .ToList() }; } public static TicketClientOptions FromApplicationSettings() { var purchaseAccount = ConfigurationManager.AppSettings["CustomerWorkOrder.PurchaseAccount"]; var appIds = ConfigurationManager.AppSettings["CustomerWorkOrder.AppIds"]; return new TicketClientOptions { UserName = purchaseAccount, AppIds = (appIds ?? string.Empty) .Split(new[] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries) .Select(a => a.Trim()) .Where(a => a.Length > 0) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList() }; } } /// /// 新建工单时需要在本地订单列表中关联的订单。 /// 微信订单号始终是字符串,禁止转换为 Number。 /// public sealed class TicketOrderOption { /// /// 订单所属店铺的 APPID,格式为 wx 加 16 位小写十六进制字符。 /// public string AppId { get; set; } /// /// 微信订单号。接口要求保持为 10~64 位数字字符串,禁止转换为 Number。 /// public string OrderId { get; set; } /// /// 商品名称,用于订单筛选和页面展示。 /// public string GoodsName { get; set; } /// /// 商品缩略图地址,用于新建工单页展示关联商品。 /// public string ImageUrl { get; set; } /// /// 订单金额,单位元,使用 decimal 保存原始金额,不在模型中保存格式化文本。 /// public decimal Amount { get; set; } /// /// 订单下单时间。 /// public DateTime OrderedAt { get; set; } /// /// 下拉列表显示文本,订单号在前、商品名在后,避免长商品名遮挡订单号。 /// public string DisplayText { get { var product = string.IsNullOrWhiteSpace(GoodsName) ? "未命名商品" : GoodsName; return $"{OrderId} · {product}"; } } /// /// 订单详情展示文本。商品名已包含在 中,这里只展示金额和下单时间。 /// public string ProductDescription { get { var amount = "¥ " + Amount.ToString("N2", CultureInfo.GetCultureInfo("zh-CN")); var orderedAt = OrderedAt == default ? "下单时间未知" : OrderedAt.ToString("yyyy-MM-dd HH:mm", CultureInfo.CurrentCulture); return $"金额 {amount} · {orderedAt}"; } } /// /// 从本地订单生成工单关联订单信息,统一商品名、缩略图、金额和下单时间的取值规则。 /// public static TicketOrderOption FromWechatOrder( oms_wei_order_info order, string appId) { if (order == null) return null; var goodsName = string.Join( "、", (order.orderItems ?? Enumerable.Empty()) .Select(item => item.title) .Where(title => !string.IsNullOrWhiteSpace(title)) .Distinct()); if (goodsName.Length > 200) goodsName = goodsName.Substring(0, 200) + "…"; return new TicketOrderOption { AppId = appId?.Trim(), OrderId = order.order_id, GoodsName = goodsName, ImageUrl = (order.orderItems ?? Enumerable.Empty()) .Select(item => item.thumb_img) .FirstOrDefault(url => !string.IsNullOrWhiteSpace(url)), Amount = (order.order_price ?? 0) / 100m, OrderedAt = order.create_time > 0 ? BaseClass.StampToDateTime(order.create_time) : default }; } /// /// 当前工单的唯一订单键,由 APPID 和微信订单号共同组成。 /// public string OrderKey => $"{AppId}|{OrderId}"; }