feat: 运单操作日志改为列表摘要,补齐费用/支付/预报/打印埋点
All checks were successful
Build and Deploy / deploy (push) Successful in 1m3s

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-10-10 11:46:33 +08:00
parent dcd985bca4
commit 64737284f3
9 changed files with 289 additions and 17 deletions

View File

@ -17,7 +17,7 @@ SET @sql := IF(
`Id` INT NOT NULL AUTO_INCREMENT COMMENT ''主键'', `Id` INT NOT NULL AUTO_INCREMENT COMMENT ''主键'',
`OrderId` INT NOT NULL COMMENT ''运单Id'', `OrderId` INT NOT NULL COMMENT ''运单Id'',
`ServiceNo` VARCHAR(64) NULL COMMENT ''运单号冗余'', `ServiceNo` VARCHAR(64) NULL COMMENT ''运单号冗余'',
`Action` VARCHAR(32) NOT NULL COMMENT ''动作码 editBasic/editWeight/recalcReceivable/recalcPayable/reallocate'', `Action` VARCHAR(32) NOT NULL COMMENT ''动作码 editBasic/editWeight/recalcReceivable/recalcPayable/reallocate/bindSnapshotVersions/updateAdditionalServices/addFee/pay/preDeclare/downstreamForward/print'',
`ActionName` VARCHAR(64) NOT NULL COMMENT ''动作中文名'', `ActionName` VARCHAR(64) NOT NULL COMMENT ''动作中文名'',
`OperatorId` INT NOT NULL DEFAULT 0 COMMENT ''操作人用户Id'', `OperatorId` INT NOT NULL DEFAULT 0 COMMENT ''操作人用户Id'',
`OperatorName` VARCHAR(64) NULL COMMENT ''操作人展示名'', `OperatorName` VARCHAR(64) NULL COMMENT ''操作人展示名'',

View File

@ -35,6 +35,11 @@ public class OrderOperationLogOutput
public string? Remark { get; set; } public string? Remark { get; set; }
/// <summary>
/// 列表「内容」列:由备注 + 字段变更摘要拼装。
/// </summary>
public string Summary { get; set; } = string.Empty;
public DateTime CreateTime { get; set; } public DateTime CreateTime { get; set; }
} }

View File

