feat: 完成商品批量工具后端接口与Excel导入导出
All checks were successful
Build and Deploy TenantApi + SkuWorker / build-and-deploy (push) Successful in 1m49s

This commit is contained in:
2026-02-26 12:07:48 +08:00
parent 3f5ca9c3ee
commit dd90bdfe0f
2 changed files with 1530 additions and 0 deletions

View File

@@ -0,0 +1,362 @@
using Microsoft.AspNetCore.Http;
namespace TakeoutSaaS.TenantApi.Contracts.Product;
/// <summary>
/// 批量范围请求。
/// </summary>
public sealed class ProductBatchScopeRequest
{
/// <summary>
/// 范围类型all/category/selected/manual
/// </summary>
public string Type { get; set; } = "all";
/// <summary>
/// 单个分类 ID兼容字段
/// </summary>
public string? CategoryId { get; set; }
/// <summary>
/// 分类 ID 列表(按分类时)。
/// </summary>
public List<string> CategoryIds { get; set; } = [];
/// <summary>
/// 商品 ID 列表(手动选择时)。
/// </summary>
public List<string> ProductIds { get; set; } = [];
}
/// <summary>
/// 批量调价预览请求。
/// </summary>
public sealed class BatchPriceAdjustPreviewRequest
{
/// <summary>
/// 门店 ID。
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// 批量范围。
/// </summary>
public ProductBatchScopeRequest Scope { get; set; } = new();
/// <summary>
/// 调价方向up/down
/// </summary>
public string Direction { get; set; } = "up";
/// <summary>
/// 调价方式fixed/percent
/// </summary>
public string AmountType { get; set; } = "fixed";
/// <summary>
/// 调价数值。
/// </summary>
public decimal Amount { get; set; }
}
/// <summary>
/// 批量调价请求。
/// </summary>
public sealed class BatchPriceAdjustRequest
{
/// <summary>
/// 门店 ID。
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// 批量范围。
/// </summary>
public ProductBatchScopeRequest Scope { get; set; } = new();
/// <summary>
/// 调价方向up/down
/// </summary>
public string Direction { get; set; } = "up";
/// <summary>
/// 调价方式fixed/percent
/// </summary>
public string AmountType { get; set; } = "fixed";
/// <summary>
/// 调价数值。
/// </summary>
public decimal Amount { get; set; }
}
/// <summary>
/// 批量上下架请求。
/// </summary>
public sealed class BatchSaleSwitchRequest
{
/// <summary>
/// 门店 ID。
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// 批量范围。
/// </summary>
public ProductBatchScopeRequest Scope { get; set; } = new();
/// <summary>
/// 动作on/off
/// </summary>
public string Action { get; set; } = "off";
}
/// <summary>
/// 批量移动分类请求。
/// </summary>
public sealed class BatchMoveCategoryRequest
{
/// <summary>
/// 门店 ID。
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// 源分类 ID可选
/// </summary>
public string? SourceCategoryId { get; set; }
/// <summary>
/// 目标分类 ID。
/// </summary>
public string TargetCategoryId { get; set; } = string.Empty;
/// <summary>
/// 批量范围。
/// </summary>
public ProductBatchScopeRequest Scope { get; set; } = new();
}
/// <summary>
/// 批量同步门店请求。
/// </summary>
public sealed class BatchSyncStoreRequest
{
/// <summary>
/// 源门店 ID。
/// </summary>
public string SourceStoreId { get; set; } = string.Empty;
/// <summary>
/// 目标门店 ID 列表。
/// </summary>
public List<string> TargetStoreIds { get; set; } = [];
/// <summary>
/// 商品 ID 列表。
/// </summary>
public List<string> ProductIds { get; set; } = [];
/// <summary>
/// 是否同步价格。
/// </summary>
public bool SyncPrice { get; set; } = true;
/// <summary>
/// 是否同步库存。
/// </summary>
public bool SyncStock { get; set; } = true;
/// <summary>
/// 是否同步状态。
/// </summary>
public bool SyncStatus { get; set; }
}
/// <summary>
/// 批量导出请求。
/// </summary>
public sealed class BatchExportRequest
{
/// <summary>
/// 门店 ID。
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// 批量范围。
/// </summary>
public ProductBatchScopeRequest Scope { get; set; } = new();
}
/// <summary>
/// 批量导入请求(表单)。
/// </summary>
public sealed class BatchImportRequest
{
/// <summary>
/// 门店 ID。
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// 导入文件。
/// </summary>
public IFormFile? File { get; set; }
}
/// <summary>
/// 批量工具通用结果。
/// </summary>
public sealed class BatchToolResultResponse
{
/// <summary>
/// 总条数。
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 成功条数。
/// </summary>
public int SuccessCount { get; set; }
/// <summary>
/// 失败条数。
/// </summary>
public int FailedCount { get; set; }
/// <summary>
/// 跳过条数。
/// </summary>
public int SkippedCount { get; set; }
}
/// <summary>
/// 调价预览项。
/// </summary>
public sealed class BatchPricePreviewItemResponse
{
/// <summary>
/// 商品 ID。
/// </summary>
public string ProductId { get; set; } = string.Empty;
/// <summary>
/// 商品名称。
/// </summary>
public string ProductName { get; set; } = string.Empty;
/// <summary>
/// 原价。
/// </summary>
public decimal OriginalPrice { get; set; }
/// <summary>
/// 新价。
/// </summary>
public decimal NewPrice { get; set; }
/// <summary>
/// 变动值。
/// </summary>
public decimal DeltaPrice { get; set; }
}
/// <summary>
/// 调价预览结果。
/// </summary>
public sealed class BatchPricePreviewResponse
{
/// <summary>
/// 预览项。
/// </summary>
public List<BatchPricePreviewItemResponse> Items { get; set; } = [];
/// <summary>
/// 总影响商品数。
/// </summary>
public int TotalCount { get; set; }
}
/// <summary>
/// Excel 文件响应。
/// </summary>
public sealed class BatchExcelFileResponse
{
/// <summary>
/// 文件名。
/// </summary>
public string FileName { get; set; } = string.Empty;
/// <summary>
/// Base64 文件内容。
/// </summary>
public string FileContentBase64 { get; set; } = string.Empty;
/// <summary>
/// 导出总条数。
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 成功条数。
/// </summary>
public int SuccessCount { get; set; }
/// <summary>
/// 失败条数。
/// </summary>
public int FailedCount { get; set; }
}
/// <summary>
/// 导入错误项。
/// </summary>
public sealed class BatchImportErrorItemResponse
{
/// <summary>
/// 行号。
/// </summary>
public int RowNo { get; set; }
/// <summary>
/// 错误说明。
/// </summary>
public string Message { get; set; } = string.Empty;
}
/// <summary>
/// 批量导入结果。
/// </summary>
public sealed class BatchImportResultResponse
{
/// <summary>
/// 总条数。
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 成功条数。
/// </summary>
public int SuccessCount { get; set; }
/// <summary>
/// 失败条数。
/// </summary>
public int FailedCount { get; set; }
/// <summary>
/// 跳过条数。
/// </summary>
public int SkippedCount { get; set; }
/// <summary>
/// 文件名。
/// </summary>
public string FileName { get; set; } = string.Empty;
/// <summary>
/// 错误明细。
/// </summary>
public List<BatchImportErrorItemResponse> Errors { get; set; } = [];
}

File diff suppressed because it is too large Load Diff