Files
docs/ui-modernization/BACKOFFICE-ARCHITECTURE.md
T

360 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🏗️ 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]
├── مدیریت سیستم
└── نسخه اپلیکیشن‌ها
─────────────────────
تنظیمات
```