@ -26,6 +26,7 @@ public sealed class OrderBatchActionExecutor(
OrderDownstreamCredentialResolver downstreamCredentialResolver, OrderDownstreamCredentialResolver downstreamCredentialResolver,
IItfxForwardClient itfxForwardClient, IItfxForwardClient itfxForwardClient,
OrderFileManager orderFileManager, OrderFileManager orderFileManager,
OrderOperationLogWriter operationLogWriter,
OrderBatchCreateActionHandler createActionHandler, OrderBatchCreateActionHandler createActionHandler,
OrderBatchOrderActionHandler orderActionHandler) : IOrderBatchActionExecutor, IScopedDependency OrderBatchOrderActionHandler orderActionHandler) : IOrderBatchActionExecutor, IScopedDependency
{ {
@ -225,6 +226,8 @@ public sealed class OrderBatchActionExecutor(
businessMessage)); businessMessage));
} }
var beforeSnap = OrderOperationLogSnapshot.CaptureOrder(order);
if (ItfxCreateOrderOneDataParser.TryParse(forward.ResponseBody, out var data) if (ItfxCreateOrderOneDataParser.TryParse(forward.ResponseBody, out var data)
&& data != null) && data != null)
{ {
@ -243,6 +246,29 @@ public sealed class OrderBatchActionExecutor(
} }
} }
var afterSnap = OrderOperationLogSnapshot.CaptureOrder(order);
var remarkParts = new List<string> { $"供应商 {creds.SupplierCode}" };
if (!string.IsNullOrWhiteSpace(order.DownstreamServiceNo))
{
remarkParts.Add($"服务商单号 {order.DownstreamServiceNo}");
}
if (!string.IsNullOrWhiteSpace(order.TrackNo))
{
remarkParts.Add($"跟踪号 {order.TrackNo}");
}
await operationLogWriter.TryWriteAsync(
order,
OrderOperationActionCodes.DownstreamForward,
beforeSnap,
afterSnap,
string.Join(";", remarkParts),
message.OperatorUserId > 0 ? message.OperatorUserId : null,
operatorName: null,
operatorType: "staff",
source: "job");
return OrderBatchActionExecuteResult.Ok( return OrderBatchActionExecuteResult.Ok(
serviceNo: order.ServiceNo, serviceNo: order.ServiceNo,
trackNo: order.TrackNo, trackNo: order.TrackNo,

View File

@ -1,4 +1,6 @@
using System.Globalization; using System.Globalization;
using Newtonsoft.Json;
using Oms.Application.Shared;
using Oms.Domain.OrdersAggregate.Consts; using Oms.Domain.OrdersAggregate.Consts;
using Oms.Domain.OrdersAggregate.Entities; using Oms.Domain.OrdersAggregate.Entities;
@ -9,6 +11,8 @@ namespace Oms.Application.Services.Orders;
/// </summary> /// </summary>
public static class OrderOperationLogSnapshot public static class OrderOperationLogSnapshot
{ {
public const int SummaryMaxChangeItems = 5;
private static readonly Dictionary<string, string> Labels = new(StringComparer.OrdinalIgnoreCase) private static readonly Dictionary<string, string> Labels = new(StringComparer.OrdinalIgnoreCase)
{ {
["orderStatus"] = "订单状态", ["orderStatus"] = "订单状态",
@ -31,6 +35,7 @@ public static class OrderOperationLogSnapshot
["salesProductRulesVersion"] = "规则版本", ["salesProductRulesVersion"] = "规则版本",
["salesProductPriceVersion"] = "价格版本", ["salesProductPriceVersion"] = "价格版本",
["isPaid"] = "是否已支付", ["isPaid"] = "是否已支付",
["additionalServices"] = "附加服务",
["sender.name"] = "发件人姓名", ["sender.name"] = "发件人姓名",
["sender.phone"] = "发件人电话", ["sender.phone"] = "发件人电话",
["sender.country"] = "发件国家", ["sender.country"] = "发件国家",
@ -75,6 +80,7 @@ public static class OrderOperationLogSnapshot
["salesProductRulesVersion"] = Norm(order.SalesProductRulesVersion), ["salesProductRulesVersion"] = Norm(order.SalesProductRulesVersion),
["salesProductPriceVersion"] = Norm(order.SalesProductPriceVersion), ["salesProductPriceVersion"] = Norm(order.SalesProductPriceVersion),
["isPaid"] = FormatByte(order.IsPaid), ["isPaid"] = FormatByte(order.IsPaid),
["additionalServices"] = FormatAdditionalServices(order.AdditionalServices),
}; };
} }
@ -225,6 +231,89 @@ public static class OrderOperationLogSnapshot
return path; return path;
} }
/// <summary>
/// 拼装列表「内容」列:备注优先,再跟最多 N 条字段变更。
/// </summary>
public static string BuildSummary(
IReadOnlyList<OrderOperationLogChangeView> changes,
string? remark,
int maxItems = SummaryMaxChangeItems)
{
var parts = new List<string>();
if (!string.IsNullOrWhiteSpace(remark))
{
parts.Add(remark.Trim());
}
if (changes.Count > 0)
{
var take = Math.Max(0, maxItems);
foreach (var change in changes.Take(take))
{
var label = string.IsNullOrWhiteSpace(change.Label) ? change.Path : change.Label;
parts.Add($"{label}:{DisplayValue(change.Path, change.Before)}→{DisplayValue(change.Path, change.After)}");
}
if (changes.Count > take)
{
parts.Add($"等{changes.Count}项变更");
}
}
return parts.Count == 0 ? "—" : string.Join(";", parts);
}
public readonly record struct OrderOperationLogChangeView(
string Path,
string Label,
string? Before,
string? After);
private static string DisplayValue(string path, string? value)
{
if (string.IsNullOrWhiteSpace(value))
{
return "空";
}
if (string.Equals(path, "isPaid", StringComparison.OrdinalIgnoreCase)
|| string.Equals(path, "isCod", StringComparison.OrdinalIgnoreCase))
{
return value == "1" ? "是" : "否";
}
if (string.Equals(path, "orderStatus", StringComparison.OrdinalIgnoreCase))
{
return OmsDocHelper.GetOrderStatusName(value) ?? value;
}
return value;
}
private static string? FormatAdditionalServices(string? json)
{
if (string.IsNullOrWhiteSpace(json))
{
return null;
}
try
{
var list = JsonConvert.DeserializeObject<List<string>>(json) ?? [];
var codes = list
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => x.Trim())
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
.ToList();
return codes.Count == 0 ? null : string.Join("、", codes);
}
catch
{
return Norm(json);
}
}
private static string? Norm(string? value) private static string? Norm(string? value)
{ {
if (string.IsNullOrWhiteSpace(value)) if (string.IsNullOrWhiteSpace(value))

View File

@ -33,23 +33,29 @@ public class OrderOperationLogWriter : IScopedDependency
_logger = logger; _logger = logger;
} }
public async Task TryWriteAsync( public Task TryWriteAsync(
Order order, Order order,
string action, string action,
IReadOnlyDictionary<string, string?> before, IReadOnlyDictionary<string, string?> before,
IReadOnlyDictionary<string, string?> after, IReadOnlyDictionary<string, string?> after,
string? remark = null) string? remark = null)
=> TryWriteAsync(order, action, before, after, remark, operatorId: null, operatorName: null);
public async Task TryWriteAsync(
Order order,
string action,
IReadOnlyDictionary<string, string?> before,
IReadOnlyDictionary<string, string?> after,
string? remark,
int? operatorId,
string? operatorName,
string operatorType = "staff",
string source = "pc")
{ {
try try
{ {
var changes = OrderOperationLogSnapshot.Diff(before, after); var changes = OrderOperationLogSnapshot.Diff(before, after);
var operatorId = 0; var (resolvedId, resolvedName) = await ResolveOperatorAsync(operatorId, operatorName);
string? operatorName = null;
if (_currentUser.IsAuthenticated)
{
operatorId = _currentUser.GetId<int>();
operatorName = await _userDisplayNameResolver.ResolveAsync(operatorId);
}
var entity = new OrderOperationLog var entity = new OrderOperationLog
{ {
@ -57,10 +63,10 @@ public class OrderOperationLogWriter : IScopedDependency
ServiceNo = order.ServiceNo, ServiceNo = order.ServiceNo,
Action = action, Action = action,
ActionName = OrderOperationActionCodes.GetActionName(action), ActionName = OrderOperationActionCodes.GetActionName(action),
OperatorId = operatorId, OperatorId = resolvedId,
OperatorName = operatorName, OperatorName = resolvedName,
OperatorType = "staff", OperatorType = string.IsNullOrWhiteSpace(operatorType) ? "staff" : operatorType.Trim(),
Source = "pc", Source = string.IsNullOrWhiteSpace(source) ? "pc" : source.Trim(),
ChangesJson = JsonConvert.SerializeObject( ChangesJson = JsonConvert.SerializeObject(
changes.Select(x => new OrderOperationLogChangeItem changes.Select(x => new OrderOperationLogChangeItem
{ {
@ -70,7 +76,7 @@ public class OrderOperationLogWriter : IScopedDependency
After = x.After After = x.After
}).ToList()), }).ToList()),
Remark = string.IsNullOrWhiteSpace(remark) ? null : remark.Trim(), Remark = string.IsNullOrWhiteSpace(remark) ? null : remark.Trim(),
CreateUserId = operatorId, CreateUserId = resolvedId,
CreateTime = DateTime.Now CreateTime = DateTime.Now
}; };
@ -86,6 +92,28 @@ public class OrderOperationLogWriter : IScopedDependency
} }
} }
/// <summary>
/// 无字段 diff 时写入叙事日志(打印、下游预报成功等)。
/// </summary>
public Task TryWriteSimpleAsync(
Order order,
string action,
string? remark,
int? operatorId = null,
string? operatorName = null,
string operatorType = "staff",
string source = "pc")
=> TryWriteAsync(
order,
action,
new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase),
new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase),
remark,
operatorId,
operatorName,
operatorType,
source);
public async Task<OrderOperationLogListOutput> ListByOrderIdAsync(int orderId) public async Task<OrderOperationLogListOutput> ListByOrderIdAsync(int orderId)
{ {
var rows = await _repository.GetListAsync(x => x.OrderId == orderId); var rows = await _repository.GetListAsync(x => x.OrderId == orderId);
@ -97,6 +125,30 @@ public class OrderOperationLogWriter : IScopedDependency
return new OrderOperationLogListOutput { Items = items }; return new OrderOperationLogListOutput { Items = items };
} }
private async Task<(int OperatorId, string? OperatorName)> ResolveOperatorAsync(
int? operatorId,
string? operatorName)
{
if (operatorId is > 0)
{
var name = string.IsNullOrWhiteSpace(operatorName)
? await _userDisplayNameResolver.ResolveAsync(operatorId.Value)
: operatorName.Trim();
return (operatorId.Value, name);
}
if (_currentUser.IsAuthenticated)
{
var id = _currentUser.GetId<int>();
var name = string.IsNullOrWhiteSpace(operatorName)
? await _userDisplayNameResolver.ResolveAsync(id)
: operatorName.Trim();
return (id, name);
}
return (0, string.IsNullOrWhiteSpace(operatorName) ? null : operatorName.Trim());
}
private static OrderOperationLogOutput MapOutput(OrderOperationLog row) private static OrderOperationLogOutput MapOutput(OrderOperationLog row)
{ {
var changes = new List<OrderOperationLogChangeItem>(); var changes = new List<OrderOperationLogChangeItem>();
@ -113,6 +165,14 @@ public class OrderOperationLogWriter : IScopedDependency
} }
} }
var views = changes
.Select(x => new OrderOperationLogSnapshot.OrderOperationLogChangeView(
x.Path,
x.Label,
x.Before,
x.After))
.ToList();
return new OrderOperationLogOutput return new OrderOperationLogOutput
{ {
Id = row.Id, Id = row.Id,
@ -126,6 +186,7 @@ public class OrderOperationLogWriter : IScopedDependency
Source = row.Source, Source = row.Source,
Changes = changes, Changes = changes,
Remark = row.Remark, Remark = row.Remark,
Summary = OrderOperationLogSnapshot.BuildSummary(views, row.Remark),
CreateTime = row.CreateTime CreateTime = row.CreateTime
}; };
} }

