Refactor code structure for improved readability and maintainability

This commit is contained in:
masoodafar-web
2026-02-16 00:59:16 +03:30
parent 956a9ff6d6
commit ad31c8be97
10 changed files with 3388 additions and 3 deletions
+359
View File
@@ -0,0 +1,359 @@
# 🏗️ BackOffice — مرجع معماری و الگوها
> **تاریخ:** ۱۴۰۴/۱۱/۲۴ (February 13, 2026)
> **پروژه:** BackOffice Admin Panel (Blazor WebAssembly)
---
## ۱. معماری کلی
```
┌─────────────────────────────────────────────────┐
│ BackOffice │
│ (Blazor WebAssembly) │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ MudBlazor│ │ Mapster │ │ DateTimeCvt │ │
│ │ v8 │ │ (mapping)│ │ (تاریخ شمسی) │ │
│ └──────────┘ └──────────┘ └──────────────┘ │
│ │ │ │ │
│ ┌─────────────────────────────────────────┐ │
│ │ Pages / Components / Shared │ │
│ │ BasePageComponent, Hub Pages, Dialogs │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ gRPC Clients │ │ HTTP REST Services│ │
│ │ (Protobuf) │ │ (DiscountShop) │ │
│ └──────┬───────┘ └────────┬─────────┘ │
└─────────┼──────────────────────┼─────────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────┐
│ CMS Microservice │
│ (ASP.NET Core + gRPC) │
│ Domain → Application (CQRS) → Infra │
└──────────────────────────────────────────┘
```
---
## ۲. Technology Stack
| لایه | تکنولوژی | نسخه |
|------|----------|------|
| Frontend Framework | Blazor WebAssembly | .NET 9 |
| UI Library | MudBlazor | v8 |
| Backend Communication (عادی) | gRPC / Protobuf | — |
| Backend Communication (تخفیفی) | HTTP REST | — |
| Object Mapping | Mapster | — |
| تاریخ شمسی | DateTimeConverterCL | — |
| Client State | Blazored.LocalStorage | — |
| Auth | JWT Role-based | Administrator, Admin, Author |
| Permission | IAuthorizationService.HasPermissionAsync | 18 permission |
---
## ۳. ساختار پوشه‌ها
```
BackOffice/src/BackOffice/
├── Common/
│ ├── BaseComponents/ ← کامپوننت‌های پایه (BasePageComponent, DateRangePicker, Image)
│ ├── Utilities/ ← RouteConstance, Extensions, Helpers
│ └── ...
├── Pages/
│ ├── Category/ ← دسته‌بندی فروشگاه عادی
│ ├── Products/ ← محصولات فروشگاه عادی
│ ├── UserOrder/ ← سفارشات + گزارش فروش (Hub)
│ ├── DiscountShop/ ← فروشگاه تخفیفی (محصولات + دسته‌بندی + سفارشات)
│ │ └── Components/ ← دیالوگ‌ها و کامپوننت‌های اختصاصی
│ ├── Inventory/ ← انبارداری (4 صفحه)
│ ├── Package/ ← پکیج‌ها
│ ├── Commission/ ← کمیسیون (5 صفحه)
│ ├── Network/ ← شبکه (4 صفحه)
│ ├── Club/ ← باشگاه مشتریان (Hub: اعضا + آمار + فیچرها)
│ ├── Blog/ ← بلاگ (Hub: پست + دسته‌بندی + تگ)
│ ├── Content/ ← صفحات سایت
│ ├── Wallet/ ← کیف‌پول (تب‌ها: لیست + تاریخچه)
│ ├── Contract/ ← قراردادها
│ ├── SystemManagement/ ← سیستم (Hub: تنظیمات + Worker + Health)
│ └── ...
├── Services/
│ ├── DiscountProduct/ ← IDiscountProductService + implementation
│ ├── DiscountCategory/ ← IDiscountCategoryService + implementation
│ ├── DiscountOrder/ ← IDiscountOrderService + implementation
│ └── Authorization/ ← IAuthorizationService
├── Shared/
│ ├── MainLayout.razor ← لایوت اصلی (AppBar + NavMenu + MudContainer)
│ ├── NavMenu.razor ← منوی ناوبری
│ ├── GlobalSearch.razor ← جستجوی سراسری
│ └── AppBreadcrumb.razor ← Breadcrumb فارسی
└── wwwroot/
├── js/main.js ← jsSaveAsFile (Excel export)
└── appsettings.json ← تنظیمات endpoints
```
---
## ۴. الگوهای اصلی
### ۴.۱ BasePageComponent — پترن صفحات لیست
**هر صفحه لیست** از `BasePageComponent` استفاده می‌کند:
```
┌──────────────────────────────────────┐
│ BasePageComponent │
│ ┌────────────────────────────────┐ │
│ │ 📋 Filter Panel (collapsible) │ │
│ │ [فیلد ۱] [فیلد ۲] [فیلد ۳] │ │
│ │ [پاک کردن فیلتر] [جستجو] │ │
│ └────────────────────────────────┘ │
│ ┌────────────────────────────────┐ │
│ │ 📊 Content (DataGrid) │ │
│ │ ToolBar: [عنوان] [Excel] [+] │ │
│ │ Columns: ... │ │
│ │ Pager: 20/50/100 │ │
│ └────────────────────────────────┘ │
└──────────────────────────────────────┘
```
**فایل:** `Common/BaseComponents/BasePageComponent.razor`
**پراپرتی‌ها:**
- `RenderFragment Filters` — محتوای فیلتر
- `RenderFragment Content` — محتوای اصلی
- `EventCallback OnSubmitClick` — کلیک جستجو
- `EventCallback OnClearFilterClick` — کلیک پاک کردن
- `bool IsFiltered` — آیا فیلتر فعال است (نشان‌دهنده badge «فعال»)
---
### ۴.۲ Hub Pages — پترن ادغام صفحات
صفحات مرتبط در یک Hub با `MudTabs` ادغام می‌شوند:
| Hub | Route‌ها | تب‌ها |
|-----|---------|-------|
| `OrdersHub` | `/OrdersPage/`, `/OrdersSalesReportsPage/` | سفارشات + گزارش فروش |
| `DiscountShopHub` | `/discount-shop`, `/discount-orders`, `/discount-sales-reports` | سفارشات + گزارش فروش |
| `ClubHub` | `/club`, `/club/members`, `/club/statistics` | اعضا + آمار |
| `BlogHub` | `/blog`, `/blog/posts`, `/blog/categories`, `/tags` | پست + دسته‌بندی + تگ |
| `SystemHub` | `/system`, `/system/configuration`, `/system/worker-control`, `/system/health` | تنظیمات + Worker + Health |
---
### ۴.۳ Code-Behind — پترن جداسازی markup/logic
```
MyPage.razor → فقط HTML/Razor markup
MyPage.razor.cs → partial class + [Inject] + methods
```
**قوانین:**
1. فایل‌هایی که سرویس inject دارند **باید** code-behind داشته باشند (محدودیت Razor source generator)
2. سرویس‌های global (`_Imports.razor`) **نباید** دوباره `[Inject]` شوند
3. `namespace` باید با مسیر فایل match کند
**سرویس‌های Global (از `_Imports.razor`):**
| سرویس | نام متغیر | توضیح |
|--------|-----------|-------|
| `IDialogService` | `DialogService` | دیالوگ MudBlazor |
| `ISnackbar` | `Snackbar` | نوتیفیکیشن MudBlazor |
| `IJSRuntime` | `jsRuntime` | ⚠️ حرف کوچک `j` |
| `NavigationManager` | `Navigation` | ناوبری |
| `ILocalStorageService` | `LocalStorageService` | ذخیره محلی |
| `AuthenticationStateProvider` | `AuthenticationStateProvider` | احراز هویت |
---
### ۴.۴ Excel Export — پترن خروجی CSV
```csharp
private async Task ExportToExcel()
{
var sb = new StringBuilder();
sb.AppendLine("ستون ۱,ستون ۲,ستون ۳"); // هدر فارسی
foreach (var item in items)
{
sb.AppendLine($"{EscapeCsv(item.Col1)},{item.Col2},{item.Col3}");
}
var bytes = Encoding.UTF8.GetPreamble() // UTF-8 BOM
.Concat(Encoding.UTF8.GetBytes(sb.ToString())).ToArray();
var base64 = Convert.ToBase64String(bytes);
await jsRuntime.InvokeVoidAsync("jsSaveAsFile", "filename.csv", base64);
}
private string EscapeCsv(string? value)
{
if (string.IsNullOrEmpty(value)) return "";
if (value.Contains(',') || value.Contains('"') || value.Contains('\n'))
return $"\"{value.Replace("\"", "\"\"")}\"";
return value;
}
```
**صفحات دارای Excel:** Products, UserOrders, ClubMembers, WithdrawalRequests, WeeklyReports, StockMovements, Users, DiscountOrders, ManualPayments, Inventory, DiscountProducts
---
### ۴.۵ Server-Side DataGrid — پترن بارگذاری صفحه‌ای
```razor
<MudDataGrid T="MyDto"
ServerData="LoadServerData"
Height="calc(100vh - 240px)"
FixedHeader="true"
Hover="true" Dense="true">
```
```csharp
private async Task<GridData<MyDto>> LoadServerData(GridState<MyDto> state)
{
var filter = new MyFilter
{
PageNumber = state.Page + 1, // MudDataGrid is 0-based
PageSize = state.PageSize
};
var (items, totalCount, _) = await MyService.GetAsync(filter);
return new GridData<MyDto> { Items = items, TotalItems = totalCount };
}
```
---
### ۴.۶ Permission System
NavMenu از `IAuthorizationService.HasPermissionAsync()` برای نمایش/مخفی کردن آیتم‌ها استفاده می‌کند:
| Permission | صفحه(ها) |
|-----------|----------|
| `dashboard.view` | داشبورد |
| `packages.manage` | پکیج‌ها |
| `products.manage` | محصولات + دسته‌بندی + ویرایش دسته‌جمعی |
| `orders.view` | سفارشات |
| `inventory.manage` | انبارداری (4 صفحه) |
| `discountshop.manage` | فروشگاه تخفیفی |
| `users.view` | کاربران |
| `roles.manage` | نقش‌ها |
| `manualpayments.create` | پرداخت دستی |
| `blog.manage` | بلاگ |
| `sitepages.manage` | صفحات سایت |
| `publicmessages.view` | پیام‌های عمومی |
| `settings.manage_configuration` | تنظیمات سیستم |
---
## ۵. مسیرهای (Routing)
### مسیرهای ثابت (`RouteConstance.cs`)
```
/ → Dashboard
/PackagePage/ → Packages
/ProductsPage/ → Products
/CategoryPage/ → Categories
/OrdersPage/ → Orders Hub
/OrdersSalesReportsPage/ → Orders Sales Reports
/InventoryPage/ → Inventory
/InventoryLowStockPage/ → Low Stock
/InventoryWarehousesPage/ → Warehouses
/InventoryMovementsPage/ → Stock Movements
/UserPage/ → Users
/RolePage/ → Roles
/ProductsBulkEditPage/ → Bulk Edit
/ProductCategoriesPage/ → Product-Category DragDrop
/CategoryProductsPage/ → Category-Product DragDrop
```
### مسیرهای hardcode (فروشگاه تخفیفی + سایر)
```
/discount-products → Discount Products
/discount-categories → Discount Categories
/discount-shop → Discount Orders Hub
/discount-orders → Discount Orders
/discount-sales-reports → Discount Sales Reports
/commission/* → Commission pages
/network/* → Network pages
/club/* → Club pages
/blog/* → Blog pages
/wallets → Wallets
/contracts → Contracts
/payment/manual-payments → Manual Payments
/system/* → System pages
/settings → Settings
/content/pages → Content Pages
/public-messages → Public Messages
```
---
## ۶. ارتباط فروشگاه عادی vs تخفیفی
| جنبه | فروشگاه عادی | فروشگاه تخفیفی |
|------|-------------|---------------|
| **سرویس محصولات** | gRPC `ProductsContractClient` | HTTP `IDiscountProductService` |
| **سرویس دسته‌بندی** | gRPC `CategoryContractClient` | HTTP `IDiscountCategoryService` |
| **سرویس سفارشات** | gRPC `UserOrderContractClient` | HTTP `IDiscountOrderService` |
| **Entity بکند** | `Product` | `DiscountProduct` |
| **پرداخت** | فقط درگاه | ترکیبی (کیف تخفیفی + درگاه) |
| **فیلد اختصاصی** | — | `MaxDiscountPercent` |
| **UI Pattern** | BasePageComponent | BasePageComponent (یکسان) |
| **ستون‌ها** | یکسان | یکسان + ستون تخفیف |
---
## ۷. نقشه NavMenu
```
داشبورد
─────────────────────
کمیسیون و شبکه
├── کمیسیون (NavGroup)
│ ├── داشبورد کمیسیون
│ ├── گزارش‌های هفتگی
│ ├── پرداخت کاربران
│ ├── درخواست‌های برداشت [Badge]
│ └── گزارش برداشت‌ها
├── شبکه (NavGroup)
│ ├── درخت شبکه
│ ├── گزارش موجودی‌ها
│ └── آمار شبکه
└── باشگاه مشتریان (NavGroup)
├── اعضا و آمار
└── فیچرهای باشگاه
─────────────────────
فروشگاه [AuthorizeView: Administrator]
├── پکیج‌ها
├── فروشگاه عادی (NavGroup)
│ ├── محصولات
│ ├── دسته‌بندی‌ها
│ └── سفارشات و گزارش
├── انبارداری (NavGroup)
│ ├── موجودی انبار
│ ├── محصولات کم‌موجود
│ ├── مدیریت انبارها
│ └── تاریخچه تغییرات
└── فروشگاه تخفیفی (NavGroup)
├── محصولات
├── دسته‌بندی‌ها
└── سفارشات و گزارش
─────────────────────
مدیریت [AuthorizeView: Administrator]
├── کاربران
├── نقش‌ها
├── پرداخت دستی
├── کیف‌پول
└── قراردادها
─────────────────────
مدیریت محتوا
├── بلاگ
├── صفحات سایت
└── پیام‌های عمومی
─────────────────────
سیستم [AuthorizeView: Administrator]
├── مدیریت سیستم
└── نسخه اپلیکیشن‌ها
─────────────────────
تنظیمات
```