feat: add image and thumbnail upload support in DiscountProduct forms and services
Build and Deploy / build (push) Failing after 17s
Build and Deploy / build (push) Failing after 17s
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -1,121 +1,155 @@
|
|||||||
@using BackOffice.Services.DiscountProduct
|
@using BackOffice.Services.DiscountProduct
|
||||||
@using BackOffice.Services.DiscountCategory
|
@using BackOffice.Services.DiscountCategory
|
||||||
|
@using Microsoft.AspNetCore.Components.Forms
|
||||||
|
@using Tizzani.MudBlazor.HtmlEditor
|
||||||
|
@using BackOffice.Common.BaseComponents
|
||||||
|
@using BackOffice.Pages.AutoComplete
|
||||||
@inject ISnackbar Snackbar
|
@inject ISnackbar Snackbar
|
||||||
|
|
||||||
<MudDialog>
|
<MudDialog>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<MudForm @ref="_form" @bind-IsValid="@_isValid">
|
<MudForm @ref="_form" @bind-IsValid="@_isValid">
|
||||||
<MudGrid>
|
<MudStack Spacing="3">
|
||||||
<MudItem xs="12">
|
<MudStack Justify="Justify.Center" AlignItems="AlignItems.Center">
|
||||||
<MudTextField @bind-Value="Model.Title"
|
@if (!string.IsNullOrWhiteSpace(_mainImagePreview))
|
||||||
Label="عنوان محصول *"
|
{
|
||||||
Required="true"
|
<Image Src="@(_mainImagePreview)" Width="220" Height="140" ObjectPosition="ObjectPosition.Center" ObjectFit="ObjectFit.Cover" />
|
||||||
RequiredError="عنوان الزامی است"
|
}
|
||||||
Variant="Variant.Outlined" />
|
else if (!string.IsNullOrEmpty(Model.ImagePath))
|
||||||
</MudItem>
|
{
|
||||||
|
<Image Src="@Model.ImagePath" Width="220" Height="140" ObjectPosition="ObjectPosition.Center" ObjectFit="ObjectFit.Cover" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudPaper Class="d-flex align-center justify-center" Style="width:220px;height:140px;">
|
||||||
|
<MudText Typo="Typo.caption">تصویری انتخاب نشده است</MudText>
|
||||||
|
</MudPaper>
|
||||||
|
}
|
||||||
|
|
||||||
<MudItem xs="12">
|
<MudFileUpload T="IBrowserFile" Accept="image/*" FilesChanged="OnMainImageSelected">
|
||||||
<MudTextField @bind-Value="Model.ShortInformation"
|
<ActivatorContent>
|
||||||
Label="توضیح کوتاه"
|
<MudButton HtmlTag="label"
|
||||||
Lines="2"
|
Variant="Variant.Filled"
|
||||||
Variant="Variant.Outlined" />
|
Color="Color.Primary"
|
||||||
</MudItem>
|
ButtonType="ButtonType.Button"
|
||||||
|
StartIcon="@Icons.Material.Filled.Image"
|
||||||
|
Style="cursor:pointer;">
|
||||||
|
انتخاب تصویر اصلی
|
||||||
|
</MudButton>
|
||||||
|
</ActivatorContent>
|
||||||
|
<SelectedTemplate>
|
||||||
|
@if (context != null)
|
||||||
|
{
|
||||||
|
<MudText Class="mt-2" Typo="Typo.subtitle2">
|
||||||
|
<MudTooltip Text="@context.Name" Inline="true">
|
||||||
|
@context.Name
|
||||||
|
</MudTooltip>
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudText Class="mt-2" Typo="Typo.subtitle2">فایلی انتخاب نشده</MudText>
|
||||||
|
}
|
||||||
|
</SelectedTemplate>
|
||||||
|
</MudFileUpload>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
<MudItem xs="12">
|
<MudStack Row="true" AlignItems="AlignItems.Center">
|
||||||
<MudTextField @bind-Value="Model.FullInformation"
|
<MudItem xs="6">
|
||||||
Label="توضیحات کامل"
|
<MudTextField T="string" @bind-Value="Model.Title"
|
||||||
Lines="4"
|
Disabled="_loading"
|
||||||
Variant="Variant.Outlined" />
|
Label="عنوان محصول *"
|
||||||
</MudItem>
|
Required="true"
|
||||||
|
RequiredError="عنوان الزامی است"
|
||||||
<MudItem xs="12" sm="6">
|
Variant="Variant.Outlined"
|
||||||
<MudNumericField @bind-Value="Model.Price"
|
Margin="Margin.Dense" />
|
||||||
Label="قیمت (ریال) *"
|
|
||||||
Required="true"
|
|
||||||
Min="0"
|
|
||||||
Format="N0"
|
|
||||||
Variant="Variant.Outlined" />
|
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
<MudItem xs="12" sm="6">
|
|
||||||
<MudNumericField @bind-Value="Model.MaxDiscountPercent"
|
|
||||||
Label="حداکثر درصد تخفیف *"
|
|
||||||
Required="true"
|
|
||||||
Min="0"
|
|
||||||
Max="100"
|
|
||||||
Variant="Variant.Outlined" />
|
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
<MudItem xs="12" sm="6">
|
|
||||||
<MudNumericField @bind-Value="Model.SortOrder"
|
|
||||||
Label="ترتیب نمایش"
|
|
||||||
Min="0"
|
|
||||||
Variant="Variant.Outlined" />
|
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
<MudItem xs="12">
|
|
||||||
<MudSelect @bind-SelectedValues="_selectedCategoryIds"
|
|
||||||
Label="دستهبندیها"
|
|
||||||
Variant="Variant.Outlined"
|
|
||||||
MultiSelection="true"
|
|
||||||
T="long">
|
|
||||||
@foreach (var category in _categories)
|
|
||||||
{
|
|
||||||
<MudSelectItem Value="@category.Id">@GetCategoryPath(category)</MudSelectItem>
|
|
||||||
}
|
|
||||||
</MudSelect>
|
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
<MudItem xs="12" sm="6">
|
|
||||||
<MudTextField @bind-Value="Model.ImagePath"
|
|
||||||
Label="مسیر تصویر اصلی"
|
|
||||||
Variant="Variant.Outlined"
|
|
||||||
Adornment="Adornment.End"
|
|
||||||
AdornmentIcon="@Icons.Material.Filled.Image" />
|
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
<MudItem xs="12" sm="6">
|
|
||||||
<MudTextField @bind-Value="Model.ThumbnailPath"
|
|
||||||
Label="مسیر تصویر بندانگشتی"
|
|
||||||
Variant="Variant.Outlined"
|
|
||||||
Adornment="Adornment.End"
|
|
||||||
AdornmentIcon="@Icons.Material.Filled.Image" />
|
|
||||||
</MudItem>
|
|
||||||
|
|
||||||
@if (!string.IsNullOrEmpty(Model.ThumbnailPath))
|
|
||||||
{
|
|
||||||
<MudItem xs="12">
|
|
||||||
<MudImage Src="@Model.ThumbnailPath"
|
|
||||||
Alt="پیشنمایش"
|
|
||||||
Height="150"
|
|
||||||
ObjectFit="ObjectFit.Contain"
|
|
||||||
Class="rounded" />
|
|
||||||
</MudItem>
|
</MudItem>
|
||||||
}
|
<MudItem xs="6">
|
||||||
|
<MudNumericField T="long" HideSpinButtons="true"
|
||||||
|
@bind-Value="Model.Price"
|
||||||
|
Format="N0"
|
||||||
|
Immediate="true"
|
||||||
|
Disabled="_loading"
|
||||||
|
Label="قیمت (ریال) *"
|
||||||
|
Required="true"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Margin="Margin.Dense" />
|
||||||
|
</MudItem>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
<MudItem xs="12">
|
<MudStack Row="true" AlignItems="AlignItems.Center">
|
||||||
<MudSwitch T="bool" @bind-Value="Model.IsActive"
|
<MudItem xs="6">
|
||||||
Label="محصول فعال"
|
<MudNumericField T="int" HideSpinButtons="true"
|
||||||
Color="Color.Success" />
|
@bind-Value="Model.MaxDiscountPercent"
|
||||||
</MudItem>
|
Disabled="_loading"
|
||||||
</MudGrid>
|
Label="حداکثر درصد تخفیف *"
|
||||||
|
Required="true"
|
||||||
|
Min="0"
|
||||||
|
Max="100"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Margin="Margin.Dense" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="6">
|
||||||
|
<MudNumericField T="int" HideSpinButtons="true"
|
||||||
|
@bind-Value="Model.SortOrder"
|
||||||
|
Disabled="_loading"
|
||||||
|
Label="ترتیب نمایش"
|
||||||
|
Min="0"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Margin="Margin.Dense" />
|
||||||
|
</MudItem>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
<MudTextField T="string" @bind-Value="Model.ShortInformation"
|
||||||
|
Disabled="_loading"
|
||||||
|
Label="توضیح کوتاه"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Margin="Margin.Dense" />
|
||||||
|
|
||||||
|
<MudHtmlEditor @bind-Html="Model.FullInformation">
|
||||||
|
<MudHtmlToolbarOptions InsertImage="false" />
|
||||||
|
</MudHtmlEditor>
|
||||||
|
|
||||||
|
<MudStack Spacing="1">
|
||||||
|
<MudText Typo="Typo.subtitle2">دستهبندیها</MudText>
|
||||||
|
<CategoryMultiSelectCombo @bind-SelectedIds="_selectedCategoryIds"
|
||||||
|
Label="انتخاب دستهبندیها"
|
||||||
|
Disabled="_loading" />
|
||||||
|
@if (_selectedCategoryIds?.Count > 0)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.caption">
|
||||||
|
تعداد دستهبندیهای انتخابشده: @_selectedCategoryIds.Count
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
<MudStack Spacing="1">
|
||||||
|
<MudText Typo="Typo.subtitle2">تصویر بندانگشتی</MudText>
|
||||||
|
<MudFileUpload T="IBrowserFile" Accept="image/*" FilesChanged="OnThumbnailSelected">
|
||||||
|
<ActivatorContent>
|
||||||
|
<MudButton HtmlTag="label"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Color="Color.Secondary"
|
||||||
|
ButtonType="ButtonType.Button"
|
||||||
|
StartIcon="@Icons.Material.Filled.Image"
|
||||||
|
Style="cursor:pointer;">
|
||||||
|
انتخاب تصویر بندانگشتی (اختیاری)
|
||||||
|
</MudButton>
|
||||||
|
</ActivatorContent>
|
||||||
|
</MudFileUpload>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
<MudSwitch T="bool" @bind-Value="Model.IsActive"
|
||||||
|
Label="محصول فعال"
|
||||||
|
Color="Color.Success" />
|
||||||
|
</MudStack>
|
||||||
</MudForm>
|
</MudForm>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<MudButton OnClick="Cancel" Variant="Variant.Text">انصراف</MudButton>
|
<MudButton OnClick="Cancel" Disabled="_loading">انصراف</MudButton>
|
||||||
<MudButton OnClick="Submit"
|
<MudButton OnClick="Submit"
|
||||||
Variant="Variant.Filled"
|
|
||||||
Color="Color.Primary"
|
Color="Color.Primary"
|
||||||
Disabled="@(!_isValid || _loading)">
|
Disabled="@(!_isValid || _loading)">ثبت</MudButton>
|
||||||
@if (_loading)
|
|
||||||
{
|
|
||||||
<MudProgressCircular Size="Size.Small" Indeterminate="true" />
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<text>@(IsEditMode ? "ذخیره تغییرات" : "ایجاد محصول")</text>
|
|
||||||
}
|
|
||||||
</MudButton>
|
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</MudDialog>
|
</MudDialog>
|
||||||
|
|
||||||
@@ -128,56 +162,35 @@
|
|||||||
private MudForm? _form;
|
private MudForm? _form;
|
||||||
private bool _isValid;
|
private bool _isValid;
|
||||||
private bool _loading;
|
private bool _loading;
|
||||||
private List<DiscountCategoryDto> _categories = new();
|
private IBrowserFile? _mainImageFile;
|
||||||
private IEnumerable<long> _selectedCategoryIds = new List<long>();
|
private IBrowserFile? _thumbnailImageFile;
|
||||||
|
private readonly long _maxAllowedSize = (1024 * 1024) * 5;
|
||||||
|
private string? _mainImagePreview;
|
||||||
|
private List<long> _selectedCategoryIds = new();
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await LoadCategories();
|
|
||||||
|
|
||||||
if (Model.CategoryIds?.Any() == true)
|
if (Model.CategoryIds?.Any() == true)
|
||||||
{
|
{
|
||||||
_selectedCategoryIds = Model.CategoryIds;
|
_selectedCategoryIds = Model.CategoryIds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadCategories()
|
private async Task OnMainImageSelected(IBrowserFile? file)
|
||||||
{
|
{
|
||||||
try
|
_mainImageFile = file;
|
||||||
|
if (file != null)
|
||||||
{
|
{
|
||||||
var tree = await CategoryService.GetCategoriesAsync(isActive: true);
|
var buffer = new byte[file.Size];
|
||||||
_categories = FlattenCategories(tree);
|
await file.OpenReadStream(_maxAllowedSize).ReadAsync(buffer);
|
||||||
}
|
_mainImagePreview = $"data:{file.ContentType};base64," + Convert.ToBase64String(buffer);
|
||||||
catch (Exception ex)
|
StateHasChanged();
|
||||||
{
|
|
||||||
Snackbar.Add($"خطا در بارگذاری دستهبندیها: {ex.Message}", Severity.Error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<DiscountCategoryDto> FlattenCategories(List<DiscountCategoryDto> categories, string prefix = "")
|
private async Task OnThumbnailSelected(IBrowserFile? file)
|
||||||
{
|
{
|
||||||
var result = new List<DiscountCategoryDto>();
|
_thumbnailImageFile = file;
|
||||||
foreach (var category in categories)
|
|
||||||
{
|
|
||||||
var catCopy = new DiscountCategoryDto
|
|
||||||
{
|
|
||||||
Id = category.Id,
|
|
||||||
Title = prefix + category.Title,
|
|
||||||
ParentCategoryId = category.ParentCategoryId
|
|
||||||
};
|
|
||||||
result.Add(catCopy);
|
|
||||||
|
|
||||||
if (category.Children.Any())
|
|
||||||
{
|
|
||||||
result.AddRange(FlattenCategories(category.Children.ToList(), prefix + " "));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetCategoryPath(DiscountCategoryDto category)
|
|
||||||
{
|
|
||||||
return category.Title;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Submit()
|
private async Task Submit()
|
||||||
@@ -193,6 +206,26 @@
|
|||||||
// Update CategoryIds from selected values
|
// Update CategoryIds from selected values
|
||||||
Model.CategoryIds = _selectedCategoryIds.ToList();
|
Model.CategoryIds = _selectedCategoryIds.ToList();
|
||||||
|
|
||||||
|
// Handle main image upload
|
||||||
|
if (_mainImageFile != null)
|
||||||
|
{
|
||||||
|
var buffer = new byte[_mainImageFile.Size];
|
||||||
|
await _mainImageFile.OpenReadStream(_maxAllowedSize).ReadAsync(buffer);
|
||||||
|
Model.ImageFile = buffer;
|
||||||
|
Model.ImageMime = _mainImageFile.ContentType;
|
||||||
|
Model.ImageFileName = Path.GetFileNameWithoutExtension(_mainImageFile.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle thumbnail upload
|
||||||
|
if (_thumbnailImageFile != null)
|
||||||
|
{
|
||||||
|
var buffer = new byte[_thumbnailImageFile.Size];
|
||||||
|
await _thumbnailImageFile.OpenReadStream(_maxAllowedSize).ReadAsync(buffer);
|
||||||
|
Model.ThumbnailFile = buffer;
|
||||||
|
Model.ThumbnailMime = _thumbnailImageFile.ContentType;
|
||||||
|
Model.ThumbnailFileName = Path.GetFileNameWithoutExtension(_thumbnailImageFile.Name);
|
||||||
|
}
|
||||||
|
|
||||||
MudDialog.Close(DialogResult.Ok(Model));
|
MudDialog.Close(DialogResult.Ok(Model));
|
||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
@@ -211,9 +244,16 @@
|
|||||||
public string? ThumbnailPath { get; set; }
|
public string? ThumbnailPath { get; set; }
|
||||||
public long Price { get; set; }
|
public long Price { get; set; }
|
||||||
public int MaxDiscountPercent { get; set; }
|
public int MaxDiscountPercent { get; set; }
|
||||||
public int InitialCount { get; set; }
|
|
||||||
public int SortOrder { get; set; }
|
public int SortOrder { get; set; }
|
||||||
public bool IsActive { get; set; } = true;
|
public bool IsActive { get; set; } = true;
|
||||||
public List<long>? CategoryIds { get; set; }
|
public List<long>? CategoryIds { get; set; }
|
||||||
|
|
||||||
|
// Image upload properties
|
||||||
|
public byte[]? ImageFile { get; set; }
|
||||||
|
public string? ImageMime { get; set; }
|
||||||
|
public string? ImageFileName { get; set; }
|
||||||
|
public byte[]? ThumbnailFile { get; set; }
|
||||||
|
public string? ThumbnailMime { get; set; }
|
||||||
|
public string? ThumbnailFileName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,10 +232,16 @@
|
|||||||
ThumbnailPath = formData.ThumbnailPath,
|
ThumbnailPath = formData.ThumbnailPath,
|
||||||
Price = formData.Price,
|
Price = formData.Price,
|
||||||
MaxDiscountPercent = formData.MaxDiscountPercent,
|
MaxDiscountPercent = formData.MaxDiscountPercent,
|
||||||
InitialCount = formData.InitialCount,
|
InitialCount = 0, // Always 0 - must use inventory management
|
||||||
SortOrder = formData.SortOrder,
|
SortOrder = formData.SortOrder,
|
||||||
IsActive = formData.IsActive,
|
IsActive = formData.IsActive,
|
||||||
CategoryIds = formData.CategoryIds
|
CategoryIds = formData.CategoryIds,
|
||||||
|
ImageFile = formData.ImageFile,
|
||||||
|
ImageMime = formData.ImageMime,
|
||||||
|
ImageFileName = formData.ImageFileName,
|
||||||
|
ThumbnailFile = formData.ThumbnailFile,
|
||||||
|
ThumbnailMime = formData.ThumbnailMime,
|
||||||
|
ThumbnailFileName = formData.ThumbnailFileName
|
||||||
};
|
};
|
||||||
|
|
||||||
await DiscountProductService.CreateAsync(dto);
|
await DiscountProductService.CreateAsync(dto);
|
||||||
@@ -269,7 +275,6 @@
|
|||||||
ThumbnailPath = product.ThumbnailPath,
|
ThumbnailPath = product.ThumbnailPath,
|
||||||
Price = product.Price,
|
Price = product.Price,
|
||||||
MaxDiscountPercent = product.MaxDiscountPercent,
|
MaxDiscountPercent = product.MaxDiscountPercent,
|
||||||
InitialCount = product.RemainingCount,
|
|
||||||
SortOrder = product.SortOrder,
|
SortOrder = product.SortOrder,
|
||||||
IsActive = product.IsActive,
|
IsActive = product.IsActive,
|
||||||
CategoryIds = product.Categories?.Select(c => c.Id).ToList() ?? new()
|
CategoryIds = product.Categories?.Select(c => c.Id).ToList() ?? new()
|
||||||
@@ -298,7 +303,13 @@
|
|||||||
MaxDiscountPercent = formData.MaxDiscountPercent,
|
MaxDiscountPercent = formData.MaxDiscountPercent,
|
||||||
SortOrder = formData.SortOrder,
|
SortOrder = formData.SortOrder,
|
||||||
IsActive = formData.IsActive,
|
IsActive = formData.IsActive,
|
||||||
CategoryIds = formData.CategoryIds
|
CategoryIds = formData.CategoryIds,
|
||||||
|
ImageFile = formData.ImageFile,
|
||||||
|
ImageMime = formData.ImageMime,
|
||||||
|
ImageFileName = formData.ImageFileName,
|
||||||
|
ThumbnailFile = formData.ThumbnailFile,
|
||||||
|
ThumbnailMime = formData.ThumbnailMime,
|
||||||
|
ThumbnailFileName = formData.ThumbnailFileName
|
||||||
};
|
};
|
||||||
|
|
||||||
await DiscountProductService.UpdateAsync(productId, dto);
|
await DiscountProductService.UpdateAsync(productId, dto);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using BackOffice.BFF.DiscountProduct.Protobuf.Protos.DiscountProduct;
|
using BackOffice.BFF.DiscountProduct.Protobuf.Protos.DiscountProduct;
|
||||||
|
using Google.Protobuf;
|
||||||
using Google.Protobuf.WellKnownTypes;
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
|
||||||
namespace BackOffice.Services.DiscountProduct;
|
namespace BackOffice.Services.DiscountProduct;
|
||||||
@@ -115,6 +116,28 @@ public class DiscountProductService : IDiscountProductService
|
|||||||
request.CategoryIds.AddRange(dto.CategoryIds);
|
request.CategoryIds.AddRange(dto.CategoryIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add image file if provided
|
||||||
|
if (dto.ImageFile != null && !string.IsNullOrEmpty(dto.ImageMime) && !string.IsNullOrEmpty(dto.ImageFileName))
|
||||||
|
{
|
||||||
|
request.ImageFile = new ImageFileModel
|
||||||
|
{
|
||||||
|
File = ByteString.CopyFrom(dto.ImageFile),
|
||||||
|
Mime = dto.ImageMime,
|
||||||
|
FileName = dto.ImageFileName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add thumbnail file if provided
|
||||||
|
if (dto.ThumbnailFile != null && !string.IsNullOrEmpty(dto.ThumbnailMime) && !string.IsNullOrEmpty(dto.ThumbnailFileName))
|
||||||
|
{
|
||||||
|
request.ThumbnailFile = new ImageFileModel
|
||||||
|
{
|
||||||
|
File = ByteString.CopyFrom(dto.ThumbnailFile),
|
||||||
|
Mime = dto.ThumbnailMime,
|
||||||
|
FileName = dto.ThumbnailFileName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var response = await _client.CreateDiscountProductAsync(request);
|
var response = await _client.CreateDiscountProductAsync(request);
|
||||||
return response.ProductId;
|
return response.ProductId;
|
||||||
}
|
}
|
||||||
@@ -140,6 +163,50 @@ public class DiscountProductService : IDiscountProductService
|
|||||||
request.CategoryIds.AddRange(dto.CategoryIds);
|
request.CategoryIds.AddRange(dto.CategoryIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle image file upload
|
||||||
|
if (dto.ImageFile != null)
|
||||||
|
{
|
||||||
|
request.ImageFile = new ImageFileModel
|
||||||
|
{
|
||||||
|
File = ByteString.CopyFrom(dto.ImageFile),
|
||||||
|
Mime = dto.ImageMime ?? string.Empty,
|
||||||
|
FileName = dto.ImageFileName ?? string.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle thumbnail file upload
|
||||||
|
if (dto.ThumbnailFile != null)
|
||||||
|
{
|
||||||
|
request.ThumbnailFile = new ImageFileModel
|
||||||
|
{
|
||||||
|
File = ByteString.CopyFrom(dto.ThumbnailFile),
|
||||||
|
Mime = dto.ThumbnailMime ?? string.Empty,
|
||||||
|
FileName = dto.ThumbnailFileName ?? string.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add image file if provided
|
||||||
|
if (dto.ImageFile != null && !string.IsNullOrEmpty(dto.ImageMime) && !string.IsNullOrEmpty(dto.ImageFileName))
|
||||||
|
{
|
||||||
|
request.ImageFile = new ImageFileModel
|
||||||
|
{
|
||||||
|
File = ByteString.CopyFrom(dto.ImageFile),
|
||||||
|
Mime = dto.ImageMime,
|
||||||
|
FileName = dto.ImageFileName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add thumbnail file if provided
|
||||||
|
if (dto.ThumbnailFile != null && !string.IsNullOrEmpty(dto.ThumbnailMime) && !string.IsNullOrEmpty(dto.ThumbnailFileName))
|
||||||
|
{
|
||||||
|
request.ThumbnailFile = new ImageFileModel
|
||||||
|
{
|
||||||
|
File = ByteString.CopyFrom(dto.ThumbnailFile),
|
||||||
|
Mime = dto.ThumbnailMime,
|
||||||
|
FileName = dto.ThumbnailFileName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
await _client.UpdateDiscountProductAsync(request);
|
await _client.UpdateDiscountProductAsync(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,14 @@ public class CreateDiscountProductDto
|
|||||||
public int SortOrder { get; set; }
|
public int SortOrder { get; set; }
|
||||||
public bool IsActive { get; set; } = true;
|
public bool IsActive { get; set; } = true;
|
||||||
public List<long>? CategoryIds { get; set; }
|
public List<long>? CategoryIds { get; set; }
|
||||||
|
|
||||||
|
// Image upload support
|
||||||
|
public byte[]? ImageFile { get; set; }
|
||||||
|
public string? ImageMime { get; set; }
|
||||||
|
public string? ImageFileName { get; set; }
|
||||||
|
public byte[]? ThumbnailFile { get; set; }
|
||||||
|
public string? ThumbnailMime { get; set; }
|
||||||
|
public string? ThumbnailFileName { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UpdateDiscountProductDto
|
public class UpdateDiscountProductDto
|
||||||
@@ -88,4 +96,13 @@ public class UpdateDiscountProductDto
|
|||||||
public int SortOrder { get; set; }
|
public int SortOrder { get; set; }
|
||||||
public bool IsActive { get; set; }
|
public bool IsActive { get; set; }
|
||||||
public List<long>? CategoryIds { get; set; }
|
public List<long>? CategoryIds { get; set; }
|
||||||
|
|
||||||
|
// Image upload support
|
||||||
|
public byte[]? ImageFile { get; set; }
|
||||||
|
public string? ImageMime { get; set; }
|
||||||
|
public string? ImageFileName { get; set; }
|
||||||
|
public byte[]? ThumbnailFile { get; set; }
|
||||||
|
public string? ThumbnailMime { get; set; }
|
||||||
|
public string? ThumbnailFileName { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user