View File

@ -1,3 +1,4 @@
using System.Globalization;
using Fake.Application; using Fake.Application;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -323,7 +324,7 @@ public partial class OrderService
"规则"); "规则");
if (!string.Equals(order.SalesProductRulesVersion, resolved, StringComparison.Ordinal)) if (!string.Equals(order.SalesProductRulesVersion, resolved, StringComparison.Ordinal))
{ {
remarkParts.Add($"rules:{order.SalesProductRulesVersion ?? "-"}→{resolved}"); remarkParts.Add($"规则版本 {order.SalesProductRulesVersion ?? "-"}→{resolved}");
order.SalesProductRulesVersion = resolved; order.SalesProductRulesVersion = resolved;
} }
} }
@ -337,7 +338,7 @@ public partial class OrderService
"价格"); "价格");
if (!string.Equals(order.SalesProductPriceVersion, resolved, StringComparison.Ordinal)) if (!string.Equals(order.SalesProductPriceVersion, resolved, StringComparison.Ordinal))
{ {
remarkParts.Add($"price:{order.SalesProductPriceVersion ?? "-"}→{resolved}"); remarkParts.Add($"价格版本 {order.SalesProductPriceVersion ?? "-"}→{resolved}");
order.SalesProductPriceVersion = resolved; order.SalesProductPriceVersion = resolved;
} }
} }
@ -354,11 +355,13 @@ public partial class OrderService
{ {
EnsureReceivableMutable(order); EnsureReceivableMutable(order);
await RecalculateReceivableCoreAsync(order); await RecalculateReceivableCoreAsync(order);
remarkParts.Add("并重算应收");
} }
if (input.RecalculatePayable) if (input.RecalculatePayable)
{ {
await RecalculatePayableCoreAsync(order); await RecalculatePayableCoreAsync(order);
remarkParts.Add("并重算应付");
} }
order = await GetOrderOrThrowAsync(order.Id); order = await GetOrderOrThrowAsync(order.Id);
@ -368,7 +371,7 @@ public partial class OrderService
OrderOperationActionCodes.BindSnapshotVersions, OrderOperationActionCodes.BindSnapshotVersions,
beforeSnap, beforeSnap,
afterSnap, afterSnap,
remarkParts.Count == 0 ? null : string.Join(';', remarkParts)); remarkParts.Count == 0 ? null : string.Join(';', remarkParts));
return (await MapOrderOutputsAsync([order])).First(); return (await MapOrderOutputsAsync([order])).First();
} }
@ -785,6 +788,7 @@ public partial class OrderService
{ {
var order = await GetOrderOrThrowAsync(input.Id); var order = await GetOrderOrThrowAsync(input.Id);
EnsureReceivableMutable(order); EnsureReceivableMutable(order);
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true);
if (string.IsNullOrWhiteSpace(order.ProductCode)) if (string.IsNullOrWhiteSpace(order.ProductCode))
{ {
@ -803,6 +807,15 @@ public partial class OrderService
order.UpdateTime = DateTime.Now; order.UpdateTime = DateTime.Now;
await OrderRepository.UpdateAsync(order); await OrderRepository.UpdateAsync(order);
order = await GetOrderOrThrowAsync(order.Id);
var afterSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true);
await OperationLogWriter.TryWriteAsync(
order,
OrderOperationActionCodes.UpdateAdditionalServices,
beforeSnap,
afterSnap);
return (await MapOrderOutputsAsync([order])).First(); return (await MapOrderOutputsAsync([order])).First();
} }
@ -892,6 +905,8 @@ public partial class OrderService
throw new BusinessException("计费阶段无效"); throw new BusinessException("计费阶段无效");
} }
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true);
var fee = new OrderFee var fee = new OrderFee
{ {
Type = type, Type = type,
@ -912,6 +927,17 @@ public partial class OrderService
order.UpdateTime = DateTime.Now; order.UpdateTime = DateTime.Now;
await OrderRepository.UpdateAsync(order); await OrderRepository.UpdateAsync(order);
order = await GetOrderOrThrowAsync(order.Id);
var afterSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true);
var typeName = type == OrderFeeTypeCodes.Receivable ? "应收" : "应付";
var amountText = input.Amount.ToString("0.####", CultureInfo.InvariantCulture);
await OperationLogWriter.TryWriteAsync(
order,
OrderOperationActionCodes.AddFee,
beforeSnap,
afterSnap,
$"新增{typeName}「{costItem}」{currency} {amountText}");
return (await MapOrderOutputsAsync([order])).First(); return (await MapOrderOutputsAsync([order])).First();
} }

