9.5 KiB
🏪 یکسانسازی فروشگاه عادی و تخفیفی — BackOffice
تاریخ: ۱۴۰۴/۱۱/۲۴ (February 13, 2026)
وضعیت: ✅ کامل
Build: 0 Error ✅
۱. هدف
فروشگاه عادی و فروشگاه تخفیفی در پنل مدیریت باید از نظر ظاهری و UX کاملاً یکسان باشند. قبل از این تغییرات، صفحات فروشگاه تخفیفی ظاهر و ساختار متفاوتی داشتند. هدف این فاز:
- NavMenu — جداسازی دو فروشگاه در گروهبندیهای مجزا
- دستهبندیها — ظاهر یکسان با فروشگاه عادی (ستونها، درخت، اکشنها)
- محصولات — ظاهر یکسان (گالری، فیلترها، ستونهای گرید، اکسپورت)
- سفارشات — حذف گزارشهای کوچک اضافی، فقط لیست خالص + رفع باگ لیست خالی
۲. خلاصه تغییرات
۲.۱ بازسازی NavMenu
| قبل | بعد |
|---|---|
| یک بخش «فروشگاه» با زیرگروههای محصولات + دستهبندی + سفارش + ویرایش دستهجمعی | دو گروه مجزا: «فروشگاه عادی» و «فروشگاه تخفیفی» |
| ویرایش دستهجمعی در منو | حذف شد از منو |
| انبارداری داخل فروشگاه | انبارداری گروه مجزا |
| پکیجها داخل فروشگاه | پکیجها آیتم مستقل |
ساختار جدید:
فروشگاه (بخش)
├── پکیجها (مستقل)
├── فروشگاه عادی (NavGroup)
│ ├── محصولات → /ProductsPage/
│ ├── دستهبندیها → /CategoryPage/
│ └── سفارشات و گزارش → /OrdersPage/
├── انبارداری (NavGroup مستقل)
│ ├── موجودی انبار
│ ├── محصولات کمموجود
│ ├── مدیریت انبارها
│ └── تاریخچه تغییرات
└── فروشگاه تخفیفی (NavGroup)
├── محصولات → /discount-products
├── دستهبندیها → /discount-categories
└── سفارشات و گزارش → /discount-orders
فایل: Shared/NavMenu.razor
۲.۲ رفع لیست خالی سفارشات + حذف گزارشهای کوچک
مشکل ۱ — لیست خالی:
PaymentDate.ToDateTime()بدون null check باعث exception در WASM میشد- Exception در Blazor WASM silent است و grid خالی نشان میدهد
- رفع: اضافه کردن
@if (context.Item.PaymentDate != null)با fallback"-"
مشکل ۲ — گزارشهای اضافی:
- کارتهای آماری (تعداد سفارشات + مجموع مبلغ) و نمودار Bar وضعیت ارسال بالای گرید بودند
- این آمار اضافی بود چون تب جداگانه «گزارش فروش» وجود دارد
- رفع: حذف کامل
MudGrid(کارتها)،MudChart(نمودار)، فیلدهای_stats/_statusChartLabels/_statusChartSeries، متدUpdateStats()، کلاسOrderStatsViewModel - عنوان تولبار از «سفارشهای کاربر» به «لیست سفارشات» تغییر کرد
فایلها:
Pages/UserOrder/UserOrderMainPage.razorPages/UserOrder/UserOrderMainPage.razor.cs
۲.۳ بازنویسی صفحه محصولات تخفیفی
قبل: markup سفارشی بدون BasePageComponent، ستونهای ساده، بدون image preview
بعد: کاملاً مطابق با ProductsMainPage فروشگاه عادی
| ویژگی | قبل | بعد |
|---|---|---|
| Wrapper | markup دستی | BasePageComponent |
| فیلترها | جستجو + دستهبندی | جستجو + دستهبندی + وضعیت + موجودی |
| ستون عنوان | متن ساده | تصویر inline (MudAvatar) + متن truncate + tooltip |
| ستون موجودی | عدد ساده | چیپ رنگی (قرمز/نارنجی/سبز) |
| ستون وضعیت | متن | چیپ Error/Success |
| خروجی Excel | ✅ (داشت) | ✅ (حفظ شد) |
| گالری تصاویر | ✅ (داشت) | ✅ (حفظ شد) |
| Server-side paging | ✅ | ✅ |
فایلها:
Pages/DiscountShop/DiscountProductsMainPage.razor— بازنویسی کاملPages/DiscountShop/DiscountProductsMainPage.razor.cs— بازنویسی کامل (code-behind)
۲.۴ بازنویسی صفحه دستهبندیهای تخفیفی
قبل: markup دستی بدون BasePageComponent، ستونهای متفاوت
بعد: کاملاً مطابق با CategoryMainPage فروشگاه عادی
| ویژگی | قبل | بعد |
|---|---|---|
| Wrapper | markup دستی | BasePageComponent |
| لایوت | درخت + گرید | درخت (3 col) + گرید (9 col) — بدون تغییر |
| ستونها | شناسه، عنوان، توضیحات، وضعیت | شناسه، نام لاتین، عنوان، دستهبندی والد، تعداد محصولات، ترتیب، فعال؟ |
| ستون والد | نداشت | resolve نام والد از لیست |
| ستون محصولات | نداشت | چیپ Info |
| ستون ترتیب | نداشت | PropertyColumn |
| فیلتر | داخل page | داخل BasePageComponent |
| حذف با فرزند | disabled | disabled (حفظ شد) |
فایلها:
Pages/DiscountShop/DiscountCategoriesMainPage.razor— بازنویسی کاملPages/DiscountShop/DiscountCategoriesMainPage.razor.cs— ایجاد (code-behind جدید)
۳. فایلهای تغییر یافته
| فایل | نوع تغییر | توضیح |
|---|---|---|
Shared/NavMenu.razor |
✏️ ویرایش | بازسازی ساختار فروشگاه |
Pages/UserOrder/UserOrderMainPage.razor |
✏️ ویرایش | حذف آمار، رفع PaymentDate |
Pages/UserOrder/UserOrderMainPage.razor.cs |
✏️ ویرایش | حذف فیلدها/متدهای آمار |
Pages/DiscountShop/DiscountProductsMainPage.razor |
🔄 بازنویسی | BasePageComponent + ستونهای جدید |
Pages/DiscountShop/DiscountProductsMainPage.razor.cs |
🔄 بازنویسی | code-behind کامل |
Pages/DiscountShop/DiscountCategoriesMainPage.razor |
🔄 بازنویسی | BasePageComponent + ستونهای جدید |
Pages/DiscountShop/DiscountCategoriesMainPage.razor.cs |
🆕 ایجاد | code-behind جدید (از @code درونخطی) |
۴. الگوی پیادهسازی — BasePageComponent
تمام صفحات لیست در BackOffice از BasePageComponent استفاده میکنند:
<BasePageComponent @ref="_basePage" OnClearFilterClick="OnFilterCleared" OnSubmitClick="OnFilterSubmit">
<Filters>
<!-- فیلدهای فیلتر در MudItem -->
</Filters>
<Content>
<!-- MudDataGrid اصلی -->
</Content>
</BasePageComponent>
در code-behind:
private BasePageComponent _basePage = default!;
private async Task OnFilterSubmit()
{
_basePage.IsFiltered = true;
// اعمال فیلتر
}
private async Task OnFilterCleared()
{
_basePage.IsFiltered = false;
// ریست فیلترها
}
۵. الگوی Code-Behind
به دلیل محدودیت Razor source generator در پروژه، همه فایلهایی که سرویس inject دارند باید code-behind داشته باشند:
Page.razor → فقط markup (بدون @code)
Page.razor.cs → partial class با [Inject] و منطق
نکته مهم: سرویسهای global از _Imports.razor نباید دوباره با [Inject] تعریف شوند:
- ❌
[Inject] public IDialogService DialogService { get; set; }— از قبل global - ❌
[Inject] public ISnackbar Snackbar { get; set; }— از قبل global - ❌
[Inject] public IJSRuntime jsRuntime { get; set; }— از قبل global (حرف کوچک!) - ✅
[Inject] public IDiscountProductService DiscountProductService { get; set; }— باید inject شود
۶. مقایسه نهایی فروشگاه عادی و تخفیفی
| جنبه | فروشگاه عادی | فروشگاه تخفیفی | وضعیت |
|---|---|---|---|
| ارتباط با بکند | gRPC/Protobuf | HTTP REST (IDiscountXxxService) | تفاوت ذاتی |
| BasePageComponent | ✅ | ✅ | 🟢 یکسان |
| فیلترهای محصول | جستجو+دستهبندی+وضعیت | جستجو+دستهبندی+وضعیت+موجودی | 🟢 یکسان+ |
| ستونهای محصول | تصویر+عنوان، قیمت، موجودی (چیپ)، وضعیت (چیپ) | تصویر+عنوان، قیمت، تخفیف، موجودی (چیپ)، وضعیت (چیپ) | 🟢 یکسان+ |
| گالری تصاویر | ✅ GalleryDialog | ✅ ProductImageGallery | 🟢 هر دو دارند |
| خروجی Excel | ✅ | ✅ | 🟢 یکسان |
| درخت دستهبندی | ✅ | ✅ | 🟢 یکسان |
| ستونهای دستهبندی | شناسه+نام+عنوان+والد+محصولات+ترتیب+فعال | شناسه+نام+عنوان+والد+محصولات+ترتیب+فعال | 🟢 یکسان |
| سفارشات Hub | MudTabs (سفارشات + گزارش فروش) | MudTabs (سفارشات + گزارش فروش) | 🟢 یکسان |