197 lines
5.5 KiB
C#
197 lines
5.5 KiB
C#
using AllBase;
|
|
using AllBase.Model.DBModel;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Configuration;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
|
|
namespace OrderSupportTicket.Models;
|
|
|
|
/// <summary>
|
|
/// 工单页运行参数。APPID 与拍单账号由宿主程序注入,页面内不硬编码账号。
|
|
/// </summary>
|
|
public sealed class TicketClientOptions
|
|
{
|
|
public TicketClientOptions()
|
|
{
|
|
AppIds = new List<string>();
|
|
Orders = new List<TicketOrderOption>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 当前拍单账号,对应接口字段 purchaseAccount。
|
|
/// </summary>
|
|
public string UserName { get; set; }
|
|
|
|
/// <summary>会话数据来源:直接修改此处默认值切换 History / Realtime。</summary>
|
|
public TicketConversationMode ConversationMode { get; set; } = TicketConversationMode.Realtime;
|
|
|
|
/// <summary>
|
|
/// 当前账号需要订阅和查询的店铺 APPID 集合,最多 50 个。
|
|
/// </summary>
|
|
public IList<string> AppIds { get; set; }
|
|
|
|
/// <summary>
|
|
/// 可关联到新工单的本地订单集合。
|
|
/// </summary>
|
|
public IList<TicketOrderOption> Orders { get; set; }
|
|
|
|
/// <summary>
|
|
/// 创建参数副本,避免宿主与页面共享可变集合。
|
|
/// </summary>
|
|
public TicketClientOptions Clone()
|
|
{
|
|
return new TicketClientOptions
|
|
{
|
|
UserName = UserName,
|
|
ConversationMode = ConversationMode,
|
|
AppIds = (AppIds ?? Enumerable.Empty<string>())
|
|
.Where(appId => !string.IsNullOrWhiteSpace(appId))
|
|
.Select(appId => appId.Trim())
|
|
.Distinct(StringComparer.Ordinal)
|
|
.ToList(),
|
|
Orders = (Orders ?? Enumerable.Empty<TicketOrderOption>())
|
|
.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(),
|
|
ConversationMode = TicketConversationMode.Realtime,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 新建工单时需要在本地订单列表中关联的订单。
|
|
/// 微信订单号始终是字符串,禁止转换为 Number。
|
|
/// </summary>
|
|
public sealed class TicketOrderOption
|
|
{
|
|
/// <summary>
|
|
/// 订单所属店铺的 APPID,格式为 wx 加 16 位小写十六进制字符。
|
|
/// </summary>
|
|
public string AppId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 微信订单号。接口要求保持为 10~64 位数字字符串,禁止转换为 Number。
|
|
/// </summary>
|
|
public string OrderId { get; set; }
|
|
|
|
/// <summary>
|
|
/// 商品名称,用于订单筛选和页面展示。
|
|
/// </summary>
|
|
public string GoodsName { get; set; }
|
|
|
|
/// <summary>
|
|
/// 商品缩略图地址,用于新建工单页展示关联商品。
|
|
/// </summary>
|
|
public string ImageUrl { get; set; }
|
|
|
|
/// <summary>
|
|
/// 订单金额,单位元,使用 decimal 保存原始金额,不在模型中保存格式化文本。
|
|
/// </summary>
|
|
public decimal Amount { get; set; }
|
|
|
|
/// <summary>
|
|
/// 订单下单时间。
|
|
/// </summary>
|
|
public DateTime OrderedAt { get; set; }
|
|
|
|
/// <summary>
|
|
/// 下拉列表显示文本,订单号在前、商品名在后,避免长商品名遮挡订单号。
|
|
/// </summary>
|
|
public string DisplayText
|
|
{
|
|
get
|
|
{
|
|
var product = string.IsNullOrWhiteSpace(GoodsName)
|
|
? "未命名商品"
|
|
: GoodsName;
|
|
return $"{OrderId} · {product}";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 订单详情展示文本。商品名已包含在 <see cref="DisplayText"/> 中,这里只展示金额和下单时间。
|
|
/// </summary>
|
|
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}";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从本地订单生成工单关联订单信息,统一商品名、缩略图、金额和下单时间的取值规则。
|
|
/// </summary>
|
|
public static TicketOrderOption FromWechatOrder(
|
|
oms_wei_order_info order,
|
|
string appId)
|
|
{
|
|
if (order == null)
|
|
return null;
|
|
|
|
var goodsName = string.Join(
|
|
"、",
|
|
(order.orderItems ?? Enumerable.Empty<oms_wei_order_item_info>())
|
|
.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<oms_wei_order_item_info>())
|
|
.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
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 当前工单的唯一订单键,由 APPID 和微信订单号共同组成。
|
|
/// </summary>
|
|
public string OrderKey => $"{AppId}|{OrderId}";
|
|
}
|
|
|
|
/// <summary>History 点击加载历史;Realtime 仅使用推送和发送回执构建会话。</summary>
|
|
public enum TicketConversationMode
|
|
{
|
|
/// <summary>
|
|
/// 点击加载历史
|
|
/// </summary>
|
|
History,
|
|
/// <summary>
|
|
/// 仅使用推送和发送回执构建会话
|
|
/// </summary>
|
|
Realtime
|
|
}
|