View File

@ -2623,6 +2623,8 @@ public partial class OrderService
return; return;
} }
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true, includeWeights: true);
int? couponInstanceId = order.CouponInstanceId; int? couponInstanceId = order.CouponInstanceId;
if (!string.IsNullOrWhiteSpace(payloadJson)) if (!string.IsNullOrWhiteSpace(payloadJson))
{ {
@ -2765,6 +2767,18 @@ public partial class OrderService
order.UpdateTime = DateTime.Now; order.UpdateTime = DateTime.Now;
await OrderRepository.UpdateAsync(order); await OrderRepository.UpdateAsync(order);
var afterSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true, includeWeights: true);
await OperationLogWriter.TryWriteAsync(
order,
OrderOperationActionCodes.PreDeclare,
beforeSnap,
afterSnap,
"预报计费/排货完成",
operatorUserId > 0 ? operatorUserId : null,
operatorName: null,
operatorType: "staff",
source: "job");
var customer = order.CustomerId.HasValue var customer = order.CustomerId.HasValue
? await CustomerRepository.FirstOrDefaultAsync(x => x.Id == order.CustomerId.Value) ? await CustomerRepository.FirstOrDefaultAsync(x => x.Id == order.CustomerId.Value)
: null; : null;

View File

@ -1,3 +1,4 @@
using System.Globalization;
using Fake.Application; using Fake.Application;
using Fake.Domain.Exceptions; using Fake.Domain.Exceptions;
using Fake.ObjectStorage; using Fake.ObjectStorage;
@ -147,6 +148,7 @@ public partial class OrderService : ApplicationService
throw new BusinessException("订单未关联客户,无法支付"); throw new BusinessException("订单未关联客户,无法支付");
} }
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order);
var fees = await OrderRepository.GetFeesByOrderIdsAsync([order.Id]); var fees = await OrderRepository.GetFeesByOrderIdsAsync([order.Id]);
var payAmount = order.PayableAmount ?? fees var payAmount = order.PayableAmount ?? fees
.Where(x => x.Type == OrderFeeTypeCodes.Receivable) .Where(x => x.Type == OrderFeeTypeCodes.Receivable)
@ -189,6 +191,16 @@ public partial class OrderService : ApplicationService
order.IsPaid = 1; order.IsPaid = 1;
order.OrderStatus = OrderStatusCodes.PendingShip; order.OrderStatus = OrderStatusCodes.PendingShip;
await UpdateOrderAsync(order); await UpdateOrderAsync(order);
order = await GetOrderOrThrowAsync(order.Id);
var afterSnap = await CaptureOrderAuditSnapshotAsync(order);
var amountText = payAmount.ToString("0.####", CultureInfo.InvariantCulture);
await OperationLogWriter.TryWriteAsync(
order,
OrderOperationActionCodes.Pay,
beforeSnap,
afterSnap,
$"支付金额 {amountText}");
} }
/// <summary> /// <summary>
@ -346,6 +358,10 @@ public partial class OrderService : ApplicationService
var existingUrl = await OrderFileManager.GetSystemLabelUrlAsync(order.Id); var existingUrl = await OrderFileManager.GetSystemLabelUrlAsync(order.Id);
if (!string.IsNullOrWhiteSpace(existingUrl)) if (!string.IsNullOrWhiteSpace(existingUrl))
{ {
await OperationLogWriter.TryWriteSimpleAsync(
order,
OrderOperationActionCodes.Print,
"打印面单(使用已有文件)");
return new OrderPrintOutput return new OrderPrintOutput
{ {
PrintUrl = existingUrl!, PrintUrl = existingUrl!,
@ -365,6 +381,10 @@ public partial class OrderService : ApplicationService
{ {
// 兼容回落:仍无模板时给 HTML stub,避免彻底不可打 // 兼容回落:仍无模板时给 HTML stub,避免彻底不可打
var fallbackUrl = await CreateOrderPrintFileAsync(mapped); var fallbackUrl = await CreateOrderPrintFileAsync(mapped);
await OperationLogWriter.TryWriteSimpleAsync(
order,
OrderOperationActionCodes.Print,
"打印面单(回落 HTML)");
return new OrderPrintOutput return new OrderPrintOutput
{ {
PrintUrl = fallbackUrl, PrintUrl = fallbackUrl,
@ -373,6 +393,10 @@ public partial class OrderService : ApplicationService
}; };
} }
await OperationLogWriter.TryWriteSimpleAsync(
order,
OrderOperationActionCodes.Print,
"打印面单");
return new OrderPrintOutput return new OrderPrintOutput
{ {
PrintUrl = result.LabelUrl!, PrintUrl = result.LabelUrl!,
@ -420,6 +444,21 @@ public partial class OrderService : ApplicationService
PrintUrl = url, PrintUrl = url,
LabelGenerateStatus = LabelGenerateStatusCodes.Ready LabelGenerateStatus = LabelGenerateStatusCodes.Ready
}); });
try
{
var existingOrder = await OrderRepository.FirstOrDefaultAsync(x => x.Id == orderId);
if (existingOrder != null)
{
await OperationLogWriter.TryWriteSimpleAsync(
existingOrder,
OrderOperationActionCodes.Print,
"批量打印(使用已有文件)");
}
}
catch
{
// 日志失败不影响打印
}
} }
else else
{ {

View File

@ -8,6 +8,12 @@ public static class OrderOperationActionCodes
public const string RecalcPayable = "recalcPayable"; public const string RecalcPayable = "recalcPayable";
public const string Reallocate = "reallocate"; public const string Reallocate = "reallocate";
public const string BindSnapshotVersions = "bindSnapshotVersions"; public const string BindSnapshotVersions = "bindSnapshotVersions";
public const string UpdateAdditionalServices = "updateAdditionalServices";
public const string AddFee = "addFee";
public const string Pay = "pay";
public const string PreDeclare = "preDeclare";
public const string DownstreamForward = "downstreamForward";
public const string Print = "print";
public static string GetActionName(string action) => action switch public static string GetActionName(string action) => action switch
{ {
@ -17,6 +23,12 @@ public static class OrderOperationActionCodes
RecalcPayable => "重算应付", RecalcPayable => "重算应付",
Reallocate => "重新排货", Reallocate => "重新排货",
BindSnapshotVersions => "切换价格/规则版本", BindSnapshotVersions => "切换价格/规则版本",
UpdateAdditionalServices => "更新附加服务",
AddFee => "添加费用",
Pay => "支付",
PreDeclare => "重新预报",
DownstreamForward => "预报下游",
Print => "打印面单",
_ => action _ => action
}; };
} }